-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Fix importer partnerGroupDefaultLinkId #2880
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds partnerGroupDefaultLink awareness to partner import flows (FirstPromoter, PartnerStack, Rewardful): program/group queries now include partnerGroupDefaultLinks; link creation propagates partnerGroupDefaultLinkId, typically assigning the first default link’s id to the first generated partner link and null to subsequent links. One function signature updated to include this field. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Src as Import Source (FirstPromoter/PartnerStack/Rewardful)
participant Svc as Import Service
participant DB as DB (Program, Groups, DefaultLinks, Partners, Links)
Src->>Svc: Start partner import
Svc->>DB: Fetch Program incl. groups.partnerGroupDefaultLinks
DB-->>Svc: Program + Groups + DefaultLinks
loop For each partner enrollment
Svc->>Svc: Resolve partnerGroup (via groupId when available)
alt Partner exists?
Svc->>DB: Upsert/Create Partner
else
Svc->>DB: Create Partner
end
Note over Svc: Iterate external links with index i
Svc->>DB: Create PartnerLink<br/>payload includes partnerGroupDefaultLinkId =<br/> i==0 ? defaultLinks[0]?.id : null
DB-->>Svc: PartnerLink created
end
Svc-->>Src: Import complete
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
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. Comment |
There was a problem hiding this 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/firstpromoter/import-partners.ts (1)
168-180: Guard against missing default link (runtime crash risk)Indexing [0].id will throw when no default links exist.
Minimal fix:
- partnerGroupDefaultLinkId: - idx === 0 ? group.partnerGroupDefaultLinks[0].id : null, + partnerGroupDefaultLinkId: + idx === 0 ? (group.partnerGroupDefaultLinks[0]?.id ?? null) : null,Optional consistency (match PartnerStack behavior by indexing):
- partnerGroupDefaultLinkId: - idx === 0 ? group.partnerGroupDefaultLinks[0].id : null, + partnerGroupDefaultLinkId: + group.partnerGroupDefaultLinks[idx]?.id ?? null,
🧹 Nitpick comments (5)
apps/web/lib/rewardful/import-partners.ts (2)
32-34: Limit relation payload: select only idFetch only the ids to reduce payload and GC pressure.
- include: { - partnerGroupDefaultLinks: true, - }, + include: { + partnerGroupDefaultLinks: { select: { id: true } }, + },
188-201: Null‑safety is fine; consider consistency with PartnerStack mappingYou set PGDL only for the first link. PartnerStack maps by index (idx) across available default links. Consider aligning for consistency and future multi-default-link support.
apps/web/lib/firstpromoter/import-partners.ts (1)
23-27: Limit relation payload: select only idFetch only ids for partnerGroupDefaultLinks.
- groups: { - include: { - partnerGroupDefaultLinks: true, - }, - }, + groups: { + include: { + partnerGroupDefaultLinks: { select: { id: true } }, + }, + },apps/web/lib/partnerstack/import-links.ts (2)
19-23: Limit relation payload: select only idFetch only ids for partnerGroupDefaultLinks.
- groups: { - include: { - partnerGroupDefaultLinks: true, - }, - }, + groups: { + include: { + partnerGroupDefaultLinks: { select: { id: true } }, + }, + },
88-89: Avoid non‑null assertion on groupIdgroupId can be null; the assertion doesn’t help at runtime. Keep it explicit.
- const partnerGroup = groupsById.get(groupId!); + const partnerGroup = groupId ? groupsById.get(groupId) : undefined;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/lib/firstpromoter/import-partners.ts(5 hunks)apps/web/lib/partnerstack/import-links.ts(7 hunks)apps/web/lib/rewardful/import-partners.ts(5 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-06-06T07:59:03.120Z
Learnt from: devkiran
PR: dubinc/dub#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/firstpromoter/import-partners.tsapps/web/lib/partnerstack/import-links.tsapps/web/lib/rewardful/import-partners.ts
📚 Learning: 2025-08-14T05:00:23.224Z
Learnt from: devkiran
PR: dubinc/dub#2735
File: apps/web/app/api/og/program/route.tsx:63-64
Timestamp: 2025-08-14T05:00:23.224Z
Learning: In Dub's partner program system, the default partner group will always exist. When programs are created, a default partner group is automatically upserted using DEFAULT_PARTNER_GROUP constant, so accessing program.groups[0] in contexts where the default group is queried is safe.
Applied to files:
apps/web/lib/firstpromoter/import-partners.tsapps/web/lib/rewardful/import-partners.ts
📚 Learning: 2025-08-14T05:17:51.825Z
Learnt from: devkiran
PR: dubinc/dub#2735
File: apps/web/lib/actions/partners/delete-reward.ts:33-41
Timestamp: 2025-08-14T05:17:51.825Z
Learning: In the partner groups system, a rewardId can only belong to one group, establishing a one-to-one relationship between rewards and groups. This means using Prisma's `update` method (rather than `updateMany`) is appropriate when updating groups by rewardId.
Applied to files:
apps/web/lib/rewardful/import-partners.ts
🧬 Code graph analysis (2)
apps/web/lib/firstpromoter/import-partners.ts (1)
apps/web/lib/types.ts (1)
PartnerGroupDefaultLink(547-549)
apps/web/lib/partnerstack/import-links.ts (2)
apps/web/lib/types.ts (3)
WorkspaceProps(186-202)ProgramProps(442-442)PartnerProps(428-428)apps/web/lib/partnerstack/types.ts (1)
PartnerStackLink(26-26)
🔇 Additional comments (8)
apps/web/lib/firstpromoter/import-partners.ts (2)
2-6: LGTM on type importsExtending types to include PartnerGroupDefaultLink is appropriate.
102-102: LGTM on group type expansionAnnotating group with partnerGroupDefaultLinks[] ensures type safety downstream.
apps/web/lib/partnerstack/import-links.ts (6)
36-38: LGTMgroupsById map is a clean lookup for per-enrollment processing.
48-49: LGTMIncluding groupId in enrollment selection is necessary for downstream PGDL mapping.
72-72: LGTMDestructuring groupId alongside partner simplifies usage.
91-101: Robust PGDL mappingIndex-based mapping with optional chaining is safe and consistent.
127-136: LGTMExtending createPartnerLink to accept partnerGroupDefaultLinkId is correct.
189-190: LGTMForwarding partnerGroupDefaultLinkId into generatePartnerLink ensures correct association at link creation.
There was a problem hiding this 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 (2)
apps/web/lib/rewardful/import-partners.ts (2)
32-34: Limit loaded fields for default links to only idYou only use the id (and array length). Reduce payload and DB transfer.
Apply:
- include: { - partnerGroupDefaultLinks: true, - }, + include: { + partnerGroupDefaultLinks: { + select: { id: true }, + }, + },
190-202: Destructure partnerGroupDefaultLinkId and simplify mapping
bulkCreateLinks already accepts partnerGroupDefaultLinkId (ProcessedLinkProps) and the Prisma schema includes the column. Extract it once:const { partnerGroupDefaultLinkId } = defaultGroupAttributes; links: affiliate.links.map((link, idx) => ({ …, partnerGroupDefaultLinkId: idx === 0 ? partnerGroupDefaultLinkId : null, })),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/web/lib/rewardful/import-partners.ts(5 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: devkiran
PR: dubinc/dub#2735
File: apps/web/app/api/og/program/route.tsx:63-64
Timestamp: 2025-08-14T05:00:23.224Z
Learning: In Dub's partner program system, the default partner group will always exist. When programs are created, a default partner group is automatically upserted using DEFAULT_PARTNER_GROUP constant, so accessing program.groups[0] in contexts where the default group is queried is safe.
📚 Learning: 2025-06-06T07:59:03.120Z
Learnt from: devkiran
PR: dubinc/dub#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/rewardful/import-partners.ts
📚 Learning: 2025-08-14T05:57:35.546Z
Learnt from: devkiran
PR: dubinc/dub#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/rewardful/import-partners.ts
📚 Learning: 2025-08-16T11:14:00.667Z
Learnt from: devkiran
PR: dubinc/dub#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/lib/rewardful/import-partners.ts
📚 Learning: 2025-08-14T05:17:51.825Z
Learnt from: devkiran
PR: dubinc/dub#2735
File: apps/web/lib/actions/partners/delete-reward.ts:33-41
Timestamp: 2025-08-14T05:17:51.825Z
Learning: In the partner groups system, a rewardId can only belong to one group, establishing a one-to-one relationship between rewards and groups. This means using Prisma's `update` method (rather than `updateMany`) is appropriate when updating groups by rewardId.
Applied to files:
apps/web/lib/rewardful/import-partners.ts
📚 Learning: 2025-08-14T05:00:23.224Z
Learnt from: devkiran
PR: dubinc/dub#2735
File: apps/web/app/api/og/program/route.tsx:63-64
Timestamp: 2025-08-14T05:00:23.224Z
Learning: In Dub's partner program system, the default partner group will always exist. When programs are created, a default partner group is automatically upserted using DEFAULT_PARTNER_GROUP constant, so accessing program.groups[0] in contexts where the default group is queried is safe.
Applied to files:
apps/web/lib/rewardful/import-partners.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 (3)
apps/web/lib/rewardful/import-partners.ts (3)
91-94: Safe guard for missing default link addressedThe length check avoids the earlier crash when no default links exist.
39-41: Guard when provided groupId doesn’t belong to the programIf a bad groupId is passed, groups[0] will be undefined and subsequent property access will throw. Add a defensive check or fallback to the default group.
Suggested:
const defaultGroup = program.groups[0]; +if (!defaultGroup) { + throw new Error( + `Group ${groupId ?? DEFAULT_PARTNER_GROUP.slug} not found for program ${program.id}`, + ); +}
142-143: Don’t pass partnerGroupDefaultLinkId into ProgramEnrollment.create (likely unknown column)Adding partnerGroupDefaultLinkId to defaultGroupAttributes means it’s now spread into ProgramEnrollment.create. ProgramEnrollment doesn’t have this field (per prior review); Prisma will reject the create.
Apply:
async function createPartnerAndLinks({ @@ defaultGroupAttributes: { groupId: string; saleRewardId: string | null; leadRewardId: string | null; clickRewardId: string | null; discountId: string | null; partnerGroupDefaultLinkId: string | null; }; }) { + // Exclude fields not present on ProgramEnrollment from the create payload + const { + partnerGroupDefaultLinkId, + ...enrollmentAttrs + } = defaultGroupAttributes; @@ create: { id: createId({ prefix: "pge_" }), programId: program.id, partnerId: partner.id, status: "approved", - ...defaultGroupAttributes, + ...enrollmentAttrs, },Also applies to: 169-170
Summary by CodeRabbit
Improvements
Bug Fixes