-
Couldn't load subscription status.
- Fork 402
chore(backend,types): Update JSDoc comments & export Feature type #6649
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
🦋 Changeset detectedLatest commit: 974fb9d The changes in this PR will be included in the next version bump. This PR includes changesets to release 22 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughExports Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Dev as App/SDK Consumer
participant SDK as Backend SDK (resources/types)
participant API as Backend API
rect rgba(220,255,220,0.12)
note right of Dev: Remove payment source (new method)
Dev->>SDK: paymentSource.remove(params?)
SDK->>API: DELETE /payment_sources/:id (params)
API-->>SDK: 200/204 + DeletedObjectResource
SDK-->>Dev: Promise<DeletedObjectResource>
end
rect rgba(220,220,255,0.12)
note right of Dev: Make default payment source (new method)
Dev->>SDK: paymentSource.makeDefault(params?)
SDK->>API: POST /payment_sources/:id/default (params)
API-->>SDK: 204 No Content
SDK-->>Dev: Promise<null>
end
rect rgba(255,240,220,0.12)
note right of Dev: Cancel subscription (new method surface)
Dev->>SDK: subscription.cancel(params?)
SDK->>API: POST /subscriptions/:id/cancel (params)
API-->>SDK: 200/204 + DeletedObjectResource
SDK-->>Dev: Promise<DeletedObjectResource>
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
@clerk/agent-toolkit
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/dev-cli
@clerk/elements
@clerk/clerk-expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/clerk-react
@clerk/react-router
@clerk/remix
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/themes
@clerk/types
@clerk/upgrade
@clerk/vue
commit: |
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: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/types/src/commerce.ts (1)
1248-1300: Update doc comment forfreeTrialEndsAtin CommerceCheckoutResourceThe documentation currently describes
freeTrialEndsAtas a Unix timestamp, but the type isDate | null. To accurately reflect the runtime shape and clarify when the value can benull, please update the doc comment.• File:
packages/types/src/commerce.ts
Lines: ~1296–1298/** - * Unix timestamp (milliseconds) when the free trial ends. + * The date when the free trial ends, or `null` if no trial is active. */ freeTrialEndsAt: Date | null;
🧹 Nitpick comments (6)
.changeset/three-knives-play.md (2)
2-3: Semver: consider minor instead of patch for new public exports/typesRe-exporting
Featureand widening the public type surface in@clerk/typesare additive features. Recommendminorbumps to reflect API surface growth.Proposed diff:
---- -'@clerk/backend': patch -'@clerk/types': patch +'@clerk/backend': minor +'@clerk/types': minor ----
6-6: Broaden the changeset summary to cover all public surface additionsMention the
Featureexport and the additional commerce-related type updates so the release notes are accurate.-export feature type from backend resource +Export `Feature` from backend resource and document commerce resources; add `CommerceMoneyAmount` docs and widen commerce types (`Checkout.id`, `PaymentSource.remove/makeDefault`, `Feature.__internal_toSnapshot`).packages/backend/src/api/resources/CommerceSubscriptionItem.ts (1)
31-38: Align nextPayment.amount type with CommerceMoneyAmount for consistency
CommerceSubscription.nextPayment.amountusesCommerceMoneyAmountbutCommerceSubscriptionItem.nextPayment.amountis anumber. Consider usingCommerceMoneyAmounthere for parity and to avoid currency/format ambiguity.Proposed change:
- readonly nextPayment: { - /** - * The amount of the next payment. - */ - amount: number; - /** - * Unix timestamp (milliseconds) when the next payment is scheduled. - */ - date: number; - } | null, + readonly nextPayment: { + /** + * The amount of the next payment. + */ + amount: CommerceMoneyAmount; + /** + * Unix timestamp (milliseconds) when the next payment is scheduled. + */ + date: number; + } | null,And in
fromJSON:- data.next_payment, + data.next_payment + ? { + amount: formatAmountJSON(data.next_payment.amount)!, + date: data.next_payment.date, + } + : null,If the current
numberis intentional, please document units (e.g., minor units) to remove ambiguity.packages/backend/src/api/resources/Feature.ts (1)
8-27: Optional: mark constructor fields as explicitly public for public API clarityHouse style often prefers explicit
publicon public APIs.- constructor( + constructor( /** * The unique identifier for the feature. */ - readonly id: string, + public readonly id: string, /** * The name of the feature. */ - readonly name: string, + public readonly name: string, /** * The description of the feature. */ - readonly description: string, + public readonly description: string, /** * The URL-friendly identifier of the feature. */ - readonly slug: string, + public readonly slug: string, /** * The URL of the feature's avatar image. */ - readonly avatarUrl: string, + public readonly avatarUrl: string, ) {}packages/backend/src/api/resources/CommercePlan.ts (1)
90-98: Type the helper return and param explicitly.Improves safety and keeps API aligned with
CommerceMoneyAmount.- static fromJSON(data: CommercePlanJSON): CommercePlan { - const formatAmountJSON = (fee: CommercePlanJSON['fee']) => { + static fromJSON(data: CommercePlanJSON): CommercePlan { + const formatAmountJSON = (fee: CommercePlanJSON['fee']): CommerceMoneyAmount => { return { amount: fee.amount, amountFormatted: fee.amount_formatted, currency: fee.currency, currencySymbol: fee.currency_symbol, }; };packages/types/src/commerce.ts (1)
1129-1148: Clarify amountFormatted example.Use a clearly formatted example to avoid ambiguity.
- * The amount as a formatted string. For example, `10` for $10.00. + * The amount as a formatted string. For example, `10.00` for $10.00 (currency symbol may be omitted).
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (9)
.changeset/three-knives-play.md(1 hunks).typedoc/custom-plugin.mjs(1 hunks)packages/backend/src/api/resources/CommercePlan.ts(2 hunks)packages/backend/src/api/resources/CommerceSubscription.ts(2 hunks)packages/backend/src/api/resources/CommerceSubscriptionItem.ts(3 hunks)packages/backend/src/api/resources/Feature.ts(1 hunks)packages/backend/src/api/resources/index.ts(1 hunks)packages/backend/src/index.ts(1 hunks)packages/types/src/commerce.ts(7 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/backend/src/api/resources/index.tspackages/backend/src/api/resources/CommerceSubscription.tspackages/backend/src/index.tspackages/backend/src/api/resources/Feature.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommercePlan.tspackages/types/src/commerce.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/backend/src/api/resources/index.tspackages/backend/src/api/resources/CommerceSubscription.tspackages/backend/src/index.tspackages/backend/src/api/resources/Feature.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommercePlan.tspackages/types/src/commerce.ts
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/backend/src/api/resources/index.tspackages/backend/src/api/resources/CommerceSubscription.tspackages/backend/src/index.tspackages/backend/src/api/resources/Feature.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommercePlan.tspackages/types/src/commerce.ts
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/backend/src/api/resources/index.tspackages/backend/src/api/resources/CommerceSubscription.tspackages/backend/src/index.tspackages/backend/src/api/resources/Feature.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommercePlan.tspackages/types/src/commerce.ts
packages/**/index.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use tree-shaking friendly exports
Files:
packages/backend/src/api/resources/index.tspackages/backend/src/index.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/backend/src/api/resources/index.tspackages/backend/src/api/resources/CommerceSubscription.tspackages/backend/src/index.tspackages/backend/src/api/resources/Feature.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommercePlan.tspackages/types/src/commerce.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/backend/src/api/resources/index.tspackages/backend/src/api/resources/CommerceSubscription.tspackages/backend/src/index.tspackages/backend/src/api/resources/Feature.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommercePlan.tspackages/types/src/commerce.ts
**/index.ts
📄 CodeRabbit inference engine (.cursor/rules/react.mdc)
Use index.ts files for clean imports but avoid deep barrel exports
Avoid barrel files (index.ts re-exports) as they can cause circular dependencies
Files:
packages/backend/src/api/resources/index.tspackages/backend/src/index.ts
.changeset/**
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Automated releases must use Changesets.
Files:
.changeset/three-knives-play.md
🧬 Code graph analysis (3)
packages/backend/src/api/resources/Feature.ts (1)
packages/backend/src/index.ts (1)
Feature(122-122)
packages/backend/src/api/resources/CommercePlan.ts (1)
packages/types/src/commerce.ts (1)
CommerceMoneyAmount(1131-1148)
packages/types/src/commerce.ts (4)
packages/types/src/resource.ts (1)
ClerkResource(8-21)packages/types/src/snapshots.ts (1)
CommerceFeatureJSONSnapshot(194-194)packages/clerk-js/src/core/resources/CommerceStatement.ts (1)
CommerceStatementGroup(39-58)packages/backend/src/api/resources/CommercePlan.ts (1)
CommerceMoneyAmount(8-25)
⏰ 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). (5)
- GitHub Check: Build Packages
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (12)
.typedoc/custom-plugin.mjs (1)
58-58: It looks like searching the repo didn’t reveal any MD/MDX files referencing “commerce-money-amount,” and we need to inspect the plugin’s heavy lifting. Since the docs content lives elsewhere (not in this plugin package), we can’t confirm end-to-end purely from here. Please manually verify that after generating the MDX, anycommerce-money-amount.mdxlinks are indeed rewritten to/docs/references/javascript/types/commerce-money-amount(including any anchors).packages/backend/src/api/resources/CommerceSubscriptionItem.ts (2)
24-24: Timestamp wording improvements LGTMClear, consistent “Unix timestamp (milliseconds)” phrasing across fields. No changes requested.
Also applies to: 53-55, 57-59, 61-63, 65-67, 69-71, 73-75
7-8: Replace TODO with the real Backend API docs URL
Avoid shipping a broken reference. Inpackages/backend/src/api/resources/CommerceSubscriptionItem.ts(lines 7–8), update the JSDoc link from(TODO)to the published Clerk Backend API overview page URL.
- Locate the exact Backend API overview URL in the Clerk documentation (e.g. on docs.clerk.com)
- Replace the
(TODO)placeholder with that URL (keepingtarget='_blank')packages/backend/src/api/resources/Feature.ts (1)
3-5: JSDoc added — clear and helpfulConcise class description reads well. No issues.
packages/backend/src/api/resources/CommerceSubscription.ts (2)
23-29: Timestamp phrasing LGTMWording now clearly indicates “when ... was created/last updated” in milliseconds.
6-7: Replace Backend API docs placeholder in JSDoc
TheTODOin the[Backend API](TODO)link needs to be swapped out for the real CommerceSubscription Backend API docs URL (e.g.https://docs.clerk.com/reference/backend-api/resources/commerce-subscription){target: '_blank'}. This same placeholder appears inSubscriptionItem—please update both to point at the official docs.packages/types/src/commerce.ts (4)
7-11: LGTM: Optional orgId doc is clear.
1181-1185: LGTM: Statement totals aliasing.ESLint suppression is appropriate here.
415-443: CommerceFeatureResource implementation confirmed
TheCommerceFeatureResourceinterface’s new__internal_toSnapshotmember is implemented in the runtime and referenced in tests, so there’s no drift or missing implementation.• packages/clerk-js/src/core/resources/CommerceFeature.ts:
•export class CommerceFeature … implements CommerceFeatureResource
• definespublic __internal_toSnapshot(): CommerceFeatureJSONSnapshot• UI tests in clerk-js (e.g.
SubscriptionDetails.test.tsx,PlanDetails.test.tsx,PricingTable.test.tsx) mock__internal_toSnapshoton feature objects to drive component tests.No further action required.
540-590: Runtime implementations verified for remove and makeDefaultThe
CommercePaymentSourceclass includes the required methods matching the interface:
public async remove(params?: RemovePaymentSourceParams)(lines 46–58)public async makeDefault(params?: MakeDefaultPaymentSourceParams)(lines 60–63)No further changes are needed.
packages/backend/src/api/resources/index.ts (1)
63-64: LGTM: Re-exporting Feature is consistent with existing resource barrel.No circular ref risk introduced by this addition alone.
packages/backend/src/index.ts (1)
121-123: LGTM: Publicly exporting Feature type.Matches the resource barrel and the changeset intent.
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * The billing period for the plan. | ||
| * | ||
| * @inline | ||
| */ | ||
| export type CommerceSubscriptionPlanPeriod = 'month' | 'annual'; |
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.
💡 Verification agent
🧩 Analysis chain
LGTM: Period enum doc.
Consider confirming naming consistency: 'annual' here vs any 'year'/'yearly' elsewhere.
🏁 Script executed:
#!/bin/bash
# Check for alternate period literals that could drift from 'annual'|'month'
rg -nP -C1 "(?<quote>'|\")(?:(year|yearly))\k<quote>" --type=tsLength of output: 713
Standardize subscription period literals across the codebase
There’s a mismatch between the type CommerceSubscriptionPlanPeriod ('month' | 'annual') and usages elsewhere that expect a 'year' literal. If left unaddressed, this will lead to missing translation keys (e.g. commerce.year vs commerce.annual) or logic errors. Please align these values consistently:
• In packages/types/src/commerce.ts
export type CommerceSubscriptionPlanPeriod = 'month' | 'annual';Either rename the second member to 'year'…
• In packages/clerk-js/src/ui/components/SubscriptionDetails/index.tsx (line 548)
{t(localizationKeys(`commerce.${subscription.planPeriod === 'month' ? 'month' : 'year'}`))}…or update this to branch on 'annual' and load commerce.annual.
• In packages/shared/src/react/commerce.tsx (line 258)
recurringPaymentIntervalUnit: checkout.planPeriod === 'annual' ? 'year' : 'month',Mirror whatever literal you choose for the type.
Please pick one naming convention—either use 'year' throughout (and rename the type) or use 'annual' throughout (and update the UI/mapping)—so that runtime checks, translations, and types all agree.
🤖 Prompt for AI Agents
In packages/types/src/commerce.ts around lines 146-151, the union for
CommerceSubscriptionPlanPeriod currently uses 'month' | 'annual' which conflicts
with usages expecting 'year'; change the second literal to 'year' (so the type
is 'month' | 'year') and then update all dependent code to use 'year'
consistently: in
packages/clerk-js/src/ui/components/SubscriptionDetails/index.tsx adjust the
branch/translation key to use 'year' instead of 'annual', and in
packages/shared/src/react/commerce.tsx update the recurringPaymentIntervalUnit
mapping to check for 'year' (and any other places that check for 'annual') so
types, runtime checks, and localization keys align.
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 keep @experimental for almost all types and their properties. Any of them can be removed/replaced/renamed at any point.
36906be to
4c745fc
Compare
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/backend/src/api/resources/CommercePlan.ts (1)
30-31: Coalesce nullable description toundefinedto match field type.Avoid assigning
nulltoreadonly description: string | undefined.- readonly description: string | undefined, + readonly description: string | undefined, @@ - data.description, + data.description ?? undefined,Also applies to: 82-84
♻️ Duplicate comments (3)
packages/backend/src/api/resources/CommerceSubscription.ts (1)
5-7: Docs: remove TODO link and restore @experimental tag.Avoid publishing "(TODO)" links; keep the experimental notice as requested in prior review.
/** - * The `CommerceSubscription` object is similar to the [`CommerceSubscriptionResource`](/docs/references/javascript/types/commerce-subscription-resource) object as it holds information about a subscription, as well as methods for managing it. However, the `CommerceSubscription` object is different in that it is used in the [Backend API](TODO){{ target: '_blank' }} and is not directly accessible from the Frontend API. + * The `CommerceSubscription` object is similar to the [`CommerceSubscriptionResource`](/docs/references/javascript/types/commerce-subscription-resource) object as it holds information about a subscription, as well as methods for managing it. However, the `CommerceSubscription` object is different in that it is used in the Backend API and is not directly accessible from the Frontend API. + * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to pin the SDK version to avoid breaking changes. */packages/backend/src/api/resources/CommercePlan.ts (1)
6-8: Docs: remove TODO link and keep @experimental.Aligns with earlier guidance to retain the experimental tag and avoid placeholder links.
- * The `CommercePlan` object is similar to the [`CommercePlanResource`](/docs/references/javascript/types/commerce-plan-resource) object as it holds information about a plan, as well as methods for managing it. However, the `CommercePlan` object is different in that it is used in the [Backend API](TODO){{ target: '_blank' }} and is not directly accessible from the Frontend API. - * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to pin the SDK version to avoid breaking changes. + * The `CommercePlan` object is similar to the [`CommercePlanResource`](/docs/references/javascript/types/commerce-plan-resource) object as it holds information about a plan, as well as methods for managing it. However, the `CommercePlan` object is different in that it is used in the Backend API and is not directly accessible from the Frontend API. + * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to pin the SDK version to avoid breaking changes.packages/backend/src/api/resources/CommerceSubscriptionItem.ts (1)
6-8: Docs: remove TODO link and add @experimental.Keep docs clean and retain experimental notice.
- * The `CommerceSubscriptionItem` object is similar to the [`CommerceSubscriptionItemResource`](/docs/references/javascript/types/commerce-subscription-item-resource) object as it holds information about a subscription item, as well as methods for managing it. However, the `CommerceSubscriptionItem` object is different in that it is used in the [Backend API](TODO){{ target: '_blank' }} and is not directly accessible from the Frontend API. + * The `CommerceSubscriptionItem` object is similar to the [`CommerceSubscriptionItemResource`](/docs/references/javascript/types/commerce-subscription-item-resource) object as it holds information about a subscription item, as well as methods for managing it. However, the `CommerceSubscriptionItem` object is different in that it is used in the Backend API and is not directly accessible from the Frontend API. + * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to pin the SDK version to avoid breaking changes.
🧹 Nitpick comments (6)
packages/backend/src/api/resources/CommerceSubscription.ts (1)
52-63: DRY up money mapping across resources.The money-shape mapping is duplicated across files. Extract a shared helper to keep formats in sync.
- const nextPayment = data.next_payment - ? { - date: data.next_payment.date, - amount: { - amount: data.next_payment.amount.amount, - amountFormatted: data.next_payment.amount.amount_formatted, - currency: data.next_payment.amount.currency, - currencySymbol: data.next_payment.amount.currency_symbol, - }, - } - : null; + const nextPayment = data.next_payment + ? { date: data.next_payment.date, amount: mapMoneyJSON(data.next_payment.amount)! } + : null;Additional file (new):
// packages/backend/src/api/resources/_internal/mapMoney.ts import type { CommerceMoneyAmountJSON, CommerceMoneyAmount } from '@clerk/types'; export function mapMoneyJSON( amount: CommerceMoneyAmountJSON | null | undefined, ): CommerceMoneyAmount | null | undefined { if (!amount) return amount; return { amount: amount.amount, amountFormatted: amount.amount_formatted, currency: amount.currency, currencySymbol: amount.currency_symbol, }; }And import where needed:
import { mapMoneyJSON } from './_internal/mapMoney';packages/backend/src/api/resources/CommercePlan.ts (3)
1-3: Use type-only import and satisfy sorter.
CommerceMoneyAmountis type-only here; switch toimport typeand run autofix to satisfy both rules.-import { CommerceMoneyAmount } from '@clerk/types'; +import type { CommerceMoneyAmount } from '@clerk/types';Then:
pnpm lint --fix --filter @clerk/backend
60-63: TieforPayerTypeto the JSON source type to prevent drift.- readonly forPayerType: 'org' | 'user', + readonly forPayerType: CommercePlanJSON['for_payer_type'],
69-77: Optional: reuse shared money mapping helper.Match the helper suggested for other resources to avoid copy/paste.
- const formatAmountJSON = (fee: CommercePlanJSON['fee']) => { - return { - amount: fee.amount, - amountFormatted: fee.amount_formatted, - currency: fee.currency, - currencySymbol: fee.currency_symbol, - }; - }; + const formatAmountJSON = mapMoneyJSON;And import:
import { mapMoneyJSON } from './_internal/mapMoney';packages/backend/src/api/resources/CommerceSubscriptionItem.ts (2)
20-23: BindplanPeriodto the JSON type.Prevents divergence if the backend adds values.
- readonly planPeriod: 'month' | 'annual', + readonly planPeriod: CommerceSubscriptionItemJSON['plan_period'],
90-104: Optional: reuse shared money mapping helper.You already have
formatAmountJSON; consider importing a common helper as suggested for other files.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
packages/backend/src/api/resources/CommercePlan.ts(2 hunks)packages/backend/src/api/resources/CommerceSubscription.ts(2 hunks)packages/backend/src/api/resources/CommerceSubscriptionItem.ts(3 hunks)packages/types/src/commerce.ts(7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/types/src/commerce.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommerceSubscription.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommerceSubscription.ts
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommerceSubscription.ts
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommerceSubscription.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommerceSubscription.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscriptionItem.tspackages/backend/src/api/resources/CommerceSubscription.ts
🪛 ESLint
packages/backend/src/api/resources/CommercePlan.ts
[error] 1-3: Run autofix to sort these imports!
(simple-import-sort/imports)
[error] 1-1: All imports in the declaration are only used as types. Use import type.
(@typescript-eslint/consistent-type-imports)
packages/backend/src/api/resources/CommerceSubscriptionItem.ts
[error] 1-4: Run autofix to sort these imports!
(simple-import-sort/imports)
packages/backend/src/api/resources/CommerceSubscription.ts
[error] 1-3: Run autofix to sort these imports!
(simple-import-sort/imports)
⏰ 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). (6)
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: Build Packages
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (5)
packages/backend/src/api/resources/CommerceSubscription.ts (2)
23-29: LGTM: clearer timestamp docs.The reworded createdAt/updatedAt descriptions are clearer and consistent.
1-3: Import order needs sorting in CommerceSubscription.tsI attempted to run the suggested autofix command but the lint script failed due to a missing
zxdependency. Please ensure your workspace dependencies are installed (e.g.pnpm installat the repo root), then rerun the lint autofix and confirm the imports are sorted:pnpm install pnpm lint --fix --filter @clerk/backend• File:
packages/backend/src/api/resources/CommerceSubscription.ts
Lines: 1–3 — sort the three import statements according tosimple-import-sortrules.
• Verify imports from external packages come before internal (sibling) imports, and that within each group they are alphabetically ordered.packages/backend/src/api/resources/CommerceSubscriptionItem.ts (3)
30-39: ConfirmnextPaymentshape vs Subscription resource.Here
nextPayment.amountis a number, whileCommerceSubscription.nextPayment.amountisCommerceMoneyAmount. Verify API parity or document why they differ.Also applies to: 90-112
24-75: LGTM: timestamp field docs are consistent.Also applies to: 53-63, 65-75
1-4: Fix import order and verify lint toolingThe imports should be reordered so that non-type imports come first, followed by all type-only imports. For example:
-import type { CommerceMoneyAmountJSON, CommerceMoneyAmount } from '@clerk/types'; -import { CommercePlan } from './CommercePlan'; -import type { CommerceSubscriptionItemJSON } from './JSON'; +import { CommercePlan } from './CommercePlan'; +import type { CommerceMoneyAmountJSON, CommerceMoneyAmount } from '@clerk/types'; +import type { CommerceSubscriptionItemJSON } from './JSON';• After adjusting the imports, run ESLint’s autofix. If you continue to use
pnpm lint --fix --filter @clerk/backendyou’ll first need to resolve the
ERR_MODULE_NOT_FOUND: zxerror inscripts/lint.mjs(for instance, by addingzxas a dev dependency or updating the script).
• As an alternative, you can bypass the broken lint script and run ESLint directly:npx eslint packages/backend/src/api/resources/CommerceSubscriptionItem.ts --fix
67cc059 to
93cc8c9
Compare
93cc8c9 to
acc2569
Compare
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 (3)
packages/types/src/commerce.ts (2)
827-839: Confirm omission ofidonCommerceStatementGroup.Runtime class
CommerceStatementGroupin clerk-js hasid, but this type omits it. If FAPI truly doesn't returnid, consider adding a note explaining the intentional difference, or addid?: stringto avoid friction when sharing types across packages.Run to see where the runtime expects
id:#!/bin/bash rg -nP -C2 "(class\s+CommerceStatementGroup\b|\.id\b)" packages/clerk-js
146-151: Unify plan period literal: 'annual' vs 'year'.This still uses 'annual' while other parts of the codebase (UI, mappings) branch on 'year'. Pick one and make it consistent repo-wide to avoid logic/translation drift. Suggest switching the type to 'year' here and updating dependents (or vice versa).
Run to locate mismatches:
#!/bin/bash rg -nP -C2 "(annual|year(?!ly))" --type=ts --type=tsxSuggested change (if standardizing on 'year'):
-export type CommerceSubscriptionPlanPeriod = 'month' | 'annual'; +export type CommerceSubscriptionPlanPeriod = 'month' | 'year';packages/backend/src/api/resources/CommerceSubscriptionItem.ts (1)
23-23: Plan period literal alignment.This uses
'month' | 'annual'. Please align with the chosen convention inpackages/types(see related comment).
🧹 Nitpick comments (6)
packages/types/src/commerce.ts (3)
1304-1307: Doc-type mismatch forfreeTrialEndsAt.JSDoc says "Unix timestamp (milliseconds)" but the type is
Date | null. Align the description.- /** - * Unix timestamp (milliseconds) of when the free trial ends. - */ + /** + * Date when the free trial ends, or `null` if not applicable. + */ freeTrialEndsAt: Date | null;
577-580: Prefer optional property overstring | undefined.Use
walletType?: stringfor clarity and to match common TS style across the repo.- walletType: string | undefined; + walletType?: string;
124-135: Clarify and document the intentional mapping betweenForPayerTypeandCommercePayerResourceTypeThe divergence between
CommercePayerResourceType = 'org' | 'user'(the JSON/DB literal)ForPayerType = 'organization' | 'user'(the external API/UI literal)is already wired up at the boundaries (e.g. in
CommerceBilling.ts:payer_type: forParam === 'organization' ? 'org' : 'user'and in UI components mapping back
'org'→'organization'). To avoid confusion and surface this intent to consumers of the types package, add JSDoc to both type aliases:– In
packages/types/src/commerce.tsaboveexport type CommercePayerResourceType/** + * @internal + * JSON API resource literal for a payer: + * use 'org' for organizations and 'user' for individuals. */ export type CommercePayerResourceType = 'org' | 'user';– And above
export type ForPayerType/** + * @experimental + * Public-facing literal for specifying a payer: + * maps to `CommercePayerResourceType` ('organization' → 'org') in API calls. * This API is in beta and may change—pin your SDK versions to avoid breaking changes. */ export type ForPayerType = 'organization' | 'user';This makes the boundary mapping explicit in the types package, preventing subtle bugs.
packages/backend/src/api/resources/CommerceSubscriptionItem.ts (2)
31-40: Clarify units fornextPayment.amount.Other money fields use
CommerceMoneyAmount, butnextPayment.amountis anumber. Document that it's in minor units (e.g., cents) to avoid misinterpretation.readonly nextPayment: { /** - * The amount of the next payment. + * The amount of the next payment in the smallest currency unit (e.g., cents). */ amount: number;
91-106: Consider hoistingformatAmountJSONto a shared helper.This helper likely exists in similar resources. Centralizing avoids duplication and keeps JSON-to-type mapping consistent.
I can extract a small
formatMoneyAmountJSONutil underpackages/backend/src/api/utils/and update call sites if you want..changeset/three-knives-play.md (1)
6-7: Tighten wording for clarity.Minor grammar/style tweak.
-- Export `Feature` type from backend resource. -- Re-export canonical `CommerceMoneyAmount` type from `@clerk/types`. +- Export the `Feature` type from backend resources. +- Re-export the canonical `CommerceMoneyAmount` type from `@clerk/types`.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
.changeset/three-knives-play.md(1 hunks)packages/backend/src/api/resources/CommercePlan.ts(2 hunks)packages/backend/src/api/resources/CommerceSubscription.ts(2 hunks)packages/backend/src/api/resources/CommerceSubscriptionItem.ts(3 hunks)packages/types/src/commerce.ts(7 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/backend/src/api/resources/CommercePlan.ts
- packages/backend/src/api/resources/CommerceSubscription.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/types/src/commerce.tspackages/backend/src/api/resources/CommerceSubscriptionItem.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/types/src/commerce.tspackages/backend/src/api/resources/CommerceSubscriptionItem.ts
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/types/src/commerce.tspackages/backend/src/api/resources/CommerceSubscriptionItem.ts
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/types/src/commerce.tspackages/backend/src/api/resources/CommerceSubscriptionItem.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/types/src/commerce.tspackages/backend/src/api/resources/CommerceSubscriptionItem.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/types/src/commerce.tspackages/backend/src/api/resources/CommerceSubscriptionItem.ts
.changeset/**
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Automated releases must use Changesets.
Files:
.changeset/three-knives-play.md
🧬 Code graph analysis (1)
packages/types/src/commerce.ts (3)
packages/types/src/resource.ts (1)
ClerkResource(8-21)packages/types/src/snapshots.ts (1)
CommerceFeatureJSONSnapshot(194-194)packages/clerk-js/src/core/resources/CommerceStatement.ts (1)
CommerceStatementGroup(39-58)
🪛 LanguageTool
.changeset/three-knives-play.md
[grammar] ~6-~6: There might be a mistake here.
Context: ...es': patch --- - Export Feature type from backend resource. - Re-export canonical...
(QB_NEW_EN)
[grammar] ~6-~6: There might be a mistake here.
Context: ...rt Feature type from backend resource. - Re-export canonical `CommerceMoneyAmount...
(QB_NEW_EN)
⏰ 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). (4)
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (7)
packages/types/src/commerce.ts (4)
415-445: LGTM: Clear feature docs and internal snapshot hook.Docs are precise;
__internal_toSnapshotis hidden. Good addition.
170-193: Payment source methods API looks good.Type surfaces and pagination use
WithOptionalOrgTypecorrectly.
1132-1152: LGTM: CanonicalCommerceMoneyAmountdocs.Accurately documents minor units and formatted amounts.
1154-1185: LGTM: Checkout totals.Clear field semantics; consistent with money type.
packages/backend/src/api/resources/CommerceSubscriptionItem.ts (3)
6-9: Fill in the Backend API doc link before merge.Replace the
(TODO)link with the actual Backend API docs URL.Would you like me to propose the final URL once the docs build preview is available?
107-126: LGTM: JSON mapping.Field mappings match JSON keys;
CommercePlan.fromJSONis correctly used.
1-1: All exports verified – no action neededThe interface
CommerceMoneyAmountJSONis publicly exported inpackages/types/src/json.tsand is re-exported through the package’s entry point, so importing it from@clerk/typeswill succeed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/backend/src/api/resources/CommerceSubscriptionItem.ts (1)
21-23: Avoid hard-coded union forplanPeriod; bind to JSON source-of-truth.Using the JSON-declared type prevents drift if the backend introduces new values.
- readonly planPeriod: 'month' | 'annual', + readonly planPeriod: CommerceSubscriptionItemJSON['plan_period'],Also applies to: 110-110
🧹 Nitpick comments (4)
packages/backend/src/api/resources/CommerceSubscriptionItem.ts (4)
1-3: Prefer type-only import for theplantype, keep value import for runtime.Use a separate type-only import to avoid pulling types into runtime bundles while still using the value for
fromJSON.import type { CommerceMoneyAmount, CommerceMoneyAmountJSON } from '@clerk/types'; -import { CommercePlan } from './CommercePlan'; +import type { CommercePlan as CommercePlanType } from './CommercePlan'; +import { CommercePlan } from './CommercePlan';And update the property annotation below:
- readonly plan: CommercePlan, + readonly plan: CommercePlanType,
44-44: Consistent optionals: alignamountwith other optional money fields.Minor: consider making
amountoptional (likelifetimePaid?) instead of| undefinedfor consistency. Defer if this is a public API stability concern.- readonly amount: CommerceMoneyAmount | null | undefined, + readonly amount?: CommerceMoneyAmount | null,Also applies to: 88-88
92-106: DeduplicateformatAmountJSONacross resources.This helper likely exists elsewhere (or will soon). Extract to a shared util to ensure consistent mapping and reduce duplication.
114-114: Fail fast if required nested resource is missing.If
data.planis unexpectedly absent, throw a typed error for easier debugging instead of crashing deeper.static fromJSON(data: CommerceSubscriptionItemJSON): CommerceSubscriptionItem { + if (!data.plan) { + throw new TypeError('Missing required "plan" in CommerceSubscriptionItemJSON'); + }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
.typedoc/__tests__/__snapshots__/file-structure.test.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (3)
packages/backend/src/api/resources/CommercePlan.ts(2 hunks)packages/backend/src/api/resources/CommerceSubscription.ts(2 hunks)packages/backend/src/api/resources/CommerceSubscriptionItem.ts(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/backend/src/api/resources/CommerceSubscription.ts
- packages/backend/src/api/resources/CommercePlan.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/backend/src/api/resources/CommerceSubscriptionItem.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/backend/src/api/resources/CommerceSubscriptionItem.ts
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/backend/src/api/resources/CommerceSubscriptionItem.ts
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/backend/src/api/resources/CommerceSubscriptionItem.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/backend/src/api/resources/CommerceSubscriptionItem.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/backend/src/api/resources/CommerceSubscriptionItem.ts
⏰ 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). (6)
- GitHub Check: Build Packages
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (3)
packages/backend/src/api/resources/CommerceSubscriptionItem.ts (3)
7-9: Good: kept the@experimentaltag with clear context.Retaining this tag aligns with prior feedback and sets expectations for consumers.
25-25: Good: unified “Unix timestamp (milliseconds)” wording across time fields.Consistent time unit doc reduces consumer confusion.
Also applies to: 54-54, 58-58, 62-62, 66-66, 70-70, 74-74
7-9: No changes required — the link to/docs/reference/backend-api/tag/commerce/get/commerce/subscription_itemsis correct, and the docs generator supports the{{ target: '_blank' }}inline prop for markdown links.
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/backend/src/api/resources/CommercePlan.ts (1)
81-95: Harden fromJSON against nullable fields and optional arrays.
- description may be
nullin JSON; coalesce toundefinedto match the constructor type.- features should default to an empty array to avoid
.mapon undefined.Apply:
- data.description, + data.description ?? undefined, @@ - data.features.map(feature => Feature.fromJSON(feature)), + (data.features ?? []).map(feature => Feature.fromJSON(feature)),
♻️ Duplicate comments (1)
packages/backend/src/api/resources/CommerceSubscription.ts (1)
9-9: Thanks for retaining the @experimental tag.Matches the prior review requirement to keep this around.
🧹 Nitpick comments (6)
packages/backend/src/api/resources/CommercePlan.ts (3)
68-68: Tighten immutability of features array.Expose as a readonly array to prevent accidental mutation by SDK consumers.
Apply:
- readonly features: Feature[], + readonly features: readonly Feature[],
52-60: Docs nit: avoid UI-component coupling in backend type docs.Optional: rephrase to describe visibility without naming a specific component, or add “e.g.” to reduce coupling.
Possible tweak:
- * Whether the plan is displayed in the `<PriceTable/>` component. + * Whether the plan is publicly visible (e.g., in pricing tables).Also applies to: 46-48
71-79: Tighten formatAmountJSON signature Change the parameter to fee: NonNullable<CommercePlanJSON['fee']> and annotate its return as : CommerceMoneyAmount—no runtime null check needed since fee, annual_fee and annual_monthly_fee are always present in CommercePlanJSON.packages/backend/src/api/resources/CommerceSubscription.ts (3)
26-26: Unify timestamp phrasing (explicit UTC + epoch).Minor doc polish for consistency across fields.
- * Unix timestamp (milliseconds) of when the subscription was created. + * Unix timestamp in milliseconds since Unix epoch (UTC) when the subscription was created. @@ - * Unix timestamp (milliseconds) of when the subscription was last updated. + * Unix timestamp in milliseconds since Unix epoch (UTC) when the subscription was last updated. @@ - * Unix timestamp (milliseconds) of when the subscription became active. + * Unix timestamp in milliseconds since Unix epoch (UTC) when the subscription became active. @@ - * Unix timestamp (milliseconds) of when the subscription became past due. + * Unix timestamp in milliseconds since Unix epoch (UTC) when the subscription became past due.Also applies to: 30-30, 34-34, 38-38
44-44: Prefer ReadonlyArray for immutability of collection properties.Aligns with the guideline to prefer immutable data structures.
- readonly subscriptionItems: CommerceSubscriptionItem[], + public readonly subscriptionItems: ReadonlyArray<CommerceSubscriptionItem>,
12-53: Add explicitpublicmodifiers to constructor parameter properties – TypeScript’s parameter properties default to public, but our style guide prefers explicit modifiers for public APIs. No external instantiations of this backend class were found outside its own file, so this change is safe to apply.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
packages/backend/src/api/resources/CommercePlan.ts(2 hunks)packages/backend/src/api/resources/CommerceSubscription.ts(2 hunks)packages/backend/src/api/resources/CommerceSubscriptionItem.ts(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/backend/src/api/resources/CommerceSubscriptionItem.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscription.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscription.ts
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscription.ts
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscription.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscription.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/backend/src/api/resources/CommercePlan.tspackages/backend/src/api/resources/CommerceSubscription.ts
⏰ 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). (6)
- GitHub Check: Build Packages
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (6)
packages/backend/src/api/resources/CommercePlan.ts (4)
1-1: Good move: rely on canonical CommerceMoneyAmount from @clerk/types.Eliminates duplication and drift across packages.
9-9: Thanks for keeping @experimental.Aligns with prior guidance; sets correct expectations for consumers.
18-20: JSDoc clarity: productId wording is clear.No further changes needed here.
7-9: Docs: confirm backend API link and remove unsupported template markup
I couldn’t locate/docs/reference/backend-api/tag/commerce/get/commerce/plansor any{{ target: '_blank' }}in the generated docs—please verify that the URL is correct in your docs pipeline and drop the{{ target: '_blank' }}if it isn’t supported.packages/backend/src/api/resources/CommerceSubscription.ts (2)
7-8: Use stable BAPI Redoc URL and add @see tagReplace the absolute Clerk.com link with the stable Redoc link to the GET /organizations/{organization_id}/billing/subscription endpoint, and add an @see tag. For example:
- * The `CommerceSubscription` object is similar to the [`CommerceSubscriptionResource`](/docs/references/javascript/types/commerce-subscription-resource) object as it holds information about a subscription, as well as methods for managing it. However, the `CommerceSubscription` object is different in that it is used in the [Backend API](https://clerk.com/docs/reference/backend-api/tag/billing/get/organizations/%7Borganization_id%7D/billing/subscription) and is not directly accessible from the Frontend API. + * The `CommerceSubscription` object is similar to the [`CommerceSubscriptionResource`](/docs/references/javascript/types/commerce-subscription-resource) object as it holds information about a subscription and methods for managing it. However, `CommerceSubscription` is used in the [Backend API](https://clerk-bapi.redoc.ly/tag/Organizations/paths/~1organizations~1%7Borganization_id%7D~1billing~1subscription/get) and is not directly accessible from the Frontend API. + * @see {@link https://clerk-bapi.redoc.ly/tag/Organizations/paths/~1organizations~1%7Borganization_id%7D~1billing~1subscription/get | GET /organizations/{organization_id}/billing/subscription}
1-1: Confirm CommerceMoneyAmount field parity
@clerk/typesis already declared in packages/backend/package.json.- Verify that the exported
CommerceMoneyAmounttype includes the fields you’re mapping (amountFormatted,currencySymbol) and no others.
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/types/src/commerce.ts (1)
170-193: Use Omit, not Exclude, to drop 'orgId' from object typesExclude works on union members, not object keys. As written, it doesn’t remove orgId and weakens type-safety for these APIs.
Apply:
initializePaymentSource: ( - params: Exclude<InitializePaymentSourceParams, 'orgId'>, + params: Omit<InitializePaymentSourceParams, 'orgId'>, ) => Promise<CommerceInitializedPaymentSourceResource>; @@ - addPaymentSource: (params: Exclude<AddPaymentSourceParams, 'orgId'>) => Promise<CommercePaymentSourceResource>; + addPaymentSource: (params: Omit<AddPaymentSourceParams, 'orgId'>) => Promise<CommercePaymentSourceResource>; @@ - getPaymentSources: ( - params: Exclude<GetPaymentSourcesParams, 'orgId'>, + getPaymentSources: ( + params: Omit<GetPaymentSourcesParams, 'orgId'>, ) => Promise<ClerkPaginatedResponse<CommercePaymentSourceResource>>;
♻️ Duplicate comments (2)
packages/types/src/commerce.ts (2)
146-151: Unify period literal: 'annual' vs 'year'This union still uses 'annual'. Other call sites (UI/logic/translations) often branch on 'year'. Pick one and use it everywhere to avoid type/logic drift.
Apply in-file fix (if you standardize on 'year'):
-export type CommerceSubscriptionPlanPeriod = 'month' | 'annual'; +export type CommerceSubscriptionPlanPeriod = 'month' | 'year';Then update downstream branches/keys accordingly. Run to find stragglers:
#!/bin/bash rg -nP -C2 "\b(annual|year)\b" --type=ts --type=tsx
1228-1259: ConfirmCheckoutParams allows {} and contradicts docs; require exactly one branch and gateway where neededCurrent union uses optional fields, so an empty object type-checks. Also gateway is optional despite docs saying required with token/test card.
Apply:
-export type ConfirmCheckoutParams = WithOptionalOrgType< - | { - /** - * The ID of a saved payment source to use for this checkout. - */ - paymentSourceId?: string; - } - | { - /** - * A token representing payment details, usually from a payment form. **Requires** `gateway` to be provided. - */ - paymentToken?: string; - /** - * The payment gateway to use. For example, `'stripe'` or `'paypal'`. **Required** if `paymentToken` or `useTestCard` is provided. - */ - gateway?: PaymentGateway; - } - | { - /** - * The payment gateway to use. For example, `'stripe'` or `'paypal'`. **Required** if `paymentToken` or `useTestCard` is provided. - */ - gateway?: PaymentGateway; - /** - * If true, uses a test card for the checkout. **Requires** `gateway` to be provided. - */ - useTestCard?: boolean; - } ->; +export type ConfirmCheckoutParams = WithOptionalOrgType< + | { + /** The ID of a saved payment source to use for this checkout. */ + paymentSourceId: string; + } + | { + /** A token representing payment details, usually from a payment form. */ + paymentToken: string; + /** Required when using `paymentToken`. */ + gateway: PaymentGateway; + } + | { + /** Use a test card for the checkout. */ + useTestCard: true; + /** Required when `useTestCard` is provided. */ + gateway: PaymentGateway; + } +>;
🧹 Nitpick comments (3)
packages/types/src/commerce.ts (3)
251-261: Align payer type naming (org vs organization)GetPlansParams accepts 'organization' while CommercePlanResource.forPayerType uses 'org'. This inconsistency leaks into consumer code and filters.
Minimal compatibility tweak:
-export type ForPayerType = 'organization' | 'user'; +export type ForPayerType = 'organization' | 'org' | 'user';If FAPI only accepts 'organization', keep the type as-is but ensure UI/resource fields use the same literal (or normalize centrally).
32-41: Normalize param typing to WithOptionalOrgType for consistencyThis method hand-inlines orgId, unlike the rest that use WithOptionalOrgType.
Apply:
- getPaymentAttempt: (params: { id: string; orgId?: string }) => Promise<CommercePaymentResource>; + getPaymentAttempt: (params: WithOptionalOrgType<{ id: string }>) => Promise<CommercePaymentResource>;
575-580: Prefer optional property over 'string | undefined'For consistency with the rest of the file, make walletType optional.
Apply:
- walletType: string | undefined; + walletType?: string;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
packages/types/src/commerce.ts(7 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/types/src/commerce.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/types/src/commerce.ts
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/types/src/commerce.ts
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/types/src/commerce.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/types/src/commerce.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/types/src/commerce.ts
🧬 Code graph analysis (1)
packages/types/src/commerce.ts (3)
packages/types/src/resource.ts (1)
ClerkResource(8-21)packages/types/src/snapshots.ts (1)
CommerceFeatureJSONSnapshot(194-194)packages/clerk-js/src/core/resources/CommerceStatement.ts (1)
CommerceStatementGroup(39-58)
⏰ 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). (6)
- GitHub Check: Build Packages
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (2)
packages/types/src/commerce.ts (2)
415-445: LGTM: Clearer Feature docs + explicit id and snapshot methodDocs are clear and the public surface matches intent. Keeping @experimental is also correct.
542-594: LGTM: Payment source surface looks coherentAdding id, status, defaults, and mutators (remove/makeDefault) aligns with expected UX flows. Good JSDoc.
| * The `CommerceCheckoutResource` type represents information about a checkout session. | ||
| * | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to pin the SDK version and the clerk-js version to avoid breaking changes. | ||
| */ | ||
| export interface CommerceCheckoutResource extends ClerkResource { | ||
| /** | ||
| * The unique identifier for the checkout session. | ||
| */ | ||
| id: string; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * A client secret from an external payment provider (such as Stripe) used to complete the payment on the client-side. | ||
| */ | ||
| externalClientSecret: string; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * The identifier for the external payment gateway used for this checkout session. | ||
| */ | ||
| externalGatewayId: string; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * The payment source being used for the checkout, such as a credit card or bank account. | ||
| */ | ||
| paymentSource?: CommercePaymentSourceResource; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * The subscription plan details for the checkout. | ||
| */ | ||
| plan: CommercePlanResource; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * The billing period for the plan. | ||
| */ | ||
| planPeriod: CommerceSubscriptionPlanPeriod; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * Unix timestamp (milliseconds) of when the current period starts. | ||
| */ | ||
| planPeriodStart?: number; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * The current status of the checkout session. | ||
| */ | ||
| status: 'needs_confirmation' | 'completed'; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * The total costs, taxes, and other pricing details for the checkout. | ||
| */ | ||
| totals: CommerceCheckoutTotals; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * A function to confirm and finalize the checkout process, usually after payment information has been provided and validated. [Learn more.](#confirm) | ||
| */ | ||
| confirm: (params: ConfirmCheckoutParams) => Promise<CommerceCheckoutResource>; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * Whether the plan change will take effect immediately after checkout. | ||
| */ | ||
| isImmediatePlanChange: boolean; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * Unix timestamp (milliseconds) of when the free trial ends. | ||
| */ | ||
| freeTrialEndsAt: Date | null; | ||
| } |
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.
🛠️ Refactor suggestion
Time fields: fix Date vs Unix ms inconsistency
planPeriodStart is number (ms) but other timestamps are Date. freeTrialEndsAt JSDoc says Unix ms but type is Date. Standardize on Date for resource types and convert at the edge.
Apply:
- /**
- * Unix timestamp (milliseconds) of when the current period starts.
- */
- planPeriodStart?: number;
+ /**
+ * The date when the current period starts.
+ */
+ planPeriodStart?: Date;
@@
- /**
- * Unix timestamp (milliseconds) of when the free trial ends.
- */
- freeTrialEndsAt: Date | null;
+ /**
+ * The date when the free trial ends.
+ */
+ freeTrialEndsAt: Date | null;If FAPI returns ms, keep the runtime conversion (JSON -> Date) consistent with other resources and document it once centrally.
📝 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.
| * The `CommerceCheckoutResource` type represents information about a checkout session. | |
| * | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to pin the SDK version and the clerk-js version to avoid breaking changes. | |
| */ | |
| export interface CommerceCheckoutResource extends ClerkResource { | |
| /** | |
| * The unique identifier for the checkout session. | |
| */ | |
| id: string; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * A client secret from an external payment provider (such as Stripe) used to complete the payment on the client-side. | |
| */ | |
| externalClientSecret: string; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * The identifier for the external payment gateway used for this checkout session. | |
| */ | |
| externalGatewayId: string; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * The payment source being used for the checkout, such as a credit card or bank account. | |
| */ | |
| paymentSource?: CommercePaymentSourceResource; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * The subscription plan details for the checkout. | |
| */ | |
| plan: CommercePlanResource; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * The billing period for the plan. | |
| */ | |
| planPeriod: CommerceSubscriptionPlanPeriod; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * Unix timestamp (milliseconds) of when the current period starts. | |
| */ | |
| planPeriodStart?: number; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * The current status of the checkout session. | |
| */ | |
| status: 'needs_confirmation' | 'completed'; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * The total costs, taxes, and other pricing details for the checkout. | |
| */ | |
| totals: CommerceCheckoutTotals; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * A function to confirm and finalize the checkout process, usually after payment information has been provided and validated. [Learn more.](#confirm) | |
| */ | |
| confirm: (params: ConfirmCheckoutParams) => Promise<CommerceCheckoutResource>; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * Whether the plan change will take effect immediately after checkout. | |
| */ | |
| isImmediatePlanChange: boolean; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * Unix timestamp (milliseconds) of when the free trial ends. | |
| */ | |
| freeTrialEndsAt: Date | null; | |
| } | |
| export interface CommerceCheckoutResource extends ClerkResource { | |
| /** | |
| * The unique identifier for the checkout session. | |
| */ | |
| id: string; | |
| /** | |
| * A client secret from an external payment provider (such as Stripe) used to complete the payment on the client-side. | |
| */ | |
| externalClientSecret: string; | |
| /** | |
| * The identifier for the external payment gateway used for this checkout session. | |
| */ | |
| externalGatewayId: string; | |
| /** | |
| * The payment source being used for the checkout, such as a credit card or bank account. | |
| */ | |
| paymentSource?: CommercePaymentSourceResource; | |
| /** | |
| * The subscription plan details for the checkout. | |
| */ | |
| plan: CommercePlanResource; | |
| /** | |
| * The billing period for the plan. | |
| */ | |
| planPeriod: CommerceSubscriptionPlanPeriod; | |
| - /** | |
| - * Unix timestamp (milliseconds) of when the current period starts. | |
| - */ | |
| /** | |
| * The date when the current period starts. | |
| */ | |
| planPeriodStart?: Date; | |
| /** | |
| * The current status of the checkout session. | |
| */ | |
| status: 'needs_confirmation' | 'completed'; | |
| /** | |
| * The total costs, taxes, and other pricing details for the checkout. | |
| */ | |
| totals: CommerceCheckoutTotals; | |
| /** | |
| * A function to confirm and finalize the checkout process, usually after payment information has been provided and validated. [Learn more.](#confirm) | |
| */ | |
| confirm: (params: ConfirmCheckoutParams) => Promise<CommerceCheckoutResource>; | |
| /** | |
| * Whether the plan change will take effect immediately after checkout. | |
| */ | |
| isImmediatePlanChange: boolean; | |
| - /** | |
| - * Unix timestamp (milliseconds) of when the free trial ends. | |
| - */ | |
| /** | |
| * The date when the free trial ends. | |
| */ | |
| freeTrialEndsAt: Date | null; | |
| } |
🤖 Prompt for AI Agents
packages/types/src/commerce.ts around lines 1262 to 1315: the timestamp fields
are inconsistent—planPeriodStart is typed as a Unix-ms number while
freeTrialEndsAt JSDoc says Unix ms but the type is Date; standardize both
resource fields to use Date (and nullable where appropriate) and update their
JSDoc to indicate they are Date objects (UTC), not raw ms; keep conversion from
FAPI (ms -> Date) at the runtime/edge layer rather than here and add a
single-line JSDoc note pointing to the central conversion behavior.
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 (3)
packages/types/src/commerce.ts (3)
146-151: Standardize plan period literal: 'annual' vs 'year'This still conflicts with usages expecting 'year'. Align now to avoid downstream condition/translation drift.
Apply:
-export type CommerceSubscriptionPlanPeriod = 'month' | 'annual'; +export type CommerceSubscriptionPlanPeriod = 'month' | 'year';Run to find remaining sites that assume either spelling:
#!/bin/bash rg -nP -C2 "\b(annual|year|yearly)\b" --type=ts --type=tsx packages
1234-1238: Encode param constraints in the type (require gateway and enforce exclusivity)
- Docs say gateway is required when using
paymentTokenoruseTestCard, but type allows omission.- Make each branch’s discriminant required; otherwise TS will accept objects containing multiple options at once.
Apply minimal fix:
| { /** * The ID of a saved payment source to use for this checkout. */ - paymentSourceId?: string; + paymentSourceId: string; } | { /** * A token representing payment details, usually from a payment form. **Requires** `gateway` to be provided. */ paymentToken?: string; /** * The payment gateway to use. For example, `'stripe'` or `'paypal'`. **Required** if `paymentToken` or `useTestCard` is provided. */ - gateway?: PaymentGateway; + gateway: PaymentGateway; } | { /** * The payment gateway to use. For example, `'stripe'` or `'paypal'`. **Required** if `paymentToken` or `useTestCard` is provided. */ - gateway?: PaymentGateway; + gateway: PaymentGateway; /** * If true, uses a test card for the checkout. **Requires** `gateway` to be provided. */ - useTestCard?: boolean; + useTestCard: true; }Optional but better: wrap the union with
WithOptionalOrgType<...>to alloworgIdconsistently on all branches.Also applies to: 1245-1248, 1251-1254
1291-1294: Fix Date vs Unix ms inconsistency in checkout timestampsResource fields should surface Dates; keep ms conversion at the edge. JSDoc for
freeTrialEndsAtalso contradicts its type.Apply:
- /** - * Unix timestamp (milliseconds) of when the current period starts. - */ - planPeriodStart?: number; + /** + * The date when the current period starts. + */ + planPeriodStart?: Date; @@ - /** - * Unix timestamp (milliseconds) of when the free trial ends. - */ - freeTrialEndsAt: Date | null; + /** + * The date when the free trial ends. + */ + freeTrialEndsAt: Date | null;Also applies to: 1311-1314
🧹 Nitpick comments (1)
packages/types/src/commerce.ts (1)
543-594: Tighten optionality and unions on payment source fields
- Prefer optional property to
string | undefinedfor walletType; it renders better in TypeDoc and matches codebase style.- Consider future follow-up to narrow
paymentMethod/cardType/walletTypeto unions if the value space is known (e.g., 'card' | 'bank_account'; 'visa' | 'mastercard'; 'apple_pay' | 'google_pay'), but that's optional for this PR.Apply:
- walletType: string | undefined; + walletType?: string;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
.typedoc/__tests__/__snapshots__/file-structure.test.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (1)
packages/types/src/commerce.ts(7 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/types/src/commerce.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/types/src/commerce.ts
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/types/src/commerce.ts
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/types/src/commerce.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/types/src/commerce.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/types/src/commerce.ts
🧬 Code graph analysis (1)
packages/types/src/commerce.ts (3)
packages/types/src/resource.ts (1)
ClerkResource(8-21)packages/types/src/snapshots.ts (1)
CommerceFeatureJSONSnapshot(194-194)packages/clerk-js/src/core/resources/CommerceStatement.ts (1)
CommerceStatementGroup(39-58)
⏰ 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). (6)
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: Build Packages
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (6)
packages/types/src/commerce.ts (6)
7-11: LGTM: Helpful JSDoc on WithOptionalOrgType.orgIdClear param docs; matches pattern used elsewhere.
415-445: LGTM: Feature resource shape and hidden snapshot hookGood addition of explicit id and @hidden snapshot method; matches export goals.
448-451: LGTM: Narrow, explicit payment source status unionWorks well for API docs and DX.
1228-1231: LGTM: Clear exclusivity note for confirm() paramsThe “only one of …” guidance is great for DX.
1135-1156: LGTM: MoneyAmount docs are clear and actionableGood examples and consistent field naming.
1159-1188: LGTM: Checkout totals surface areaFields are cohesive and map cleanly to MoneyAmount.
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * The `CommerceStatementGroup` type represents a group of payment items within a statement. | ||
| * | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to pin the SDK version and the clerk-js version to avoid breaking changes. | ||
| */ | ||
| export interface CommerceStatementGroup { | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * The date and time when this group of payment items was created or last updated. | ||
| */ | ||
| timestamp: Date; | ||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | ||
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | ||
| * @example | ||
| * ```tsx | ||
| * <ClerkProvider clerkJsVersion="x.x.x" /> | ||
| * ``` | ||
| * An array of payment resources that belong to this group. | ||
| */ | ||
| items: CommercePaymentResource[]; | ||
| } |
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.
💡 Verification agent
🧩 Analysis chain
Statement group id mismatch between runtime and types
Runtime class consumes data.id and exposes id: string, but the type omits it. If FAPI truly does not return an id, we either need (a) a synthetic, documented id in the runtime or (b) to remove/adjust the runtime reliance. Leaving this divergent guarantees undefined at runtime or type unsafety.
If we decide to model the runtime shape in types, apply:
export interface CommerceStatementGroup {
+ /**
+ * Unique identifier for this group (matches runtime class). If FAPI does not provide one,
+ * use a stable synthetic id and document the derivation.
+ */
+ id: string;
/**
* The date and time when this group of payment items was created or last updated.
*/
timestamp: Date;
/**
* An array of payment resources that belong to this group.
*/
items: CommercePaymentResource[];
}To verify current runtime expectation:
🏁 Script executed:
#!/bin/bash
rg -nC2 "class\s+CommerceStatementGroup|data\.id\b" packagesLength of output: 46220
Add missing id property to CommerceStatementGroup type
export interface CommerceStatementGroup {
+ /**
+ * Unique identifier for this group (matches runtime class `id`).
+ * If FAPI doesn’t supply one, derive a stable synthetic ID and document it.
+ */
+ id: string;
/**
* The date and time when this group of payment items was created or last updated.
*/
timestamp: Date;
/**
* An array of payment resources that belong to this group.
*/
items: CommercePaymentResource[];
}📝 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.
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * The `CommerceStatementGroup` type represents a group of payment items within a statement. | |
| * | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to pin the SDK version and the clerk-js version to avoid breaking changes. | |
| */ | |
| export interface CommerceStatementGroup { | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * The date and time when this group of payment items was created or last updated. | |
| */ | |
| timestamp: Date; | |
| /** | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. | |
| * It is advised to pin the SDK version and the clerk-js version to a specific version to avoid breaking changes. | |
| * @example | |
| * ```tsx | |
| * <ClerkProvider clerkJsVersion="x.x.x" /> | |
| * ``` | |
| * An array of payment resources that belong to this group. | |
| */ | |
| items: CommercePaymentResource[]; | |
| } | |
| /** | |
| * The `CommerceStatementGroup` type represents a group of payment items within a statement. | |
| * | |
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to pin the SDK version and the clerk-js version to avoid breaking changes. | |
| */ | |
| export interface CommerceStatementGroup { | |
| /** | |
| * Unique identifier for this group (matches runtime class `id`). | |
| * If FAPI doesn’t supply one, derive a stable synthetic ID in the runtime layer and document it here. | |
| */ | |
| id: string; | |
| /** | |
| * The date and time when this group of payment items was created or last updated. | |
| */ | |
| timestamp: Date; | |
| /** | |
| * An array of payment resources that belong to this group. | |
| */ | |
| items: CommercePaymentResource[]; | |
| } |
🤖 Prompt for AI Agents
In packages/types/src/commerce.ts around lines 827 to 841, the
CommerceStatementGroup type is missing an id property; add a required id: string
field to the interface (with a brief JSDoc comment like "A unique identifier for
this statement group") so consumers can reference groups by id, and place it
alongside timestamp and items in the exported interface.
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/types/src/commerce.ts (2)
1213-1275: Fix Date vs Unix-ms inconsistency on checkout timestamps.Most timestamps are
Date, butplanPeriodStartisnumberandfreeTrialEndsAtJSDoc says Unix ms while type isDate. Standardize both asDateand update JSDoc.export interface CommerceCheckoutResource extends ClerkResource { @@ - /** - * Unix timestamp (milliseconds) of when the current period starts. - */ - planPeriodStart?: number; + /** + * The date when the current billing period starts. + */ + planPeriodStart?: Date; @@ - /** - * Unix timestamp (milliseconds) of when the free trial ends. - */ - freeTrialEndsAt: Date | null; + /** + * The date when the free trial ends. + */ + freeTrialEndsAt: Date | null;
845-847: MakepaymentSourceIdnullable across the API surface.
- In packages/types/src/commerce.ts, change
to//TODO(@COMMERCE): should this be nullable ? paymentSourceId: string;/** * The payment source used for this subscription item, if any. */ paymentSourceId: string | null;- In packages/clerk-js/src/core/resources/CommerceSubscription.ts, update the class property to
so its type matches incomingpaymentSourceId!: string | null;data.payment_source_idand avoids runtime type errors.
♻️ Duplicate comments (3)
packages/types/src/commerce.ts (3)
147-151: Standardize period literal: use 'year' instead of 'annual' (matches UI logic).There are known usages checking for
'year'. Keep literals consistent to avoid branching bugs and missing i18n keys.-export type CommerceSubscriptionPlanPeriod = 'month' | 'annual'; +export type CommerceSubscriptionPlanPeriod = 'month' | 'year';To verify drift across the repo:
#!/bin/bash rg -nP -C2 "\b(annual|year)\b" --type=ts --type=tsx
1180-1210: Enforce XOR and gateway requirement inconfirm()params.Type allows empty objects and multiple fields simultaneously; JSDoc requires exactly one, and gateway when token/test-card is used. Encode constraints in the type.
-export type ConfirmCheckoutParams = - | { - /** - * The ID of a saved payment source to use for this checkout. - */ - paymentSourceId?: string; - } - | { - /** - * A token representing payment details, usually from a payment form. **Requires** `gateway` to be provided. - */ - paymentToken?: string; - /** - * The payment gateway to use. For example, `'stripe'` or `'paypal'`. **Required** if `paymentToken` or `useTestCard` is provided. - */ - gateway?: PaymentGateway; - } - | { - /** - * The payment gateway to use. For example, `'stripe'` or `'paypal'`. **Required** if `paymentToken` or `useTestCard` is provided. - */ - gateway?: PaymentGateway; - /** - * If true, uses a test card for the checkout. **Requires** `gateway` to be provided. - */ - useTestCard?: boolean; - }; +export type ConfirmCheckoutParams = + // Use a saved payment source + | { + paymentSourceId: string; + paymentToken?: never; + useTestCard?: never; + gateway?: never; + } + // Use a payment token with an explicit gateway + | { + paymentToken: string; + gateway: PaymentGateway; + paymentSourceId?: never; + useTestCard?: never; + } + // Use a test card with an explicit gateway + | { + useTestCard: true; + gateway: PaymentGateway; + paymentSourceId?: never; + paymentToken?: never; + };
779-793: Add missingid: stringtoCommerceStatementGrouptype
Runtime mapsdata.idontoCommerceStatementGroup.id, but the interface omits it, causing a type/runtime mismatch.export interface CommerceStatementGroup { + /** + * Unique identifier for this group, matching the runtime `data.id`. + */ + id: string; /** * The date and time when this group of payment items was created or last updated. */
🧹 Nitpick comments (4)
packages/types/src/commerce.ts (4)
124-135: Unify payer literal names: 'org' vs 'organization'.
CommercePayerResourceType = 'org' | 'user'butForPayerType = 'organization' | 'user'. This drift can leak into APIs and filters. Pick one and use consistently (prefer 'organization' for external params, and mirror the same literals in resources), or add a single source type and aliases with explicit conversions in runtime.Apply if you choose to standardize on 'organization':
-export type CommercePayerResourceType = 'org' | 'user'; +export type CommercePayerResourceType = 'organization' | 'user';
495-546: Tighten types and return shapes for payment source; minor ergonomics.
- Prefer optional field over
string | undefinedforwalletType.- Consider
Promise<void>instead ofPromise<null>formakeDefault(idiomatic and tree-shake friendly). If API must return null, keep as-is.- Optionally narrow
paymentMethodandcardTypeto known unions while allowing string fallback later.export interface CommercePaymentSourceResource extends ClerkResource { @@ - walletType: string | undefined; + walletType?: string; @@ - makeDefault: (params?: MakeDefaultPaymentSourceParams) => Promise<null>; + makeDefault: (params?: MakeDefaultPaymentSourceParams) => Promise<void>; }
482-493: Prefer explicit empty-object params overunknown.
WithOptionalOrgType<unknown>collapses to just{ orgId?: string }. Use{}for readability in generated docs and type hints.-export type RemovePaymentSourceParams = WithOptionalOrgType<unknown>; +export type RemovePaymentSourceParams = WithOptionalOrgType<{}>; @@ -export type MakeDefaultPaymentSourceParams = WithOptionalOrgType<unknown>; +export type MakeDefaultPaymentSourceParams = WithOptionalOrgType<{}>;
1087-1108: Clarify money amount invariants (locale/format).Document whether
amountFormattedis locale-agnostic (e.g., dot decimal, no grouping) and whethercurrencySymbolis ASCII vs localized. Otherwise consumers may double-localize or mis-render./** - * The amount as a formatted string. For example, `10.00` for $10.00. + * The amount as a normalized, non-localized decimal string (dot as decimal separator, no grouping). + * For example, "10.00". Prefer localizing in the UI layer using `amount` + `currency`. */ amountFormatted: string; @@ /** - * The symbol for the currency. For example, `$`. + * The canonical currency symbol (ASCII). UI layers may substitute locale-specific symbols. */ currencySymbol: string;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
.typedoc/__tests__/__snapshots__/file-structure.test.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (1)
packages/types/src/commerce.ts(7 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/types/src/commerce.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/types/src/commerce.ts
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/types/src/commerce.ts
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/types/src/commerce.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/types/src/commerce.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/types/src/commerce.ts
🧬 Code graph analysis (1)
packages/types/src/commerce.ts (3)
packages/types/src/resource.ts (1)
ClerkResource(8-21)packages/types/src/snapshots.ts (1)
CommerceFeatureJSONSnapshot(194-194)packages/clerk-js/src/core/resources/CommerceStatement.ts (1)
CommerceStatementGroup(39-58)
⏰ 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). (6)
- GitHub Check: Build Packages
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (5)
packages/types/src/commerce.ts (5)
7-9: LGTM: Clear JSDoc for org scoping.Doc clarifies the optional org scoping cleanly.
367-397: LGTM: Feature resource JSDoc and snapshot hook.Good public fields and hidden snapshot method docs. Matches the intent to expose
Feature.
399-404: LGTM: PaymentSource status union is crisp.Status values are clear and documented inline.
1110-1141: LGTM: Checkout totals surface.Fields are well-defined and align with statement totals reuse.
1143-1148: LGTM: Statement totals omittotalDueNow.Makes sense for historical statements.
Description
Adds JSDoc comments to many commerce-related classes and types/interfaces.
Exports the
Featuretype from our backend resourceChecklist
pnpm testruns as expected.pnpm buildruns as expected.Type of change
Summary by CodeRabbit