-
Notifications
You must be signed in to change notification settings - Fork 498
inline product metadata #963
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThreads client-, client-read-only-, and server-side product metadata through shared schemas, backend payments types and functions (ProductWithMetadata), inline product generation, owned-product responses, and E2E tests to preserve and validate metadata across purchase flows. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Backend
participant PaymentsLib
participant Schema
Client->>Backend: POST /create-purchase (inline product + metadata)
Backend->>PaymentsLib: ensureProductIdOrInlineProduct(inlineProduct)
PaymentsLib->>Schema: validate with productSchemaWithMetadata
Schema-->>PaymentsLib: ProductWithMetadata (validated)
PaymentsLib->>PaymentsLib: productToInlineProduct(ProductWithMetadata)
Note right of PaymentsLib: inline representation now carries client/server metadata
PaymentsLib-->>Backend: inline product (with metadata)
Backend->>PaymentsLib: grantProductToCustomer(ProductWithMetadata)
PaymentsLib-->>Backend: grant persisted (metadata attached)
Client->>Backend: GET /owned-products
Backend->>PaymentsLib: getOwnedProductsForCustomer()
PaymentsLib-->>Backend: owned products as ProductWithMetadata (include metadata)
Backend-->>Client: owned products (with metadata)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
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.
Review by RecurseML
🔍 Review performed on 542d444..d42cf54
✨ No bugs found, your code is sparkling clean
✅ Files analyzed, no issues (5)
• apps/backend/src/lib/payments.tsx
• apps/e2e/tests/backend/endpoints/api/v1/payments/create-purchase-url.test.ts
• apps/e2e/tests/backend/endpoints/api/v1/payments/products.test.ts
• apps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.ts
• packages/stack-shared/src/schema-fields.ts
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.
Greptile Overview
Summary
This PR adds support for custom metadata to inline products in the payments system, allowing developers to attach arbitrary JSON data to products created without pre-configuration.
Key Changes:
- Added
productMetadataschema field (optional JSON) andproductSchemaWithMetadatatype that extends the base product schema - Updated
inlineProductSchemato include the metadata field - Modified backend payment logic to use
ProductWithMetadatatype throughout, ensuring metadata flows through product creation, validation, and retrieval - Added metadata handling in
ensureProductIdOrInlineProductandproductToInlineProductfunctions - Comprehensive e2e tests verify metadata persists correctly through purchase creation, code validation, and product listing endpoints
Testing Coverage:
- Metadata persistence through test-mode purchase flow
- Metadata returned in purchase code validation
- Metadata included in product grant responses
The implementation is clean and follows existing patterns in the codebase.
Confidence Score: 5/5
- This PR is safe to merge with minimal risk
- The changes are well-isolated, properly typed, and thoroughly tested. The metadata field is optional and uses the existing
jsonSchemapattern. All type signatures are updated consistently, and comprehensive e2e tests verify the feature works correctly across multiple endpoints. - No files require special attention
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| packages/stack-shared/src/schema-fields.ts | 5/5 | Added productMetadata schema and productSchemaWithMetadata to support optional metadata field, added metadata to inlineProductSchema |
| apps/backend/src/lib/payments.tsx | 5/5 | Updated to use ProductWithMetadata type throughout, added metadata handling in inline product conversion and type casts |
Sequence Diagram
sequenceDiagram
participant Client
participant API as Backend API
participant Payments as payments.tsx
participant Schema as schema-fields
participant DB as Database
Note over Client,DB: Creating Purchase with Inline Product + Metadata
Client->>API: POST /create-purchase-url<br/>{product_inline: {metadata: {...}}}
API->>Payments: ensureProductIdOrInlineProduct()
Payments->>Schema: Validate inlineProductSchema<br/>(includes metadata field)
Schema-->>Payments: Valid inline product
Payments->>Payments: Convert to ProductWithMetadata<br/>(metadata field preserved)
Payments-->>API: ProductWithMetadata object
API->>DB: Store purchase code with<br/>product data (including metadata)
DB-->>API: Success
API-->>Client: Purchase URL
Note over Client,DB: Validating Purchase Code
Client->>API: POST /validate-code<br/>{full_code: "..."}
API->>DB: Retrieve purchase code data
DB-->>API: Product with metadata
API-->>Client: Product details<br/>(metadata included)
Note over Client,DB: Completing Purchase & Listing Products
Client->>API: POST /purchase-session<br/>{full_code: "..."}
API->>Payments: grantProductToCustomer()
Payments->>DB: Create subscription/purchase<br/>(product as ProductWithMetadata)
DB-->>Payments: Success
Payments-->>API: Grant result
API-->>Client: Success
Client->>API: GET /products/user/{userId}
API->>DB: Fetch owned products
DB-->>API: Products with metadata
API->>Payments: Cast to ProductWithMetadata
API-->>Client: Product list<br/>(metadata included)
5 files reviewed, no comments
N2D4
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.
we should have clientReadonlyMetadata and serverMetadata (in the future we could also have clientMetadata — maybe we can implement it now, even if in the SDK there's no way to make use it?)
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 (5)
apps/backend/src/lib/payments.tsx(6 hunks)apps/e2e/tests/backend/endpoints/api/v1/payments/create-purchase-url.test.ts(1 hunks)apps/e2e/tests/backend/endpoints/api/v1/payments/products.test.ts(16 hunks)apps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.ts(1 hunks)packages/stack-shared/src/schema-fields.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/e2e/tests/backend/endpoints/api/v1/payments/create-purchase-url.test.ts
- apps/e2e/tests/backend/endpoints/api/v1/payments/products.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.test.{ts,tsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
In tests, prefer .toMatchInlineSnapshot where possible; refer to snapshot-serializer.ts for snapshot formatting and handling of non-deterministic values
Files:
apps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Prefer ES6 Map over Record when representing key–value collections
Files:
apps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.tspackages/stack-shared/src/schema-fields.tsapps/backend/src/lib/payments.tsx
🧬 Code graph analysis (2)
apps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.ts (1)
apps/e2e/tests/backend/backend-helpers.ts (1)
niceBackendFetch(107-171)
apps/backend/src/lib/payments.tsx (2)
packages/stack-shared/src/schema-fields.ts (2)
productSchemaWithMetadata(600-604)inlineProductSchema(606-631)apps/backend/src/lib/tenancies.tsx (1)
Tenancy(47-47)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: Vercel Agent Review
- GitHub Check: docker
- GitHub Check: docker
- GitHub Check: build (22.x)
- GitHub Check: all-good
- GitHub Check: setup-tests
- GitHub Check: build (22.x)
- GitHub Check: lint_and_build (latest)
- GitHub Check: restart-dev-and-test
- GitHub Check: check_prisma_migrations (22.x)
- GitHub Check: Security Check
🔇 Additional comments (7)
packages/stack-shared/src/schema-fields.ts (2)
593-604: LGTM: Metadata schemas properly defined.The metadata schemas follow the existing pattern for user and team metadata. The use of
concat()to extendproductSchemais appropriate and type-safe.Minor observation: All three metadata schemas share the same
exampleValue. Consider differentiating them to clarify their distinct purposes (e.g., client-visible flags forclientMetadata, subscription status forclientReadOnlyMetadata, internal correlation IDs forserverMetadata).
628-630: LGTM: Inline product metadata fields properly added.The metadata fields are correctly added to
inlineProductSchemawith appropriate snake_case naming, consistent with other fields in the schema. The use of the same metadata schemas ensures consistency between config-based and inline products.apps/backend/src/lib/payments.tsx (4)
4-4: LGTM: ProductWithMetadata type properly introduced.The import and type definition follow the existing pattern for
Product. Both types now coexist in the codebase, withProductWithMetadataused for public APIs and storage whileProductremains for internal use.Also applies to: 19-19
27-27: LGTM: Metadata properly threaded through inline product construction.The return type correctly reflects that products now carry metadata, and the inline product path properly maps all three metadata fields from the snake_case input to camelCase output.
Also applies to: 65-67
427-427: LGTM: Product-to-inline conversion includes metadata.The function signature correctly accepts
ProductWithMetadata, and the metadata fields are properly mapped to the snake_case inline product format with appropriate null fallbacks.Also applies to: 434-436
562-562: LGTM: Grant function signature updated for metadata support.The parameter type correctly reflects that products with metadata can now be granted, ensuring metadata persists through purchase creation.
apps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.ts (1)
439-510: LGTM: End-to-end test validates inline product metadata persistence.The test properly verifies that
server_metadataflows through the purchase creation, test-mode purchase, and product listing endpoints. The use oftoMatchInlineSnapshotaligns with coding guidelines.Minor observation: Consider adding assertions for
client_metadataandclient_read_only_metadatain a follow-up test to ensure comprehensive coverage of all metadata types.As per coding guidelines
|
You have run out of free Bugbot PR reviews for this billing cycle. This will reset on November 10. To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial. |
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)
apps/e2e/tests/backend/endpoints/api/v1/payments/create-purchase-url.test.ts(1 hunks)apps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/e2e/tests/backend/endpoints/api/v1/payments/create-purchase-url.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use ES6 Maps instead of Records wherever possible in TypeScript code
Files:
apps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
When writing tests, prefer .toMatchInlineSnapshot over other selectors where possible
Files:
apps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.ts
🧬 Code graph analysis (1)
apps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.ts (2)
apps/e2e/tests/helpers.ts (1)
it(12-12)apps/e2e/tests/backend/backend-helpers.ts (1)
niceBackendFetch(108-172)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: docker
- GitHub Check: check_prisma_migrations (22.x)
- GitHub Check: setup-tests
- GitHub Check: restart-dev-and-test-with-custom-base-port
- GitHub Check: lint_and_build (latest)
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: restart-dev-and-test
- GitHub Check: all-good
- GitHub Check: Security Check
🔇 Additional comments (1)
apps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.ts (1)
440-511: Well-structured test for inline product metadata persistence.The test effectively verifies that server_metadata on inline products persists through the test-mode purchase flow and is correctly returned in the product listing. The test follows existing patterns in the file and appropriately uses
.toMatchInlineSnapshot()as per the coding guidelines.
High-level PR Summary
This PR adds support for custom
metadatato inline products in the payments system. The change allows developers to attach arbitrary metadata to products created inline (without pre-configuration), which Stack Auth will store and return with the product. This enables applications to associate custom data such as feature flags, reference IDs, or other application-specific attributes with products. The implementation adds a newproductSchemaWithMetadataschema, updates the product type handling in the backend, and includes comprehensive e2e tests verifying metadata is persisted and returned correctly through purchase creation, validation, and listing endpoints.⏱️ Estimated Review Time: 15-30 minutes
💡 Review Order Suggestion
packages/stack-shared/src/schema-fields.tsapps/backend/src/lib/payments.tsxapps/e2e/tests/backend/endpoints/api/v1/payments/purchase-session.test.tsapps/e2e/tests/backend/endpoints/api/v1/payments/create-purchase-url.test.tsapps/e2e/tests/backend/endpoints/api/v1/payments/products.test.tsSummary by CodeRabbit
New Features
Tests
Important
Adds support for custom metadata in inline products, updating schemas and functions to handle metadata, with comprehensive tests verifying the changes.
ensureProductIdOrInlineProduct()andproductToInlineProduct()inpayments.tsxto handle metadata.productSchemaWithMetadatainschema-fields.tsto includeclientMetadata,clientReadOnlyMetadata, andserverMetadata.inlineProductSchemato support metadata fields.purchase-session.test.ts,create-purchase-url.test.ts, andproducts.test.tsto verify metadata handling.This description was created by
for 1b5601c. You can customize this summary. It will automatically update as commits are pushed.