@usethrottle/subscriptions 3.4.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +3 -3
- package/README.md +4 -0
- package/dist/{chunk-XXR5PITK.js → chunk-QDARSRCR.js} +19 -1
- package/dist/chunk-QDARSRCR.js.map +1 -0
- package/dist/{errors-BkGOg36x.d.cts → errors-CfDCslmT.d.cts} +29 -0
- package/dist/{errors-BkGOg36x.d.ts → errors-CfDCslmT.d.ts} +29 -0
- package/dist/index.cjs +18 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/server.cjs +23 -2
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +6 -3
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-XXR5PITK.js.map +0 -1
package/CLAUDE.md
CHANGED
|
@@ -38,9 +38,9 @@ Direct customer-scoped browser tokens are intentionally not in v1 because the AP
|
|
|
38
38
|
no charge. Before 3.0.0, `changePlan()` silently WAS `update()` (a naming
|
|
39
39
|
trap: merchants calling `changePlan()` to upgrade never got the charge). Do
|
|
40
40
|
not re-merge these two.
|
|
41
|
-
- `changeQuantity()`, `retryCharge()`, `waivePeriod()`, `
|
|
42
|
-
`listUsage()` mirror the REST API 1:1 (`change-quantity`,
|
|
43
|
-
`waive-period`, `usage` POST + GET). `listUsage()`'s route answers
|
|
41
|
+
- `changeQuantity()`, `retryCharge()`, `waivePeriod()`, `setPaymentMethod()`,
|
|
42
|
+
`recordUsage()`, and `listUsage()` mirror the REST API 1:1 (`change-quantity`,
|
|
43
|
+
`retry-charge`, `waive-period`, `PATCH payment-method`, `usage` POST + GET). `listUsage()`'s route answers
|
|
44
44
|
`{ items: [...] }`, not the usual `{ data, meta }` envelope — read `items`
|
|
45
45
|
directly off `requestEnvelope()`, never `request()`'s data-unwrap.
|
|
46
46
|
- Keep API payloads camelCase on writes because the live Fastify validators expect camelCase.
|
package/README.md
CHANGED
|
@@ -102,8 +102,12 @@ const subscriptions = createSubscriptionsClient({
|
|
|
102
102
|
|
|
103
103
|
await subscriptions.cancel('sub_123', { atPeriodEnd: true });
|
|
104
104
|
await subscriptions.listCustomerPaymentMethods('cus_123');
|
|
105
|
+
// Move one subscription to another of its customer's saved cards.
|
|
106
|
+
await subscriptions.setPaymentMethod('sub_123', 'pm_456');
|
|
105
107
|
```
|
|
106
108
|
|
|
109
|
+
`setPaymentMethod()` changes only that subscription; the customer's default card and their other subscriptions stay as they are. The proxy helper forwards the same `PATCH .../payment-method` for the buyer's own subscriptions.
|
|
110
|
+
|
|
107
111
|
`create()` accepts either a Throttle `customerId` or your own `externalCustomerId`. When you pass `externalCustomerId`, the client resolves the Throttle customer row before calling the subscription create endpoint.
|
|
108
112
|
|
|
109
113
|
`createCheckoutSession()` takes an optional `recurring` intent. Send it for one
|
|
@@ -45,6 +45,7 @@ function normalizeSubscription(raw) {
|
|
|
45
45
|
pausedAt: optionalDateString(raw?.pausedAt),
|
|
46
46
|
cancelledAt: optionalDateString(raw?.cancelledAt),
|
|
47
47
|
metadata: objectOrEmpty(raw?.metadata),
|
|
48
|
+
paymentMethodId: optionalString(raw?.paymentMethodId),
|
|
48
49
|
renewalIssue: normalizeRenewalIssue(raw?.renewalIssue),
|
|
49
50
|
proration: raw?.proration ? {
|
|
50
51
|
creditCents: raw.proration.creditCents,
|
|
@@ -258,6 +259,7 @@ var SubscriptionsClient = class {
|
|
|
258
259
|
intervalCount: input.intervalCount,
|
|
259
260
|
totalPayments: input.totalPayments,
|
|
260
261
|
amount: input.amount,
|
|
262
|
+
allowZeroAmount: input.allowZeroAmount,
|
|
261
263
|
schedule: input.schedule,
|
|
262
264
|
currency: input.currency,
|
|
263
265
|
currentPeriodStart: toIso(input.currentPeriodStart),
|
|
@@ -330,6 +332,7 @@ var SubscriptionsClient = class {
|
|
|
330
332
|
intervalUnit: body.intervalUnit,
|
|
331
333
|
intervalCount: body.intervalCount,
|
|
332
334
|
amount: body.amount,
|
|
335
|
+
allowZeroAmount: body.allowZeroAmount,
|
|
333
336
|
effective: body.effective
|
|
334
337
|
}
|
|
335
338
|
);
|
|
@@ -372,6 +375,21 @@ var SubscriptionsClient = class {
|
|
|
372
375
|
);
|
|
373
376
|
return normalizeSubscription(data);
|
|
374
377
|
}
|
|
378
|
+
/**
|
|
379
|
+
* Set the saved card this one subscription renews on. Only this
|
|
380
|
+
* subscription moves: the customer's default card and their other
|
|
381
|
+
* subscriptions stay as they are. Nothing is charged now; the next renewal
|
|
382
|
+
* (or dunning retry) charges the new card. Mirrors
|
|
383
|
+
* `PATCH /api/v1/subscriptions/{id}/payment-method`.
|
|
384
|
+
*/
|
|
385
|
+
async setPaymentMethod(id, paymentMethodId) {
|
|
386
|
+
const data = await this.request(
|
|
387
|
+
"PATCH",
|
|
388
|
+
`/api/v1/subscriptions/${encodeURIComponent(id)}/payment-method`,
|
|
389
|
+
{ paymentMethodId }
|
|
390
|
+
);
|
|
391
|
+
return normalizeSubscription(data);
|
|
392
|
+
}
|
|
375
393
|
/**
|
|
376
394
|
* Record (upsert) a usage item for the subscription's current billing
|
|
377
395
|
* period. Mirrors `POST /api/v1/subscriptions/{id}/usage`.
|
|
@@ -500,4 +518,4 @@ export {
|
|
|
500
518
|
SubscriptionsClient,
|
|
501
519
|
createSubscriptionsClient
|
|
502
520
|
};
|
|
503
|
-
//# sourceMappingURL=chunk-
|
|
521
|
+
//# sourceMappingURL=chunk-QDARSRCR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/normalize.ts","../src/client.ts"],"sourcesContent":["import { ThrottleError, type ThrottleErrorArgs } from '@usethrottle/errors';\n\n/**\n * Thrown on a non-2xx response from the Throttle Subscriptions API.\n *\n * Extends the shared {@link ThrottleError} so a single\n * `catch (e) { if (e instanceof ThrottleError) … }` covers errors from every\n * Throttle SDK. `instanceof ThrottleSubscriptionsError` keeps working.\n */\nexport class ThrottleSubscriptionsError extends ThrottleError {\n constructor(args: {\n code: string;\n message: string;\n statusCode: number;\n details?: unknown;\n responseHeaders?: ThrottleErrorArgs['responseHeaders'];\n }) {\n super(args);\n this.name = 'ThrottleSubscriptionsError';\n }\n}\n\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\n","import type {\n CheckoutSession,\n Customer,\n CustomerPaymentMethod,\n Pagination,\n Subscription,\n SubscriptionInterval,\n SubscriptionIntervalUnit,\n SubscriptionRenewalIssue,\n SubscriptionStatus,\n SubscriptionUsageItem,\n TrialEligibilityResult,\n} from './types';\n\nexport function normalizeSubscription(raw: any): Subscription {\n return {\n id: requiredString(raw?.id, 'subscription.id'),\n workspaceId: optionalString(raw?.workspaceId),\n applicationId: optionalString(raw?.applicationId),\n customerId: requiredString(raw?.customerId, 'subscription.customerId'),\n status: (raw?.status ?? 'active') as SubscriptionStatus,\n planReference: requiredString(raw?.planReference, 'subscription.planReference'),\n planName: optionalString(raw?.planName),\n interval: (raw?.interval ?? 'monthly') as SubscriptionInterval,\n intervalUnit: (optionalString(raw?.intervalUnit) as Subscription['intervalUnit']) ?? null,\n intervalCount: raw?.intervalCount == null ? null : Number(raw.intervalCount),\n totalPayments: raw?.totalPayments == null ? null : Number(raw.totalPayments),\n paymentsMade: Number(raw?.paymentsMade ?? 0),\n completedAt: optionalIsoDateString(raw?.completedAt),\n paymentSchedule: normalizePaymentSchedule(raw?.paymentSchedule),\n scheduleTotal: raw?.scheduleTotal == null ? null : Number(raw.scheduleTotal),\n nextPaymentAmount: raw?.nextPaymentAmount == null ? null : Number(raw.nextPaymentAmount),\n amount: Number(raw?.amount ?? 0),\n quantity: Number(raw?.quantity ?? 1),\n currency: optionalString(raw?.currency) ?? 'USD',\n currentPeriodStart: requiredDateString(\n raw?.currentPeriodStart,\n 'subscription.currentPeriodStart',\n ),\n currentPeriodEnd: requiredDateString(\n raw?.currentPeriodEnd,\n 'subscription.currentPeriodEnd',\n ),\n trialEnd: optionalDateString(raw?.trialEnd),\n cancelAtPeriodEnd: Boolean(raw?.cancelAtPeriodEnd ?? false),\n failureCount: Number(raw?.failureCount ?? 0),\n lastPaymentAt: optionalDateString(raw?.lastPaymentAt),\n pausedAt: optionalDateString(raw?.pausedAt),\n cancelledAt: optionalDateString(raw?.cancelledAt),\n metadata: objectOrEmpty(raw?.metadata),\n paymentMethodId: optionalString(raw?.paymentMethodId),\n renewalIssue: normalizeRenewalIssue(raw?.renewalIssue),\n proration: raw?.proration\n ? {\n creditCents: raw.proration.creditCents,\n chargedCents: raw.proration.chargedCents,\n fullAmount: raw.proration.fullAmount,\n }\n : undefined,\n createdAt: optionalDateString(raw?.createdAt) ?? undefined,\n updatedAt: optionalDateString(raw?.updatedAt) ?? undefined,\n };\n}\n\nfunction normalizePaymentSchedule(raw: any): Subscription['paymentSchedule'] {\n if (!Array.isArray(raw)) return null;\n return raw.map((r: any) => ({\n index: Number(r?.index ?? 0),\n amount: Number(r?.amount ?? 0),\n discount: Number(r?.discount ?? 0),\n net: Number(r?.net ?? 0),\n intervalUnit: (optionalString(r?.intervalUnit) as SubscriptionIntervalUnit | null) ?? null,\n intervalCount: r?.intervalCount == null ? null : Number(r.intervalCount),\n status: r?.status as 'paid' | 'due' | 'upcoming',\n dueAt: optionalDateString(r?.dueAt),\n }));\n}\n\nfunction normalizeRenewalIssue(raw: any): SubscriptionRenewalIssue | null {\n if (!raw || typeof raw !== 'object') return null;\n return {\n kind: raw.kind,\n reason: raw.reason,\n count: Number(raw.count ?? 0),\n firstAt: optionalString(raw.firstAt) ?? undefined,\n lastAt: requiredString(raw.lastAt, 'subscription.renewalIssue.lastAt'),\n message: raw.message ?? '',\n alertedAt: optionalDateString(raw.alertedAt),\n charge: raw.charge\n ? {\n transactionId: optionalString(raw.charge.transactionId),\n amount: Number(raw.charge.amount ?? 0),\n currency: optionalString(raw.charge.currency) ?? 'USD',\n periodStart: optionalString(raw.charge.periodStart) ?? undefined,\n }\n : null,\n };\n}\n\nexport function normalizeUsageItem(raw: any): SubscriptionUsageItem {\n return {\n id: requiredString(raw?.id, 'usageItem.id'),\n subscriptionId: requiredString(raw?.subscriptionId, 'usageItem.subscriptionId'),\n kind: raw?.kind ?? '',\n unitCount: Number(raw?.unitCount ?? 0),\n unitPriceCents: Number(raw?.unitPriceCents ?? 0),\n totalCents: Number(raw?.totalCents ?? 0),\n periodStart: requiredDateString(raw?.periodStart, 'usageItem.periodStart'),\n periodEnd: requiredDateString(raw?.periodEnd, 'usageItem.periodEnd'),\n createdAt: requiredDateString(raw?.createdAt, 'usageItem.createdAt'),\n };\n}\n\nexport function normalizeCustomer(raw: any): Customer | null {\n if (!raw) return null;\n return {\n id: requiredString(raw?.id, 'customer.id'),\n externalId: optionalString(raw?.externalId),\n email: optionalString(raw?.email),\n firstName: optionalString(raw?.firstName),\n lastName: optionalString(raw?.lastName),\n phone: optionalString(raw?.phone),\n company: optionalString(raw?.company),\n metadata: objectOrEmpty(raw?.metadata),\n createdAt: optionalDateString(raw?.createdAt) ?? undefined,\n updatedAt: optionalDateString(raw?.updatedAt) ?? undefined,\n };\n}\n\nexport function normalizeCustomerPaymentMethod(raw: any): CustomerPaymentMethod {\n return {\n id: requiredString(raw?.id, 'paymentMethod.id'),\n processor: optionalString(raw?.processor),\n methodType: optionalString(raw?.methodType),\n cardBrand: optionalString(raw?.cardBrand),\n cardLastFour: optionalString(raw?.cardLastFour),\n isDefault: Boolean(raw?.isDefault ?? false),\n isActive: Boolean(raw?.isActive ?? true),\n createdAt: optionalDateString(raw?.createdAt) ?? undefined,\n updatedAt: optionalDateString(raw?.updatedAt) ?? undefined,\n };\n}\n\nexport function normalizeCheckoutSession(raw: any): CheckoutSession {\n const sessionId = raw?.sessionId ?? raw?.id;\n return {\n ...withoutUnderscoreKeys(raw),\n id: optionalString(raw?.id) ?? undefined,\n sessionId: requiredString(sessionId, 'checkoutSession.sessionId'),\n checkoutUrl: optionalString(raw?.checkoutUrl) ?? undefined,\n embedToken: optionalString(raw?.embedToken) ?? undefined,\n expiresAt: optionalDateString(raw?.expiresAt) ?? undefined,\n };\n}\n\nexport function normalizeTrialEligibility(raw: any): TrialEligibilityResult {\n return {\n eligible: Boolean(raw?.eligible),\n reason: raw?.reason,\n };\n}\n\nexport function normalizePagination(raw: any): Pagination | undefined {\n if (!raw) return undefined;\n return {\n cursor: raw.cursor ?? null,\n hasMore: Boolean(raw.hasMore ?? false),\n };\n}\n\nexport function toIso(value: string | Date | undefined): string | undefined {\n if (value === undefined) return undefined;\n return value instanceof Date ? value.toISOString() : value;\n}\n\nfunction requiredString(value: unknown, label: string): string {\n if (typeof value === 'string' && value.length > 0) return value;\n throw new Error(`Invalid Throttle response: missing ${label}`);\n}\n\nfunction optionalString(value: unknown): string | null {\n return typeof value === 'string' ? value : null;\n}\n\nfunction requiredDateString(value: unknown, label: string): string {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && value.length > 0) return value;\n throw new Error(`Invalid Throttle response: missing ${label}`);\n}\n\nfunction optionalDateString(value: unknown): string | null {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && value.length > 0) return value;\n return null;\n}\n\n/**\n * Like `optionalDateString`, but always reserializes to a full ISO string\n * (with milliseconds) rather than passing a raw string through unchanged.\n * `completedAt` is a fresh field with no legacy raw-string callers to stay\n * compatible with, so it normalizes cleanly instead of echoing whatever the\n * API sent.\n */\nfunction optionalIsoDateString(value: unknown): string | null {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && value.length > 0) {\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? value : d.toISOString();\n }\n return null;\n}\n\nfunction objectOrEmpty(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction withoutUnderscoreKeys(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return {};\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).filter(([key]) => !key.includes('_')),\n );\n}\n","import { ThrottleSubscriptionsError } from './errors';\nimport {\n normalizeCheckoutSession,\n normalizeCustomer,\n normalizeCustomerPaymentMethod,\n normalizePagination,\n normalizeSubscription,\n normalizeTrialEligibility,\n normalizeUsageItem,\n toIso,\n} from './normalize';\nimport type {\n ChangePlanInput,\n ChangeQuantityInput,\n CheckoutSession,\n CreateCheckoutSessionInput,\n CreateSubscriptionInput,\n Customer,\n CustomerPaymentMethod,\n ListSubscriptionsParams,\n PaginatedSubscriptions,\n RecordUsageInput,\n Subscription,\n SubscriptionInvoiceRefund,\n SubscriptionUsageItem,\n SubscriptionsClientContract,\n SubscriptionsClientOptions,\n ThrottleEnvelope,\n TrialEligibilityInput,\n TrialEligibilityResult,\n UpdateSubscriptionInput,\n WaivePeriodInput,\n} from './types';\n\nexport class SubscriptionsClient implements SubscriptionsClientContract {\n private readonly apiKey?: string;\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof globalThis.fetch;\n private readonly fetcher?: SubscriptionsClientOptions['fetcher'];\n private readonly timeoutMs: number;\n\n constructor(opts: SubscriptionsClientOptions = {}) {\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('SubscriptionsClient: fetch is required');\n if (!opts.apiKey && !opts.fetcher) {\n throw new Error('SubscriptionsClient: apiKey or fetcher is required');\n }\n\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? 'https://api.usethrottle.dev').replace(/\\/+$/, '');\n this.fetchImpl = fetchImpl;\n this.fetcher = opts.fetcher;\n this.timeoutMs = opts.timeoutMs ?? 30_000;\n }\n\n async request<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const envelope = await this.requestEnvelope<T>(method, path, body);\n if (Object.prototype.hasOwnProperty.call(envelope, 'data')) {\n return envelope.data as T;\n }\n return envelope as T;\n }\n\n async requestEnvelope<T = unknown>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<ThrottleEnvelope<T>> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n\n try {\n const init: RequestInit = {\n method,\n headers: {\n 'content-type': 'application/json',\n ...(this.apiKey ? { 'x-api-key': this.apiKey } : {}),\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: ctrl.signal,\n };\n\n const res = this.fetcher\n ? await this.fetcher(path, init)\n : await this.fetchImpl(toAbsoluteUrl(this.baseUrl, path), init);\n\n if (res.status === 204) return { data: undefined as T };\n\n const json = (await res.json().catch(() => ({}))) as ThrottleEnvelope<T>;\n if (!res.ok) {\n throw new ThrottleSubscriptionsError({\n code: json.error?.code ?? 'unknown_error',\n message: json.error?.message ?? `HTTP ${res.status}`,\n statusCode: res.status,\n details: json.error?.details,\n responseHeaders: res.headers,\n });\n }\n return json;\n } finally {\n clearTimeout(timer);\n }\n }\n\n async create(input: CreateSubscriptionInput): Promise<Subscription> {\n const customerId = await this.resolveCustomerId(input.customerId, input.externalCustomerId);\n const data = await this.request<unknown>('POST', '/api/v1/subscriptions', {\n applicationId: input.applicationId,\n customerId,\n planReference: input.planReference,\n planName: input.planName,\n interval: input.interval,\n intervalUnit: input.intervalUnit,\n intervalCount: input.intervalCount,\n totalPayments: input.totalPayments,\n amount: input.amount,\n allowZeroAmount: input.allowZeroAmount,\n schedule: input.schedule,\n currency: input.currency,\n currentPeriodStart: toIso(input.currentPeriodStart),\n currentPeriodEnd: toIso(input.currentPeriodEnd),\n trialEnd: toIso(input.trialEnd),\n metadata: input.metadata ?? {},\n orderId: input.orderId,\n });\n return normalizeSubscription(data);\n }\n\n async list(params: ListSubscriptionsParams = {}): Promise<PaginatedSubscriptions> {\n const query = new URLSearchParams();\n setQuery(query, 'customerId', params.customerId);\n setQuery(query, 'externalCustomerId', params.externalCustomerId);\n setQuery(query, 'status', params.status);\n setQuery(query, 'interval', params.interval);\n setQuery(query, 'installment', params.installment);\n setQuery(query, 'q', params.q);\n setQuery(query, 'cursor', params.cursor);\n setQuery(query, 'limit', params.limit);\n setQuery(query, 'sort', params.sort);\n setQuery(query, 'createdAfter', toIso(params.createdAfter));\n setQuery(query, 'createdBefore', toIso(params.createdBefore));\n\n const suffix = query.toString() ? `?${query}` : '';\n const envelope = await this.requestEnvelope<unknown[]>('GET', `/api/v1/subscriptions${suffix}`);\n return {\n data: (envelope.data ?? []).map(normalizeSubscription),\n pagination: normalizePagination(envelope.meta?.pagination),\n };\n }\n\n async get(id: string): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'GET',\n `/api/v1/subscriptions/${encodeURIComponent(id)}`,\n );\n return normalizeSubscription(data);\n }\n\n /**\n * A term-only edit: rename the plan, correct the cadence or the amount on\n * the row — no proration, no charge, no period reset. Mirrors\n * `PATCH /api/v1/subscriptions/{id}`. This is what `changePlan()` did\n * before 3.0.0; use `changePlan()` now for an actual plan change.\n */\n async update(id: string, input: UpdateSubscriptionInput): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'PATCH',\n `/api/v1/subscriptions/${encodeURIComponent(id)}`,\n input,\n );\n return normalizeSubscription(data);\n }\n\n /**\n * A real plan change: prorated and charged immediately when\n * `effective: 'now'`, or scheduled for period end with no charge today.\n * Mirrors `POST /api/v1/subscriptions/{id}/change-plan`. The resolved\n * subscription carries `proration` when the server computed one.\n *\n * This is NOT the old `changePlan()` (a PATCH-style term edit with no\n * proration and no charge) — use `update()` for that.\n */\n async changePlan(input: ChangePlanInput): Promise<Subscription> {\n const { id, ...body } = input;\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/change-plan`,\n {\n planReference: body.planReference,\n planName: body.planName,\n interval: body.interval,\n intervalUnit: body.intervalUnit,\n intervalCount: body.intervalCount,\n amount: body.amount,\n allowZeroAmount: body.allowZeroAmount,\n effective: body.effective,\n },\n );\n return normalizeSubscription(data);\n }\n\n /**\n * Change the seat quantity: prorated and charged immediately when\n * `effective: 'now'`, or scheduled for period end with no charge today.\n * Mirrors `POST /api/v1/subscriptions/{id}/change-quantity`.\n */\n async changeQuantity(id: string, input: ChangeQuantityInput): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/change-quantity`,\n { quantity: input.quantity, effective: input.effective },\n );\n return normalizeSubscription(data);\n }\n\n /**\n * Charge a past-due subscription's card again now, instead of waiting for\n * the next scheduled dunning retry. Mirrors\n * `POST /api/v1/subscriptions/{id}/retry-charge`.\n */\n async retryCharge(id: string): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/retry-charge`,\n );\n return normalizeSubscription(data);\n }\n\n /**\n * Forgive the current past-due period — the merchant is not collecting it.\n * Mirrors `POST /api/v1/subscriptions/{id}/waive-period`.\n */\n async waivePeriod(id: string, input: WaivePeriodInput): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/waive-period`,\n { reason: input.reason },\n );\n return normalizeSubscription(data);\n }\n\n /**\n * Set the saved card this one subscription renews on. Only this\n * subscription moves: the customer's default card and their other\n * subscriptions stay as they are. Nothing is charged now; the next renewal\n * (or dunning retry) charges the new card. Mirrors\n * `PATCH /api/v1/subscriptions/{id}/payment-method`.\n */\n async setPaymentMethod(id: string, paymentMethodId: string): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'PATCH',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/payment-method`,\n { paymentMethodId },\n );\n return normalizeSubscription(data);\n }\n\n /**\n * Record (upsert) a usage item for the subscription's current billing\n * period. Mirrors `POST /api/v1/subscriptions/{id}/usage`.\n */\n async recordUsage(id: string, input: RecordUsageInput): Promise<SubscriptionUsageItem> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/usage`,\n { kind: input.kind, unitCount: input.unitCount, unitPriceCents: input.unitPriceCents },\n );\n return normalizeUsageItem(data);\n }\n\n /**\n * List usage items recorded for the subscription's current billing period.\n * Mirrors `GET /api/v1/subscriptions/{id}/usage`.\n */\n async listUsage(id: string): Promise<SubscriptionUsageItem[]> {\n const envelope = await this.requestEnvelope<{ items?: unknown[] }>(\n 'GET',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/usage`,\n );\n // This route answers `{ items: [...] }`, not the usual `{ data, meta }`\n // envelope, so `request()`'s data-unwrap would just hand back the whole\n // body — read `items` off the raw envelope instead.\n const items = (envelope as unknown as { items?: unknown[] }).items ?? [];\n return items.map(normalizeUsageItem);\n }\n\n async pause(id: string): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/pause`,\n );\n return normalizeSubscription(data);\n }\n\n async resume(id: string): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/resume`,\n );\n return normalizeSubscription(data);\n }\n\n async cancel(\n id: string,\n input: { atPeriodEnd?: boolean; refund?: 'none' | 'prorated' | 'last_cycle' } = {},\n ): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/cancel`,\n { atPeriodEnd: input.atPeriodEnd ?? false, refund: input.refund ?? 'none' },\n );\n return normalizeSubscription(data);\n }\n\n /**\n * Refund one billing cycle.\n *\n * `intent` has no default: refunding money and ending the subscription are\n * separate decisions, and guessing either way is wrong often enough that the\n * API requires the caller to say which one they mean.\n */\n async refundInvoice(\n id: string,\n invoiceId: string,\n input: { intent: 'money_only' | 'refund_and_cancel'; amount?: number; reason?: string },\n ): Promise<SubscriptionInvoiceRefund> {\n return this.request<SubscriptionInvoiceRefund>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/invoices/${encodeURIComponent(invoiceId)}/refund`,\n input,\n );\n }\n\n async createCheckoutSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession> {\n const data = await this.request<unknown>('POST', '/api/v1/checkout/sessions', input);\n return normalizeCheckoutSession(data);\n }\n\n async checkTrialEligibility(input: TrialEligibilityInput): Promise<TrialEligibilityResult> {\n const data = await this.request<unknown>('POST', '/api/v1/subscriptions/eligibility-check', {\n paymentMethodId: input.paymentMethodId,\n });\n return normalizeTrialEligibility(data);\n }\n\n async getCustomerByExternalId(externalId: string): Promise<Customer | null> {\n try {\n const data = await this.request<unknown>(\n 'GET',\n `/api/v1/customers/by-external/${encodeURIComponent(externalId)}`,\n );\n return normalizeCustomer(data);\n } catch (err) {\n if (err instanceof ThrottleSubscriptionsError && err.statusCode === 404) return null;\n throw err;\n }\n }\n\n async listCustomerPaymentMethods(customerId: string): Promise<CustomerPaymentMethod[]> {\n const data = await this.request<unknown[]>(\n 'GET',\n `/api/v1/customers/${encodeURIComponent(customerId)}/payment-methods`,\n );\n return (data ?? []).map(normalizeCustomerPaymentMethod);\n }\n\n private async resolveCustomerId(\n customerId?: string,\n externalCustomerId?: string,\n ): Promise<string> {\n if (customerId) return customerId;\n if (!externalCustomerId) {\n throw new ThrottleSubscriptionsError({\n code: 'invalid_request',\n message: 'customerId or externalCustomerId is required',\n statusCode: 400,\n });\n }\n\n const customer = await this.getCustomerByExternalId(externalCustomerId);\n if (!customer) {\n throw new ThrottleSubscriptionsError({\n code: 'customer_not_found',\n message: 'Customer not found',\n statusCode: 404,\n });\n }\n return customer.id;\n }\n}\n\nexport function createSubscriptionsClient(opts: SubscriptionsClientOptions): SubscriptionsClient {\n return new SubscriptionsClient(opts);\n}\n\nfunction toAbsoluteUrl(baseUrl: string, path: string): string {\n if (/^https?:\\/\\//i.test(path)) return path;\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n}\n\nfunction setQuery(query: URLSearchParams, key: string, value: unknown): void {\n if (value === undefined || value === null || value === '') return;\n query.set(key, String(value));\n}\n"],"mappings":"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","names":["ThrottleError"]}
|
|
@@ -169,6 +169,12 @@ interface CreateSubscriptionInput {
|
|
|
169
169
|
totalPayments?: number;
|
|
170
170
|
/** Required unless `schedule` is sent (the first payment's amount is then taken from the schedule). */
|
|
171
171
|
amount?: number;
|
|
172
|
+
/**
|
|
173
|
+
* Set to `true` to allow `amount: 0` (a free or usage-only plan that renews
|
|
174
|
+
* for nothing). Without it the API refuses `amount: 0` with
|
|
175
|
+
* `400 invalid_amount`. Applies to this request only; it is not stored.
|
|
176
|
+
*/
|
|
177
|
+
allowZeroAmount?: boolean;
|
|
172
178
|
currency?: string;
|
|
173
179
|
currentPeriodStart: string | Date;
|
|
174
180
|
/** Optional when `schedule` is sent; the first period end is derived from the schedule's first gap. */
|
|
@@ -204,6 +210,12 @@ interface UpdateSubscriptionInput {
|
|
|
204
210
|
intervalUnit?: SubscriptionIntervalUnit;
|
|
205
211
|
intervalCount?: number;
|
|
206
212
|
amount?: number;
|
|
213
|
+
/**
|
|
214
|
+
* Set to `true` to allow `amount: 0` (a free or usage-only plan that renews
|
|
215
|
+
* for nothing). Without it the API refuses `amount: 0` with
|
|
216
|
+
* `400 invalid_amount`. Applies to this request only; it is not stored.
|
|
217
|
+
*/
|
|
218
|
+
allowZeroAmount?: boolean;
|
|
207
219
|
metadata?: Record<string, unknown>;
|
|
208
220
|
}
|
|
209
221
|
interface CancelSubscriptionInput {
|
|
@@ -225,6 +237,12 @@ interface ChangePlanInput {
|
|
|
225
237
|
intervalUnit?: SubscriptionIntervalUnit;
|
|
226
238
|
intervalCount?: number;
|
|
227
239
|
amount: number;
|
|
240
|
+
/**
|
|
241
|
+
* Set to `true` to allow `amount: 0` (a free or usage-only plan that renews
|
|
242
|
+
* for nothing). Without it the API refuses `amount: 0` with
|
|
243
|
+
* `400 invalid_amount`. Applies to this request only; it is not stored.
|
|
244
|
+
*/
|
|
245
|
+
allowZeroAmount?: boolean;
|
|
228
246
|
/** `'now'` prorates and charges immediately; `'period_end'` schedules it, charging nothing today. */
|
|
229
247
|
effective: 'now' | 'period_end';
|
|
230
248
|
}
|
|
@@ -263,6 +281,7 @@ interface RecurringIntent {
|
|
|
263
281
|
intervalUnit?: SubscriptionIntervalUnit;
|
|
264
282
|
intervalCount?: number;
|
|
265
283
|
totalPayments?: number;
|
|
284
|
+
/** The renewal price, in minor units. Must be above 0 when sent (`400 invalid_amount`); on a trial it is what the plan renews at. */
|
|
266
285
|
amount?: number;
|
|
267
286
|
trialDays?: number;
|
|
268
287
|
planName?: string;
|
|
@@ -417,6 +436,8 @@ interface SubscriptionsClientContract {
|
|
|
417
436
|
}): Promise<Subscription>;
|
|
418
437
|
retryCharge(id: string): Promise<Subscription>;
|
|
419
438
|
waivePeriod(id: string, input: WaivePeriodInput): Promise<Subscription>;
|
|
439
|
+
/** Set the saved card this one subscription renews on (`PATCH /api/v1/subscriptions/{id}/payment-method`). */
|
|
440
|
+
setPaymentMethod(id: string, paymentMethodId: string): Promise<Subscription>;
|
|
420
441
|
recordUsage(id: string, input: RecordUsageInput): Promise<SubscriptionUsageItem>;
|
|
421
442
|
listUsage(id: string): Promise<SubscriptionUsageItem[]>;
|
|
422
443
|
createCheckoutSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession>;
|
|
@@ -471,6 +492,14 @@ declare class SubscriptionsClient implements SubscriptionsClientContract {
|
|
|
471
492
|
* Mirrors `POST /api/v1/subscriptions/{id}/waive-period`.
|
|
472
493
|
*/
|
|
473
494
|
waivePeriod(id: string, input: WaivePeriodInput): Promise<Subscription>;
|
|
495
|
+
/**
|
|
496
|
+
* Set the saved card this one subscription renews on. Only this
|
|
497
|
+
* subscription moves: the customer's default card and their other
|
|
498
|
+
* subscriptions stay as they are. Nothing is charged now; the next renewal
|
|
499
|
+
* (or dunning retry) charges the new card. Mirrors
|
|
500
|
+
* `PATCH /api/v1/subscriptions/{id}/payment-method`.
|
|
501
|
+
*/
|
|
502
|
+
setPaymentMethod(id: string, paymentMethodId: string): Promise<Subscription>;
|
|
474
503
|
/**
|
|
475
504
|
* Record (upsert) a usage item for the subscription's current billing
|
|
476
505
|
* period. Mirrors `POST /api/v1/subscriptions/{id}/usage`.
|
|
@@ -169,6 +169,12 @@ interface CreateSubscriptionInput {
|
|
|
169
169
|
totalPayments?: number;
|
|
170
170
|
/** Required unless `schedule` is sent (the first payment's amount is then taken from the schedule). */
|
|
171
171
|
amount?: number;
|
|
172
|
+
/**
|
|
173
|
+
* Set to `true` to allow `amount: 0` (a free or usage-only plan that renews
|
|
174
|
+
* for nothing). Without it the API refuses `amount: 0` with
|
|
175
|
+
* `400 invalid_amount`. Applies to this request only; it is not stored.
|
|
176
|
+
*/
|
|
177
|
+
allowZeroAmount?: boolean;
|
|
172
178
|
currency?: string;
|
|
173
179
|
currentPeriodStart: string | Date;
|
|
174
180
|
/** Optional when `schedule` is sent; the first period end is derived from the schedule's first gap. */
|
|
@@ -204,6 +210,12 @@ interface UpdateSubscriptionInput {
|
|
|
204
210
|
intervalUnit?: SubscriptionIntervalUnit;
|
|
205
211
|
intervalCount?: number;
|
|
206
212
|
amount?: number;
|
|
213
|
+
/**
|
|
214
|
+
* Set to `true` to allow `amount: 0` (a free or usage-only plan that renews
|
|
215
|
+
* for nothing). Without it the API refuses `amount: 0` with
|
|
216
|
+
* `400 invalid_amount`. Applies to this request only; it is not stored.
|
|
217
|
+
*/
|
|
218
|
+
allowZeroAmount?: boolean;
|
|
207
219
|
metadata?: Record<string, unknown>;
|
|
208
220
|
}
|
|
209
221
|
interface CancelSubscriptionInput {
|
|
@@ -225,6 +237,12 @@ interface ChangePlanInput {
|
|
|
225
237
|
intervalUnit?: SubscriptionIntervalUnit;
|
|
226
238
|
intervalCount?: number;
|
|
227
239
|
amount: number;
|
|
240
|
+
/**
|
|
241
|
+
* Set to `true` to allow `amount: 0` (a free or usage-only plan that renews
|
|
242
|
+
* for nothing). Without it the API refuses `amount: 0` with
|
|
243
|
+
* `400 invalid_amount`. Applies to this request only; it is not stored.
|
|
244
|
+
*/
|
|
245
|
+
allowZeroAmount?: boolean;
|
|
228
246
|
/** `'now'` prorates and charges immediately; `'period_end'` schedules it, charging nothing today. */
|
|
229
247
|
effective: 'now' | 'period_end';
|
|
230
248
|
}
|
|
@@ -263,6 +281,7 @@ interface RecurringIntent {
|
|
|
263
281
|
intervalUnit?: SubscriptionIntervalUnit;
|
|
264
282
|
intervalCount?: number;
|
|
265
283
|
totalPayments?: number;
|
|
284
|
+
/** The renewal price, in minor units. Must be above 0 when sent (`400 invalid_amount`); on a trial it is what the plan renews at. */
|
|
266
285
|
amount?: number;
|
|
267
286
|
trialDays?: number;
|
|
268
287
|
planName?: string;
|
|
@@ -417,6 +436,8 @@ interface SubscriptionsClientContract {
|
|
|
417
436
|
}): Promise<Subscription>;
|
|
418
437
|
retryCharge(id: string): Promise<Subscription>;
|
|
419
438
|
waivePeriod(id: string, input: WaivePeriodInput): Promise<Subscription>;
|
|
439
|
+
/** Set the saved card this one subscription renews on (`PATCH /api/v1/subscriptions/{id}/payment-method`). */
|
|
440
|
+
setPaymentMethod(id: string, paymentMethodId: string): Promise<Subscription>;
|
|
420
441
|
recordUsage(id: string, input: RecordUsageInput): Promise<SubscriptionUsageItem>;
|
|
421
442
|
listUsage(id: string): Promise<SubscriptionUsageItem[]>;
|
|
422
443
|
createCheckoutSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession>;
|
|
@@ -471,6 +492,14 @@ declare class SubscriptionsClient implements SubscriptionsClientContract {
|
|
|
471
492
|
* Mirrors `POST /api/v1/subscriptions/{id}/waive-period`.
|
|
472
493
|
*/
|
|
473
494
|
waivePeriod(id: string, input: WaivePeriodInput): Promise<Subscription>;
|
|
495
|
+
/**
|
|
496
|
+
* Set the saved card this one subscription renews on. Only this
|
|
497
|
+
* subscription moves: the customer's default card and their other
|
|
498
|
+
* subscriptions stay as they are. Nothing is charged now; the next renewal
|
|
499
|
+
* (or dunning retry) charges the new card. Mirrors
|
|
500
|
+
* `PATCH /api/v1/subscriptions/{id}/payment-method`.
|
|
501
|
+
*/
|
|
502
|
+
setPaymentMethod(id: string, paymentMethodId: string): Promise<Subscription>;
|
|
474
503
|
/**
|
|
475
504
|
* Record (upsert) a usage item for the subscription's current billing
|
|
476
505
|
* period. Mirrors `POST /api/v1/subscriptions/{id}/usage`.
|
package/dist/index.cjs
CHANGED
|
@@ -105,6 +105,7 @@ function normalizeSubscription(raw) {
|
|
|
105
105
|
pausedAt: optionalDateString(raw?.pausedAt),
|
|
106
106
|
cancelledAt: optionalDateString(raw?.cancelledAt),
|
|
107
107
|
metadata: objectOrEmpty(raw?.metadata),
|
|
108
|
+
paymentMethodId: optionalString(raw?.paymentMethodId),
|
|
108
109
|
renewalIssue: normalizeRenewalIssue(raw?.renewalIssue),
|
|
109
110
|
proration: raw?.proration ? {
|
|
110
111
|
creditCents: raw.proration.creditCents,
|
|
@@ -318,6 +319,7 @@ var SubscriptionsClient = class {
|
|
|
318
319
|
intervalCount: input.intervalCount,
|
|
319
320
|
totalPayments: input.totalPayments,
|
|
320
321
|
amount: input.amount,
|
|
322
|
+
allowZeroAmount: input.allowZeroAmount,
|
|
321
323
|
schedule: input.schedule,
|
|
322
324
|
currency: input.currency,
|
|
323
325
|
currentPeriodStart: toIso(input.currentPeriodStart),
|
|
@@ -390,6 +392,7 @@ var SubscriptionsClient = class {
|
|
|
390
392
|
intervalUnit: body.intervalUnit,
|
|
391
393
|
intervalCount: body.intervalCount,
|
|
392
394
|
amount: body.amount,
|
|
395
|
+
allowZeroAmount: body.allowZeroAmount,
|
|
393
396
|
effective: body.effective
|
|
394
397
|
}
|
|
395
398
|
);
|
|
@@ -432,6 +435,21 @@ var SubscriptionsClient = class {
|
|
|
432
435
|
);
|
|
433
436
|
return normalizeSubscription(data);
|
|
434
437
|
}
|
|
438
|
+
/**
|
|
439
|
+
* Set the saved card this one subscription renews on. Only this
|
|
440
|
+
* subscription moves: the customer's default card and their other
|
|
441
|
+
* subscriptions stay as they are. Nothing is charged now; the next renewal
|
|
442
|
+
* (or dunning retry) charges the new card. Mirrors
|
|
443
|
+
* `PATCH /api/v1/subscriptions/{id}/payment-method`.
|
|
444
|
+
*/
|
|
445
|
+
async setPaymentMethod(id, paymentMethodId) {
|
|
446
|
+
const data = await this.request(
|
|
447
|
+
"PATCH",
|
|
448
|
+
`/api/v1/subscriptions/${encodeURIComponent(id)}/payment-method`,
|
|
449
|
+
{ paymentMethodId }
|
|
450
|
+
);
|
|
451
|
+
return normalizeSubscription(data);
|
|
452
|
+
}
|
|
435
453
|
/**
|
|
436
454
|
* Record (upsert) a usage item for the subscription's current billing
|
|
437
455
|
* period. Mirrors `POST /api/v1/subscriptions/{id}/usage`.
|