Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@steven-tey
Copy link
Collaborator

@steven-tey steven-tey commented Dec 17, 2025

Summary by CodeRabbit

  • New Features

    • Partner tracking now includes optional groupId and tenantId for finer attribution.
  • Behavior Changes

    • Partner enrollment responses now expose groupId and tenantId directly.
    • Link creation/update now derive programEnrollment groupId from partner.groupId when present.
    • Group listing sorting simplified to use only the primary sort.
  • Tests

    • Added runtime validations ensuring partner.groupId and partner.tenantId are null/undefined or strings.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Contributor

vercel bot commented Dec 17, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
dub Ready Ready Preview Dec 18, 2025 1:15am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 17, 2025

Walkthrough

Adds optional nullable groupId and tenantId to partner payloads and types, updates SQL queries and mappings to select and return those fields, switches programEnrollment usage to partner.groupId, removes a secondary sort in groups query, and adds tests asserting the new partner fields' runtime types.

Changes

Cohort / File(s) Summary
Track click response & schema
apps/web/app/(ee)/api/track/click/route.ts
Extended partner schema to include optional groupId and tenantId (nullable strings).
DB read β€” link/partner enrollment
apps/web/lib/planetscale/get-link-with-partner.ts, apps/web/lib/planetscale/get-partner-enrollment-info.ts
SQL SELECTs and result mapping updated to fetch ProgramEnrollment.groupId and ProgramEnrollment.tenantId; getPartnerEnrollmentInfo now returns groupId and tenantId at top level (removed nested group object).
Link create/update integrations
apps/web/lib/api/links/create-link.ts, apps/web/lib/api/links/update-link.ts
Removed reliance on separate group value from getPartnerEnrollmentInfo; Tinybird/recordLink payloads now conditionally set programEnrollment.groupId from partner.groupId.
Types & transformations
apps/web/lib/types.ts, apps/web/lib/api/links/utils/transform-link.ts
RedisLinkProps.partner and ExpandedLink.partner augmented to include optional `groupId?: string
Redis formatting
apps/web/lib/upstash/format-redis-link.ts
Include partner.groupId and partner.tenantId in Redis output when present.
Tests
apps/web/tests/tracks/track-click.test.ts
Added runtime assertions that partner.groupId and partner.tenantId (when partner exists) are either strings or null/undefined.
Query ordering change
apps/web/lib/api/groups/get-groups.ts
Removed secondary sort mapping and simplified ORDER BY to use only the primary sort column and direction.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify SQL aliases, nullability, and column selection in get-link-with-partner.ts and get-partner-enrollment-info.ts.
  • Confirm callers handle the changed return shape (group -> groupId/tenantId) and no remaining references to the removed group object.
  • Check type updates in apps/web/lib/types.ts and transform-link.ts for consistent consumption sites.
  • Ensure tests properly assert nullable string types and are not flaky.

Possibly related PRs

Suggested reviewers

  • devkiran

Poem

πŸ‡ I hopped through rows and schema bright,
two tiny fields joined partner's sight.
groupId, tenantId β€” tucked in the lane,
from SQL burrows to response they came.
I twitch my nose and hop again. πŸ₯•

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
βœ… Passed checks (2 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The PR title accurately describes the primary change: adding groupId and tenantId fields to the trackClickResponseSchema, though the changeset extends beyond just the schema.
✨ Finishing touches
  • πŸ“ Generate docstrings
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch track-click-groupId

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/lib/planetscale/get-link-with-partner.ts (1)

10-22: Update the TypeScript interface to include the new fields.

The QueryResult interface's partner property is missing the newly added groupId and tenantId fields, creating a type mismatch with the actual return value constructed at lines 94-95.

Apply this diff to update the interface:

 interface QueryResult extends EdgeLinkProps {
   partner?: {
     id: string;
     name: string;
     image: string | null;
+    groupId: string | null;
+    tenantId: string | null;
   } | null;
   discount?: {
     id: string;
     amount: number;
     type: "percentage" | "flat";
     maxDuration: number | null;
   } | null;
 }
πŸ“œ Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between d0daa2e and f0634a9.

πŸ“’ Files selected for processing (3)
  • apps/web/app/(ee)/api/track/click/route.ts (1 hunks)
  • apps/web/lib/planetscale/get-link-with-partner.ts (3 hunks)
  • apps/web/tests/tracks/track-click.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
πŸ““ Common learnings
Learnt from: devkiran
Repo: dubinc/dub PR: 2754
File: apps/web/lib/partnerstack/schemas.ts:47-52
Timestamp: 2025-08-16T11:14:00.667Z
Learning: The PartnerStack API always includes the `group` field in partner responses, so the schema should use `.nullable()` rather than `.nullish()` since the field is never omitted/undefined.
πŸ“š Learning: 2025-08-14T05:57:35.546Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2735
File: apps/web/lib/actions/partners/update-discount.ts:60-66
Timestamp: 2025-08-14T05:57:35.546Z
Learning: In the partner groups system, discounts should always belong to a group. The partnerGroup relation should never be null when updating discounts, so optional chaining on partnerGroup?.id may be unnecessary defensive programming.

Applied to files:

  • apps/web/lib/planetscale/get-link-with-partner.ts
πŸ“š Learning: 2025-08-16T11:14:00.667Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2754
File: apps/web/lib/partnerstack/schemas.ts:47-52
Timestamp: 2025-08-16T11:14:00.667Z
Learning: The PartnerStack API always includes the `group` field in partner responses, so the schema should use `.nullable()` rather than `.nullish()` since the field is never omitted/undefined.

Applied to files:

  • apps/web/app/(ee)/api/track/click/route.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
πŸ”‡ Additional comments (2)
apps/web/lib/planetscale/get-link-with-partner.ts (2)

44-45: LGTM!

The SQL query correctly fetches groupId and tenantId from the already-joined ProgramEnrollment table.


70-96: LGTM!

The destructuring correctly extracts the new fields from the query result, and they're properly included in the partner object construction.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/lib/planetscale/get-partner-enrollment-info.ts (1)

56-60: Remove deprecated group field for consistent return shape.

The early return includes group: null, but the success path (lines 63-81) only returns partner and discount. This creates an inconsistent return type. Since callers no longer destructure a group field, remove it from the early return.

Apply this diff:

   if (!result) {
     return {
       partner: null,
-      group: null,
       discount: null,
     };
   }
πŸ“œ Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between eb717bf and 1105359.

πŸ“’ Files selected for processing (5)
  • apps/web/lib/api/groups/get-groups.ts (1 hunks)
  • apps/web/lib/api/links/create-link.ts (2 hunks)
  • apps/web/lib/api/links/update-link.ts (2 hunks)
  • apps/web/lib/planetscale/get-partner-enrollment-info.ts (3 hunks)
  • apps/web/lib/types.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
πŸ“š Learning: 2025-06-06T07:59:03.120Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.

Applied to files:

  • apps/web/lib/api/links/update-link.ts
  • apps/web/lib/api/links/create-link.ts
πŸ“š Learning: 2025-09-17T17:44:03.965Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2857
File: apps/web/lib/actions/partners/update-program.ts:96-0
Timestamp: 2025-09-17T17:44:03.965Z
Learning: In apps/web/lib/actions/partners/update-program.ts, the team prefers to keep the messagingEnabledAt update logic simple by allowing client-provided timestamps rather than implementing server-controlled timestamp logic to avoid added complexity.

Applied to files:

  • apps/web/lib/api/links/update-link.ts
πŸ“š Learning: 2025-08-14T05:57:35.546Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2735
File: apps/web/lib/actions/partners/update-discount.ts:60-66
Timestamp: 2025-08-14T05:57:35.546Z
Learning: In the partner groups system, discounts should always belong to a group. The partnerGroup relation should never be null when updating discounts, so optional chaining on partnerGroup?.id may be unnecessary defensive programming.

Applied to files:

  • apps/web/lib/planetscale/get-partner-enrollment-info.ts
🧬 Code graph analysis (2)
apps/web/lib/api/links/update-link.ts (1)
apps/web/lib/planetscale/get-partner-enrollment-info.ts (1)
  • getPartnerEnrollmentInfo (18-82)
apps/web/lib/api/links/create-link.ts (1)
apps/web/lib/planetscale/get-partner-enrollment-info.ts (1)
  • getPartnerEnrollmentInfo (18-82)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
πŸ”‡ Additional comments (9)
apps/web/lib/api/links/update-link.ts (2)

173-176: LGTM! Destructuring aligns with updated return shape.

The removal of group from the destructuring is correct, as getPartnerEnrollmentInfo now returns groupId and tenantId within the partner object instead of as a separate group field.


189-191: LGTM! Conditional programEnrollment logic is correct.

The conditional spread correctly derives programEnrollment.groupId from partner.groupId when present, replacing the previous approach that used a separate group value.

apps/web/lib/api/links/create-link.ts (2)

144-147: LGTM! Consistent with the updated return shape.

The destructuring correctly extracts only partner and discount, matching the changes in update-link.ts and the updated getPartnerEnrollmentInfo signature.


160-162: LGTM! Conditional logic matches update-link flow.

The conditional spread correctly derives programEnrollment.groupId from partner.groupId, consistent with the implementation in update-link.ts.

apps/web/lib/types.ts (1)

191-194: LGTM! Type extension correctly reflects the updated partner structure.

The addition of optional groupId and tenantId fields to RedisLinkProps.partner aligns with the partner object shape returned by getPartnerEnrollmentInfo and enables caching of program enrollment context.

apps/web/lib/planetscale/get-partner-enrollment-info.ts (3)

14-14: LGTM! Interface extension is correct.

The addition of tenantId to the QueryResult interface correctly reflects the SQL query results and matches the nullable type of the database field.


43-44: LGTM! SQL query correctly selects the new fields.

The query appropriately selects groupId and tenantId from the ProgramEnrollment table, which will be included in the returned partner object.


68-69: LGTM! Partner object correctly includes new fields.

The addition of groupId and tenantId to the returned partner object aligns with the type changes in RedisLinkProps and enables callers to access program enrollment context through the partner object.

apps/web/lib/api/groups/get-groups.ts (1)

77-77: The SQL injection risk is properly mitigated by Zod schema validation.

The getGroupsQuerySchema validates both sortBy and sortOrder using strict enums:

  • sortBy is limited to a whitelist of aggregate columns: createdAt, totalPartners, totalClicks, totalLeads, totalSales, totalSaleAmount, totalConversions, totalCommissions
  • sortOrder is limited to "asc" or "desc"

This enum validation prevents SQL injection. The table prefix logic is also correctβ€”only "createdAt" receives the "pg." prefix because other sortBy values are computed aliases, not table columns. No action required.

Likely an incorrect or invalid review comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/web/lib/api/links/utils/transform-link.ts (1)

16-21: Type definition is correct; consider simplifying if undefined vs null distinction is unnecessary.

The type uses both optional (?:) and nullable (| null), allowing three states: undefined, null, or string. This is valid TypeScript, but if the distinction between "not set" (undefined) and "explicitly null" isn't needed, you could simplify to just groupId?: string or groupId: string | null.

Looking at the usage in format-redis-link.ts, the truthy check treats both undefined and null identically, so the extra optionality might not be necessary. However, if API contracts or future logic need to distinguish these states, the current typing is appropriate.

πŸ“œ Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 9411f1f and 2c61eff.

πŸ“’ Files selected for processing (2)
  • apps/web/lib/api/links/utils/transform-link.ts (1 hunks)
  • apps/web/lib/upstash/format-redis-link.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
πŸ““ Common learnings
Learnt from: devkiran
Repo: dubinc/dub PR: 2735
File: apps/web/lib/actions/partners/update-discount.ts:60-66
Timestamp: 2025-08-14T05:57:35.546Z
Learning: In the partner groups system, discounts should always belong to a group. The partnerGroup relation should never be null when updating discounts, so optional chaining on partnerGroup?.id may be unnecessary defensive programming.
Learnt from: devkiran
Repo: dubinc/dub PR: 2754
File: apps/web/lib/partnerstack/schemas.ts:47-52
Timestamp: 2025-08-16T11:14:00.667Z
Learning: The PartnerStack API always includes the `group` field in partner responses, so the schema should use `.nullable()` rather than `.nullish()` since the field is never omitted/undefined.
πŸ“š Learning: 2025-08-14T05:57:35.546Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2735
File: apps/web/lib/actions/partners/update-discount.ts:60-66
Timestamp: 2025-08-14T05:57:35.546Z
Learning: In the partner groups system, discounts should always belong to a group. The partnerGroup relation should never be null when updating discounts, so optional chaining on partnerGroup?.id may be unnecessary defensive programming.

Applied to files:

  • apps/web/lib/upstash/format-redis-link.ts
🧬 Code graph analysis (1)
apps/web/lib/api/links/utils/transform-link.ts (1)
apps/web/lib/types.ts (1)
  • PartnerProps (457-460)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
πŸ”‡ Additional comments (1)
apps/web/lib/upstash/format-redis-link.ts (1)

59-60: LGTM! Conditional inclusion follows existing patterns.

The conditional spread pattern correctly adds groupId and tenantId to the partner object when they have truthy values, consistent with the existing code style in this file. Filtering out null/undefined values is appropriate for Redis storage.

@steven-tey steven-tey merged commit a4ec17b into main Dec 18, 2025
7 of 8 checks passed
@steven-tey steven-tey deleted the track-click-groupId branch December 18, 2025 05:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants