feat: add support to coupons#39
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughAdds Changes
Normalized coupons feature
Sequence Diagram(s)sequenceDiagram
participant App
participant PaymeshClient
participant couponsClient as createCouponsClient
participant providerCoupons as provider.coupons
participant CouponsRepo as PaymeshCouponsRepository
App->>PaymeshClient: coupons.create(data)
PaymeshClient->>couponsClient: create(data)
couponsClient->>providerCoupons: create(provider fields)
providerCoupons-->>couponsClient: Coupon
couponsClient->>CouponsRepo: upsert(schema, coupon)
CouponsRepo-->>couponsClient: stored coupon
couponsClient-->>PaymeshClient: Coupon
PaymeshClient-->>App: normalized coupon
App->>PaymeshClient: webhooks.handle(event)
PaymeshClient->>providerCoupons: webhook normalization
providerCoupons->>CouponsRepo: findByProviderId()
providerCoupons->>CouponsRepo: upsert()/markDeleted()
providerCoupons-->>PaymeshClient: normalized coupon event
PaymeshClient-->>App: hook + event
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related issues
Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/cli/test/cli.test.ts (1)
912-917:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate the comment to include
couponsin the table list.The expectation was correctly updated to 12, but the comment on lines 914-915 still lists only 11 tables and doesn't mention
coupons.📝 Suggested fix
// Each built-in sandbox table should have a DO $$ block for constraint replacement const doBlocks = (sandboxMigration?.sql.match(/DO \$\$/g) ?? []).length; - // 11 built-in sandbox tables: customers, pix, checkouts, invoices, + // 12 built-in sandbox tables: customers, coupons, pix, checkouts, invoices, // paymentMethods, entitlements, usage, webhookEvents, subscriptions, products, prices expect(doBlocks).toBe(12);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/cli/test/cli.test.ts` around lines 912 - 917, Update the comment block that documents the built-in sandbox tables to reflect the current count and include the coupons table. Change the count from "11 built-in sandbox tables" to "12 built-in sandbox tables" and add coupons to the comma-separated list of table names (customers, pix, checkouts, invoices, paymentMethods, entitlements, usage, webhookEvents, subscriptions, products, prices) to match the expect statement that verifies doBlocks equals 12.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/content/docs/concepts/coupons.mdx`:
- Line 420: The file apps/web/content/docs/concepts/coupons.mdx contains
hardcoded absolute file system paths in documentation links at lines 420 and 434
instead of using the relative documentation link format used throughout the
codebase. At line 420, replace the absolute path
/home/almeida/Documents/Projects/paymesh/paymesh/apps/web/content/docs/providers/stripe.mdx
with the relative documentation path /docs/providers/stripe (removing the
leading full system path and the .mdx extension). Similarly, at line 434,
replace any absolute path reference to the Polar provider with
/docs/providers/polar using the same format. This will ensure the documentation
links follow the consistent `/docs/[path]` pattern used throughout the codebase
and allow proper navigation.
In `@apps/web/public/llms.txt`:
- Line 12: The file `apps/web/public/llms.txt` now includes `@paymesh/dodo` in
the "Official live providers" list, but the "Recommended documentation
entrypoints → Providers" section is missing the corresponding
`/docs/providers/dodo` entry. Add `/docs/providers/dodo` to the Providers
documentation list in the same file to keep these two sections aligned and
consistent.
In `@apps/web/src/lib/docs.tsx`:
- Around line 3871-3884: The documentation states that delete is intentionally
unsupported for Dodo customers, but the DocCodeBlock component currently renders
customerSnippet which includes an unsupported delete operation. Replace the
customerSnippet variable reference with a Dodo-specific code snippet that only
demonstrates the supported upsert and get operations for customers, ensuring the
code example matches the documented behavior.
In `@packages/dodo/src/index.ts`:
- Around line 301-313: Add validation for the event.data shape immediately after
validating event and event.type in the webhook payload check. Before calling
resolveDodoWebhookData, check that event.data exists and is an object (using
isRecord or similar validation), and throw a TypeError with a clear message if
validation fails. This ensures malformed webhook data is rejected early with a
deterministic error instead of failing downstream during resolver mapping.
In `@packages/dodo/src/shared/constants.ts`:
- Around line 44-46: The mapping in the constants file incorrectly remaps
refund.failed to payment.failed, which causes refund operation failures to be
treated as payment lifecycle failures and can incorrectly downgrade a successful
payment state. Remove or replace the line that maps 'refund.failed' to
'payment.failed' with an appropriate mapping that correctly represents a refund
failure without affecting payment state transitions.
In `@packages/dodo/src/shared/sync.ts`:
- Around line 57-67: The Promise.all call at line 57 executes the invoice and
Pix upserts concurrently, which can lead to partial persistence if one succeeds
and the other fails. Instead, await the database.repositories.invoices.upsert
operation first, then conditionally execute the Pix upsert only after the
invoice is successfully persisted. This ensures deterministic persistence where
Pix data cannot be stored independently of its parent payment record,
maintaining consistency within a single sync unit.
In `@packages/dodo/src/shared/utils.ts`:
- Around line 165-195: The validation in ensureDodoProductIds function only
checks array length but does not validate that each product ID is a valid
non-empty string, allowing invalid entries to pass through. Additionally, the
validation in buildDodoProductCart function only checks typeof for amount being
a number, but does not validate that it is a valid positive number (allowing
NaN, Infinity, or values <= 0). Strengthen ensureDodoProductIds to iterate
through productIds and verify each is a non-empty string, and enhance the amount
validation in buildDodoProductCart to check that the numeric value is finite and
greater than zero before allowing it to be used in the cart.
In `@packages/dodo/src/shared/webhooks.ts`:
- Around line 53-58: The resolveDodoWebhookType function defaults unmapped
webhook types to payment.created using the ?? operator, which causes unsupported
events to be misrouted to payment handlers with incorrect semantics. Remove the
fallback to payment.created from the expression DODO_EVENTS[type] ??
'payment.created' and instead throw an error or handle unknown types explicitly
to prevent silent misclassification of webhooks that do not have proper event
mappings defined.
In `@packages/dodo/test/dodo.test.ts`:
- Around line 192-227: The three expect statements using
.rejects.toMatchObject() are not awaited or returned, which means the test can
complete before the rejection checks run, causing false-positive passing tests.
Add await before each of the three expect() calls that check for rejections from
provider.payments.create() to ensure the Promise rejections are properly
validated before the test completes.
In `@packages/drizzle/src/repositories.ts`:
- Around line 438-441: The coupons.list implementation is currently using
decodeCustomerCursor which produces customer-specific error messages when
validating coupon cursors. Replace the decodeCustomerCursor call in
packages/drizzle/src/repositories.ts at lines 438-441,
packages/postgres/src/repositories.ts at lines 438-441, and
packages/prisma/src/repositories.ts at lines 438-441 with a coupon-specific
decoder that generates appropriate coupon error messaging. Additionally, apply
the same coupon-specific decoder change to packages/memory/src/repositories.ts
at lines 313-316. Either create a separate decodeCouponCursor function or
parameterize the shared decoder with an entity context parameter that allows it
to return entity-appropriate error labels.
In `@packages/paymesh/src/client/coupons.ts`:
- Around line 206-208: The local markDeleted call on couponsRepository is not
gated on the success of the provider-side deletion operation. Currently, it
executes whenever couponsRepository exists, regardless of whether the provider
deletion succeeded. Add an additional condition to check that result.deleted is
true before calling couponsRepository.markDeleted(schema, result), so that local
tombstoning only occurs after confirming the provider-side deletion was
successful.
In `@packages/paymesh/src/types/client.ts`:
- Around line 302-306: The PaymeshCouponUpdateData type definition requires all
schema-required coupon extra fields from DatabaseTableInputExtraFields to be
provided on every update, breaking partial update semantics. Modify the type
definition to make the DatabaseTableInputExtraFields extra fields optional by
wrapping them with Partial<> utility type, allowing callers to perform partial
updates without needing to provide all custom required columns.
In `@packages/paymesh/src/types/database.ts`:
- Around line 431-446: The PaymeshCouponListOptions interface is missing the
status field that exists in the provider's CouponListOptions type. Add a status
field to PaymeshCouponListOptions to enable status filtering for coupon list
queries, matching the provider contract. This will allow client.coupons.list()
to accept and forward the status filter parameter correctly.
---
Outside diff comments:
In `@packages/cli/test/cli.test.ts`:
- Around line 912-917: Update the comment block that documents the built-in
sandbox tables to reflect the current count and include the coupons table.
Change the count from "11 built-in sandbox tables" to "12 built-in sandbox
tables" and add coupons to the comma-separated list of table names (customers,
pix, checkouts, invoices, paymentMethods, entitlements, usage, webhookEvents,
subscriptions, products, prices) to match the expect statement that verifies
doBlocks equals 12.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 8a633df1-c58e-45e7-927b-6f454dd473d4
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (52)
.changeset/cyan-poems-boil.mdREADME.mdapps/web/.source/browser.tsapps/web/.source/server.tsapps/web/content/docs/basic-usage.mdxapps/web/content/docs/concepts/api.mdxapps/web/content/docs/concepts/coupons.mdxapps/web/content/docs/concepts/payment-providers.mdxapps/web/content/docs/concepts/pix.mdxapps/web/content/docs/guides/create-a-provider.mdxapps/web/content/docs/installation.mdxapps/web/content/docs/introduction.mdxapps/web/content/docs/providers/dodo.mdxapps/web/public/llms.txtapps/web/src/app/page.tsxapps/web/src/components/docs/mdx-components.tsxapps/web/src/lib/docs-navigation.tsapps/web/src/lib/docs.tsxpackage.jsonpackages/cli/src/lib/migrations.tspackages/cli/src/shared/providers.tspackages/cli/test/cli.test.tspackages/dodo/README.mdpackages/dodo/package.jsonpackages/dodo/src/index.tspackages/dodo/src/shared/constants.tspackages/dodo/src/shared/mapper.tspackages/dodo/src/shared/sync.tspackages/dodo/src/shared/utils.tspackages/dodo/src/shared/webhooks.tspackages/dodo/src/types.tspackages/dodo/test/catalog.test.tspackages/dodo/test/customers.test.tspackages/dodo/test/dashboard.test.tspackages/dodo/test/dodo.test.tspackages/dodo/test/webhooks.test.tspackages/dodo/tsconfig.jsonpackages/dodo/tsdown.config.mjspackages/drizzle/src/repositories.tspackages/memory/src/repositories.tspackages/memory/src/state.tspackages/memory/src/types.tspackages/paymesh/README.mdpackages/paymesh/src/client/coupons.tspackages/paymesh/src/client/managers.tspackages/paymesh/src/database/schema.tspackages/paymesh/src/types/client.tspackages/paymesh/src/types/database.tspackages/paymesh/src/types/providers.tspackages/paymesh/test/client.test.tspackages/postgres/src/repositories.tspackages/prisma/src/repositories.ts
Summary by CodeRabbit
Release Notes
New Features
@paymesh/dodoprovider (catalog-driven hosted checkout, customer management, subscriptions, and normalized webhooks).checkvalidation, coupon webhook events, and integration withpayments.create(coupon code application options).Documentation
paymesh.pix).