-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Improve support for disabled links #3082
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 a nullable Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant NextMiddleware
participant LinkMiddleware
participant Cache as CachedLinkStore
participant Edge as getDomainViaEdge
participant NotFoundHandler
participant Response
User->>NextMiddleware: HTTP request /{short}
NextMiddleware->>LinkMiddleware: handoff
LinkMiddleware->>Cache: fetch cachedLink
alt cachedLink exists
LinkMiddleware->>LinkMiddleware: check cachedLink.disabledAt
alt disabledAt set
LinkMiddleware->>NotFoundHandler: handleNotFoundLink(req)
NotFoundHandler->>Edge: fetch domain config
Edge-->>NotFoundHandler: domain (maybe notFoundUrl)
alt domain.notFoundUrl
NotFoundHandler-->>Response: 302 redirect (+ X-Robots-Tag, headers)
else
NotFoundHandler-->>Response: rewrite -> /{domain}/not-found (with headers)
end
else active link
LinkMiddleware-->>Response: redirect to target
end
else not found
LinkMiddleware->>NotFoundHandler: handleNotFoundLink(req)
NotFoundHandler-->>Response: redirect or rewrite
end
Response-->>User: HTTP response
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 (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: 3
π§Ή Nitpick comments (3)
apps/web/scripts/migrations/backfill-banned-partner-links.ts (2)
5-5: Use absolute import path for consistency.The import path changed to a relative path (
../../lib/tinybird/record-link), while other imports use absolute paths with the@/alias. Relative paths are more brittle and inconsistent with the codebase style.Apply this diff to use the absolute import:
-import { recordLink } from "../../lib/tinybird/record-link"; +import { recordLink } from "@/lib/tinybird/record-link";
31-47: Add error handling to prevent data inconsistency.If the
updateManyoperation succeeds butrecordLinkfails, the database will be updated but Tinybird won't reflect the changes. Consider adding error handling and logging to track failures.Apply this diff to add basic error handling:
console.log(`Found ${links.length} links to process.`); - const prismaRes = await prisma.link.updateMany({ - where: { - id: { - in: links.map((link) => link.id), - }, - }, - data: { - disabledAt: new Date(), - }, - }); - console.log(`Updated ${prismaRes.count} links to be disabled.`); - - const tbRes = await recordLink(links, { - deleted: true, - }); - - console.log("Deleted links in Tinybird", tbRes); + try { + const prismaRes = await prisma.link.updateMany({ + where: { + id: { + in: links.map((link) => link.id), + }, + }, + data: { + disabledAt: new Date(), + }, + }); + console.log(`Updated ${prismaRes.count} links to be disabled.`); + + const tbRes = await recordLink(links, { + deleted: true, + }); + + console.log("Deleted links in Tinybird", tbRes); + } catch (error) { + console.error("Error processing batch:", error); + throw error; + }apps/web/ui/partners/partner-info-section.tsx (1)
52-54: Excellent refactoring to use the shared component.The replacement of inline badge/tooltip logic with
PartnerStatusBadgeWithTooltipimproves code reusability and maintainability. The component correctly receives all required properties through thepartnerobject.If different badge sizes are needed in the future, consider exposing a
badgeSizeprop that can be passed through toPartnerStatusBadgeWithTooltip:export function PartnerInfoSection({ partner, showPartnerStatus = true, badgeSize = "md", children, }: PropsWithChildren<{ showPartnerStatus?: boolean; badgeSize?: "sm" | "md"; partner: Pick<...>; }>) { // ... <PartnerStatusBadgeWithTooltip partner={partner} size={badgeSize} /> }
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π Files selected for processing (16)
apps/web/lib/api/links/utils/transform-link.ts(0 hunks)apps/web/lib/middleware/link.ts(4 hunks)apps/web/lib/middleware/utils/handle-not-found-link.ts(1 hunks)apps/web/lib/tinybird/record-link.ts(2 hunks)apps/web/lib/types.ts(1 hunks)apps/web/lib/upstash/format-redis-link.ts(2 hunks)apps/web/lib/zod/schemas/links.ts(1 hunks)apps/web/scripts/migrations/backfill-banned-partner-links.ts(1 hunks)apps/web/ui/links/disabled-link-tooltip.tsx(1 hunks)apps/web/ui/links/link-builder/link-partner-details.tsx(2 hunks)apps/web/ui/links/link-title-column.tsx(2 hunks)apps/web/ui/links/short-link-input.tsx(2 hunks)apps/web/ui/partners/partner-info-cards.tsx(2 hunks)apps/web/ui/partners/partner-info-section.tsx(2 hunks)apps/web/ui/partners/partner-status-badge-with-tooltip.tsx(1 hunks)packages/ui/src/status-badge.tsx(3 hunks)
π€ Files with no reviewable changes (1)
- apps/web/lib/api/links/utils/transform-link.ts
π§° Additional context used
π§ Learnings (8)
π Learning: 2025-10-08T21:33:23.553Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2936
File: apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/analytics/add-hostname-modal.tsx:28-34
Timestamp: 2025-10-08T21:33:23.553Z
Learning: In the dub/ui Button component, when the `disabledTooltip` prop is set to a non-undefined value (e.g., a string), the button is automatically disabled. Therefore, it's not necessary to also add the same condition to the `disabled` propβsetting `disabledTooltip={permissionsError || undefined}` is sufficient to disable the button when there's a permissions error.
Applied to files:
apps/web/ui/links/short-link-input.tsxapps/web/ui/links/link-title-column.tsxapps/web/ui/links/disabled-link-tooltip.tsx
π Learning: 2025-09-17T17:40:35.470Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2857
File: apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/resources/program-help-and-support.tsx:95-121
Timestamp: 2025-09-17T17:40:35.470Z
Learning: In the Dub UI Switch component, providing a truthy `disabledTooltip` prop automatically disables the switch and prevents user interaction, so an explicit `disabled` prop is not needed when using `disabledTooltip`.
Applied to files:
apps/web/ui/links/short-link-input.tsxapps/web/ui/links/link-title-column.tsxapps/web/ui/links/disabled-link-tooltip.tsx
π Learning: 2025-09-17T17:40:35.470Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2857
File: apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/resources/program-help-and-support.tsx:95-121
Timestamp: 2025-09-17T17:40:35.470Z
Learning: In the Dub UI Switch component, providing a truthy `disabledTooltip` prop automatically disables the switch and prevents user interaction, so an explicit `disabled` prop is not needed when using `disabledTooltip`. The component computes `switchDisabled = disabledTooltip ? true : disabled || loading` and passes this to the underlying Radix Switch primitive.
Applied to files:
apps/web/ui/links/short-link-input.tsxapps/web/ui/links/link-title-column.tsxapps/web/ui/links/disabled-link-tooltip.tsx
π Learning: 2025-05-29T04:45:18.504Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
Applied to files:
apps/web/ui/links/link-builder/link-partner-details.tsxapps/web/ui/partners/partner-info-cards.tsx
π 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/tinybird/record-link.tsapps/web/scripts/migrations/backfill-banned-partner-links.tsapps/web/lib/middleware/utils/handle-not-found-link.tsapps/web/lib/middleware/link.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/ui/partners/partner-info-cards.tsx
π Learning: 2025-09-19T18:46:43.787Z
Learnt from: CR
Repo: dubinc/dub PR: 0
File: packages/hubspot-app/CLAUDE.md:0-0
Timestamp: 2025-09-19T18:46:43.787Z
Learning: Applies to packages/hubspot-app/app/cards/**/*.{js,jsx,ts,tsx} : Only use components exported by hubspot/ui-extensions within card components
Applied to files:
apps/web/ui/partners/partner-info-cards.tsx
π 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/ui/partners/partner-info-section.tsx
𧬠Code graph analysis (10)
apps/web/ui/links/short-link-input.tsx (2)
apps/web/lib/types.ts (1)
LinkProps(134-134)apps/web/ui/links/disabled-link-tooltip.tsx (1)
DisabledLinkTooltip(3-33)
apps/web/ui/links/link-builder/link-partner-details.tsx (1)
apps/web/ui/partners/partner-status-badge-with-tooltip.tsx (1)
PartnerStatusBadgeWithTooltip(7-57)
apps/web/lib/tinybird/record-link.ts (2)
apps/web/lib/tinybird/client.ts (2)
tb(3-6)tbOld(9-12)apps/web/lib/api/links/utils/transform-link.ts (1)
ExpandedLink(12-22)
apps/web/ui/partners/partner-info-cards.tsx (1)
apps/web/ui/partners/partner-status-badge-with-tooltip.tsx (1)
PartnerStatusBadgeWithTooltip(7-57)
apps/web/scripts/migrations/backfill-banned-partner-links.ts (3)
packages/prisma/index.ts (1)
prisma(3-9)apps/web/lib/api/links/include-program-enrollment.ts (1)
includeProgramEnrollment(3-9)apps/web/lib/tinybird/record-link.ts (1)
recordLink(83-100)
apps/web/ui/links/link-title-column.tsx (1)
apps/web/ui/links/disabled-link-tooltip.tsx (1)
DisabledLinkTooltip(3-33)
apps/web/ui/partners/partner-info-section.tsx (1)
apps/web/ui/partners/partner-status-badge-with-tooltip.tsx (1)
PartnerStatusBadgeWithTooltip(7-57)
apps/web/lib/middleware/link.ts (1)
apps/web/lib/middleware/utils/handle-not-found-link.ts (1)
handleNotFoundLink(6-26)
apps/web/ui/links/disabled-link-tooltip.tsx (1)
packages/ui/src/tooltip.tsx (1)
Tooltip(32-88)
apps/web/ui/partners/partner-status-badge-with-tooltip.tsx (4)
apps/web/lib/types.ts (1)
EnrolledPartnerProps(453-453)apps/web/ui/partners/partner-status-badges.ts (1)
PartnerStatusBadges(11-60)packages/ui/src/tooltip.tsx (1)
DynamicTooltipWrapper(280-294)apps/web/lib/zod/schemas/partners.ts (1)
BAN_PARTNER_REASONS(67-74)
πͺ Biome (2.1.2)
apps/web/ui/links/disabled-link-tooltip.tsx
[error] 11-11: Avoid using target="_blank" without rel="noopener" or rel="noreferrer".
Opening external links in new tabs without rel="noopener" is a security risk. See the explanation for more details.
Safe fix: Add the rel="noopener" attribute.
(lint/security/noBlankTarget)
[error] 19-19: Avoid using target="_blank" without rel="noopener" or rel="noreferrer".
Opening external links in new tabs without rel="noopener" is a security risk. See the explanation for more details.
Safe fix: Add the rel="noopener" attribute.
(lint/security/noBlankTarget)
β° 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/scripts/migrations/backfill-banned-partner-links.ts (1)
43-45: Verify thedeleted: trueflag is correct for disabled links.The script sets
disabledAton links (disabling them) but marks them asdeleted: truein Tinybird. Ensure this is intentional behavior, as "disabled" and "deleted" have different semantic meanings.If disabled links should be tracked separately from deleted links in Tinybird, consider whether a different flag or approach is needed.
packages/ui/src/status-badge.tsx (1)
25-28: LGTM! Size variant implementation is clean.The size prop integration follows the established cva pattern correctly, with appropriate padding adjustments for
smandmdvariants.Also applies to: 55-55, 69-69
apps/web/lib/types.ts (1)
166-166: LGTM! Field addition follows existing patterns.The
disabledAtfield is correctly typed and placed alongside similar timestamp fields likeexpiresAt.apps/web/lib/zod/schemas/links.ts (1)
646-651: LGTM! Schema definition is clear and comprehensive.The
disabledAtfield follows the existing pattern for timestamp fields, and the description clearly explains the impact on both redirection and analytics.apps/web/ui/links/link-builder/link-partner-details.tsx (1)
36-41: LGTM! Partner status badge integration is clean.The flex layout with
gap-2properly accommodates both the partner name and status badge, while maintaining text truncation behavior.apps/web/ui/links/link-title-column.tsx (1)
145-145: LGTM! Disabled link indicator is properly placed.The conditional rendering of
DisabledLinkTooltipfollows the existing pattern for other badges and indicators in the link title row.apps/web/lib/upstash/format-redis-link.ts (1)
16-16: LGTM! Propagation follows established patterns.The
disabledAtfield is correctly destructured and conditionally spread into the return object, mirroring the handling of similar optional fields likeexpiresAtandexpiredUrl.Also applies to: 45-45
apps/web/ui/partners/partner-info-cards.tsx (1)
178-180: LGTM! Badge rendering is now centralized.The refactoring to use
PartnerStatusBadgeWithTooltipconsolidates the badge logic while maintaining the same conditional rendering behavior for enrolled partners.apps/web/ui/partners/partner-info-section.tsx (1)
2-5: LGTM! Clean import refactoring.The import changes correctly reflect the delegation of badge rendering logic to the
PartnerStatusBadgeWithTooltipcomponent. TheTooltipimport is appropriately retained for the country flag tooltip on line 34.
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 (7)
apps/web/lib/webhook/sample-events/lead-created.json(1 hunks)apps/web/lib/webhook/sample-events/link-clicked.json(1 hunks)apps/web/lib/webhook/sample-events/link-created.json(1 hunks)apps/web/lib/webhook/sample-events/link-deleted.json(1 hunks)apps/web/lib/webhook/sample-events/link-updated.json(1 hunks)apps/web/lib/webhook/sample-events/sale-created.json(1 hunks)apps/web/lib/zod/schemas/links.ts(2 hunks)
β Files skipped from review due to trivial changes (1)
- apps/web/lib/webhook/sample-events/link-updated.json
β° 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 (6)
apps/web/lib/zod/schemas/links.ts (1)
646-651: LGTM! Clear description for the new field.The
disabledAtfield is properly defined with a clear description explaining the behavior when a link is disabled.apps/web/lib/webhook/sample-events/link-created.json (1)
14-14: LGTM! Sample event updated with new field.The addition of
disabledAt: nullaligns with the schema changes and maintains consistency across webhook sample events.apps/web/lib/webhook/sample-events/sale-created.json (1)
40-40: LGTM! Consistent with schema changes.The
disabledAt: nullfield addition maintains consistency with other webhook samples.apps/web/lib/webhook/sample-events/link-clicked.json (1)
31-31: LGTM! Field properly added.The addition of
disabledAt: nullis correctly positioned and consistent with the schema update.apps/web/lib/webhook/sample-events/lead-created.json (1)
40-40: LGTM! Sample event aligned with schema.The
disabledAt: nullfield properly reflects the new schema definition.apps/web/lib/webhook/sample-events/link-deleted.json (1)
14-14: LGTM! Webhook sample updated correctly.The addition of
disabledAt: nullcompletes the consistent update across all webhook sample events.
Summary by CodeRabbit
New Features
Improvements
Tests