From db2486f265fd9b49800045bc3a40bc8a96fd7336 Mon Sep 17 00:00:00 2001 From: Paddy Carver Date: Thu, 18 Sep 2025 11:58:17 -0700 Subject: [PATCH 1/6] feat: Make SubscriptionItem's plan and planId optional and nullable We're introducing changes in future API versions that will either not send plan/plan_id at all on some subscription items, or may send null instead. Which hasn't been determined yet. Updating the client and webhooks to accept either, though. C1s must take an explicit action before any subscription item will return a null or omitted plan/plan_id, so we'll have the opportunity to warn them. --- .changeset/silly-rooms-sleep.md | 5 +++ .../api/resources/CommerceSubscriptionItem.ts | 17 ++++++-- packages/backend/src/api/resources/JSON.ts | 42 ++++++++++--------- 3 files changed, 40 insertions(+), 24 deletions(-) create mode 100644 .changeset/silly-rooms-sleep.md diff --git a/.changeset/silly-rooms-sleep.md b/.changeset/silly-rooms-sleep.md new file mode 100644 index 00000000000..50adcc373a2 --- /dev/null +++ b/.changeset/silly-rooms-sleep.md @@ -0,0 +1,5 @@ +--- +'@clerk/backend': minor +--- + +Allow subscription item plan and planId to be null or undefined diff --git a/packages/backend/src/api/resources/CommerceSubscriptionItem.ts b/packages/backend/src/api/resources/CommerceSubscriptionItem.ts index 081737fd033..2064a8c89f2 100644 --- a/packages/backend/src/api/resources/CommerceSubscriptionItem.ts +++ b/packages/backend/src/api/resources/CommerceSubscriptionItem.ts @@ -46,11 +46,11 @@ export class BillingSubscriptionItem { /** * The plan associated with this subscription item. */ - readonly plan: BillingPlan, + readonly plan: BillingPlan | null, /** * The plan ID. */ - readonly planId: string, + readonly planId: string | null, /** * Unix timestamp (milliseconds) of when the subscription item was created. */ @@ -105,6 +105,15 @@ export class BillingSubscriptionItem { }; } + let plan = null; + if (data.plan !== undefined && data.plan !== null) { + plan = BillingPlan.fromJSON(data.plan); + } + let planId = null; + if (data.plan_id !== undefined) { + planId = data.plan_id; + } + return new BillingSubscriptionItem( data.id, data.status, @@ -112,8 +121,8 @@ export class BillingSubscriptionItem { data.period_start, data.next_payment, formatAmountJSON(data.amount), - BillingPlan.fromJSON(data.plan), - data.plan_id, + plan, + planId, data.created_at, data.updated_at, data.period_end, diff --git a/packages/backend/src/api/resources/JSON.ts b/packages/backend/src/api/resources/JSON.ts index 8bef448909c..faf6dcd052f 100644 --- a/packages/backend/src/api/resources/JSON.ts +++ b/packages/backend/src/api/resources/JSON.ts @@ -880,8 +880,8 @@ export interface BillingSubscriptionItemJSON extends ClerkResourceJSON { date: number; } | null; amount: BillingMoneyAmountJSON | null; - plan: BillingPlanJSON; - plan_id: string; + plan?: BillingPlanJSON | null; + plan_id?: string | null; } /** @@ -906,24 +906,26 @@ export interface BillingSubscriptionItemWebhookEventJSON extends ClerkResourceJS next_payment_amount: number; next_payment_date: number; amount: BillingMoneyAmountJSON; - plan: { - id: string; - instance_id: string; - product_id: string; - name: string; - slug: string; - description?: string; - is_default: boolean; - is_recurring: boolean; - amount: number; - period: 'month' | 'annual'; - interval: number; - has_base_fee: boolean; - currency: string; - annual_monthly_amount: number; - publicly_visible: boolean; - }; - plan_id: string; + plan?: + | { + id: string; + instance_id: string; + product_id: string; + name: string; + slug: string; + description?: string; + is_default: boolean; + is_recurring: boolean; + amount: number; + period: 'month' | 'annual'; + interval: number; + has_base_fee: boolean; + currency: string; + annual_monthly_amount: number; + publicly_visible: boolean; + } + | null; + plan_id?: string | null; } /** From 070be0f64b317874e0731536f2e14f9a766325d9 Mon Sep 17 00:00:00 2001 From: Paddy Carver Date: Mon, 22 Sep 2025 11:39:40 -0700 Subject: [PATCH 2/6] Update changeset. --- .changeset/silly-rooms-sleep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/silly-rooms-sleep.md b/.changeset/silly-rooms-sleep.md index 50adcc373a2..f5cb9759029 100644 --- a/.changeset/silly-rooms-sleep.md +++ b/.changeset/silly-rooms-sleep.md @@ -2,4 +2,4 @@ '@clerk/backend': minor --- -Allow subscription item plan and planId to be null or undefined +Allow subscription item plan and planId to be null. From 79a3a856f54fab36c73f778c6e30b1158fb1144d Mon Sep 17 00:00:00 2001 From: Paddy Carver Date: Mon, 22 Sep 2025 11:46:24 -0700 Subject: [PATCH 3/6] Prettier. --- packages/backend/src/api/resources/JSON.ts | 36 ++++++++++------------ 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/packages/backend/src/api/resources/JSON.ts b/packages/backend/src/api/resources/JSON.ts index faf6dcd052f..dd28c67a1a3 100644 --- a/packages/backend/src/api/resources/JSON.ts +++ b/packages/backend/src/api/resources/JSON.ts @@ -906,25 +906,23 @@ export interface BillingSubscriptionItemWebhookEventJSON extends ClerkResourceJS next_payment_amount: number; next_payment_date: number; amount: BillingMoneyAmountJSON; - plan?: - | { - id: string; - instance_id: string; - product_id: string; - name: string; - slug: string; - description?: string; - is_default: boolean; - is_recurring: boolean; - amount: number; - period: 'month' | 'annual'; - interval: number; - has_base_fee: boolean; - currency: string; - annual_monthly_amount: number; - publicly_visible: boolean; - } - | null; + plan?: { + id: string; + instance_id: string; + product_id: string; + name: string; + slug: string; + description?: string; + is_default: boolean; + is_recurring: boolean; + amount: number; + period: 'month' | 'annual'; + interval: number; + has_base_fee: boolean; + currency: string; + annual_monthly_amount: number; + publicly_visible: boolean; + } | null; plan_id?: string | null; } From bba5243f74bef7e890dd40c7931ebe30097fc69b Mon Sep 17 00:00:00 2001 From: Paddy Date: Mon, 22 Sep 2025 11:48:31 -0700 Subject: [PATCH 4/6] Much more concise conversion from JSON. Co-authored-by: panteliselef --- .../src/api/resources/CommerceSubscriptionItem.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/backend/src/api/resources/CommerceSubscriptionItem.ts b/packages/backend/src/api/resources/CommerceSubscriptionItem.ts index 2064a8c89f2..38891fcf5a6 100644 --- a/packages/backend/src/api/resources/CommerceSubscriptionItem.ts +++ b/packages/backend/src/api/resources/CommerceSubscriptionItem.ts @@ -105,15 +105,6 @@ export class BillingSubscriptionItem { }; } - let plan = null; - if (data.plan !== undefined && data.plan !== null) { - plan = BillingPlan.fromJSON(data.plan); - } - let planId = null; - if (data.plan_id !== undefined) { - planId = data.plan_id; - } - return new BillingSubscriptionItem( data.id, data.status, @@ -121,8 +112,8 @@ export class BillingSubscriptionItem { data.period_start, data.next_payment, formatAmountJSON(data.amount), - plan, - planId, + data.plan ? BillingPlan.fromJSON(data.plan) : null, + data.plan_id ?? null, data.created_at, data.updated_at, data.period_end, From eff9f8ad69e3ce3c136372482a9a6ea584c7d8e9 Mon Sep 17 00:00:00 2001 From: Paddy Carver Date: Mon, 22 Sep 2025 11:49:16 -0700 Subject: [PATCH 5/6] Fix changeset. --- .changeset/silly-rooms-sleep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/silly-rooms-sleep.md b/.changeset/silly-rooms-sleep.md index f5cb9759029..a456c3810f6 100644 --- a/.changeset/silly-rooms-sleep.md +++ b/.changeset/silly-rooms-sleep.md @@ -2,4 +2,4 @@ '@clerk/backend': minor --- -Allow subscription item plan and planId to be null. +[Billing Beta] Update subscription item plan and planId to be null. From 8e3ac0c421d0882e79720ba7069f7be66bba9e88 Mon Sep 17 00:00:00 2001 From: Paddy Carver Date: Mon, 22 Sep 2025 11:50:09 -0700 Subject: [PATCH 6/6] Actually fix changeset. --- .changeset/silly-rooms-sleep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/silly-rooms-sleep.md b/.changeset/silly-rooms-sleep.md index a456c3810f6..d217e19ef8d 100644 --- a/.changeset/silly-rooms-sleep.md +++ b/.changeset/silly-rooms-sleep.md @@ -2,4 +2,4 @@ '@clerk/backend': minor --- -[Billing Beta] Update subscription item plan and planId to be null. +[Billing Beta] Update subscription item `plan` and `planId` properties to be `null`.