Skip to content
Merged
5 changes: 5 additions & 0 deletions .changeset/fix-billing-typedoc-pages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/shared': patch
---

Fix broken Billing TypeDoc links and add missing JSDoc descriptions for the credit and discount types.
90 changes: 90 additions & 0 deletions .typedoc/__tests__/relative-link-replacements.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { describe, expect, it } from 'vitest';

// @ts-expect-error — .mjs plugin has no type declarations
import { applyRelativeLinkReplacements } from '../custom-plugin.mjs';

/**
* Unit coverage for the `LINK_REPLACEMENTS` rules exercised through the exported
* `applyRelativeLinkReplacements()` entry point. These guard the Billing checkout
* links so an incorrect route or anchor cannot silently pass CI.
*/
describe('applyRelativeLinkReplacements', () => {
const cases: Array<[label: string, input: string, expected: string]> = [
[
'confirm-checkout-params routes to the #confirm-parameters section',
'[x](confirm-checkout-params.mdx)',
'[x](/docs/reference/types/billing-checkout-resource#confirm-parameters)',
],
[
'update-checkout-params routes to the #update-parameters section',
'[x](update-checkout-params.mdx)',
'[x](/docs/reference/types/billing-checkout-resource#update-parameters)',
],
[
'preserves an anchor from the source link',
'[x](billing-credits.mdx#total)',
'[x](/docs/reference/types/billing-credits#total)',
],
[
'billing-credits routes to its standalone page',
'[x](billing-credits.mdx)',
'[x](/docs/reference/types/billing-credits)',
],
[
'billing-applied-discount routes to its standalone page',
'[x](billing-applied-discount.mdx)',
'[x](/docs/reference/types/billing-applied-discount)',
],
[
'billing-discount-redemption routes to its standalone page',
'[x](billing-discount-redemption.mdx)',
'[x](/docs/reference/types/billing-discount-redemption)',
],
[
'billing-payer-credit routes to its standalone page',
'[x](billing-payer-credit.mdx)',
'[x](/docs/reference/types/billing-payer-credit)',
],
[
'billing-proration-credit-detail routes to its standalone page',
'[x](billing-proration-credit-detail.mdx)',
'[x](/docs/reference/types/billing-proration-credit-detail)',
],
[
'resolves relative path prefixes',
'[x](../../types/billing-credits.mdx)',
'[x](/docs/reference/types/billing-credits)',
],
[
'resolves nested object-doc links',
'[x](billing-credits/billing-credits.mdx)',
'[x](/docs/reference/types/billing-credits)',
],
];

it.each(cases)('%s', (_label, input, expected) => {
expect(applyRelativeLinkReplacements(input)).toBe(expected);
});

it('routes the two sibling next-payment pages independently', () => {
expect(applyRelativeLinkReplacements('[x](billing-subscription-item-next-payment.mdx)')).toBe(
'[x](/docs/reference/types/billing-subscription-item-next-payment)',
);
expect(applyRelativeLinkReplacements('[x](billing-subscription-next-payment.mdx)')).toBe(
'[x](/docs/reference/types/billing-subscription-next-payment)',
);
});

it('does not rewrite a page whose name is a prefix of a replacement key', () => {
// `billing-payer` is a prefix of `billing-payer-credit`, but the `.mdx` boundary
// must keep an unrelated `billing-payer-resource.mdx` link from being mis-routed.
expect(applyRelativeLinkReplacements('[x](billing-payer-resource.mdx)')).toBe(
'[x](/docs/reference/types/billing-payer-resource)',
);
});

it('leaves content without matching links untouched', () => {
expect(applyRelativeLinkReplacements('no links here')).toBe('no links here');
expect(applyRelativeLinkReplacements('')).toBe('');
});
});
15 changes: 14 additions & 1 deletion .typedoc/custom-plugin.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const FILES_WITHOUT_HEADINGS = [
'organization-membership-public-user-data.mdx',
'checkout-signal-value.mdx',
'checkout-flow-resource.mdx',
'update-checkout-params.mdx',
'use-checkout-options.mdx',
'use-payment-element-return.mdx',
'use-payment-methods-return.mdx',
Expand Down Expand Up @@ -108,26 +109,38 @@ const LINK_REPLACEMENTS = [
['invitation', '/docs/reference/backend/types/backend-invitation'],
['verify-token-options', '#verify-token-options'],
['localization-resource', '/docs/guides/customizing-clerk/localization'],
['confirm-checkout-params', '/docs/reference/types/billing-checkout-resource#parameters'],
['confirm-checkout-params', '/docs/reference/types/billing-checkout-resource#confirm-parameters'],
['update-checkout-params', '/docs/reference/types/billing-checkout-resource#update-parameters'],
['billing-applied-discount', '/docs/reference/types/billing-applied-discount'],
['billing-credits', '/docs/reference/types/billing-credits'],
['billing-discount-redemption', '/docs/reference/types/billing-discount-redemption'],
['billing-discounts', '/docs/reference/types/billing-discounts'],
['billing-payment-totals', '/docs/reference/types/billing-payment-totals'],
['billing-payment-method-resource', '/docs/reference/types/billing-payment-method-resource'],
['billing-payer-credit', '/docs/reference/types/billing-payer-credit'],
['billing-payer-resource', '/docs/reference/types/billing-payer-resource'],
['billing-period-totals', '/docs/reference/types/billing-period-totals'],
['billing-plan-price', '/docs/reference/types/billing-plan-price'],
['billing-plan-resource', '/docs/reference/types/billing-plan-resource'],
['billing-plan-unit-price', '/docs/reference/types/billing-plan-unit-price'],
['billing-plan-unit-price-tier', '/docs/reference/types/billing-plan-unit-price-tier'],
['billing-proration-discount', '/docs/reference/types/billing-proration-discount'],
['billing-proration-credit-detail', '/docs/reference/types/billing-proration-credit-detail'],
['billing-checkout-totals', '/docs/reference/types/billing-checkout-totals'],
['billing-checkout-resource', '/docs/reference/types/billing-checkout-resource'],
['billing-money-amount', '/docs/reference/types/billing-money-amount'],
['billing-per-unit-total', '/docs/reference/types/billing-per-unit-total'],
['billing-per-unit-total-tier', '/docs/reference/types/billing-per-unit-total-tier'],
['billing-subscription-item-resource', '/docs/reference/types/billing-subscription-item-resource'],
['billing-subscription-item-next-payment', '/docs/reference/types/billing-subscription-item-next-payment'],
['billing-subscription-item-seats', '/docs/reference/types/billing-subscription-item-seats'],
['billing-subscription-item-status', '/docs/reference/backend/types/billing-subscription-item-status'],
['feature-resource', '/docs/reference/types/feature-resource'],
['billing-statement-group', '/docs/reference/types/billing-statement-group'],
['billing-statement-resource', '/docs/reference/types/billing-statement-resource'],
['billing-totals', '/docs/reference/types/billing-totals'],
['billing-subscription-resource', '/docs/reference/types/billing-subscription-resource'],
['billing-subscription-next-payment', '/docs/reference/types/billing-subscription-next-payment'],
['clerk-api-response-error', '/docs/reference/types/clerk-api-response-error'],
['clerk-api-error', '/docs/reference/types/clerk-api-error'],
['billing-statement-totals', '/docs/reference/types/billing-statement-totals'],
Expand Down
139 changes: 134 additions & 5 deletions packages/shared/src/types/billing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,9 @@ export interface BillingSubscriptionItemResource extends ClerkResource {
*/
amount: BillingMoneyAmount;
};
/**
* The credits applied to this subscription item.
*/
credits?: BillingCredits;
/**
* The active discount applied to this subscription item.
Expand Down Expand Up @@ -994,21 +997,63 @@ export interface BillingMoneyAmount {
currencySymbol: string;
}

/**
* Contains details about a proration credit, including the remaining portion of the billing cycle.
*
* @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](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
*/
export interface BillingProrationCreditDetail {
/**
* The monetary value of the proration credit.
*/
amount: BillingMoneyAmount;
/**
* The number of days remaining in the current billing cycle.
*/
cycleDaysRemaining: number;
/**
* The total number of days in the billing cycle.
*/
cycleDaysTotal: number;
/**
* The percentage of the billing cycle that remains.
*/
cycleRemainingPercent: number;
}

/**
* Contains details about the payer's available credit and the amount applied to the transaction.
*
* @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](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
*/
export interface BillingPayerCredit {
/**
* The payer's credit balance remaining after the transaction.
*/
remainingBalance: BillingMoneyAmount;
/**
* The amount of payer credit applied to the transaction.
*/
appliedAmount: BillingMoneyAmount;
}

/**
* The `BillingCredits` type represents the credits applied to a checkout or payment.
*
* @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](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
*/
export interface BillingCredits {
/**
* The credit for the unused portion of the current billing cycle. `null` when no proration credit applies.
*/
proration: BillingProrationCreditDetail | null;
/**
* The payer credit applied to the transaction. `null` when no payer credit applies.
*/
payer: BillingPayerCredit | null;
/**
* The total monetary value of all credits applied to the transaction.
*/
total: BillingMoneyAmount;
}

Expand Down Expand Up @@ -1043,14 +1088,44 @@ export interface BillingProrationDiscount {
* @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](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
*/
export interface BillingAppliedDiscount {
/**
* The monetary value of the discount applied to the transaction.
*/
amount: BillingMoneyAmount;
/**
* The unique identifier of the discount.
*/
discountId: string;
/**
* The display name of the discount.
*/
name: string;
/**
* Whether the discount subtracts a percentage or a fixed amount.
*/
effect: 'percentage' | 'fixed_amount';
/**
* The percentage deducted when `effect` is `'percentage'`.
*/
percentOff?: number;
/**
* The configured fixed amount off when `effect` is `'fixed_amount'`. This is the discount's configured value, which
* can differ from the `amount` actually applied to the transaction.
*/
amountOff?: BillingMoneyAmount;
/**
* The promotion code used to apply the discount.
*/
promoCode?: string;
/**
* The number of billing cycles for which the discount remains active. `null` means the discount does not expire
* after a fixed number of cycles.
*/
cyclesRemaining: number | null;
/**
* The originally configured duration in billing cycles. `null` means the discount does not expire after a fixed
* number of cycles.
*/
durationInCycles?: number | null;
}

Expand All @@ -1060,20 +1135,67 @@ export interface BillingAppliedDiscount {
* @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](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
*/
export interface BillingDiscountRedemption {
/**
* The unique identifier of the discount redemption.
*/
id: string;
/**
* The unique identifier of the subscription item receiving the discount.
*/
subscriptionItemId: string;
/**
* The unique identifier of the redeemed discount.
*/
discountId: string;
/**
* The display name of the discount.
*/
name: string;
/**
* How the discount was applied to the subscription item.
*/
source: 'promotion' | 'manual' | 'promo_code';
/**
* The promotion code used to redeem the discount.
*/
promoCode?: string;
/**
* Whether the discount subtracts a percentage or a fixed amount.
*/
effect?: 'percentage' | 'fixed_amount';
/**
* The percentage deducted when `effect` is `'percentage'`.
*/
percentOff?: number;
/**
* The configured fixed amount off when `effect` is `'fixed_amount'`. This is the discount's configured value, which
* can differ from the `amount` actually applied to the transaction.
*/
amountOff?: BillingMoneyAmount;
/**
* The monetary value of the discount applied to the subscription item.
*/
amount?: BillingMoneyAmount;
/**
* The number of billing cycles for which the discount remains active. `null` means the discount does not expire
* after a fixed number of cycles.
*/
cyclesRemaining: number | null;
/**
* The number of billing cycles to which the discount has already been applied.
*/
cyclesApplied: number;
/**
* The current status of the discount redemption.
*/
status?: 'active' | 'exhausted' | 'removed';
/**
* The date and time when the discount was redeemed.
*/
redeemedAt: Date;
/**
* The identifier of the user who redeemed the discount. `null` if no user was recorded.
*/
redeemedBy: string | null;
}

Expand Down Expand Up @@ -1232,6 +1354,9 @@ export interface BillingCheckoutTotals {
* Any credits (like account balance or promo credits) that are being applied to the checkout.
*/
credit: BillingMoneyAmount | null;
/**
* The credits applied to the checkout. `null` when no credits apply.
*/
credits: BillingCredits | null;
/**
* Any outstanding amount from previous unpaid invoices that is being collected as part of the checkout.
Expand Down Expand Up @@ -1302,16 +1427,20 @@ export type CreateCheckoutParams = WithOptionalOrgType<{
*
* @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](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
*/
export type UpdateCheckoutParams = WithOptionalOrgType<{
export type UpdateCheckoutParams = {
/**
* The unique identifier for the checkout session.
*/
id: string;
/**
* The Organization ID to perform the request on.
*/
orgId?: string;
/**
* The promo code to apply. Use an empty string to remove the applied promo code.
*/
promoCode: string;
}>;
};

/**
* The `confirm()` method accepts the following parameters. **Only one of `paymentMethodId`, `paymentToken`, or `useTestCard` should be provided.**
Expand Down Expand Up @@ -1392,7 +1521,7 @@ export interface BillingCheckoutResource extends ClerkResource {
*/
totals: BillingTotals;
/**
* A function to confirm and finalize the checkout process, usually after payment information has been provided and validated. [Learn more.](#confirm)
* A function to confirm and finalize the checkout process, usually after payment information has been provided and validated. [Learn more.](https://clerk.com/docs/reference/types/billing-checkout-resource#confirm)
*/
confirm: (params: ConfirmCheckoutParams) => Promise<BillingCheckoutResource>;
/**
Expand Down Expand Up @@ -1542,12 +1671,12 @@ export interface CheckoutFlowFinalizeParams {
*/
interface CheckoutFlowMethods {
/**
* Updates the current checkout. Use an empty promo code to remove the applied promo code.
* Updates the current checkout. Use an empty promo code to remove the applied promo code. [Learn more.](https://clerk.com/docs/reference/types/billing-checkout-resource#update)
*/
update: (params: Pick<UpdateCheckoutParams, 'promoCode'>) => Promise<{ error: ClerkError | null }>;

/**
* A function to confirm and finalize the checkout process, usually after payment information has been provided and validated. [Learn more.](#confirm)
* A function to confirm and finalize the checkout process, usually after payment information has been provided and validated. [Learn more.](https://clerk.com/docs/reference/types/billing-checkout-resource#confirm)
*/
confirm: (params: ConfirmCheckoutParams) => Promise<{ error: ClerkError | null }>;

Expand Down
Loading
Loading