-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Standardize on @dub/prisma/client
#3215
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.
|
WalkthroughThe pull request systematically migrates Prisma type imports across the web application from Changes
Estimated code review effortπ― 3 (Moderate) | β±οΈ ~30 minutes Areas requiring extra attention during review:
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touchesβ Failed checks (1 warning)
β Passed checks (2 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: 1
π§Ή Nitpick comments (2)
apps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/action-buttons.tsx (1)
3-3: Import path swap looks correct; considerimport typefor LinkThe change to
@dub/prisma/clientmatches the PR's goal. SinceLinkis only used in a type position (line 10:Pick<Link, "shortLink">), switching to a type-only import is a best practice in client components to avoid pulling the Prisma client into the client bundle:-import { Link } from "@dub/prisma/client"; +import type { Link } from "@dub/prisma/client";apps/web/scripts/partners/sanitize-social-handles.ts (1)
3-45: PrismaPartnertype import looks correct; consider making it type-only.Switching the
Partnerimport to@dub/prisma/clientmatches the new standard and keeps thePick<Partner, ...>typing intact with no runtime behavior change. SincePartneris only used in a type position here, you may want to change this to a type-only import for clarity:import type { Partner } from "@dub/prisma/client";
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
β Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
π Files selected for processing (107)
apps/web/app/(ee)/api/bounties/[bountyId]/route.ts(1 hunks)apps/web/app/(ee)/api/campaigns/[campaignId]/duplicate/route.ts(1 hunks)apps/web/app/(ee)/api/campaigns/[campaignId]/route.ts(1 hunks)apps/web/app/(ee)/api/campaigns/route.ts(1 hunks)apps/web/app/(ee)/api/cron/bounties/notify-partners/route.ts(1 hunks)apps/web/app/(ee)/api/cron/cleanup/link-retention/route.ts(1 hunks)apps/web/app/(ee)/api/cron/domains/renewal-payments/route.ts(1 hunks)apps/web/app/(ee)/api/cron/email-domains/verify/route.ts(1 hunks)apps/web/app/(ee)/api/cron/payouts/charge-succeeded/queue-stripe-payouts.ts(1 hunks)apps/web/app/(ee)/api/cron/payouts/process/split-payouts.ts(1 hunks)apps/web/app/(ee)/api/customers/route.ts(1 hunks)apps/web/app/(ee)/api/email-domains/[domain]/route.ts(1 hunks)apps/web/app/(ee)/api/email-domains/route.ts(1 hunks)apps/web/app/(ee)/api/fraud/rules/route.ts(1 hunks)apps/web/app/(ee)/api/groups/[groupIdOrSlug]/route.ts(1 hunks)apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/timeseries/route.ts(1 hunks)apps/web/app/(ee)/api/partner-profile/programs/[programId]/route.ts(1 hunks)apps/web/app/(ee)/api/partner-profile/programs/route.ts(1 hunks)apps/web/app/(ee)/app.dub.co/embed/referrals/add-edit-link.tsx(1 hunks)apps/web/app/(ee)/app.dub.co/embed/referrals/links-list.tsx(1 hunks)apps/web/app/(ee)/app.dub.co/embed/referrals/links.tsx(1 hunks)apps/web/app/(ee)/app.dub.co/embed/referrals/utils.ts(1 hunks)apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/domain-renewal-invoice.tsx(1 hunks)apps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/partner-payout-invoice.tsx(1 hunks)apps/web/app/(ee)/partners.dub.co/(auth)/partner-banner.tsx(1 hunks)apps/web/app/(ee)/partners.dub.co/(auth)/register/page-client.tsx(1 hunks)apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/earnings/earnings-composite-chart.tsx(1 hunks)apps/web/app/api/domains/[domain]/route.ts(1 hunks)apps/web/app/api/domains/route.ts(1 hunks)apps/web/app/api/tokens/embed/referrals/route.ts(1 hunks)apps/web/app/api/workspaces/[idOrSlug]/invites/route.ts(1 hunks)apps/web/app/api/workspaces/[idOrSlug]/users/route.ts(1 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-stats.tsx(1 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/create-commission-sheet.tsx(1 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/use-commission-filters.tsx(1 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/example-fraud-events.tsx(1 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partners-table.tsx(1 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/use-partner-filters.tsx(1 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/success/page-client.tsx(1 hunks)apps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/action-buttons.tsx(1 hunks)apps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/brand-logo-badge.tsx(1 hunks)apps/web/lib/actions/partners/ban-partner.ts(1 hunks)apps/web/lib/actions/partners/bulk-ban-partners.ts(1 hunks)apps/web/lib/actions/partners/bulk-reject-partner-applications.ts(1 hunks)apps/web/lib/actions/partners/create-bounty-submission.ts(1 hunks)apps/web/lib/actions/partners/create-manual-commission.ts(1 hunks)apps/web/lib/actions/partners/create-program.ts(1 hunks)apps/web/lib/actions/partners/deactivate-partner.ts(1 hunks)apps/web/lib/actions/partners/onboard-program.ts(1 hunks)apps/web/lib/actions/partners/online-presence-providers.ts(1 hunks)apps/web/lib/actions/partners/reject-partner-application.ts(1 hunks)apps/web/lib/actions/partners/update-partner-payout-settings.ts(1 hunks)apps/web/lib/actions/partners/update-partner-profile.ts(1 hunks)apps/web/lib/analytics/get-analytics.ts(1 hunks)apps/web/lib/analytics/get-folder-ids-to-filter.ts(1 hunks)apps/web/lib/analytics/is-first-conversion.ts(1 hunks)apps/web/lib/api/bounties/get-bounties-by-groups.ts(1 hunks)apps/web/lib/api/bounties/trigger-draft-bounty-submissions.ts(1 hunks)apps/web/lib/api/campaigns/constants.ts(1 hunks)apps/web/lib/api/domains/get-domain-or-throw.ts(1 hunks)apps/web/lib/api/fraud/resolve-fraud-groups.ts(1 hunks)apps/web/lib/api/get-workspace-users.ts(1 hunks)apps/web/lib/api/groups/get-groups.ts(1 hunks)apps/web/lib/api/links/bulk-create-links.ts(1 hunks)apps/web/lib/api/links/complete-ab-tests.ts(1 hunks)apps/web/lib/api/links/utils/key-checks.ts(1 hunks)apps/web/lib/api/links/validate-partner-link-url.ts(1 hunks)apps/web/lib/api/partners/create-partner-default-links.ts(1 hunks)apps/web/lib/api/partners/get-network-invites-usage.ts(1 hunks)apps/web/lib/api/partners/invite-partner-user.ts(1 hunks)apps/web/lib/api/payouts/get-effective-payout-mode.ts(1 hunks)apps/web/lib/auth/partner-users/partner-user-permissions.ts(1 hunks)apps/web/lib/auth/partner.ts(1 hunks)apps/web/lib/auth/publishable-key.ts(1 hunks)apps/web/lib/client-access-check.ts(1 hunks)apps/web/lib/fetchers/get-program.ts(1 hunks)apps/web/lib/firstpromoter/import-commissions.ts(1 hunks)apps/web/lib/firstpromoter/import-customers.ts(1 hunks)apps/web/lib/folder/get-folders.ts(1 hunks)apps/web/lib/integrations/shopify/create-sale.ts(1 hunks)apps/web/lib/integrations/slack/oauth.ts(1 hunks)apps/web/lib/partners/complete-program-applications.ts(1 hunks)apps/web/lib/partners/format-application-form-data.ts(1 hunks)apps/web/lib/partners/sort-rewards-by-event-order.ts(1 hunks)apps/web/lib/partnerstack/import-commissions.ts(1 hunks)apps/web/lib/partnerstack/import-customers.ts(1 hunks)apps/web/lib/paypal/get-pending-payouts.ts(1 hunks)apps/web/lib/rewardful/import-commissions.ts(1 hunks)apps/web/lib/rewardful/import-customers.ts(1 hunks)apps/web/lib/tolt/import-commissions.ts(1 hunks)apps/web/lib/tolt/import-customers.ts(1 hunks)apps/web/lib/webhook/publish.ts(1 hunks)apps/web/lib/zod/schemas/invites.ts(1 hunks)apps/web/lib/zod/schemas/messages.ts(1 hunks)apps/web/lib/zod/schemas/misc.ts(1 hunks)apps/web/lib/zod/schemas/partner-profile.ts(1 hunks)apps/web/lib/zod/schemas/workspaces.ts(2 hunks)apps/web/package.json(0 hunks)apps/web/scripts/convert-case-sensitive.ts(1 hunks)apps/web/scripts/convert-manual-commissions.ts(1 hunks)apps/web/scripts/framer/backfill-commissions.ts(1 hunks)apps/web/scripts/migrate-commission-attributes.ts(1 hunks)apps/web/scripts/migrations/backfill-deepview.ts(1 hunks)apps/web/scripts/migrations/migrate-duplicate-payout-fraud-events.ts(1 hunks)apps/web/scripts/migrations/migrate-reward-amounts.ts(1 hunks)apps/web/scripts/partners/sanitize-social-handles.ts(1 hunks)apps/web/scripts/partners/sanitize-websites.ts(1 hunks)
β Files not processed due to max files limit (7)
- apps/web/scripts/unsubscribe-inactive-users.ts
- apps/web/tests/fraud/index.test.ts
- apps/web/ui/modals/add-partner-link-modal.tsx
- apps/web/ui/partners/groups/design/application-form/application-hero-preview.tsx
- apps/web/ui/partners/lander/lander-hero.tsx
- apps/web/ui/partners/partner-application-details.tsx
- apps/web/ui/partners/program-category-select.tsx
π€ Files with no reviewable changes (1)
- apps/web/package.json
π§° Additional context used
π§ Learnings (35)
π Common learnings
Learnt from: TWilson023
Repo: dubinc/dub PR: 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.
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx:432-457
Timestamp: 2025-10-15T01:05:43.266Z
Learning: In apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx, defer refactoring the custom MenuItem component (lines 432-457) to use the shared dub/ui MenuItem component to a future PR, as requested by steven-tey.
π Learning: 2025-10-06T15:48:45.956Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 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.
Applied to files:
apps/web/lib/partners/format-application-form-data.tsapps/web/lib/actions/partners/create-manual-commission.tsapps/web/lib/actions/partners/create-bounty-submission.tsapps/web/lib/api/get-workspace-users.tsapps/web/lib/auth/partner-users/partner-user-permissions.tsapps/web/scripts/migrations/backfill-deepview.tsapps/web/lib/partners/complete-program-applications.tsapps/web/lib/firstpromoter/import-customers.tsapps/web/app/(ee)/app.dub.co/embed/referrals/add-edit-link.tsxapps/web/lib/analytics/get-folder-ids-to-filter.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partners-table.tsxapps/web/lib/api/payouts/get-effective-payout-mode.tsapps/web/lib/partnerstack/import-customers.tsapps/web/lib/rewardful/import-commissions.tsapps/web/lib/partnerstack/import-commissions.tsapps/web/lib/zod/schemas/partner-profile.tsapps/web/app/(ee)/api/cron/email-domains/verify/route.tsapps/web/lib/api/fraud/resolve-fraud-groups.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/success/page-client.tsxapps/web/lib/actions/partners/bulk-ban-partners.tsapps/web/app/api/domains/[domain]/route.tsapps/web/app/(ee)/app.dub.co/embed/referrals/utils.tsapps/web/lib/zod/schemas/messages.tsapps/web/app/(ee)/api/cron/domains/renewal-payments/route.tsapps/web/lib/folder/get-folders.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/use-partner-filters.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/create-commission-sheet.tsxapps/web/scripts/migrations/migrate-duplicate-payout-fraud-events.tsapps/web/lib/api/bounties/trigger-draft-bounty-submissions.tsapps/web/app/api/domains/route.tsapps/web/app/(ee)/app.dub.co/embed/referrals/links-list.tsxapps/web/lib/tolt/import-commissions.tsapps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/earnings/earnings-composite-chart.tsxapps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/partner-payout-invoice.tsxapps/web/lib/client-access-check.tsapps/web/lib/integrations/slack/oauth.tsapps/web/lib/actions/partners/reject-partner-application.tsapps/web/app/(ee)/app.dub.co/invoices/[invoiceId]/domain-renewal-invoice.tsxapps/web/lib/api/groups/get-groups.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/example-fraud-events.tsxapps/web/app/(ee)/api/cron/payouts/process/split-payouts.tsapps/web/lib/actions/partners/create-program.tsapps/web/lib/actions/partners/online-presence-providers.tsapps/web/app/(ee)/api/bounties/[bountyId]/route.tsapps/web/lib/actions/partners/update-partner-profile.tsapps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/action-buttons.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-stats.tsxapps/web/app/(ee)/app.dub.co/embed/referrals/links.tsxapps/web/app/(ee)/api/campaigns/route.tsapps/web/lib/auth/partner.tsapps/web/app/(ee)/api/fraud/rules/route.tsapps/web/lib/actions/partners/update-partner-payout-settings.tsapps/web/app/(ee)/partners.dub.co/(auth)/register/page-client.tsxapps/web/app/api/workspaces/[idOrSlug]/users/route.tsapps/web/lib/firstpromoter/import-commissions.tsapps/web/scripts/migrate-commission-attributes.tsapps/web/lib/zod/schemas/invites.tsapps/web/lib/api/links/utils/key-checks.tsapps/web/lib/api/domains/get-domain-or-throw.tsapps/web/scripts/migrations/migrate-reward-amounts.tsapps/web/lib/actions/partners/bulk-reject-partner-applications.tsapps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/brand-logo-badge.tsxapps/web/lib/zod/schemas/misc.tsapps/web/app/(ee)/partners.dub.co/(auth)/partner-banner.tsxapps/web/lib/actions/partners/deactivate-partner.tsapps/web/lib/api/campaigns/constants.tsapps/web/app/(ee)/api/email-domains/[domain]/route.tsapps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/timeseries/route.tsapps/web/scripts/convert-manual-commissions.tsapps/web/app/(ee)/api/email-domains/route.tsapps/web/lib/api/links/bulk-create-links.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/use-commission-filters.tsxapps/web/lib/api/partners/create-partner-default-links.tsapps/web/lib/tolt/import-customers.tsapps/web/scripts/convert-case-sensitive.tsapps/web/lib/zod/schemas/workspaces.tsapps/web/lib/auth/publishable-key.tsapps/web/lib/webhook/publish.tsapps/web/lib/rewardful/import-customers.tsapps/web/lib/actions/partners/onboard-program.ts
π Learning: 2025-08-25T17:33:45.072Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2736
File: apps/web/app/(ee)/api/stripe/integration/webhook/invoice-paid.ts:12-12
Timestamp: 2025-08-25T17:33:45.072Z
Learning: The WorkflowTrigger enum in packages/prisma/schema/workflow.prisma contains three values: leadRecorded, saleRecorded, and commissionEarned. All three are properly used throughout the codebase.
Applied to files:
apps/web/lib/actions/partners/create-manual-commission.tsapps/web/lib/integrations/shopify/create-sale.tsapps/web/app/(ee)/api/campaigns/route.ts
π Learning: 2025-08-26T14:20:23.943Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2736
File: apps/web/app/api/workspaces/[idOrSlug]/notification-preferences/route.ts:13-14
Timestamp: 2025-08-26T14:20:23.943Z
Learning: The updateNotificationPreference action in apps/web/lib/actions/update-notification-preference.ts already handles all notification preference types dynamically, including newBountySubmitted, through its schema validation using the notificationTypes enum and Prisma's dynamic field update pattern.
Applied to files:
apps/web/lib/actions/partners/create-bounty-submission.tsapps/web/lib/api/bounties/trigger-draft-bounty-submissions.tsapps/web/app/(ee)/api/cron/bounties/notify-partners/route.tsapps/web/lib/api/bounties/get-bounties-by-groups.tsapps/web/lib/zod/schemas/workspaces.ts
π Learning: 2025-08-26T14:32:33.851Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2736
File: apps/web/lib/actions/partners/create-bounty-submission.ts:105-112
Timestamp: 2025-08-26T14:32:33.851Z
Learning: Non-performance bounties are required to have submissionRequirements. In create-bounty-submission.ts, it's appropriate to let the parsing fail if submissionRequirements is null for non-performance bounties, as this indicates a data integrity issue that should be caught.
Applied to files:
apps/web/lib/actions/partners/create-bounty-submission.tsapps/web/lib/api/bounties/trigger-draft-bounty-submissions.ts
π Learning: 2025-09-12T17:31:10.548Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2833
File: apps/web/lib/actions/partners/approve-bounty-submission.ts:53-61
Timestamp: 2025-09-12T17:31:10.548Z
Learning: In approve-bounty-submission.ts, the logic `bounty.rewardAmount ?? rewardAmount` is intentional. Bounties with preset reward amounts should use those fixed amounts, and the rewardAmount override parameter is only used when bounty.rewardAmount is null/undefined (for custom reward bounties). This follows the design pattern where bounties are either "flat rate" (fixed amount) or "custom" (variable amount set during approval).
Applied to files:
apps/web/lib/actions/partners/create-bounty-submission.tsapps/web/lib/api/bounties/trigger-draft-bounty-submissions.ts
π 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/complete-ab-tests.tsapps/web/lib/api/links/validate-partner-link-url.tsapps/web/lib/firstpromoter/import-customers.tsapps/web/lib/partnerstack/import-customers.tsapps/web/app/(ee)/api/cron/cleanup/link-retention/route.tsapps/web/lib/api/links/bulk-create-links.tsapps/web/lib/api/partners/create-partner-default-links.tsapps/web/lib/tolt/import-customers.ts
π Learning: 2025-10-17T08:18:19.278Z
Learnt from: devkiran
Repo: dubinc/dub PR: 0
File: :0-0
Timestamp: 2025-10-17T08:18:19.278Z
Learning: In the apps/web codebase, `@/lib/zod` should only be used for places that need OpenAPI extended zod schema. All other places should import from the standard `zod` package directly using `import { z } from "zod"`.
Applied to files:
apps/web/lib/api/get-workspace-users.tsapps/web/app/(ee)/api/customers/route.tsapps/web/app/api/domains/[domain]/route.tsapps/web/lib/actions/partners/update-partner-profile.tsapps/web/app/api/workspaces/[idOrSlug]/users/route.tsapps/web/lib/zod/schemas/misc.tsapps/web/lib/analytics/get-analytics.tsapps/web/app/(ee)/api/email-domains/route.tsapps/web/lib/zod/schemas/workspaces.tsapps/web/app/api/workspaces/[idOrSlug]/invites/route.ts
π Learning: 2025-06-18T20:26:25.177Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in `WorkspaceAuth` which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
Applied to files:
apps/web/lib/api/get-workspace-users.tsapps/web/lib/zod/schemas/workspaces.ts
π Learning: 2025-08-26T15:05:55.081Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2736
File: apps/web/lib/swr/use-bounty.ts:11-16
Timestamp: 2025-08-26T15:05:55.081Z
Learning: In the Dub codebase, workspace authentication and route structures prevent endless loading states when workspaceId or similar route parameters are missing, so gating SWR loading states on parameter availability is often unnecessary.
Applied to files:
apps/web/lib/api/get-workspace-users.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/use-partner-filters.tsxapps/web/app/api/workspaces/[idOrSlug]/users/route.tsapps/web/lib/zod/schemas/workspaces.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/partners/complete-program-applications.tsapps/web/lib/actions/partners/bulk-ban-partners.tsapps/web/lib/zod/schemas/messages.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/use-partner-filters.tsxapps/web/lib/actions/partners/ban-partner.tsapps/web/lib/actions/partners/create-program.tsapps/web/lib/actions/partners/online-presence-providers.tsapps/web/lib/actions/partners/update-partner-payout-settings.tsapps/web/lib/actions/partners/bulk-reject-partner-applications.tsapps/web/lib/actions/partners/deactivate-partner.tsapps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/timeseries/route.ts
π Learning: 2025-09-24T16:13:00.387Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: packages/prisma/schema/partner.prisma:151-153
Timestamp: 2025-09-24T16:13:00.387Z
Learning: In the Dub codebase, Prisma schemas use single-column indexes without brackets (e.g., `@index(partnerId)`) and multi-column indexes with brackets (e.g., `@index([programId, partnerId])`). This syntax pattern is consistently used throughout their schema files and works correctly with their Prisma version.
Applied to files:
apps/web/lib/partners/complete-program-applications.tsapps/web/lib/zod/schemas/partner-profile.tsapps/web/lib/zod/schemas/messages.tsapps/web/lib/actions/partners/online-presence-providers.tsapps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/timeseries/route.tsapps/web/scripts/convert-case-sensitive.tsapps/web/lib/rewardful/import-customers.ts
π Learning: 2025-10-15T01:05:43.266Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx:432-457
Timestamp: 2025-10-15T01:05:43.266Z
Learning: In apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx, defer refactoring the custom MenuItem component (lines 432-457) to use the shared dub/ui MenuItem component to a future PR, as requested by steven-tey.
Applied to files:
apps/web/app/(ee)/app.dub.co/embed/referrals/add-edit-link.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partners-table.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/success/page-client.tsxapps/web/app/(ee)/app.dub.co/embed/referrals/utils.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/use-partner-filters.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/create-commission-sheet.tsxapps/web/app/(ee)/app.dub.co/embed/referrals/links-list.tsxapps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/earnings/earnings-composite-chart.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/example-fraud-events.tsxapps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/action-buttons.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-stats.tsxapps/web/app/(ee)/app.dub.co/embed/referrals/links.tsxapps/web/app/(ee)/partners.dub.co/(auth)/register/page-client.tsxapps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/brand-logo-badge.tsxapps/web/app/(ee)/partners.dub.co/(auth)/partner-banner.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/use-commission-filters.tsx
π Learning: 2025-07-17T06:41:45.620Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2637
File: apps/web/app/(ee)/api/singular/webhook/route.ts:0-0
Timestamp: 2025-07-17T06:41:45.620Z
Learning: In the Singular integration (apps/web/app/(ee)/api/singular/webhook/route.ts), the event names in the singularToDubEvent object have intentionally different casing: "Copy GAID" and "copy IDFA". This casing difference is valid and should not be changed, as these are the correct event names expected from Singular.
Applied to files:
apps/web/app/(ee)/api/campaigns/[campaignId]/route.tsapps/web/scripts/migrations/migrate-duplicate-payout-fraud-events.tsapps/web/app/(ee)/api/campaigns/[campaignId]/duplicate/route.tsapps/web/app/(ee)/api/campaigns/route.tsapps/web/scripts/convert-case-sensitive.ts
π Learning: 2025-12-03T09:19:48.164Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3175
File: apps/web/lib/actions/partners/bulk-reject-partner-applications.ts:14-21
Timestamp: 2025-12-03T09:19:48.164Z
Learning: In apps/web/lib/actions/partners/bulk-reject-partner-applications.ts, the bulkRejectPartnerApplicationsAction does not need explicit plan capability checks for fraud operations (when reportFraud is true) because the authorization is handled automatically by the underlying fraud operation functions (resolveFraudGroups, createFraudEvents) or through other automated mechanisms in the system.
Applied to files:
apps/web/lib/api/fraud/resolve-fraud-groups.tsapps/web/lib/actions/partners/bulk-ban-partners.tsapps/web/lib/actions/partners/reject-partner-application.tsapps/web/lib/actions/partners/ban-partner.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/example-fraud-events.tsxapps/web/lib/actions/partners/bulk-reject-partner-applications.ts
π Learning: 2025-11-24T09:10:12.536Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/lib/api/fraud/fraud-rules-registry.ts:17-25
Timestamp: 2025-11-24T09:10:12.536Z
Learning: In apps/web/lib/api/fraud/fraud-rules-registry.ts, the fraud rules `partnerCrossProgramBan` and `partnerDuplicatePayoutMethod` intentionally have stub implementations that return `{ triggered: false }` because they are partner-scoped rules handled separately during partner application/onboarding flows (e.g., in detect-record-fraud-application.ts), rather than being evaluated per conversion event like other rules in the registry. The stubs exist only to satisfy the `Record<FraudRuleType, ...>` type constraint.
Applied to files:
apps/web/lib/api/fraud/resolve-fraud-groups.tsapps/web/lib/actions/partners/bulk-ban-partners.tsapps/web/scripts/migrations/migrate-duplicate-payout-fraud-events.tsapps/web/lib/actions/partners/reject-partner-application.tsapps/web/lib/actions/partners/ban-partner.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/example-fraud-events.tsxapps/web/app/(ee)/api/fraud/rules/route.tsapps/web/lib/actions/partners/bulk-reject-partner-applications.ts
π Learning: 2025-12-08T09:44:28.429Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3200
File: apps/web/lib/api/fraud/detect-duplicate-payout-method-fraud.ts:55-73
Timestamp: 2025-12-08T09:44:28.429Z
Learning: In apps/web/lib/api/fraud/detect-duplicate-payout-method-fraud.ts, the fraud event creation logic intentionally generates self-referential fraud events (where partnerId equals duplicatePartnerId) for partners with duplicate payout methods. This is by design to create raw events for all partners involved in a duplicate payout method scenario, regardless of whether they reference themselves.
Applied to files:
apps/web/lib/api/fraud/resolve-fraud-groups.tsapps/web/scripts/migrations/migrate-duplicate-payout-fraud-events.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/example-fraud-events.tsxapps/web/lib/actions/partners/bulk-reject-partner-applications.ts
π Learning: 2025-10-28T19:17:28.085Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2985
File: apps/web/app/(ee)/api/network/programs/[programSlug]/route.ts:20-27
Timestamp: 2025-10-28T19:17:28.085Z
Learning: In this codebase, Prisma's extendedWhereUnique feature is enabled (or Prisma 5.x is used), allowing findUniqueOrThrow to accept additional non-unique filters alongside unique fields like slug. This pattern is valid and acceptable.
Applied to files:
apps/web/lib/api/fraud/resolve-fraud-groups.ts
π Learning: 2025-11-24T16:36:36.196Z
Learnt from: CR
Repo: dubinc/dub PR: 0
File: packages/hubspot-app/CLAUDE.md:0-0
Timestamp: 2025-11-24T16:36:36.196Z
Learning: Applies to packages/hubspot-app/app/cards/**/*.{js,jsx,ts,tsx} : Card components cannot use `window.fetch`; must use `hubspot.fetch` function from `hubspot/ui-extensions` npm package and add URLs to `config.permittedUrls.fetch` in the app component's hsmeta.json
Applied to files:
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/success/page-client.tsx
π Learning: 2025-11-12T22:23:10.414Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 3098
File: apps/web/lib/actions/partners/message-program.ts:49-58
Timestamp: 2025-11-12T22:23:10.414Z
Learning: In apps/web/lib/actions/partners/message-program.ts, when checking if a partner can continue messaging after messaging is disabled, the code intentionally requires `senderPartnerId: null` (program-initiated messages) to prevent partners from continuing to send junk messages. Only conversations started by the program should continue after messaging is disabled, as a spam prevention mechanism.
Applied to files:
apps/web/lib/actions/partners/bulk-ban-partners.tsapps/web/lib/actions/partners/ban-partner.tsapps/web/lib/actions/partners/bulk-reject-partner-applications.tsapps/web/lib/actions/partners/deactivate-partner.ts
π Learning: 2025-07-30T15:29:54.131Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2673
File: apps/web/ui/partners/rewards/rewards-logic.tsx:268-275
Timestamp: 2025-07-30T15:29:54.131Z
Learning: In apps/web/ui/partners/rewards/rewards-logic.tsx, when setting the entity field in a reward condition, dependent fields (attribute, operator, value) should be reset rather than preserved because different entities (customer vs sale) have different available attributes. Maintaining existing fields when the entity changes would create invalid state combinations and confusing UX.
Applied to files:
apps/web/app/(ee)/app.dub.co/embed/referrals/utils.tsapps/web/scripts/migrations/migrate-reward-amounts.tsapps/web/lib/partners/sort-rewards-by-event-order.tsapps/web/app/(ee)/api/partner-profile/programs/[programId]/route.tsapps/web/app/(ee)/api/partner-profile/programs/route.ts
π Learning: 2025-08-14T05:17:51.825Z
Learnt from: devkiran
Repo: dubinc/dub PR: 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/app/(ee)/app.dub.co/embed/referrals/utils.tsapps/web/scripts/migrations/migrate-reward-amounts.tsapps/web/lib/api/bounties/get-bounties-by-groups.tsapps/web/app/(ee)/api/partner-profile/programs/[programId]/route.tsapps/web/lib/fetchers/get-program.tsapps/web/app/(ee)/api/partner-profile/programs/route.ts
π Learning: 2025-07-30T15:25:13.936Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2673
File: apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx:56-66
Timestamp: 2025-07-30T15:25:13.936Z
Learning: In apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx, the form schema uses partial condition objects to allow users to add empty/unconfigured condition fields without type errors, while submission validation uses strict schemas to ensure data integrity. This two-stage validation pattern improves UX by allowing progressive completion of complex forms.
Applied to files:
apps/web/app/(ee)/app.dub.co/embed/referrals/utils.tsapps/web/scripts/migrations/migrate-reward-amounts.tsapps/web/lib/fetchers/get-program.tsapps/web/app/(ee)/api/partner-profile/programs/route.ts
π Learning: 2025-11-24T08:55:31.332Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/app/(ee)/api/fraud-rules/route.ts:71-87
Timestamp: 2025-11-24T08:55:31.332Z
Learning: In apps/web/app/(ee)/api/fraud-rules/route.ts, fraud rules cannot be created in a disabled state. When using prisma.fraudRule.upsert, the create branch intentionally omits the disabledAt field (defaulting to null, meaning enabled), while the update branch allows toggling enabled/disabled state via the disabledAt field. This is a business logic constraint.
Applied to files:
apps/web/scripts/migrations/migrate-duplicate-payout-fraud-events.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/fraud/example-fraud-events.tsxapps/web/app/(ee)/api/fraud/rules/route.tsapps/web/lib/actions/partners/bulk-reject-partner-applications.ts
π Learning: 2025-09-24T16:10:37.349Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/ui/partners/partner-about.tsx:11-11
Timestamp: 2025-09-24T16:10:37.349Z
Learning: In the Dub codebase, the team prefers to import Icon as a runtime value from "dub/ui" and uses Icon as both a type and variable name in component props, even when this creates shadowing. This is their established pattern and should not be suggested for refactoring.
Applied to files:
apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/earnings/earnings-composite-chart.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/use-commission-filters.tsx
π Learning: 2025-11-17T05:19:11.972Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3113
File: apps/web/app/(ee)/api/cron/payouts/charge-succeeded/send-paypal-payouts.ts:65-75
Timestamp: 2025-11-17T05:19:11.972Z
Learning: In the Dub codebase, `sendBatchEmail` (implemented in packages/email/src/send-via-resend.ts) handles filtering of emails with invalid `to` addresses internally. Call sites can safely use non-null assertions on email addresses because the email sending layer will filter out any entries with null/undefined `to` values before sending. This centralized validation pattern is intentional and removes the need for filtering at individual call sites.
Applied to files:
apps/web/app/(ee)/api/cron/bounties/notify-partners/route.ts
π Learning: 2025-08-26T15:38:48.173Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2736
File: apps/web/lib/api/bounties/get-bounty-or-throw.ts:53-63
Timestamp: 2025-08-26T15:38:48.173Z
Learning: In bounty-related code, getBountyOrThrow returns group objects with { id } field (transformed from BountyGroup.groupId), while other routes working directly with BountyGroup Prisma records use the actual groupId field. This is intentional - getBountyOrThrow abstracts the join table details.
Applied to files:
apps/web/app/(ee)/api/bounties/[bountyId]/route.tsapps/web/lib/api/bounties/get-bounties-by-groups.ts
π Learning: 2025-08-25T21:03:24.285Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2736
File: apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/bounty-card.tsx:1-1
Timestamp: 2025-08-25T21:03:24.285Z
Learning: In Next.js App Router, Server Components that use hooks can work without "use client" directive if they are only imported by Client Components, as they get "promoted" to run on the client side within the Client Component boundary.
Applied to files:
apps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/action-buttons.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-stats.tsx
π Learning: 2025-09-18T16:33:17.719Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2858
File: apps/web/ui/partners/partner-application-tabs.tsx:1-1
Timestamp: 2025-09-18T16:33:17.719Z
Learning: When a React component in Next.js App Router uses non-serializable props (like setState functions), adding "use client" directive can cause serialization warnings. If the component is only imported by Client Components, it's better to omit the "use client" directive to avoid these warnings while still getting client-side execution through promotion.
Applied to files:
apps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/action-buttons.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-stats.tsx
π Learning: 2025-09-24T15:47:40.293Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/about-you-form.tsx:152-157
Timestamp: 2025-09-24T15:47:40.293Z
Learning: The Button component from dub/ui automatically adds type="button" when an onClick prop is passed, preventing accidental form submissions without requiring explicit type specification. The implementation uses: type={onClick ? "button" : type}
Applied to files:
apps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/action-buttons.tsx
π Learning: 2025-09-24T15:47:40.293Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/about-you-form.tsx:152-157
Timestamp: 2025-09-24T15:47:40.293Z
Learning: The Button component from dub/ui automatically adds type="button" when an onClick prop is passed, preventing accidental form submissions without requiring explicit type specification.
Applied to files:
apps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/action-buttons.tsx
π Learning: 2025-09-24T15:47:40.293Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/about-you-form.tsx:152-157
Timestamp: 2025-09-24T15:47:40.293Z
Learning: The Button component from dub/ui automatically sets type="button" when an onClick prop is passed and defaults to type="submit" otherwise, using the logic: type={props.onClick ? "button" : "submit"}. This prevents accidental form submissions when buttons are used for modal triggers or other non-form actions.
Applied to files:
apps/web/app/app.dub.co/(deeplink)/deeplink/[domain]/[key]/action-buttons.tsx
π Learning: 2025-10-06T15:48:14.205Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2935
File: apps/web/lib/actions/partners/invite-partner-from-network.ts:21-28
Timestamp: 2025-10-06T15:48:14.205Z
Learning: For the network invites limit check in apps/web/lib/actions/partners/invite-partner-from-network.ts, the team accepts that concurrent invites may bypass the limit due to race conditions. Perfect atomicity is not required for this feature.
Applied to files:
apps/web/app/api/workspaces/[idOrSlug]/invites/route.ts
π Learning: 2025-08-21T03:03:39.879Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2737
File: apps/web/lib/api/cors.ts:1-5
Timestamp: 2025-08-21T03:03:39.879Z
Learning: Dub publishable keys are sent via Authorization header using Bearer token format, not via custom X-Dub-Publishable-Key header. The publishable key middleware extracts keys using req.headers.get("Authorization")?.replace("Bearer ", "") and validates they start with "dub_pk_".
Applied to files:
apps/web/lib/auth/publishable-key.ts
π Learning: 2025-08-21T03:03:39.879Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2737
File: apps/web/lib/api/cors.ts:1-5
Timestamp: 2025-08-21T03:03:39.879Z
Learning: Dub publishable keys are sent via Authorization header using Bearer token format, not via custom X-Dub-Publishable-Key header. The publishable key middleware extracts keys using req.headers.get("authorization")?.replace("Bearer ", "").
Applied to files:
apps/web/lib/auth/publishable-key.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
Summary by CodeRabbit
βοΈ Tip: You can customize this high-level summary in your review settings.