-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Cleanup Prisma schemas #2961
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
Cleanup Prisma schemas #2961
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughRemoves lander- and cookieLength-related fields and logic across schemas, APIs, actions, and UI types; simplifies get-program API to a single path; updates analytics hook to use program.domain; adjusts Prisma relations and cascade behaviors; converts delete-program script to a single transaction; adds ts-nocheck to legacy migration scripts; updates an FAQ to fixed 90 days. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client
participant Route as GET /api/programs/[programId]
participant Svc as getProgramOrThrow
participant DB
Client->>Route: HTTP GET
Route->>Svc: getProgramOrThrow({ workspaceId, programId })
Svc->>DB: Query program by IDs
DB-->>Svc: Program
Svc-->>Route: ProgramSchema.parse(program)
Route-->>Client: 200 JSON (program)
sequenceDiagram
autonumber
participant Dev as Script
participant DB as Prisma.$transaction
participant Storage as Logo Storage
Dev->>DB: Begin transaction (extended timeouts)
DB->>DB: Delete commissions, payouts, rewards, discounts, partner groups
DB->>DB: Delete enrollments, default folder
DB->>DB: Update links (programId = null)
DB->>DB: Update project (defaultProgramId = null)
DB-->>Dev: Commit
Dev->>Storage: Delete program logo
Storage-->>Dev: OK
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (4)
apps/web/scripts/migrations/backfill-group-links-settings.ts (1)
1-1: Use@ts-nocheckfor file-wide suppression instead of@ts-ignore.
@ts-ignoreonly affects the next line. If you intend to disable type checks for this legacy script, switch to@ts-nocheck.Also confirm
program.urlandprogram.domainare guaranteed non-null for the paths you touch (you use non-null assertions several times). If not, either filter in the query or guard before use.Apply:
-// @ts-ignore - old migration script +// @ts-nocheck // old migration scriptapps/web/app/(ee)/app.dub.co/embed/referrals/faq.tsx (1)
42-42: Avoid hard-coding 90 days; centralize the attribution window.If 90 days is the global, export it from a shared constant (e.g.,
ATTRIBUTION_WINDOW_DAYS) and reference it here to prevent drift from backend logic.Confirm backend attribution also uses 90 days universally after removing
cookieLength. If not universal, consider deriving this from program/embed config instead.packages/prisma/schema/discount.prisma (1)
31-31: Add onUpdate: Cascade to Discount.program relation
At packages/prisma/schema/discount.prisma:31, includeonUpdate: Cascadeto match the existing ProgramDiscounts relation and prevent FK update inconsistencies.packages/prisma/schema/payout.prisma (1)
31-31: Cascade delete onPayout.programapproved;Commission.payoutback-relation exists. Optional: addonUpdate: Cascadeon these relations for symmetry.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
apps/web/app/(ee)/app.dub.co/embed/referrals/faq.tsx(1 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/settings/analytics/use-dynamic-guide.ts(4 hunks)apps/web/lib/actions/partners/update-program.ts(0 hunks)apps/web/lib/zod/schemas/programs.ts(0 hunks)apps/web/scripts/migrations/backfill-group-links-settings.ts(1 hunks)apps/web/scripts/partners/delete-program.ts(1 hunks)packages/prisma/schema/campaign.prisma(1 hunks)packages/prisma/schema/commission.prisma(1 hunks)packages/prisma/schema/discount.prisma(1 hunks)packages/prisma/schema/domain.prisma(0 hunks)packages/prisma/schema/invoice.prisma(1 hunks)packages/prisma/schema/payout.prisma(1 hunks)packages/prisma/schema/program.prisma(1 hunks)
💤 Files with no reviewable changes (3)
- apps/web/lib/zod/schemas/programs.ts
- packages/prisma/schema/domain.prisma
- apps/web/lib/actions/partners/update-program.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: TWilson023
PR: dubinc/dub#2935
File: packages/prisma/schema/workspace.prisma:21-36
Timestamp: 2025-10-06T15:48:45.956Z
Learning: In the Dub repository (dubinc/dub), Prisma schema changes are not managed with separate migration files. Do not flag missing Prisma migration files when schema changes are made to files like `packages/prisma/schema/workspace.prisma` or other schema files.
🧬 Code graph analysis (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/settings/analytics/use-dynamic-guide.ts (1)
apps/web/lib/swr/use-program.ts (1)
useProgram(6-40)
⏰ 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 (4)
packages/prisma/schema/campaign.prisma (1)
27-28: LGTM!The cascade delete behavior changes are appropriate:
- Adding
onDelete: Cascadeto the program relation ensures campaigns are cleaned up when a program is deleted, which makes sense since campaigns are program-specific.- Removing
onDelete: Cascadefrom the workflow relation is safer - sinceworkflowIdis optional, it will default toSetNullbehavior when a workflow is deleted.apps/web/app/app.dub.co/(dashboard)/[slug]/settings/analytics/use-dynamic-guide.ts (1)
2-2: LGTM!The refactor from
useDomainstouseProgramcorrectly updates the domain sourcing:
- Import and hook call properly switched (lines 2, 15)
- Domain reference changed from
primaryDomaintoprogram?.domainwith appropriate optional chaining (lines 30-31)- Dependency array correctly updated (line 75)
- Logic remains consistent: replaces placeholder domain with actual program domain
This aligns with the PR objective to source domain from the program configuration.
Also applies to: 15-15, 30-31, 75-75
packages/prisma/schema/program.prisma (1)
143-143: LGTM!Adding
onDelete: Cascadeto the ProgramApplication.program relation is appropriate. Applications are enrollment requests specific to a program, so deleting them when the program is deleted maintains referential integrity and cleans up orphaned data.packages/prisma/schema/invoice.prisma (1)
40-40: Review cascade delete on Invoice.program relation
onDelete: Cascade will remove all Invoice records when a Program is deleted, risking loss of financial/audit data and potential compliance violations. Use Restrict to block Program deletion when invoices exist or change to SetNull to preserve invoice history.
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/web/lib/actions/partners/update-program.ts (1)
88-93: Avoid deleting non-R2 URLsGuard deletes with isStored to prevent attempting to delete external URLs as R2 keys.
- ...(logoUrl && program.logo - ? [storage.delete(program.logo.replace(`${R2_URL}/`, ""))] + ...(logoUrl && program.logo && isStored(program.logo) + ? [storage.delete(program.logo.replace(`${R2_URL}/`, ""))] : []), - ...(wordmarkUrl && program.wordmark - ? [storage.delete(program.wordmark.replace(`${R2_URL}/`, ""))] + ...(wordmarkUrl && program.wordmark && isStored(program.wordmark) + ? [storage.delete(program.wordmark.replace(`${R2_URL}/`, ""))] : []),apps/web/lib/actions/partners/update-group-branding.ts (1)
197-203: Null-safe parsing for response dataIf no update was supplied and DB fields are null, parse() will throw. Return null when absent.
- applicationFormData: programApplicationFormSchema.parse( - updatedGroup.applicationFormData, - ), - landerData: programLanderSchema.parse(updatedGroup.landerData), + applicationFormData: updatedGroup.applicationFormData + ? programApplicationFormSchema.parse(updatedGroup.applicationFormData) + : null, + landerData: updatedGroup.landerData + ? programLanderSchema.parse(updatedGroup.landerData) + : null, program: ProgramSchema.parse(updatedProgram),apps/web/lib/api/programs/get-program-or-throw.ts (1)
13-18: Fix invalid prisma.program.findUnique call
Prisma’sfindUniqueonly accepts unique fields; includingworkspaceIdwill error. Either use:
findUnique({ where: { id: programId } })- or
findFirst({ where: { id: programId, workspaceId } })for workspace scoping.
🧹 Nitpick comments (5)
apps/web/scripts/migrations/migrate-application-formdata.ts (1)
15-40: Consider documenting the purpose of generated field IDs.The
uuid()calls generate unique identifiers for form fields, which is appropriate. However, it's unclear whether these IDs need to be stable across runs or if they're ephemeral.If this migration has already been executed in production, consider adding a comment at the top of the file indicating its status (e.g., "Legacy migration - executed on YYYY-MM-DD") to clarify that it's no longer actively used.
apps/web/lib/actions/partners/update-program.ts (2)
7-7: Remove unused landerData from schema and destructuringThis action no longer processes lander data. Keeping it in the schema/input is confusing and increases surface area.
Apply:
-import { programLanderSchema } from "@/lib/zod/schemas/program-lander"; @@ -const schema = updateProgramSchema.partial().extend({ +const schema = updateProgramSchema.partial().extend({ workspaceId: z.string(), logo: z.string().nullish(), wordmark: z.string().nullish(), brandColor: z.string().nullish(), - landerData: programLanderSchema.nullish(), }); @@ - const { + const { name, logo, wordmark, brandColor, - landerData: landerDataInput, domain, url, supportEmail, helpUrl, termsUrl, holdingPeriodDays, minPayoutAmount, messagingEnabledAt, } = parsedInput;Also applies to: 17-23, 30-43
102-106: Tighten revalidation conditions to avoid false positivesname and brandColor may be undefined. Current check can revalidate when nothing changed.
- ...(name !== program.name || - logoUrl || - wordmarkUrl || - brandColor !== program.brandColor + ...(((typeof name !== "undefined" && name !== program.name) || + Boolean(logoUrl) || + Boolean(wordmarkUrl) || + (typeof brandColor !== "undefined" && + brandColor !== program.brandColor)) ? [apps/web/lib/actions/partners/update-group-branding.ts (2)
54-57: brandColorUpdated may be true when input is undefinedGuard on defined input to avoid unnecessary revalidation and work.
- const brandColorUpdated = brandColor !== program.brandColor; + const brandColorUpdated = + typeof brandColor !== "undefined" && brandColor !== program.brandColor;
219-229: Deduplicate foreignImageUrls and enforce HTTP(S) only
Replace your current map + filter with:const foreignImageUrls = Array.from( new Set( landerData.blocks .filter((b) => b.type === "image") .map((b) => b.data.url), ), ).filter((url) => { const isHttp = /^https?:\/\//i.test(url); const isOwnProgramAsset = url.startsWith(`${R2_URL}/programs/${programId}/lander/`); return isHttp && !isOwnProgramAsset; });Optionally swap the own-asset check for
isStored(url) && url.includes("/programs/${programId}/lander/").
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
apps/web/app/(ee)/api/programs/[programId]/route.ts(1 hunks)apps/web/lib/actions/partners/update-group-branding.ts(7 hunks)apps/web/lib/actions/partners/update-program.ts(3 hunks)apps/web/lib/api/programs/get-program-or-throw.ts(2 hunks)apps/web/lib/types.ts(0 hunks)apps/web/lib/zod/schemas/programs.ts(0 hunks)apps/web/scripts/migrations/backfill-group-links-settings.ts(1 hunks)apps/web/scripts/migrations/migrate-application-formdata.ts(1 hunks)apps/web/scripts/migrations/migrate-application-submissions.ts(1 hunks)apps/web/scripts/migrations/migrate-lander-data.ts(1 hunks)apps/web/ui/partners/groups/design/lander/modals/earnings-calculator-block-modal.tsx(1 hunks)apps/web/ui/partners/lander/blocks/earnings-calculator-block.tsx(2 hunks)
💤 Files with no reviewable changes (2)
- apps/web/lib/types.ts
- apps/web/lib/zod/schemas/programs.ts
✅ Files skipped from review due to trivial changes (1)
- apps/web/scripts/migrations/migrate-application-submissions.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/scripts/migrations/backfill-group-links-settings.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: TWilson023
PR: dubinc/dub#2935
File: packages/prisma/schema/workspace.prisma:21-36
Timestamp: 2025-10-06T15:48:45.956Z
Learning: In the Dub repository (dubinc/dub), Prisma schema changes are not managed with separate migration files. Do not flag missing Prisma migration files when schema changes are made to files like `packages/prisma/schema/workspace.prisma` or other schema files.
🧬 Code graph analysis (5)
apps/web/ui/partners/lander/blocks/earnings-calculator-block.tsx (1)
apps/web/lib/types.ts (1)
ProgramProps(470-470)
apps/web/lib/actions/partners/update-program.ts (1)
apps/web/lib/zod/schemas/programs.ts (1)
ProgramSchema(22-48)
apps/web/app/(ee)/api/programs/[programId]/route.ts (2)
apps/web/lib/auth/workspace.ts (1)
withWorkspace(42-436)apps/web/lib/api/programs/get-program-or-throw.ts (1)
getProgramOrThrow(6-28)
apps/web/lib/actions/partners/update-group-branding.ts (3)
apps/web/lib/zod/schemas/programs.ts (1)
ProgramSchema(22-48)apps/web/lib/types.ts (1)
ProgramLanderData(472-472)apps/web/lib/zod/schemas/program-lander.ts (1)
programLanderImageBlockSchema(9-18)
apps/web/lib/api/programs/get-program-or-throw.ts (1)
apps/web/lib/zod/schemas/programs.ts (1)
ProgramSchema(22-48)
⏰ 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 (10)
apps/web/ui/partners/groups/design/lander/modals/earnings-calculator-block-modal.tsx (1)
202-202: LGTM! Type refactor aligns with broader cleanup.The removal of
landerDatafrom the program prop is consistent with the type change fromProgramWithLanderDataPropstoProgramPropsin the consuming component. The program object is correctly composed withbrandColor,rewards, anddiscountsfrom their respective sources.apps/web/ui/partners/lander/blocks/earnings-calculator-block.tsx (1)
4-4: LGTM! Clean type refactor.The import and parameter type updates from
ProgramWithLanderDataPropstoProgramPropsare correct. The component doesn't referencelanderData, so the type change is safe and aligns with the broader cleanup effort to remove lander-specific data from the program model.Also applies to: 20-20
apps/web/scripts/migrations/migrate-lander-data.ts (2)
1-2: LGTM! Appropriate handling of legacy migration.The
@ts-nocheckdirective correctly suppresses type errors for this historical migration script that references removed schema fields (e.g.,landerData,landerPublishedAt). This preserves the script for documentation purposes while preventing build failures.
7-7: dotenv-flow dependency verified
Found in apps/web/package.json at ^4.1.0; side-effect import is appropriate.apps/web/scripts/migrations/migrate-application-formdata.ts (3)
1-2: LGTM: Appropriate use of @ts-nocheck for legacy migration.The directive correctly allows this script to reference old schema types that are being removed in this PR cleanup. This is a valid approach for maintaining backward compatibility in migration scripts.
6-6: uuid dependency verified
Founduuidinapps/web/package.jsonat version^11.0.3.
45-90: Archive one-time migration script
Confirm this script (it uses@ts-nocheckand touches removed schema fields) has already run in production. If so, move it toapps/web/scripts/migrations/archived/, add execution metadata (date, status) in a header comment, and document the process for archiving executed migrations.apps/web/lib/api/programs/get-program-or-throw.ts (1)
6-12: Simpler signature and unified return look goodLean param shape and single ProgramSchema.parse return is cleaner.
Also applies to: 27-27
apps/web/lib/actions/partners/update-group-branding.ts (1)
231-241: Consider input size/validation before fetching remote imagesIf storage.upload performs server-side fetches, cap image size and timeouts to avoid abuse.
Please verify upload() enforces size/timeouts. If not, add fetch options/streaming with limits.
apps/web/app/(ee)/api/programs/[programId]/route.ts (1)
6-13: LGTM: simpler GET path
Delegating to getProgramOrThrow and returning JSON directly is clean; no occurrences of includeLanderData found.
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: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/prisma/schema/discount.prisma(2 hunks)packages/prisma/schema/program.prisma(0 hunks)packages/prisma/schema/reward.prisma(1 hunks)
💤 Files with no reviewable changes (1)
- packages/prisma/schema/program.prisma
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/prisma/schema/discount.prisma
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: TWilson023
PR: dubinc/dub#2935
File: packages/prisma/schema/workspace.prisma:21-36
Timestamp: 2025-10-06T15:48:45.956Z
Learning: In the Dub repository (dubinc/dub), Prisma schema changes are not managed with separate migration files. Do not flag missing Prisma migration files when schema changes are made to files like `packages/prisma/schema/workspace.prisma` or other schema files.
⏰ 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
| updatedAt DateTime @updatedAt | ||
| program Program @relation(fields: [programId], references: [id], onDelete: Cascade) | ||
| program Program @relation(fields: [programId], references: [id]) |
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.
Do not drop the cascade delete without replacing the cleanup.
Reward.program is required, so removing onDelete: Cascade reverts the FK to RESTRICT. Any code that deletes a Program (e.g., the delete-program script/API) will now fail once rewards exist unless they are deleted first. Previously the cascade handled this automatically. Please either keep the cascade or add explicit reward deletions wherever programs are removed so the operation still succeeds.
Summary by CodeRabbit