Conversation
- Updated the GET endpoint for partner links to include discount codes in the response. - Modified the partner-approved workflow to omit discount codes when parsing existing partner links. - Adjusted the getPartners function to include discount codes in the links response. - Extended the ProgramPartnerLinkSchema to include discount code details.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/web/app/(ee)/api/partners/links/route.ts (1)
48-52: Optional: narrow the nesteddiscountCodeselection to what's exposed.The include fetches all
DiscountCodecolumns (includingpartnerId,linkId,discountId), butProgramPartnerLinkSchema.discountCodeonly exposes{ id, code }and Zod's defaultstripmode silently drops the rest. You could make the Prisma selection match the public shape to avoid overfetching.♻️ Suggested narrowing
links: { - include: { - discountCode: true, + include: { + discountCode: { + select: { id: true, code: true }, + }, }, },🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/app/`(ee)/api/partners/links/route.ts around lines 48 - 52, The nested Prisma include is overfetching DiscountCode fields; update the include under links (where `discountCode: true` is used) to explicitly select only the public fields that `ProgramPartnerLinkSchema.discountCode` exposes (e.g., `id` and `code`) so the DB query matches the public Zod shape and avoids pulling `partnerId`, `linkId`, `discountId`, etc.; locate the include inside the `links` selection in apps/web/app/(ee)/api/partners/links/route.ts and replace the boolean include with a selective `select` for `id` and `code`.apps/web/app/(ee)/api/discount-codes/route.ts (1)
27-89: Align thediscountandlinklookups for consistency.The two guarded lookups use different patterns for the same goal (ensure the record belongs to
programId):
discountusesfindUnique({ where: { id: discountId, programId } })— scoped in the where clauselinkusesfindUnique({ where: { id: linkId } })— unscoped, relies on the post-checkSince your codebase already uses the extended where pattern for
discount, alignlinkby addingprogramIdto its where clause:♻️ Suggested alignment
linkId ? prisma.link.findUnique({ where: { id: linkId, + programId, }, select: { programId: true, }, }) : null,Optionally drop the now-redundant
discount.programId !== programIdandlink.programId !== programIdcomparisons once both are scoped.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/app/`(ee)/api/discount-codes/route.ts around lines 27 - 89, Align the link lookup with the discount lookup by scoping the prisma.link.findUnique call to include programId in its where clause (i.e., use where: { id: linkId, programId } when linkId is present) so it directly enforces record ownership; update the linkId branch that calls prisma.link.findUnique and then you can optionally remove the redundant post-check comparing link.programId !== programId, similar to how discount is handled in the same Promise.all block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/web/app/`(ee)/api/discount-codes/route.ts:
- Around line 19-102: The GET handler currently returns an unbounded array of
DiscountCode rows; add pagination to the GET exported handler by extending
getDiscountCodesQuerySchema to accept page and pageSize (same convention as
getPartnersQuerySchema), validate/normalize them in the GET handler, and change
the prisma.discountCode.findMany call in the GET handler to use take and skip
(or cursor) based on page/pageSize; also fetch total via
prisma.discountCode.count with the same where filter and return a paginated
response object (e.g. { items: DiscountCodeSchema.array().parse(items), total,
page, pageSize }) and update the OpenAPI/response schema accordingly. Ensure you
still apply existing filters (partnerId, tenantId, discountId, linkId,
programId) to both count and findMany and keep existing not_found checks
(programEnrollment, discount, link) unchanged.
---
Nitpick comments:
In `@apps/web/app/`(ee)/api/discount-codes/route.ts:
- Around line 27-89: Align the link lookup with the discount lookup by scoping
the prisma.link.findUnique call to include programId in its where clause (i.e.,
use where: { id: linkId, programId } when linkId is present) so it directly
enforces record ownership; update the linkId branch that calls
prisma.link.findUnique and then you can optionally remove the redundant
post-check comparing link.programId !== programId, similar to how discount is
handled in the same Promise.all block.
In `@apps/web/app/`(ee)/api/partners/links/route.ts:
- Around line 48-52: The nested Prisma include is overfetching DiscountCode
fields; update the include under links (where `discountCode: true` is used) to
explicitly select only the public fields that
`ProgramPartnerLinkSchema.discountCode` exposes (e.g., `id` and `code`) so the
DB query matches the public Zod shape and avoids pulling `partnerId`, `linkId`,
`discountId`, etc.; locate the include inside the `links` selection in
apps/web/app/(ee)/api/partners/links/route.ts and replace the boolean include
with a selective `select` for `id` and `code`.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1737b41e-04c6-4398-ad68-a6d17d446f99
📒 Files selected for processing (9)
apps/web/app/(ee)/api/discount-codes/route.tsapps/web/app/(ee)/api/partners/links/route.tsapps/web/app/(ee)/api/workflows/partner-approved/route.tsapps/web/lib/api/partners/get-partners.tsapps/web/lib/openapi/discount-codes/index.tsapps/web/lib/openapi/discount-codes/list-discount-codes.tsapps/web/lib/openapi/index.tsapps/web/lib/zod/schemas/discount.tsapps/web/lib/zod/schemas/programs.ts
| // GET /api/discount-codes - get all discount codes for a program | ||
| export const GET = withWorkspace( | ||
| async ({ workspace, searchParams }) => { | ||
| const programId = getDefaultProgramIdOrThrow(workspace); | ||
|
|
||
| const { partnerId } = getDiscountCodesQuerySchema.parse(searchParams); | ||
| let { partnerId, tenantId, discountId, linkId } = | ||
| getDiscountCodesQuerySchema.parse(searchParams); | ||
|
|
||
| const programEnrollment = await getProgramEnrollmentOrThrow({ | ||
| partnerId, | ||
| programId, | ||
| include: { | ||
| discountCodes: true, | ||
| const [programEnrollment, discount, link] = await Promise.all([ | ||
| partnerId || tenantId | ||
| ? prisma.programEnrollment.findUnique({ | ||
| where: partnerId | ||
| ? { partnerId_programId: { partnerId, programId } } | ||
| : { tenantId_programId: { tenantId: tenantId!, programId } }, | ||
| select: { | ||
| partnerId: true, | ||
| }, | ||
| }) | ||
| : null, | ||
|
|
||
| discountId | ||
| ? prisma.discount.findUnique({ | ||
| where: { | ||
| id: discountId, | ||
| programId, | ||
| }, | ||
| select: { | ||
| programId: true, | ||
| }, | ||
| }) | ||
| : null, | ||
|
|
||
| linkId | ||
| ? prisma.link.findUnique({ | ||
| where: { | ||
| id: linkId, | ||
| }, | ||
| select: { | ||
| programId: true, | ||
| }, | ||
| }) | ||
| : null, | ||
| ]); | ||
|
|
||
| // Filter by partner or tenant | ||
| if ((partnerId || tenantId) && !programEnrollment) { | ||
| throw new DubApiError({ | ||
| code: "not_found", | ||
| message: `The partner with ${partnerId ? "partnerId" : "tenantId"} ${partnerId ?? tenantId} is not enrolled in your program.`, | ||
| }); | ||
| } | ||
|
|
||
| if (programEnrollment) { | ||
| partnerId = programEnrollment.partnerId; | ||
| } | ||
|
|
||
| // Filter by discount | ||
| if (discountId && (!discount || discount.programId !== programId)) { | ||
| throw new DubApiError({ | ||
| code: "not_found", | ||
| message: "Discount not found.", | ||
| }); | ||
| } | ||
|
|
||
| // Filter by link | ||
| if (linkId && (!link || link.programId !== programId)) { | ||
| throw new DubApiError({ | ||
| code: "not_found", | ||
| message: "Link not found.", | ||
| }); | ||
| } | ||
|
|
||
| const discountCodes = await prisma.discountCode.findMany({ | ||
| where: { | ||
| programId, | ||
| ...(partnerId && { partnerId }), | ||
| ...(linkId && { linkId }), | ||
| ...(discountId && { discountId }), | ||
| }, | ||
| }); | ||
|
|
||
| const response = DiscountCodeSchema.array().parse( | ||
| programEnrollment.discountCodes, | ||
| ); | ||
| const response = DiscountCodeSchema.array().parse(discountCodes); | ||
|
|
||
| return NextResponse.json(response); |
There was a problem hiding this comment.
Add pagination before shipping this as a public API.
GET /discount-codes returns every DiscountCode row for the program in a single response — no take/skip/cursor, and the OpenAPI schema (z.array(DiscountCodeSchema)) bakes the unbounded-array contract into the SDK. For programs with many partner links (each link can have its own discount code), this will grow linearly with partners × links and cause slow/oversized responses on the request path. Once published, adding pagination later is a breaking change for SDK consumers.
Recommend introducing page/pageSize (matching the getPartnersQuerySchema convention elsewhere in this repo) now, and updating the OpenAPI response accordingly.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/web/app/`(ee)/api/discount-codes/route.ts around lines 19 - 102, The GET
handler currently returns an unbounded array of DiscountCode rows; add
pagination to the GET exported handler by extending getDiscountCodesQuerySchema
to accept page and pageSize (same convention as getPartnersQuerySchema),
validate/normalize them in the GET handler, and change the
prisma.discountCode.findMany call in the GET handler to use take and skip (or
cursor) based on page/pageSize; also fetch total via prisma.discountCode.count
with the same where filter and return a paginated response object (e.g. { items:
DiscountCodeSchema.array().parse(items), total, page, pageSize }) and update the
OpenAPI/response schema accordingly. Ensure you still apply existing filters
(partnerId, tenantId, discountId, linkId, programId) to both count and findMany
and keep existing not_found checks (programEnrollment, discount, link)
unchanged.
Summary by CodeRabbit