-
Notifications
You must be signed in to change notification settings - Fork 106
Nestjs cli support for dodopayments and stripe #313
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
…t, customer, products, subscriptions, payments, and webhook handling
…kout, customer, payments, products, subscriptions, and webhooks - Implemented CheckoutController for creating Stripe checkout sessions. - Added CustomerController for managing customer data. - Created PaymentsController for retrieving payment intents. - Developed ProductsController for fetching product information. - Introduced SubscriptionsController for handling subscription data. - Added WebhookController for processing Stripe webhooks. - Configured TypeScript settings in tsconfig.json. - Updated registry.json to include new Stripe template files.
- Updated package.json to include NestJS and Stripe dependencies. - Created a new template for NestJS Stripe integration in public/tr/nestjs-stripe.json. - Added controllers for handling products, customers, subscriptions, payments, and checkout sessions. - Implemented webhook handling for Stripe events. - Included example environment variables in .env.example for configuration.
…-level config files
|
@vedantlavale is attempting to deploy a commit to the Dodo Payments Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughAdds NestJS support across CLI, templates, and docs: framework detection, matrix entries, file-placement logic, package deps, full NestJS templates for DodoPayments and Stripe (clients, modules, controllers, webhooks, tsconfig, env), registry entries, and docs updates. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI
participant Detect as detectFramework()
participant Matrix
participant Registry as Template Registry
participant FS as File placement
User->>CLI: run `init`
CLI->>Detect: detectFramework()
alt NestJS detected
Detect->>Detect: check @nestjs deps, nest-cli.json, nest scripts
Detect-->>CLI: "nestjs"
else other framework
Detect-->>CLI: other framework
end
CLI->>Matrix: validate framework + provider
Matrix-->>CLI: validation result
CLI->>Registry: load nestjs-dodopayments / nestjs-stripe
Registry-->>CLI: template files
CLI->>FS: determine target paths
alt framework in (nestjs, express, fastify, hono)
FS-->>CLI: place files under `src/` (except root configs)
else
FS-->>CLI: place files at project root
end
CLI-->>User: project scaffolded
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 18
🧹 Nitpick comments (13)
packages/templates/nestjs/tsconfig.json (1)
15-19: Consider enabling strict type checking for better type safety.Multiple strict TypeScript checks are disabled (strictNullChecks, noImplicitAny, strictBindCallApply, strictFunctionTypes, noFallthroughCasesInSwitch). While this provides flexibility for templates, enabling these checks would improve type safety and catch potential bugs earlier.
Consider setting these to
truefor production-ready templates:- "strictNullChecks": false, - "noImplicitAny": false, - "strictBindCallApply": false, - "strictFunctionTypes": false, - "noFallthroughCasesInSwitch": false, + "strictNullChecks": true, + "noImplicitAny": true, + "strictBindCallApply": true, + "strictFunctionTypes": true, + "noFallthroughCasesInSwitch": true,packages/templates/nestjs/src/modules/dodopayments/dodopayments.module.ts (1)
19-19: Consider class name casing for readability.Rename DodopaymentsModule → DodoPaymentsModule to match common casing and the lib name.
packages/templates/nestjs/src/lib/dodopayments.ts (1)
7-9: Validate and normalize env values; optionally default to test_mode.Trim envs and default environment to "test_mode" in dev. Also, confirm allowed values ("live_mode" | "test_mode") against the SDK docs.
Apply this minimal refactor:
- const token = process.env.DODO_PAYMENTS_API_KEY - const environment = process.env.DODO_PAYMENTS_ENVIRONMENT as "live_mode" | "test_mode" + const token = process.env.DODO_PAYMENTS_API_KEY?.trim() + const env = process.env.DODO_PAYMENTS_ENVIRONMENT?.trim() + const environment: "live_mode" | "test_mode" = + env === "live_mode" ? "live_mode" : "test_mode" // default for local/dev @@ - if (!environment || (environment !== "live_mode" && environment !== "test_mode")) { - throw new Error('DODO_PAYMENTS_ENVIRONMENT must be either "live_mode" or "test_mode"') - } + // If you prefer fail-fast instead of defaulting, keep the explicit check above.Also applies to: 22-24
packages/templates/nestjs/src/modules/dodopayments/subscriptions.controller.ts (1)
24-47: Add parseInt radix and NaN validation for consistency.Line 36 uses
parseInt(limit)without a radix parameter and lacks NaN validation. This is inconsistent with the Stripe implementation (see packages/templates/nestjs/src/modules/stripe/subscriptions.controller.ts, lines 46-47) which usesparseInt(limit, 10)with proper NaN checking.Additionally, the error handling in
getSubscriptionsList(lines 44-47) doesn't check forHttpExceptionbefore rethrowing, whilegetSubscriptiondoes (lines 17-18). This inconsistency could mask validation errors.Apply this diff:
if (limit) { - params.limit = parseInt(limit); + const parsed = parseInt(limit, 10); + if (!isNaN(parsed)) params.limit = parsed; } if (starting_after) { params.starting_after = starting_after; } const subscriptions = await getDodoPaymentsClient().subscriptions.list(params); return subscriptions; } catch (error) { console.error('Error fetching subscriptions list:', error); + if (error instanceof HttpException) { + throw error; + } throw new HttpException('Internal server error', HttpStatus.INTERNAL_SERVER_ERROR); }packages/templates/nestjs/src/modules/stripe/products.controller.ts (1)
9-33: Add HttpException check for consistency.The
getProductsendpoint's error handler (lines 27-33) doesn't check if the error is anHttpExceptionbefore rethrowing, while thegetProductendpoint does (lines 47-49). This inconsistency means validation errors from the API might not propagate correctly in the list endpoint.Apply this diff:
const products = await this.stripe.products.list(params); return products.data; // this returns only product array } catch (error) { console.error('Error fetching products:', error); + if (error instanceof HttpException) { + throw error; + } throw new HttpException( { error: 'Internal server error', details: (error as Error).message }, HttpStatus.INTERNAL_SERVER_ERROR ); }packages/templates/nestjs/src/modules/dodopayments/products.controller.ts (1)
6-26: Add parseInt radix, NaN validation, and HttpException check.Similar to the subscriptions controller, this endpoint has several issues:
- Line 14:
parseInt(limit)is missing the radix parameter and NaN validation- Lines 22-25: Missing
HttpExceptioncheck in the error handler, inconsistent withgetProduct(lines 39-40)For reference, the Stripe products controller (packages/templates/nestjs/src/modules/stripe/products.controller.ts) implements this correctly with
parseInt(limit, 10)and NaN checking.Apply this diff:
const params: any = {}; if (limit) { - params.limit = parseInt(limit); + const parsed = parseInt(limit, 10); + if (!isNaN(parsed)) params.limit = parsed; } if (starting_after) { params.starting_after = starting_after; } const products = await getDodoPaymentsClient().products.list(params); return products; } catch (error) { console.error('Error fetching products:', error); + if (error instanceof HttpException) { + throw error; + } throw new HttpException('Internal server error', HttpStatus.INTERNAL_SERVER_ERROR); }packages/templates/nestjs/src/modules/dodopayments/checkout.controller.ts (2)
63-69: Avoid type assertions with 'as any' - may hide type mismatches.Lines 64-66 use
as anyto bypass type checking when passing validated data to the Dodopayments client. This suppresses TypeScript's ability to catch potential type mismatches between your Zod schemas and the actual Dodopayments API types.Consider one of these approaches:
- If Dodopayments SDK exports proper types: Import and use them instead of
any:import type { CheckoutSessionCreateParams } from 'dodopayments'; const session = await getDodoPaymentsClient().checkoutSessions.create({ product_cart: productCart, customer: customer, billing_address: billing_address, return_url: return_url, metadata: customMetadata, } as CheckoutSessionCreateParams);
- If types are unavailable: Document the gap and verify at runtime or with integration tests.
15-20: Unused field in schema - clarify intent.Line 19 defines
create_new_customeras an optional boolean innewCustomerSchema, but this field is never used in the checkout logic (lines 61-69). If the Dodopayments API requires this field, ensure it's passed through. Otherwise, remove it to avoid confusion.const newCustomerSchema = z.object({ email: z.string().email("Invalid email format"), name: z.string().min(1, "Name is required"), phone_number: z.string().optional().nullable(), - create_new_customer: z.boolean().optional(), });packages/templates/nestjs/src/modules/dodopayments/payments.controller.ts (1)
24-48: Add parseInt radix, NaN validation, and HttpException check.Same issues as the other Dodopayments list endpoints:
- Line 36:
parseInt(limit)lacks radix parameter and NaN validation- Lines 44-47: Missing
HttpExceptioncheck before rethrowing, inconsistent withgetPayment(lines 17-18)This pattern appears across all Dodopayments list endpoints (subscriptions, products, payments). Consider standardizing the pagination parameter handling.
Apply this diff:
if (limit) { - params.limit = parseInt(limit); + const parsed = parseInt(limit, 10); + if (!isNaN(parsed)) params.limit = parsed; } if (starting_after) { params.starting_after = starting_after; } const payments = await getDodoPaymentsClient().payments.list(params); return payments; } catch (error) { console.error('Error fetching payments list:', error); + if (error instanceof HttpException) { + throw error; + } throw new HttpException('Internal server error', HttpStatus.INTERNAL_SERVER_ERROR); }packages/templates/nestjs/src/modules/stripe/customer.controller.ts (1)
25-41: Consider more specific return types.All methods return
Promise<any>, which loses type safety. Consider using Stripe's types for better developer experience:
getCustomer:Promise<Stripe.Customer | Stripe.DeletedCustomer>createCustomer:Promise<Stripe.Customer>updateCustomer:Promise<Stripe.Customer>getCustomerSubscriptions:Promise<Stripe.Subscription[]>getCustomerPayments:Promise<Stripe.PaymentIntent[]>Also applies to: 43-74, 76-111, 113-155
packages/templates/nestjs/src/modules/stripe/checkout.controller.ts (2)
15-20: Remove unused schema field.The
create_new_customerfield innewCustomerSchemais defined but never used in the implementation. This could confuse API consumers.const newCustomerSchema = z.object({ email: z.string().email("Invalid email format"), name: z.string().min(1, "Name is required"), phone_number: z.string().optional().nullable(), - create_new_customer: z.boolean().optional(), });
58-67: Simplify null coalescing for required fields.Lines 60-61 use
?? ""forname, but these fields are already required by the schema and cannot be undefined after validation.const stripeCustomer = await this.stripe.customers.create({ - email: customer.email ?? "", - name: customer.name ?? "", + email: customer.email, + name: customer.name, phone: customer.phone_number ?? "", });packages/templates/nestjs/src/lib/stripe.ts (1)
28-122: Preserve error context in error handling.All exported functions catch errors, log them, and throw generic messages. This loses valuable context from the original Stripe API errors (error codes, request IDs, detailed messages) that would help with debugging.
Consider preserving the original error or wrapping it:
export async function getProducts(): Promise<Product[]> { try { const { data } = await stripe.products.list({ limit: 100 }); return data; } catch (error) { console.error('Error fetching products', error); - throw new Error('Failed to fetch products'); + if (error instanceof Error) { + error.message = `Failed to fetch products: ${error.message}`; + throw error; + } + throw new Error('Failed to fetch products'); } }This pattern retains stack traces and original error details while adding context.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (27)
content/docs/cli.mdx(7 hunks)package.json(5 hunks)packages/cli/src/commands/init.ts(1 hunks)packages/cli/src/config/matrix.ts(2 hunks)packages/cli/src/scripts/add-files.ts(3 hunks)packages/cli/src/scripts/detect-framework.ts(2 hunks)packages/templates/nestjs/.env.example(1 hunks)packages/templates/nestjs/src/lib/dodopayments.ts(1 hunks)packages/templates/nestjs/src/lib/stripe.ts(1 hunks)packages/templates/nestjs/src/modules/dodopayments/checkout.controller.ts(1 hunks)packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts(1 hunks)packages/templates/nestjs/src/modules/dodopayments/dodopayments.module.ts(1 hunks)packages/templates/nestjs/src/modules/dodopayments/payments.controller.ts(1 hunks)packages/templates/nestjs/src/modules/dodopayments/products.controller.ts(1 hunks)packages/templates/nestjs/src/modules/dodopayments/subscriptions.controller.ts(1 hunks)packages/templates/nestjs/src/modules/dodopayments/webhook.controller.ts(1 hunks)packages/templates/nestjs/src/modules/stripe/checkout.controller.ts(1 hunks)packages/templates/nestjs/src/modules/stripe/customer.controller.ts(1 hunks)packages/templates/nestjs/src/modules/stripe/payments.controller.ts(1 hunks)packages/templates/nestjs/src/modules/stripe/products.controller.ts(1 hunks)packages/templates/nestjs/src/modules/stripe/stripe.module.ts(1 hunks)packages/templates/nestjs/src/modules/stripe/subscriptions.controller.ts(1 hunks)packages/templates/nestjs/src/modules/stripe/webhook.controller.ts(1 hunks)packages/templates/nestjs/tsconfig.json(1 hunks)packages/templates/registry.json(1 hunks)public/tr/nestjs-dodopayments.json(1 hunks)public/tr/nestjs-stripe.json(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (13)
packages/templates/nestjs/src/modules/dodopayments/subscriptions.controller.ts (3)
packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts (1)
Controller(20-139)packages/templates/nestjs/src/modules/dodopayments/payments.controller.ts (1)
Controller(4-49)packages/templates/nestjs/src/modules/dodopayments/webhook.controller.ts (1)
Controller(6-73)
packages/templates/nestjs/src/modules/dodopayments/checkout.controller.ts (2)
packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts (1)
Controller(20-139)packages/templates/nestjs/src/modules/stripe/checkout.controller.ts (1)
Controller(34-97)
packages/templates/nestjs/src/modules/dodopayments/products.controller.ts (4)
packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts (1)
Controller(20-139)packages/templates/nestjs/src/modules/dodopayments/payments.controller.ts (1)
Controller(4-49)packages/templates/nestjs/src/modules/dodopayments/subscriptions.controller.ts (1)
Controller(4-49)packages/templates/nestjs/src/modules/stripe/products.controller.ts (1)
Controller(5-56)
packages/templates/nestjs/src/modules/stripe/webhook.controller.ts (1)
packages/templates/nestjs/src/lib/stripe.ts (3)
getStripe(4-15)Subscription(24-24)PaymentIntent(25-25)
packages/templates/nestjs/src/modules/stripe/subscriptions.controller.ts (3)
packages/templates/nestjs/src/modules/stripe/customer.controller.ts (1)
Controller(21-156)packages/templates/nestjs/src/modules/stripe/products.controller.ts (1)
Controller(5-56)packages/templates/nestjs/src/lib/stripe.ts (1)
getStripe(4-15)
packages/templates/nestjs/src/modules/dodopayments/webhook.controller.ts (3)
packages/templates/nestjs/src/modules/dodopayments/payments.controller.ts (1)
Controller(4-49)packages/templates/nestjs/src/modules/dodopayments/subscriptions.controller.ts (1)
Controller(4-49)packages/templates/nestjs/src/modules/stripe/webhook.controller.ts (1)
Controller(6-68)
packages/templates/nestjs/src/modules/stripe/products.controller.ts (4)
packages/templates/nestjs/src/modules/stripe/customer.controller.ts (1)
Controller(21-156)packages/templates/nestjs/src/modules/stripe/payments.controller.ts (1)
Controller(4-51)packages/templates/nestjs/src/modules/stripe/subscriptions.controller.ts (1)
Controller(5-67)packages/templates/nestjs/src/lib/stripe.ts (1)
getStripe(4-15)
packages/templates/nestjs/src/modules/stripe/payments.controller.ts (3)
packages/templates/nestjs/src/modules/stripe/customer.controller.ts (1)
Controller(21-156)packages/templates/nestjs/src/modules/stripe/subscriptions.controller.ts (1)
Controller(5-67)packages/templates/nestjs/src/lib/stripe.ts (1)
getStripe(4-15)
packages/templates/nestjs/src/modules/stripe/customer.controller.ts (6)
packages/templates/nestjs/src/modules/stripe/checkout.controller.ts (1)
Controller(34-97)packages/templates/nestjs/src/modules/stripe/payments.controller.ts (1)
Controller(4-51)packages/templates/nestjs/src/modules/stripe/products.controller.ts (1)
Controller(5-56)packages/templates/nestjs/src/modules/stripe/subscriptions.controller.ts (1)
Controller(5-67)packages/templates/nestjs/src/modules/stripe/webhook.controller.ts (1)
Controller(6-68)packages/templates/nestjs/src/lib/stripe.ts (1)
getStripe(4-15)
packages/templates/nestjs/src/lib/stripe.ts (2)
packages/templates/nestjs/src/modules/stripe/products.controller.ts (2)
getProducts(10-34)getProduct(37-55)packages/templates/nestjs/src/modules/stripe/customer.controller.ts (5)
getCustomer(26-41)createCustomer(44-74)updateCustomer(77-111)getCustomerSubscriptions(114-133)getCustomerPayments(136-155)
packages/templates/nestjs/src/modules/dodopayments/payments.controller.ts (2)
packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts (1)
Controller(20-139)packages/templates/nestjs/src/modules/stripe/payments.controller.ts (1)
Controller(4-51)
packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts (4)
packages/templates/nestjs/src/modules/dodopayments/checkout.controller.ts (1)
Controller(42-80)packages/templates/nestjs/src/modules/dodopayments/payments.controller.ts (1)
Controller(4-49)packages/templates/nestjs/src/modules/dodopayments/subscriptions.controller.ts (1)
Controller(4-49)packages/templates/nestjs/src/modules/stripe/customer.controller.ts (1)
Controller(21-156)
packages/templates/nestjs/src/modules/stripe/checkout.controller.ts (3)
packages/templates/nestjs/src/modules/dodopayments/checkout.controller.ts (1)
Controller(42-80)packages/templates/nestjs/src/modules/stripe/customer.controller.ts (1)
Controller(21-156)packages/templates/nestjs/src/lib/stripe.ts (1)
getStripe(4-15)
🪛 Biome (2.1.2)
packages/templates/nestjs/src/modules/dodopayments/webhook.controller.ts
[error] 26-26: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 50-50: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
🪛 dotenv-linter (3.3.0)
packages/templates/nestjs/.env.example
[warning] 8-8: [UnorderedKey] The NODE_ENV key should go before the PORT key
(UnorderedKey)
[warning] 10-10: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
[warning] 11-11: [DuplicatedKey] The STRIPE_SECRET_KEY key is duplicated
(DuplicatedKey)
🔇 Additional comments (17)
packages/cli/src/config/matrix.ts (1)
1-21: LGTM! NestJS support properly integrated.The changes consistently add "nestjs" across the type definition, supported frameworks array, and valid combinations matrix for both Dodopayments and Stripe providers.
packages/cli/src/commands/init.ts (1)
14-15: LGTM! Framework label added correctly.The NestJS display name is properly added to the framework names mapping.
package.json (2)
21-23: LGTM! NestJS dependencies added correctly.The @nestjs packages are at the latest stable version (11.1.6) and are necessary for the NestJS template support.
67-67: LGTM! Required NestJS peer dependencies added.
reflect-metadataandrxjsare essential peer dependencies for NestJS decorators and reactive programming support.Also applies to: 72-72
packages/templates/nestjs/tsconfig.json (1)
1-14: LGTM! NestJS-specific compiler options configured correctly.The decorator metadata, experimental decorators, and CommonJS module settings are properly configured for NestJS applications.
Also applies to: 20-27
packages/cli/src/scripts/detect-framework.ts (2)
39-52: LGTM! Comprehensive NestJS detection logic.The detection checks multiple indicators:
- NestJS core dependencies (@nestjs/core, @nestjs/common, @nestjs/platform-express)
- NestJS CLI configuration file (nest-cli.json)
- Build/dev scripts referencing "nest"
The logic correctly guards against undefined
pkg.scriptsand uses optional chaining for script checks.
5-5: LGTM! Return type properly extended.The function return type correctly includes "nestjs" alongside other supported frameworks.
packages/cli/src/scripts/add-files.ts (2)
43-43: LGTM! Registry base URL configured for local development.The default registry base now uses a local file URL, which is appropriate for development and testing. The fallback to environment variable allows production configuration.
103-122: LGTM! Framework-aware file placement implemented correctly.The logic properly:
- Places source files under
src/for backend frameworks (nestjs, express, fastify, hono)- Keeps root-level configuration files (
.env*,tsconfig.json,package.json) at the project root- Maintains compatibility with frameworks that don't use the src/ convention
content/docs/cli.mdx (4)
60-60: LGTM! Framework support table and descriptions updated.NestJS is correctly added to the supported frameworks table and referenced in descriptive text throughout the documentation.
Also applies to: 87-87, 102-102
174-190: LGTM! File structure documentation added for NestJS.The generated file structure for NestJS templates clearly shows the modules/controllers organization pattern, which is consistent with NestJS conventions (modules/dodopayments and modules/stripe with respective controllers).
Also applies to: 278-294
492-528: LGTM! Clear NestJS integration instructions provided.The setup instructions properly guide users to:
- Import and register the generated modules (DodoPaymentsModule, StripeModule)
- Configure environment variables
- Integrate with their NestJS application
695-707: LGTM! Dependencies documented correctly for NestJS.The required dependencies are properly listed for both DodoPayments and Stripe integrations with NestJS, including the necessary @nestjs/common and @nestjs/core packages.
Also applies to: 752-764
packages/templates/nestjs/.env.example (1)
1-9: LGTM! DodoPayments and server configuration defined correctly.The environment variables for DodoPayments API integration and server configuration are properly structured.
packages/templates/nestjs/src/modules/dodopayments/dodopayments.module.ts (1)
9-18: Module wiring looks good.Controllers are registered cleanly; no providers needed here.
packages/templates/nestjs/src/modules/stripe/stripe.module.ts (1)
9-18: LGTM.Clean controller registration; aligns with Nest patterns.
packages/templates/nestjs/src/modules/stripe/subscriptions.controller.ts (1)
1-67: LGTM! Well-implemented controller with consistent patterns.The implementation demonstrates good practices:
- Proper input validation with meaningful error messages
- Correct
parseInt(limit, 10)with NaN checking- Consistent
HttpExceptionhandling across both endpoints- Appropriate return values (returns only
subscriptions.dataarray for the list endpoint)
| "shiki": "^3.12.2", | ||
| "sonner": "^2.0.7", | ||
| "standardwebhooks": "^1.0.0", | ||
| "stripe": "^19.1.0", |
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
Verify the Stripe prerelease version selection.
The specified version ^19.1.0 corresponds to a prerelease/beta build. Based on learnings, the current stable Stripe SDK version is v18.5.0, while v19.x contains preview features for upcoming API versions.
For production use, consider using the stable v18.x release unless you specifically require preview features and accept prerelease instability. Based on learnings.
🌐 Web query:
What is the current stable version of stripe-node SDK and is 19.1.0 a stable release?
💡 Result:
As of Oct 20, 2025 the stable npm "stripe" package version is 18.5.0. [1]
Version 19.1.0 is not published as the stable "latest" on npm — references to v19.x on GitHub are pre-release/preview builds (alpha/beta/private-preview), so 19.1.0 should be treated as a non-stable preview release unless Stripe publishes it to the npm "latest" tag. [1][2]
Sources:
- npm package page (stripe) — shows Version 18.5.0 as latest. [1]
- stripe-node GitHub / releases (v19 entries are pre-release/preview). [2]
Use stable Stripe SDK version 18.5.0 for production instead of prerelease 19.1.0.
Version 19.1.0 is not published as the stable "latest" on npm and should be treated as a non-stable preview release. The current stable version is 18.5.0. Update package.json to use ^18.5.0 unless your application specifically requires preview features and accepts prerelease instability.
🤖 Prompt for AI Agents
In package.json around line 76, the Stripe dependency is pinned to prerelease
"stripe": "^19.1.0"; change it to the stable release "^18.5.0" to avoid using a
non-stable preview SDK, then run your package manager (npm/yarn/pnpm) to update
node_modules and regenerate the lockfile
(package-lock.json/yarn.lock/pnpm-lock.yaml).
| STRIPE_SECRET_KEY="your_secret_key_here" | ||
| STRIPE_SECRET_KEY=sk_test_12345... | ||
| STRIPE_WEBHOOK_SECRET=whsec_12345 |
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.
Fix duplicate STRIPE_SECRET_KEY and remove quotes.
The STRIPE_SECRET_KEY is defined twice (lines 10 and 11), and line 10 contains unnecessary quotes around the value. Remove the duplicate entry.
Apply this diff:
-STRIPE_SECRET_KEY="your_secret_key_here"
STRIPE_SECRET_KEY=sk_test_12345...
STRIPE_WEBHOOK_SECRET=whsec_12345📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| STRIPE_SECRET_KEY="your_secret_key_here" | |
| STRIPE_SECRET_KEY=sk_test_12345... | |
| STRIPE_WEBHOOK_SECRET=whsec_12345 | |
| STRIPE_SECRET_KEY=sk_test_12345... | |
| STRIPE_WEBHOOK_SECRET=whsec_12345 |
🧰 Tools
🪛 dotenv-linter (3.3.0)
[warning] 10-10: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
[warning] 11-11: [DuplicatedKey] The STRIPE_SECRET_KEY key is duplicated
(DuplicatedKey)
🤖 Prompt for AI Agents
In packages/templates/nestjs/.env.example around lines 10 to 12, there is a
duplicate STRIPE_SECRET_KEY and the first occurrence includes unnecessary
quotes; remove the duplicated entry and keep a single unquoted STRIPE_SECRET_KEY
line (e.g. STRIPE_SECRET_KEY=sk_test_12345...) and ensure STRIPE_WEBHOOK_SECRET
remains unchanged.
packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts
Outdated
Show resolved
Hide resolved
| @Post() | ||
| async handleWebhook(@Req() req: Request, @Res() res: Response): Promise<any> { | ||
| const sig = req.headers['stripe-signature'] as string | undefined; | ||
| if (!sig) { | ||
| return res.status(400).json({ error: 'Missing Stripe signature' }); | ||
| } | ||
|
|
||
| const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!; | ||
| let event: Stripe.Event; | ||
|
|
||
| try { | ||
| event = this.stripe.webhooks.constructEvent(req.body, sig, webhookSecret); | ||
| } catch (err) { | ||
| console.error('Webhook signature verification failed:', err); | ||
| return res.status(400).json({ error: 'Webhook verification failed' }); | ||
| } |
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
Ensure raw body is available for webhook verification.
Stripe webhook signature verification (line 21) requires the raw request body as a string or Buffer. NestJS with Express typically parses JSON bodies by default, which would break signature verification.
Ensure your NestJS application is configured to preserve the raw body for webhook endpoints, typically by using a custom middleware or the rawBody option in body-parser configuration.
🏁 Script executed:
#!/bin/bash
# Check if there's any NestJS configuration for raw body handling in webhook routes
# Search for raw body configuration in main.ts or app configuration
rg -n -C3 'rawBody|raw.*body|bodyParser.*raw' --type=ts
# Search for any middleware configuration for webhooks
rg -n -C3 'webhook.*middleware|middleware.*webhook' --type=ts
# Check if there's express-specific body parser config
rg -n -C3 'express\.json|bodyParser|urlencoded' --type=tsLength of output: 9393
🏁 Script executed:
#!/bin/bash
# Check for the specific Stripe webhook controller in NestJS template
fd -e ts -p '*stripe*webhook*' packages/templates/nestjs/
# List all webhook controllers in NestJS template to see structure
fd -e ts -p '*webhook*' packages/templates/nestjs/
# Check the main.ts or app bootstrap file for NestJS Stripe template
fd -e ts -n 'main.ts' packages/templates/nestjs/
# Search for any references to Stripe in NestJS template configuration
rg -n -C2 'Stripe' packages/templates/nestjs/ --type=ts | head -50Length of output: 525
---
🏁 Script executed:
```shell
#!/bin/bash
# Explore repository structure
ls -la packages/templates/ 2>/dev/null || echo "packages/templates does not exist"
# Search for any stripe webhook files in entire repo
find . -name "*stripe*webhook*" -type f 2>/dev/null | head -20
# Search for nestjs references
find . -name "*nestjs*" -type d 2>/dev/null | head -10
# Search for any file mentioning Stripe and webhook
rg -l 'Stripe.*webhook|webhook.*Stripe' --type=ts 2>/dev/null | head -10
Length of output: 65
---
🏁 Script executed:
```shell
#!/bin/bash
# Find Stripe webhook controller in correct path
find ./git/packages/templates/nestjs -name "*stripe*webhook*" -type f 2>/dev/null
# List all webhook controllers
find ./git/packages/templates/nestjs -name "*webhook*" -type f 2>/dev/null
# Check for main.ts in NestJS template
find ./git/packages/templates/nestjs -name "main.ts" -type f 2>/dev/null
# Search for Stripe references in NestJS template
rg -n 'Stripe' ./git/packages/templates/nestjs --type=ts | head -30
# Look at actual file structure
ls -la ./git/packages/templates/nestjs/src/modules/
Length of output: 4013
---
🏁 Script executed:
```shell
#!/bin/bash
# Read the Stripe webhook controller file
cat ./git/packages/templates/nestjs/src/modules/stripe/webhook.controller.ts
# Check for any middleware related to raw body in the module
cat ./git/packages/templates/nestjs/src/modules/stripe/stripe.module.ts
# Check main.ts for any global body parser configuration
find ./git/packages/templates/nestjs -name "main.ts" -o -name "app.module.ts" | xargs cat 2>/dev/null
# Search for any bodyParser or express configuration
rg -n 'bodyParser|express\.json|express\.raw|rawBody' ./git/packages/templates/nestjs --type=ts
Length of output: 3277
Stripe webhook signature verification will fail—raw request body must be accessible.
Stripe's constructEvent() requires the raw request body (string/Buffer) to verify the signature. With default NestJS/Express configuration, the body is parsed into JSON before reaching the handler, breaking verification.
Configure your NestJS application to preserve the raw body for this endpoint. Common approaches:
- Use middleware to capture raw body before parsing (e.g., a guard with
bodyParser.raw({ type: 'application/json' })) - Or configure the body parser globally to use raw for webhook routes
- Reference the Express template implementation:
express.raw({ type: 'application/json' })on the webhook route
packages/templates/nestjs/src/modules/stripe/webhook.controller.ts
Outdated
Show resolved
Hide resolved
| { | ||
| "name": "nestjs-stripe", | ||
| "description": "Stripe template for NestJS", | ||
| "framework": "nestjs", | ||
| "files": [ | ||
| { | ||
| "path": "packages/templates/nestjs/tsconfig.json", | ||
| "content": "TypeScript configuration for NestJS", | ||
| "type": "template", | ||
| "target": "tsconfig.json" | ||
| }, | ||
| { | ||
| "path": "packages/templates/nestjs/src/lib/stripe.ts", | ||
| "content": "Stripe client setup for NestJS", | ||
| "type": "template", | ||
| "target": "lib/stripe.ts" | ||
| }, | ||
| { | ||
| "path": "packages/templates/nestjs/src/modules/stripe/stripe.module.ts", | ||
| "content": "Main Stripe module for NestJS", | ||
| "type": "template", | ||
| "target": "modules/stripe/stripe.module.ts" | ||
| }, | ||
| { | ||
| "path": "packages/templates/nestjs/src/modules/stripe/checkout.controller.ts", | ||
| "content": "Stripe checkout controller", | ||
| "type": "template", | ||
| "target": "modules/stripe/checkout.controller.ts" | ||
| }, | ||
| { | ||
| "path": "packages/templates/nestjs/src/modules/stripe/customer.controller.ts", | ||
| "content": "Stripe customer controller", | ||
| "type": "template", | ||
| "target": "modules/stripe/customer.controller.ts" | ||
| }, | ||
| { | ||
| "path": "packages/templates/nestjs/src/modules/stripe/payments.controller.ts", | ||
| "content": "Stripe payments controller", | ||
| "type": "template", | ||
| "target": "modules/stripe/payments.controller.ts" | ||
| }, | ||
| { | ||
| "path": "packages/templates/nestjs/src/modules/stripe/products.controller.ts", | ||
| "content": "Stripe product controller", | ||
| "type": "template", | ||
| "target": "modules/stripe/products.controller.ts" | ||
| }, | ||
| { | ||
| "path": "packages/templates/nestjs/src/modules/stripe/subscriptions.controller.ts", | ||
| "content": "Stripe subscription controller", | ||
| "type": "template", | ||
| "target": "modules/stripe/subscriptions.controller.ts" | ||
| }, | ||
| { | ||
| "path": "packages/templates/nestjs/src/modules/stripe/webhook.controller.ts", | ||
| "content": "Webhook handling controller for NestJS", | ||
| "type": "template", | ||
| "target": "modules/stripe/webhook.controller.ts" | ||
| }, | ||
| { | ||
| "path": "packages/templates/nestjs/.env.example", | ||
| "content": "Stripe .env.example for NestJS", | ||
| "type": "template", | ||
| "target": ".env.example" | ||
| } | ||
| ], | ||
| "dependencies": [ | ||
| "stripe", | ||
| "zod", | ||
| "@nestjs/common", | ||
| "@nestjs/core", | ||
| "@nestjs/platform-express", | ||
| "reflect-metadata", | ||
| "rxjs", | ||
| "@types/express" | ||
| ] | ||
| } |
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.
Add missing development dependencies to nestjs-stripe.
The nestjs-stripe template is missing development dependencies that are present in nestjs-dodopayments (lines 524-526). NestJS projects typically need @nestjs/cli, typescript, and ts-node for development and build processes.
Apply this diff:
"dependencies": [
"stripe",
"zod",
"@nestjs/common",
"@nestjs/core",
"@nestjs/platform-express",
"reflect-metadata",
"rxjs",
- "@types/express"
+ "@types/express",
+ "@nestjs/cli",
+ "typescript",
+ "ts-node"
]📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| { | |
| "name": "nestjs-stripe", | |
| "description": "Stripe template for NestJS", | |
| "framework": "nestjs", | |
| "files": [ | |
| { | |
| "path": "packages/templates/nestjs/tsconfig.json", | |
| "content": "TypeScript configuration for NestJS", | |
| "type": "template", | |
| "target": "tsconfig.json" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/lib/stripe.ts", | |
| "content": "Stripe client setup for NestJS", | |
| "type": "template", | |
| "target": "lib/stripe.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/stripe.module.ts", | |
| "content": "Main Stripe module for NestJS", | |
| "type": "template", | |
| "target": "modules/stripe/stripe.module.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/checkout.controller.ts", | |
| "content": "Stripe checkout controller", | |
| "type": "template", | |
| "target": "modules/stripe/checkout.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/customer.controller.ts", | |
| "content": "Stripe customer controller", | |
| "type": "template", | |
| "target": "modules/stripe/customer.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/payments.controller.ts", | |
| "content": "Stripe payments controller", | |
| "type": "template", | |
| "target": "modules/stripe/payments.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/products.controller.ts", | |
| "content": "Stripe product controller", | |
| "type": "template", | |
| "target": "modules/stripe/products.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/subscriptions.controller.ts", | |
| "content": "Stripe subscription controller", | |
| "type": "template", | |
| "target": "modules/stripe/subscriptions.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/webhook.controller.ts", | |
| "content": "Webhook handling controller for NestJS", | |
| "type": "template", | |
| "target": "modules/stripe/webhook.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/.env.example", | |
| "content": "Stripe .env.example for NestJS", | |
| "type": "template", | |
| "target": ".env.example" | |
| } | |
| ], | |
| "dependencies": [ | |
| "stripe", | |
| "zod", | |
| "@nestjs/common", | |
| "@nestjs/core", | |
| "@nestjs/platform-express", | |
| "reflect-metadata", | |
| "rxjs", | |
| "@types/express" | |
| ] | |
| } | |
| { | |
| "name": "nestjs-stripe", | |
| "description": "Stripe template for NestJS", | |
| "framework": "nestjs", | |
| "files": [ | |
| { | |
| "path": "packages/templates/nestjs/tsconfig.json", | |
| "content": "TypeScript configuration for NestJS", | |
| "type": "template", | |
| "target": "tsconfig.json" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/lib/stripe.ts", | |
| "content": "Stripe client setup for NestJS", | |
| "type": "template", | |
| "target": "lib/stripe.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/stripe.module.ts", | |
| "content": "Main Stripe module for NestJS", | |
| "type": "template", | |
| "target": "modules/stripe/stripe.module.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/checkout.controller.ts", | |
| "content": "Stripe checkout controller", | |
| "type": "template", | |
| "target": "modules/stripe/checkout.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/customer.controller.ts", | |
| "content": "Stripe customer controller", | |
| "type": "template", | |
| "target": "modules/stripe/customer.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/payments.controller.ts", | |
| "content": "Stripe payments controller", | |
| "type": "template", | |
| "target": "modules/stripe/payments.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/products.controller.ts", | |
| "content": "Stripe product controller", | |
| "type": "template", | |
| "target": "modules/stripe/products.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/subscriptions.controller.ts", | |
| "content": "Stripe subscription controller", | |
| "type": "template", | |
| "target": "modules/stripe/subscriptions.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/src/modules/stripe/webhook.controller.ts", | |
| "content": "Webhook handling controller for NestJS", | |
| "type": "template", | |
| "target": "modules/stripe/webhook.controller.ts" | |
| }, | |
| { | |
| "path": "packages/templates/nestjs/.env.example", | |
| "content": "Stripe .env.example for NestJS", | |
| "type": "template", | |
| "target": ".env.example" | |
| } | |
| ], | |
| "dependencies": [ | |
| "stripe", | |
| "zod", | |
| "@nestjs/common", | |
| "@nestjs/core", | |
| "@nestjs/platform-express", | |
| "reflect-metadata", | |
| "rxjs", | |
| "@types/express", | |
| "@nestjs/cli", | |
| "typescript", | |
| "ts-node" | |
| ] | |
| } |
🤖 Prompt for AI Agents
In packages/templates/registry.json around lines 529 to 605, the nestjs-stripe
template entry lacks development dependencies; add a devDependencies array
containing "@nestjs/cli", "typescript", and "ts-node" to the nestjs-stripe
object (mirroring nestjs-dodopayments) so the template includes necessary
tooling for development and build tasks.
| { | ||
| "target": ".env.example", | ||
| "type": "template", | ||
| "content": "# DodoPayments Configuration\nDODO_PAYMENTS_API_KEY=your_api_key_here\nDODO_PAYMENTS_ENVIRONMENT=test_mode\nDODO_PAYMENTS_WEBHOOK_KEY=your_webhook_key_here\n\n# Server Configuration\nPORT=3000\nNODE_ENV=development\n\nSTRIPE_SECRET_KEY=\"your_secret_key_here\"\nSTRIPE_SECRET_KEY=sk_test_12345...\nSTRIPE_WEBHOOK_SECRET=whsec_12345\n" | ||
| } |
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.
Remove Stripe configuration from Dodopayments template.
The .env.example content (line 54) includes duplicate STRIPE_SECRET_KEY entries and a STRIPE_WEBHOOK_SECRET, which don't belong in the Dodopayments template. This appears to be a copy-paste error from the Stripe template.
The .env.example should only contain Dodopayments-specific configuration:
- "content": "# DodoPayments Configuration\nDODO_PAYMENTS_API_KEY=your_api_key_here\nDODO_PAYMENTS_ENVIRONMENT=test_mode\nDODO_PAYMENTS_WEBHOOK_KEY=your_webhook_key_here\n\n# Server Configuration\nPORT=3000\nNODE_ENV=development\n\nSTRIPE_SECRET_KEY=\"your_secret_key_here\"\nSTRIPE_SECRET_KEY=sk_test_12345...\nSTRIPE_WEBHOOK_SECRET=whsec_12345\n"
+ "content": "# DodoPayments Configuration\nDODO_PAYMENTS_API_KEY=your_api_key_here\nDODO_PAYMENTS_ENVIRONMENT=test_mode\nDODO_PAYMENTS_WEBHOOK_KEY=your_webhook_key_here\n\n# Server Configuration\nPORT=3000\nNODE_ENV=development\n"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| { | |
| "target": ".env.example", | |
| "type": "template", | |
| "content": "# DodoPayments Configuration\nDODO_PAYMENTS_API_KEY=your_api_key_here\nDODO_PAYMENTS_ENVIRONMENT=test_mode\nDODO_PAYMENTS_WEBHOOK_KEY=your_webhook_key_here\n\n# Server Configuration\nPORT=3000\nNODE_ENV=development\n\nSTRIPE_SECRET_KEY=\"your_secret_key_here\"\nSTRIPE_SECRET_KEY=sk_test_12345...\nSTRIPE_WEBHOOK_SECRET=whsec_12345\n" | |
| } | |
| { | |
| "target": ".env.example", | |
| "type": "template", | |
| "content": "# DodoPayments Configuration\nDODO_PAYMENTS_API_KEY=your_api_key_here\nDODO_PAYMENTS_ENVIRONMENT=test_mode\nDODO_PAYMENTS_WEBHOOK_KEY=your_webhook_key_here\n\n# Server Configuration\nPORT=3000\nNODE_ENV=development\n" | |
| } |
🤖 Prompt for AI Agents
In public/tr/nestjs-dodopayments.json around lines 51 to 55, the .env.example
content contains stray Stripe configuration (duplicate STRIPE_SECRET_KEY entries
and STRIPE_WEBHOOK_SECRET) that must be removed; update the template to remove
all Stripe-related environment variables and duplicate lines so the file only
contains Dodopayments-specific keys (DODO_PAYMENTS_API_KEY,
DODO_PAYMENTS_ENVIRONMENT, DODO_PAYMENTS_WEBHOOK_KEY) plus the general server
config (PORT, NODE_ENV) and ensure formatting/newlines remain correct.
…dling and pagination support
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: 2
♻️ Duplicate comments (1)
packages/templates/nestjs/src/modules/dodopayments/webhook.controller.ts (1)
54-56: Avoid logging full subscription and payment objects.The code still logs complete objects which may contain PII. This was previously flagged but remains unaddressed.
Replace with minimal logging:
case "subscription.active": { const subscription = await getDodoPaymentsClient().subscriptions.retrieve(payload.data.subscription_id); - console.log("-------SUBSCRIPTION DATA START ---------") - console.log(subscription) - console.log("-------SUBSCRIPTION DATA END ---------") + console.log("Subscription active:", subscription.id, "customer:", subscription.customer_id); break; }case "payment.succeeded": { const paymentDataResp = await getDodoPaymentsClient().payments.retrieve(payload.data.payment_id) - console.log("-------PAYMENT DATA START ---------") - console.log(paymentDataResp) - console.log("-------PAYMENT DATA END ---------") + console.log("Payment succeeded:", paymentDataResp.id, "amount:", paymentDataResp.amount); break; }Also applies to: 79-81
🧹 Nitpick comments (3)
packages/templates/nestjs/src/modules/dodopayments/webhook.controller.ts (1)
50-94: Consider adding defensive checks for payload structure.The code assumes
payload.dataandpayload.data.payload_typeexist. If the payload structure differs, this will throw and return a 500 error. While the outer try-catch handles this, adding explicit validation would provide clearer error messages.Consider adding validation before processing:
// Process the webhook payload try { + if (!payload.data || !payload.data.payload_type) { + console.warn("Invalid webhook payload structure:", payload.type); + res.status(400).json({ error: "Invalid payload structure" }); + return; + } + if (payload.data.payload_type === "Subscription") {This would return 400 (client error) for malformed payloads instead of 500 (server error).
packages/templates/nestjs/src/lib/stripe.ts (2)
4-15: Refine Stripe client initialization.Several improvements can be made to the
getStripefunction:
- Line 10 re-reads
process.env.STRIPE_SECRET_KEYand usesas stringafter already validating the key exists at line 5-8. Use thekeyvariable instead.- Lines 11-12 contain an empty options object with trailing whitespace. Consider either removing it or specifying common options like
apiVersion.Apply this diff:
export const getStripe = (): Stripe => { const key = process.env.STRIPE_SECRET_KEY; if(!key){ throw new Error("STRIPE_SECRET_KEY is not set") } if (!_stripe) { - _stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string, { - - }); + _stripe = new Stripe(key, { + apiVersion: '2024-11-20.acacia', + typescript: true, + }); } return _stripe; };Note: Adjust the
apiVersionto match your Stripe API version. Based on learnings, Stripe releases new API versions regularly.
24-96: Consider error handling strategy for helper functions.The helper functions (lines 24-96) catch Stripe errors and throw generic
Errorinstances with messages like "Failed to fetch products". This masks valuable debugging information from the original Stripe errors, which include error codes, types, decline codes, and other details useful for troubleshooting.Additionally, based on the relevant code snippets, the controllers don't appear to use these helper functions—they call
getStripe()directly and use the Stripe instance. This raises questions about the purpose of these helpers:
- If they're meant as convenience wrappers, consider preserving original error details
- If they're unused, consider removing them to reduce maintenance burden
- If they're examples for documentation, consider marking them as such
Options:
- Re-throw original errors to preserve Stripe error details
- Document the intended usage if these are meant as examples
- Add pagination parameters (limit, starting_after) to match controller functionality
export async function getProducts(): Promise<Product[]> { try { const { data } = await getStripe().products.list({ limit: 100 }); return data; } catch (error) { console.error('Error fetching products', error); - throw new Error('Failed to fetch products'); + throw error; // Preserve original Stripe error details } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
packages/templates/nestjs/src/lib/stripe.ts(1 hunks)packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts(1 hunks)packages/templates/nestjs/src/modules/dodopayments/webhook.controller.ts(1 hunks)packages/templates/nestjs/src/modules/stripe/customer.controller.ts(1 hunks)packages/templates/nestjs/src/modules/stripe/payments.controller.ts(1 hunks)packages/templates/nestjs/src/modules/stripe/webhook.controller.ts(1 hunks)packages/templates/registry.json(1 hunks)public/tr/nestjs-stripe.json(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- packages/templates/registry.json
- packages/templates/nestjs/src/modules/stripe/customer.controller.ts
- packages/templates/nestjs/src/modules/stripe/payments.controller.ts
- packages/templates/nestjs/src/modules/stripe/webhook.controller.ts
🧰 Additional context used
🧬 Code graph analysis (3)
packages/templates/nestjs/src/lib/stripe.ts (2)
packages/templates/nestjs/src/modules/stripe/products.controller.ts (2)
getProducts(10-34)getProduct(37-55)packages/templates/nestjs/src/modules/stripe/customer.controller.ts (5)
getCustomer(26-41)createCustomer(44-74)updateCustomer(77-111)getCustomerSubscriptions(114-148)getCustomerPayments(151-185)
packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts (3)
packages/templates/nestjs/src/modules/stripe/customer.controller.ts (1)
Controller(21-186)packages/templates/nestjs/src/modules/dodopayments/payments.controller.ts (1)
Controller(4-49)packages/templates/nestjs/src/modules/dodopayments/subscriptions.controller.ts (1)
Controller(4-49)
packages/templates/nestjs/src/modules/dodopayments/webhook.controller.ts (4)
packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts (1)
Controller(20-194)packages/templates/nestjs/src/modules/stripe/webhook.controller.ts (1)
Controller(6-80)packages/templates/nestjs/src/modules/dodopayments/payments.controller.ts (1)
Controller(4-49)packages/templates/nestjs/src/modules/dodopayments/subscriptions.controller.ts (1)
Controller(4-49)
🔇 Additional comments (9)
packages/templates/nestjs/src/modules/dodopayments/webhook.controller.ts (2)
10-16: Excellent fix for webhook secret validation!The constructor now properly validates the environment variable and throws a clear startup error, eliminating the previous non-null assertion risk.
18-46: Well-structured verification and parsing flow!The signature verification and payload parsing are properly separated with appropriate error handling. Each phase returns the correct status code (400 for verification/parse failures).
Note: This implementation assumes raw body middleware is configured for the webhook route (e.g.,
app.use('/webhook', express.raw({ type: 'application/json' }))), which is standard practice for webhook endpoints.packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts (4)
5-18: LGTM! Well-structured validation schemas.The Zod schemas provide appropriate validation rules, and type inference ensures type safety throughout the controller.
22-38: LGTM! Correct implementation.The method correctly validates input, retrieves the customer, and handles errors appropriately.
40-70: Excellent! Type safety issue resolved.The previous
as anyassertion has been removed. The method now constructs a properly typed object before passing it to the SDK, matching the pattern in the Stripe controller.
72-107: Excellent! Type safety issue resolved.The previous
as anyassertion has been removed. The method now conditionally builds a properly typedupdateDataobject, matching the pattern in the Stripe controller.public/tr/nestjs-stripe.json (2)
52-55: Previous issue resolved - LGTM!The
.env.examplecontent has been corrected and now only includes Stripe-related environment variables without DodoPayments configuration or duplicate keys. This addresses the concern raised in the previous review.
57-67: Verify TypeScript version constraint with zod v3.25+.Stripe Node.js SDK v19 supports Node.js 12+, and NestJS peer dependency now includes v11 in nestjs-zod. The dependency list is appropriate, but be aware: zod 3.25.76 can break TypeScript 4.9 builds due to zod v4 being included via subpaths within zod v3. Ensure your project uses TypeScript 5+ if pinning zod to the latest v3 version.
packages/templates/nestjs/src/lib/stripe.ts (1)
99-128: LGTM - Previous issues addressed.The
checkoutfunction has been improved to address all concerns from the previous review:
- Mode is now configurable with a default value (line 104, 108)
- Customer ID is conditionally added only when provided (lines 114-116)
- Null URL check prevents runtime errors (lines 120-122)
packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts
Show resolved
Hide resolved
…and improve error handling
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 (2)
packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts(1 hunks)public/tr/nestjs-stripe.json(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/templates/nestjs/src/modules/dodopayments/customer.controller.ts
🔇 Additional comments (7)
public/tr/nestjs-stripe.json (7)
52-55: ✅ Past issue resolved: .env.example is correct.The configuration now contains only Stripe-related variables and basic server configuration, with no unrelated DodoPayments settings. This is properly fixed from the previous review.
12-15: ✅ Past issue appears resolved: stripe.ts uses lazy initialization pattern.The template now shows each helper function calling
getStripe()directly rather than using eager module-level initialization. The singleton caching is properly encapsulated within thegetStripe()function itself, matching the intended lazy per-call pattern.
22-25: ✅ CheckoutController validation and session creation look solid.The controller properly validates complex nested schemas (product cart items, customer union type), handles customer creation/attachment logic, and creates checkout sessions with appropriate metadata support. Error handling is consistent with other controllers.
27-30: ✅ CustomerController CRUD patterns are well-structured.Consistent validation using Zod schemas, proper error handling, and logical separation of concerns (CRUD on line 1-2, subscriptions query, payments query). The union logic for customer updates (optional fields) is correct.
32-35: ✅ PaymentsController, ProductsController, and SubscriptionsController follow consistent patterns.All three controllers handle pagination parameters (
limit,starting_after), validate query inputs with safe integer parsing, provide both single-item and list endpoints, and include appropriate error handling. The pattern is consistent across the codebase.Also applies to: 37-40, 42-45
17-20: ✅ StripeModule wiring is complete and consistent.All six controllers are properly imported and registered. The module structure aligns with NestJS conventions.
57-66: ✅ Dependencies are appropriately scoped.The dependency list includes core NestJS packages (
@nestjs/common,@nestjs/core,@nestjs/platform-express), Stripe SDK, Zod for validation, Express types, and reflection metadata. This is a reasonable set for a NestJS Stripe scaffold.
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 (2)
public/tr/nestjs-stripe.json (2)
22-25: Customer creation on checkout may produce duplicates.In the checkout controller, when a customer email is provided, the code unconditionally creates a new Stripe customer via
this.stripe.customers.create(). This could result in duplicate customer records if the same email is used for multiple checkout sessions. For a template, this is acceptable, but consider adding a comment suggesting users check for existing customers before creation:// In production, consider checking for existing customers first // to avoid duplicates: const customer = await this.stripe.customers.search(...); const stripeCustomer = await this.stripe.customers.create({ ... });
14-15: Minor: Empty Stripe client options object.The Stripe client is initialized with an empty options object:
_stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string, { });While this is harmless and Stripe will apply defaults, you could clean this up slightly:
-_stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string, { - -}); +_stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
public/tr/nestjs-stripe.json(1 hunks)
🔇 Additional comments (4)
public/tr/nestjs-stripe.json (4)
52-55: ✅ DodoPayments configuration successfully removed from Stripe template.The
.env.examplenow correctly contains only Stripe-related configuration (STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET) with minimal server config. Previous issue resolved.
12-15: ✅ Stripe client initialization pattern is correct.The
lib/stripe.tstemplate correctly implements a lazy singleton pattern withgetStripe()called within each helper function (e.g.,getProducts(),getCustomer(), etc.) rather than eager initialization. This matches the intended implementation and avoids unnecessary client instantiation.
47-50: ✅ Webhook handler correctly preserves raw request body for signature verification.The webhook controller properly retrieves the raw body via
const rawBody: Buffer | string = (req as any).rawBody || req.body;before passing it tothis.stripe.webhooks.constructEvent(). This ensures Stripe signature verification will succeed when configured with appropriate NestJS middleware.
22-25:payment_method_types: ["card"]is a valid parameter in Stripe SessionCreateParams.The
payment_method_typesparameter is valid in the Stripe Checkout Sessions API and accepts "card" as a value. The code is correct as written.Note: Stripe now recommends omitting this parameter and using Dynamic Payment Methods (configured in the Dashboard) so Checkout automatically shows eligible payment methods. This is a modern best practice recommendation rather than a requirement, and the current implementation is not incorrect.
Likely an incorrect or invalid review comment.
|
@tsahil01 I’ve made all the updates from Coderabbit’s review. |
This PR introduces NestJS CLI support for generating templates related to Dodopayments and Stripe integrations. The implementation follows the existing Express folder structure to maintain consistency across the billing SDK.
Key Changes:
Promotes code reusability and reduces boilerplate by adhering to the established Express structure.
Supports both Dodopayments and Stripe integrations seamlessly.
Here is the detailed video about the PR :
DODO_NEST_PR.1.mp4
Summary by CodeRabbit
New Features
Documentation
Chores