-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Fix Upstash QStash warning on the client side #2783
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
WalkthroughRefactors domain validation by extracting isValidDomain into a new module, updates imports accordingly, and introduces validateDomain and domainExists in utils.ts to orchestrate syntax validation and database existence checks. No behavioral changes to existing routes or UI usage aside from the new import path. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Caller
participant Utils as utils.validateDomain
participant Syntax as is-valid-domain.isValidDomain
participant DB as Prisma
Caller->>Utils: validateDomain(domain)
alt Missing/invalid input
Utils-->>Caller: { error: "...", code: "unprocessable_entity" }
else Input present
Utils->>Syntax: isValidDomain(domain)
alt Invalid syntax
Utils-->>Caller: { error: "...", code: "unprocessable_entity" }
else Valid syntax
Utils->>DB: domainExists(domain)
alt Exists
Utils-->>Caller: { error: "...", code: "conflict" }
else Not found
Utils-->>Caller: { error: null }
end
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
✨ 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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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
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/api/domains/utils.ts (1)
5-19: Normalize once; pass normalized value through validation and existence checksPrevents case/whitespace/trailing-dot mismatches between validation and DB lookup.
Apply:
export const validateDomain = async ( domain: string, ): Promise<{ error: string | null; code?: DubApiError["code"] }> => { - if (!domain || typeof domain !== "string") { + if (!domain || typeof domain !== "string") { return { error: "Missing domain", code: "unprocessable_entity" }; } - if (!isValidDomain(domain)) { + const normalized = domain.trim().replace(/\.$/, "").toLowerCase(); + if (!isValidDomain(normalized)) { return { error: "Invalid domain", code: "unprocessable_entity" }; } - const exists = await domainExists(domain); + const exists = await domainExists(normalized); if (exists) { return { error: "Domain is already in use.", code: "conflict" }; } return { error: null }; };
🧹 Nitpick comments (4)
apps/web/lib/api/domains/is-valid-domain.ts (1)
3-9: Normalize input and tighten blacklist to prevent edge-case bypassesTrim, lowercase, and strip a trailing dot before checks; require at least one subdomain label for the blacklist entries.
Apply:
-import { validDomainRegex } from "@dub/utils"; - -export const isValidDomain = (domain: string) => { - return ( - validDomainRegex.test(domain) && - // make sure the domain doesn't contain dub.co/dub.sh/d.to - !/^(dub\.co|.*\.dub\.co|dub\.sh|.*\.dub\.sh|d\.to|.*\.d\.to)$/i.test(domain) - ); -}; +import { validDomainRegex } from "@dub/utils"; + +const DISALLOWED = /^(dub\.co|.+\.dub\.co|dub\.sh|.+\.dub\.sh|d\.to|.+\.d\.to)$/i; + +export const isValidDomain = (domain: string) => { + const normalized = domain.trim().replace(/\.$/, "").toLowerCase(); + return validDomainRegex.test(normalized) && !DISALLOWED.test(normalized); +};apps/web/app/api/domains/[domain]/validate/route.ts (1)
7-7: Typo in comment: “valdiate” → “validate”Apply the rename as in the diff above.
apps/web/lib/api/domains/utils.ts (2)
21-31: Consider enforcing server-only usage of this moduleAdd server-only guard to prevent accidental client bundling.
Apply at the top of the file:
+import "server-only"; import { prisma } from "@dub/prisma";
21-31: Optional: add a unique index on domain.slug (if not already present)Avoids race conditions on existence checks and speeds lookups.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
apps/web/app/api/domains/[domain]/validate/route.ts(1 hunks)apps/web/lib/api/domains/is-valid-domain.ts(1 hunks)apps/web/lib/api/domains/utils.ts(1 hunks)apps/web/ui/domains/add-edit-domain-form.tsx(1 hunks)
⏰ 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/api/domains/is-valid-domain.ts (1)
1-9: Client-safe extraction of isValidDomain — LGTMIsolating validation into a pure module removes server-only deps from the client path and should address the QStash warning.
apps/web/ui/domains/add-edit-domain-form.tsx (2)
1-1: Good: import narrowed to a client-safe moduleThis avoids pulling server-only code (e.g., QStash) into the client bundle.
1-1: No remaining client-side imports of@/lib/api/domains– all occurrences are confined to server-only API routes underapps/web/app/api, so the UI code no longer pulls from the server-only barrel.apps/web/app/api/domains/[domain]/validate/route.ts (1)
33-78: Optional SSRF hardening: add private/link-local IP guard before fetch
I didn’t find any existingisPrivateIP-style utilities in apps/web; consider resolving the domain (e.g., viadns.lookup), checking the returned IP against private and link-local ranges, and skipping the HTTP HEAD fetch if it’s in a forbidden range—retaining the 3 s timeouts and extracting this into a shared helper.apps/web/lib/api/domains/utils.ts (2)
3-3: Good: server-only validator is no longer exported from hereThis reduces accidental client imports from the barrel.
21-31: Ensure slug normalization (lowercasing) on write and read
Write-side calls (e.g.prisma.domain.create({ data: { slug: domain } })) pass raw values with no.toLowerCase()and no DB-level lowercase enforcement was found; addslug: domain.toLowerCase()(or a schema constraint) on both writes and indomainExiststo avoid case-sensitive lookup failures.
Summary by CodeRabbit
New Features
Bug Fixes