-
Notifications
You must be signed in to change notification settings - Fork 130
Adds runtime validation for required environment variables to prevent startup failures when API keys or webhook secrets are missing #323
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
base: main
Are you sure you want to change the base?
Conversation
|
@abhinav-anshul is attempting to deploy a commit to the Dodo Payments Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughAdds module-load Zod validation for Stripe and DodoPayments environment variables across Express, Fastify, Hono, and Next.js templates, exporting typed Changes
Sequence Diagram(s)sequenceDiagram
participant Loader as Module Load
participant Zod as Zod Validator
participant Env as validatedEnv (export)
participant Library as Library (getStripe/getDodoPayments)
participant Webhook as Webhook Route
rect rgb(220,235,255)
note over Loader,Zod: New fast-fail validation at module load
Loader->>Zod: parse(process.env)
alt valid
Zod->>Env: return validated values
Env->>Library: exported validatedEnv used to init clients
Library->>Webhook: Webhook imports validatedEnv for secret
else invalid
Zod->>Loader: throw descriptive error (fail-fast)
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. 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: 0
🧹 Nitpick comments (5)
packages/templates/express/.env.example (1)
10-12: Minor: Address linter conventions (optional).Two low-priority items flagged by dotenv-linter:
- Missing blank line at EOF (line 12): Add a newline at the end of the file.
- Key ordering (lines 11–12): Conventionally, NODE_ENV should precede PORT for consistency in environment file organization.
These are style refinements and can be addressed if the project enforces dotenv-linter rules.
If addressing these conventions, apply this diff:
# Server Configuration -PORT=3000 NODE_ENV=development +PORT=3000 +packages/templates/nextjs/.env.example (1)
1-8: Add a trailing newline for .env file convention.The file is missing a blank line at the end. While this doesn't affect functionality, it's a standard convention for .env files.
Apply this diff:
# Stripe Configuration STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key_here -STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here +STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_hereBased on static analysis.
packages/templates/hono/.env.example (1)
1-12: Add a trailing newline for .env file convention.The file is missing a blank line at the end. While this doesn't affect functionality, it's a standard convention for .env files.
Apply this diff:
# Server Configuration PORT=3000 -BUN_ENV=development +BUN_ENV=developmentBased on static analysis.
packages/templates/hono/src/lib/dodopayments.ts (1)
13-35: Minor: Error message formatting differs from other templates.Line 18-19 starts the error message with a newline and space (
\n DodoPayments...), while the Fastify version (line 18 in packages/templates/fastify/src/lib/dodopayments.ts) starts directly with the text. Consider aligning the formatting for consistency across templates.Apply this diff to match the Fastify template:
- throw new Error(` - DodoPayments environment validation failed: ${errors} + throw new Error(`DodoPayments environment validation failed: ${errors}packages/templates/hono/src/lib/stripe.ts (1)
14-34: Minor: Consistent error message formatting.Line 19 has a leading space in the error message (
" Stripe environment validation failed"). While this doesn't affect functionality, consider removing it for consistency with error message formatting in other templates.Apply this diff:
- throw new Error(` Stripe environment validation failed: ${errors} + throw new Error(`Stripe environment validation failed: ${errors}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
packages/templates/express/.env.example(1 hunks)packages/templates/express/src/lib/dodopayments.ts(1 hunks)packages/templates/express/src/lib/stripe.ts(1 hunks)packages/templates/express/src/routes/dodopayments/webhook.ts(1 hunks)packages/templates/express/src/routes/stripe/webhook.ts(2 hunks)packages/templates/fastify/src/lib/dodopayments.ts(1 hunks)packages/templates/fastify/src/routes/dodopayments/webhook.ts(1 hunks)packages/templates/hono/.env.example(1 hunks)packages/templates/hono/src/lib/dodopayments.ts(1 hunks)packages/templates/hono/src/lib/stripe.ts(1 hunks)packages/templates/hono/src/routes/dodopayments/webhook.ts(1 hunks)packages/templates/hono/src/routes/stripe/webhook.ts(2 hunks)packages/templates/nextjs/.env.example(1 hunks)packages/templates/nextjs/api-routes/(dodopayments)/webhook/route.ts(1 hunks)packages/templates/nextjs/api-routes/(stripe)/webhook/route.ts(2 hunks)packages/templates/nextjs/lib/dodopayments.ts(1 hunks)packages/templates/nextjs/lib/stripe.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (13)
packages/templates/nextjs/lib/dodopayments.ts (3)
packages/templates/express/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/fastify/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/hono/src/lib/dodopayments.ts (2)
validatedEnv(41-41)getDodoPaymentsClient(45-54)
packages/templates/hono/src/lib/stripe.ts (6)
packages/templates/express/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/express/src/lib/stripe.ts (2)
validatedEnv(40-40)getStripe(43-50)packages/templates/fastify/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/hono/src/lib/dodopayments.ts (1)
validatedEnv(41-41)packages/templates/nextjs/lib/dodopayments.ts (1)
validatedEnv(42-42)packages/templates/nextjs/lib/stripe.ts (2)
validatedEnv(40-40)getStripe(43-50)
packages/templates/nextjs/api-routes/(dodopayments)/webhook/route.ts (1)
packages/templates/nextjs/lib/dodopayments.ts (1)
validatedEnv(42-42)
packages/templates/nextjs/api-routes/(stripe)/webhook/route.ts (1)
packages/templates/nextjs/lib/stripe.ts (1)
validatedEnv(40-40)
packages/templates/hono/src/routes/dodopayments/webhook.ts (1)
packages/templates/hono/src/lib/dodopayments.ts (1)
validatedEnv(41-41)
packages/templates/fastify/src/lib/dodopayments.ts (6)
packages/templates/express/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/express/src/lib/stripe.ts (1)
validatedEnv(40-40)packages/templates/hono/src/lib/dodopayments.ts (2)
validatedEnv(41-41)getDodoPaymentsClient(45-54)packages/templates/hono/src/lib/stripe.ts (1)
validatedEnv(40-40)packages/templates/nextjs/lib/dodopayments.ts (2)
validatedEnv(42-42)getDodoPaymentsClient(46-55)packages/templates/nextjs/lib/stripe.ts (1)
validatedEnv(40-40)
packages/templates/express/src/routes/dodopayments/webhook.ts (1)
packages/templates/express/src/lib/dodopayments.ts (1)
validatedEnv(40-40)
packages/templates/hono/src/lib/dodopayments.ts (3)
packages/templates/express/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/fastify/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/nextjs/lib/dodopayments.ts (2)
validatedEnv(42-42)getDodoPaymentsClient(46-55)
packages/templates/hono/src/routes/stripe/webhook.ts (1)
packages/templates/hono/src/lib/stripe.ts (1)
validatedEnv(40-40)
packages/templates/express/src/lib/stripe.ts (6)
packages/templates/express/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/fastify/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/hono/src/lib/dodopayments.ts (1)
validatedEnv(41-41)packages/templates/hono/src/lib/stripe.ts (2)
validatedEnv(40-40)getStripe(43-50)packages/templates/nextjs/lib/dodopayments.ts (1)
validatedEnv(42-42)packages/templates/nextjs/lib/stripe.ts (2)
validatedEnv(40-40)getStripe(43-50)
packages/templates/nextjs/lib/stripe.ts (6)
packages/templates/express/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/express/src/lib/stripe.ts (2)
validatedEnv(40-40)getStripe(43-50)packages/templates/fastify/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/hono/src/lib/dodopayments.ts (1)
validatedEnv(41-41)packages/templates/hono/src/lib/stripe.ts (2)
validatedEnv(40-40)getStripe(43-50)packages/templates/nextjs/lib/dodopayments.ts (1)
validatedEnv(42-42)
packages/templates/fastify/src/routes/dodopayments/webhook.ts (1)
packages/templates/fastify/src/lib/dodopayments.ts (1)
validatedEnv(40-40)
packages/templates/express/src/lib/dodopayments.ts (6)
packages/templates/express/src/lib/stripe.ts (1)
validatedEnv(40-40)packages/templates/fastify/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/hono/src/lib/dodopayments.ts (2)
validatedEnv(41-41)getDodoPaymentsClient(45-54)packages/templates/hono/src/lib/stripe.ts (1)
validatedEnv(40-40)packages/templates/nextjs/lib/dodopayments.ts (2)
validatedEnv(42-42)getDodoPaymentsClient(46-55)packages/templates/nextjs/lib/stripe.ts (1)
validatedEnv(40-40)
🪛 dotenv-linter (4.0.0)
packages/templates/express/.env.example
[warning] 12-12: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
[warning] 12-12: [UnorderedKey] The NODE_ENV key should go before the PORT key
(UnorderedKey)
packages/templates/hono/.env.example
[warning] 12-12: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
[warning] 12-12: [UnorderedKey] The BUN_ENV key should go before the PORT key
(UnorderedKey)
packages/templates/nextjs/.env.example
[warning] 8-8: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
🔇 Additional comments (26)
packages/templates/express/.env.example (1)
6-8: ✓ Stripe configuration properly documented.The addition of STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET with appropriate placeholder values aligns with the PR objectives and follows the existing documentation pattern. These entries match the environment variables expected by the validation schema used in Stripe initialization across the templates.
packages/templates/fastify/src/lib/dodopayments.ts (4)
4-10: LGTM! Schema validates required fields correctly.The Zod schema properly validates:
- Required environment variables with non-empty string checks
- Environment enum with clear error message
- All three essential DodoPayments configuration values
13-34: Excellent error messaging for developer experience.The validation function provides:
- Clear, actionable error messages with formatting
- Helpful troubleshooting checklist
- Documentation of all required variables
- Good use of
safeParsefor controlled error handlingThis will significantly improve the developer experience when environment variables are misconfigured.
44-53: LGTM! Clean client initialization with validated config.The function correctly:
- Uses pre-validated environment variables from
validatedEnv- Maintains lazy initialization pattern
- Eliminates redundant runtime checks (validation happens at module load)
36-40: Review comment is not applicable to this codebase.This is template/boilerplate code in
packages/templates/with no automated tests. The module-load validation is an intentional fail-fast pattern used consistently across all template frameworks (Stripe, Hono, etc.), andvalidatedEnvis properly exported for use in webhook handlers. No test setup verification is needed.Likely an incorrect or invalid review comment.
packages/templates/fastify/src/routes/dodopayments/webhook.ts (1)
5-8: LGTM! Webhook now uses validated environment.The webhook correctly sources its secret from
validatedEnv, ensuring the key is validated at application startup rather than at runtime.packages/templates/hono/src/lib/dodopayments.ts (3)
4-10: LGTM! Schema is consistent across templates.Identical validation schema to other templates, ensuring consistent environment validation across all frameworks.
45-54: LGTM! Consistent implementation across templates.Client initialization correctly uses validated environment variables.
37-41: No test compatibility issues detected; verification complete.The hono template contains no test files, so there are no tests to break with module-level validation. The
validatedEnvis properly exported and designed for use in handlers. This fail-fast validation pattern at startup is intentional and appropriate for a template.packages/templates/nextjs/api-routes/(stripe)/webhook/route.ts (1)
2-15: LGTM! Stripe webhook uses validated configuration.The webhook correctly sources the Stripe webhook secret from
validatedEnv, ensuring validation at startup. This aligns with the same pattern used for DodoPayments webhooks.packages/templates/nextjs/api-routes/(dodopayments)/webhook/route.ts (1)
3-5: LGTM! DodoPayments webhook uses validated configuration.Correctly uses
validatedEnvfor the webhook key, ensuring validation occurs at startup.packages/templates/hono/src/lib/stripe.ts (3)
4-11: Excellent format validation for Stripe keys!The schema correctly validates:
- STRIPE_SECRET_KEY must start with
sk_(standard Stripe prefix)- STRIPE_WEBHOOK_SECRET must start with
whsec_(webhook secret prefix)This catches common copy-paste errors and provides better validation than simple non-empty checks.
43-50: LGTM! Clean Stripe client initialization.The function correctly uses validated environment variables and maintains the lazy initialization pattern.
36-40: Module-level validation doesn't affect this template; guidance should be documented.No tests exist in this template package, so module-level validation isn't an immediate concern. However, the routes (webhook.ts, subscriptions.ts, products.ts, payments.ts, checkout.ts, customer.ts) import
lib/stripeat the module level, which means validation runs at app startup rather than test time. This is the expected behavior for a deployed application. If tests are added in the future, they'll need environment variables configured before importing these routes.packages/templates/express/src/routes/stripe/webhook.ts (1)
3-3: LGTM! Clean refactor to validated environment.The webhook secret now sources from
validatedEnv, ensuring the value was validated at module load time. This eliminates runtime errors from missing or malformed secrets.Also applies to: 15-15
packages/templates/hono/src/routes/dodopayments/webhook.ts (1)
3-3: LGTM! Consistent with the validation pattern.The webhook key now uses the pre-validated environment value, preventing initialization with missing credentials.
Also applies to: 7-7
packages/templates/hono/src/routes/stripe/webhook.ts (1)
3-3: LGTM! Validated environment used correctly.Also applies to: 16-16
packages/templates/nextjs/lib/stripe.ts (2)
45-45: LGTM! Stripe client now uses validated configuration.
4-40: Excellent validation implementation with clear error messaging.The Zod schema correctly validates Stripe key formats and provides comprehensive error messages. The fail-fast approach at module load ensures configuration issues are caught immediately during development. Verified that
zodis available in the project's root dependencies (version ^3.25.76), so the validation code will function as intended.packages/templates/express/src/routes/dodopayments/webhook.ts (1)
3-3: LGTM! Webhook initialization now uses validated credentials.Also applies to: 7-7
packages/templates/nextjs/lib/dodopayments.ts (2)
6-42: Well-structured validation with enum constraints.The schema correctly validates the DodoPayments environment as an enum with a helpful custom error message. The validation pattern is consistent with the Stripe implementation.
49-50: LGTM! Client initialization uses validated configuration.packages/templates/express/src/lib/dodopayments.ts (2)
4-40: LGTM! Framework-appropriate validation for Express.The validation correctly references
.envfile instead of.env.local, which is appropriate for Express applications. The implementation is consistent with other templates.
47-48: LGTM! Client configuration uses validated environment.packages/templates/express/src/lib/stripe.ts (2)
4-40: LGTM! Robust validation with Stripe-specific prefix checks.The schema enforces correct Stripe key formats with the
sk_andwhsec_prefix validations. Error messaging is clear and framework-appropriate for Express.
45-45: LGTM! Stripe client initialization uses validated key.
|
@abhinav-anshul you need to rebase your PR. |
01c2e91 to
d8fb89d
Compare
|
@aagarwal1012 done! |
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
♻️ Duplicate comments (2)
packages/templates/nextjs/lib/stripe.ts (1)
2-40: Next.js Stripe env helper is consistent; apply same schema tweak as Hono/ExpressThis mirrors the Hono/Express helpers nicely: module-load validation, a reusable
validatedEnv, andgetStripenow sourcing from it. The added Stripe type exports are also useful for API route typing.The same minor Zod nuance applies here: a missing env var yields a generic
Requiredmessage, while your custom"… is required"text only covers the “empty string” case. If you adopt therequired_error+.min(1, { message: … })pattern from my Hono comment, I’d mirror it here so all templates emit equally explicit messages.Also applies to: 45-53
packages/templates/express/src/lib/stripe.ts (1)
2-40: Express Stripe env validation is solid; consider aligning schema and other templatesThe Express helper cleanly centralizes Stripe configuration: validation at module load,
validatedEnvexported for webhooks, andgetStripenow usingvalidatedEnv.STRIPE_SECRET_KEY. That’s a nice DX improvement over ad‑hocprocess.envchecks.Two small follow‑ups you might consider:
- Apply the same
required_error+.min(1, { message: … })refinement as suggested on the Hono helper so missing vs empty variables get clearer, non‑generic messages.- For cross‑template consistency, ensure the Fastify Stripe helper also uses this shared
stripeEnvSchema/validatedEnvpattern rather than a bespokeprocess.envcheck, so developers get identical behavior regardless of framework.Also applies to: 45-52
🧹 Nitpick comments (6)
packages/templates/express/.env.example (1)
6-8: Stripe env examples look good; consider minor dotenv-linter cleanupsThe added Stripe keys and example values line up with the rest of the templates and the validation logic implied by the PR description, so the semantics look correct.
If you care about keeping
dotenv-linterfully green, you can also:
- Move
NODE_ENVabovePORT, and- Add a trailing blank line at EOF.
Example:
-# Server Configuration -PORT=3000 -NODE_ENV=development +# Server Configuration +NODE_ENV=development +PORT=3000 +Also applies to: 10-12
packages/templates/express/src/lib/dodopayments.ts (1)
2-40: Server-side env validation and client construction look correctFor the Express template, the zod schema +
validateDodoPaymentsEnvgive you a clean fail-fast path on misconfiguredDODO_PAYMENTS_*variables, and usingvalidatedEnvinsidegetDodoPaymentsClientremoves the scatteredprocess.envreads and inline checks. This matches the stated PR objective nicely.There is some repetition of the same schema/validation logic across Express/Fastify/Hono; that’s reasonable for templates, but if these ever start drifting it might be worth centralizing into a small shared helper in the monorepo.
Also applies to: 47-48
packages/templates/hono/.env.example (1)
1-12: Env example keys align with code; minor optional dotenv-linter tweaksThe updated DodoPayments block and the new Stripe Configuration section (with
STRIPE_SECRET_KEY/STRIPE_WEBHOOK_SECRET) look consistent with the runtime validation behavior described for the Hono template.If you want to satisfy
dotenv-linterfully, you can also:
- Put
BUN_ENVbeforePORT, and- Add a blank line at EOF.
Example:
-# Server Configuration -PORT=3000 -BUN_ENV=development +# Server Configuration +BUN_ENV=development +PORT=3000 +packages/templates/fastify/src/lib/dodopayments.ts (1)
2-40: Fastify env validation matches Express/Hono patterns and looks correctThe Fastify DodoPayments lib follows the same schema + module-load validation pattern as the other templates and correctly wires
getDodoPaymentsClientthroughvalidatedEnv, eliminating ad-hocprocess.envreads and runtime checks.Given the near-identical logic across frameworks, you might later extract a small shared helper for the schema +
validateDodoPaymentsEnvto avoid divergence, but that’s optional for template code.Also applies to: 47-48
packages/templates/nextjs/.env.example (1)
1-8: Env example matches validation; optional trailing newline for toolingThe placeholders and prefixes line up with the Stripe validators you added elsewhere (
sk_/whsec_), and the DodoPayments block is clear. To satisfydotenv-linter’sEndingBlankLinewarning, you can add a final blank line at EOF; it’s non-functional but keeps tools quiet.packages/templates/hono/src/lib/stripe.ts (1)
2-40: Centralized Stripe env validation looks good; consider sharpening Zod error messagesThe
stripeEnvSchema+validateStripeEnv+validatedEnvpattern is solid and aligns well with the “fail fast with clear messaging” goal. One small DX improvement: when a variable is missing vs just empty, Zod currently reports a genericRequiredmessage; your custom"… is required"text only applies to the.min(1, …)check.If you want fully explicit messages for both cases, you could tweak the schema like this:
-const stripeEnvSchema = z.object({ - STRIPE_SECRET_KEY: z.string().min(1, 'STRIPE_SECRET_KEY is required').startsWith('sk_', { - message: 'STRIPE_SECRET_KEY must start with "sk_"' - }), - STRIPE_WEBHOOK_SECRET: z.string().min(1, 'STRIPE_WEBHOOK_SECRET is required').startsWith('whsec_', { - message: 'STRIPE_WEBHOOK_SECRET must start with "whsec_"' - }), -}); +const stripeEnvSchema = z.object({ + STRIPE_SECRET_KEY: z + .string({ required_error: 'STRIPE_SECRET_KEY is required' }) + .min(1, { message: 'STRIPE_SECRET_KEY cannot be empty' }) + .startsWith('sk_', { message: 'STRIPE_SECRET_KEY must start with "sk_"' }), + STRIPE_WEBHOOK_SECRET: z + .string({ required_error: 'STRIPE_WEBHOOK_SECRET is required' }) + .min(1, { message: 'STRIPE_WEBHOOK_SECRET cannot be empty' }) + .startsWith('whsec_', { message: 'STRIPE_WEBHOOK_SECRET must start with "whsec_"' }), +});That keeps the behavior the same while making the thrown error text even more explicit for missing vs empty values.
Also applies to: 45-45
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
packages/templates/express/.env.example(1 hunks)packages/templates/express/src/lib/dodopayments.ts(1 hunks)packages/templates/express/src/lib/stripe.ts(1 hunks)packages/templates/express/src/routes/dodopayments/webhook.ts(1 hunks)packages/templates/express/src/routes/stripe/webhook.ts(2 hunks)packages/templates/fastify/src/lib/dodopayments.ts(1 hunks)packages/templates/fastify/src/routes/dodopayments/webhook.ts(1 hunks)packages/templates/hono/.env.example(1 hunks)packages/templates/hono/src/lib/dodopayments.ts(1 hunks)packages/templates/hono/src/lib/stripe.ts(1 hunks)packages/templates/hono/src/routes/dodopayments/webhook.ts(1 hunks)packages/templates/hono/src/routes/stripe/webhook.ts(2 hunks)packages/templates/nextjs/.env.example(1 hunks)packages/templates/nextjs/api-routes/(dodopayments)/webhook/route.ts(1 hunks)packages/templates/nextjs/api-routes/(stripe)/webhook/route.ts(2 hunks)packages/templates/nextjs/lib/dodopayments.ts(1 hunks)packages/templates/nextjs/lib/stripe.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
- packages/templates/nextjs/api-routes/(dodopayments)/webhook/route.ts
- packages/templates/hono/src/routes/stripe/webhook.ts
- packages/templates/hono/src/lib/dodopayments.ts
- packages/templates/hono/src/routes/dodopayments/webhook.ts
- packages/templates/fastify/src/routes/dodopayments/webhook.ts
- packages/templates/nextjs/api-routes/(stripe)/webhook/route.ts
- packages/templates/express/src/routes/stripe/webhook.ts
- packages/templates/express/src/routes/dodopayments/webhook.ts
🧰 Additional context used
🧬 Code graph analysis (6)
packages/templates/fastify/src/lib/dodopayments.ts (3)
packages/templates/express/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/hono/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/nextjs/lib/dodopayments.ts (2)
validatedEnv(42-42)getDodoPaymentsClient(46-55)
packages/templates/nextjs/lib/stripe.ts (3)
packages/templates/express/src/lib/stripe.ts (6)
validatedEnv(40-40)getStripe(43-48)Product(49-49)Customer(50-50)Subscription(51-51)PaymentIntent(52-52)packages/templates/hono/src/lib/stripe.ts (6)
validatedEnv(40-40)getStripe(43-48)Product(50-50)Customer(51-51)Subscription(52-52)PaymentIntent(53-53)packages/templates/fastify/src/lib/stripe.ts (5)
getStripe(5-23)Product(25-25)Customer(26-26)Subscription(27-27)PaymentIntent(28-28)
packages/templates/hono/src/lib/stripe.ts (7)
packages/templates/express/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/express/src/lib/stripe.ts (2)
validatedEnv(40-40)getStripe(43-48)packages/templates/fastify/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/hono/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/nextjs/lib/dodopayments.ts (1)
validatedEnv(42-42)packages/templates/nextjs/lib/stripe.ts (2)
validatedEnv(40-40)getStripe(43-48)packages/templates/fastify/src/lib/stripe.ts (1)
getStripe(5-23)
packages/templates/nextjs/lib/dodopayments.ts (3)
packages/templates/express/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/fastify/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/hono/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)
packages/templates/express/src/lib/dodopayments.ts (4)
packages/templates/express/src/lib/stripe.ts (1)
validatedEnv(40-40)packages/templates/fastify/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/hono/src/lib/dodopayments.ts (2)
validatedEnv(40-40)getDodoPaymentsClient(44-53)packages/templates/nextjs/lib/dodopayments.ts (2)
validatedEnv(42-42)getDodoPaymentsClient(46-55)
packages/templates/express/src/lib/stripe.ts (7)
packages/templates/express/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/fastify/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/hono/src/lib/dodopayments.ts (1)
validatedEnv(40-40)packages/templates/hono/src/lib/stripe.ts (2)
validatedEnv(40-40)getStripe(43-48)packages/templates/nextjs/lib/dodopayments.ts (1)
validatedEnv(42-42)packages/templates/nextjs/lib/stripe.ts (2)
validatedEnv(40-40)getStripe(43-48)packages/templates/fastify/src/lib/stripe.ts (1)
getStripe(5-23)
🪛 dotenv-linter (4.0.0)
packages/templates/hono/.env.example
[warning] 12-12: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
[warning] 12-12: [UnorderedKey] The BUN_ENV key should go before the PORT key
(UnorderedKey)
packages/templates/express/.env.example
[warning] 12-12: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
[warning] 12-12: [UnorderedKey] The NODE_ENV key should go before the PORT key
(UnorderedKey)
packages/templates/nextjs/.env.example
[warning] 8-8: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
| import { z } from 'zod' | ||
|
|
||
| type Product = DodoPayments.Product; | ||
|
|
||
| const dodoPaymentsEnvSchema = z.object({ | ||
| DODO_PAYMENTS_API_KEY: z.string().min(1, 'DODO_PAYMENTS_API_KEY is required'), | ||
| DODO_PAYMENTS_ENVIRONMENT: z.enum(['live_mode', 'test_mode'], { | ||
| errorMap: () => ({ message: 'DODO_PAYMENTS_ENVIRONMENT must be either "live_mode" or "test_mode"' }) | ||
| }), | ||
| DODO_PAYMENTS_WEBHOOK_KEY: z.string().min(1, 'DODO_PAYMENTS_WEBHOOK_KEY is required'), | ||
| }) | ||
|
|
||
| // Validate environment variables at module load time (fails fast!) | ||
| function validateDodoPaymentsEnv() { | ||
| const result = dodoPaymentsEnvSchema.safeParse(process.env) | ||
|
|
||
| if (!result.success) { | ||
| const errors = result.error.errors.map(err => ` - ${err.path.join('.')}: ${err.message}`).join('\n') | ||
| throw new Error(`DodoPayments environment validation failed: ${errors} | ||
| Please check: | ||
| 1. Your .env.local file exists in the project root | ||
| 2. All required variables are set correctly | ||
| 3. You've restarted your development server | ||
| 4. No extra quotes or spaces in the .env.local file | ||
| Required variables: | ||
| - DODO_PAYMENTS_API_KEY: Your DodoPayments API key | ||
| - DODO_PAYMENTS_ENVIRONMENT: Either "live_mode" or "test_mode" | ||
| - DODO_PAYMENTS_WEBHOOK_KEY: Your DodoPayments webhook secret key | ||
| `) | ||
| } | ||
|
|
||
| return result.data | ||
| } | ||
|
|
||
| // Validate once at module load | ||
| const validatedEnv = validateDodoPaymentsEnv() | ||
|
|
||
| // Export for use in webhook handlers | ||
| export { validatedEnv } |
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.
🧩 Analysis chain
Env validation is solid; verify this module stays server-only in Next.js
The zod schema + safeParse(process.env) + detailed error message give clear, early feedback when DodoPayments env is misconfigured, and wiring getDodoPaymentsClient through validatedEnv is consistent with the rest of the PR.
One thing to double‑check: this file also exports purely client-safe helpers (getProducts, getCustomer, etc.). If any client component imports them from "@/lib/dodopayments", the module-level validation will run in the browser build, where process.env.DODO_PAYMENTS_* are typically unavailable, and you’ll throw before rendering.
If those helpers are (or might be) used from client components, consider either:
- Moving the env validation +
getDodoPaymentsClientinto a server-only module (e.g.lib/server/dodopayments), and re-exporting only fetch helpers from the client-facing module, or - Lazily validating only when
getDodoPaymentsClientis actually called, in a server-only path.
To verify current usage, you can run:
Also applies to: 49-50
🏁 Script executed:
#!/bin/bash
# Find client components (or any files) importing the Next.js DodoPayments lib
rg -n "from ['\"]@/lib/dodopayments['\"]" packages/templates/nextjs -C3 || trueLength of output: 3880
---
🏁 Script executed:
```shell
#!/bin/bash
# Check what useBilling.ts imports from dodopayments
sed -n '11,14p' packages/templates/nextjs/hooks/dodopayments/useBilling.ts
# Also check full exports from dodopayments.ts to see what's available
rg -n "^export" packages/templates/nextjs/lib/dodopayments.ts
Length of output: 503
Module-level validation throws in browser; move server code to separate module
Verification confirms the issue: packages/templates/nextjs/hooks/dodopayments/useBilling.ts (a client hook) imports createCustomer, updateCustomer, and checkout from @/lib/dodopayments. When this module loads in the browser bundle, the module-level validation at line 37 (const validatedEnv = validateDodoPaymentsEnv()) executes immediately and throws because process.env.DODO_PAYMENTS_* are not available in the browser.
Split the module:
lib/server/dodopayments.ts: MovevalidateDodoPaymentsEnv(),validatedEnv, andgetDodoPaymentsClient().lib/dodopayments.ts: Re-export only the client-safe fetch helpers (getProducts,getCustomer,createCustomer,updateCustomer,checkout, etc.).
This prevents the validation from executing in client bundles while keeping API routes able to import everything from the server module.
|
@thepushkaraj can you review this? |
thepushkaraj
left a 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.
Hey @abhinav-anshul - Thanks for the PR!
I found a few issues that need to be addressed:
1. In Zod v4, enum parameters don't support errorMap, it only accept the error field

2. Property errors doesn't exist on zod error type, should be issues

3. The NestJS integration hasn’t been updated with this new validation change. Could you please update that as well to keep consistency across all frameworks?
Let me know if you need any help!
|
@thepushkaraj I had a review of this, there seems to be an underlying issue with the Zod type here. The installed version of Zod is as however this package is pulling Zod ts type from A better solution for this would be to upgrade the helper packges with zodv4 or downgrade the zod to v3 here. Let me know your thoughts cc - @aagarwal1012 |
|
@abhinav-anshul I found that only one dependency
|
|
Hey @abhinav-anshul, thanks again for digging into this, really appreciate the effort on tightening env validation across the templates. Given the follow‑up findings:
It’s probably cleaner to tackle these in a fresh PR instead of layering more changes on this one. Lemme know if you need any help. |

Changes
DODO_PAYMENTS_API_KEY,STRIPE_API_KEY, and webhook secrets at startup.env.examplefiles with proper documentationTemplates Updated
Benefits
Summary by CodeRabbit
Refactor
Chores
✏️ Tip: You can customize this high-level summary in your review settings.