Skip to content

Commit e20fb6b

Browse files
authored
feat(clerk-js): OrgProfile billing page and new subscription methods (#5423)
1 parent 7fac110 commit e20fb6b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+538
-141
lines changed

.changeset/yellow-hairs-refuse.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@clerk/localizations': patch
3+
'@clerk/clerk-js': patch
4+
'@clerk/shared': patch
5+
'@clerk/types': patch
6+
---
7+
8+
Add billing page to `OrgProfile`, use new `usePlans` hook, and adds new subscription methods

packages/clerk-js/bundlewatch.config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"files": [
3-
{ "path": "./dist/clerk.js", "maxSize": "580.7kB" },
4-
{ "path": "./dist/clerk.browser.js", "maxSize": "79.25kB" },
3+
{ "path": "./dist/clerk.js", "maxSize": "581.5kB" },
4+
{ "path": "./dist/clerk.browser.js", "maxSize": "79.30kB" },
55
{ "path": "./dist/clerk.headless.js", "maxSize": "55KB" },
66
{ "path": "./dist/ui-common*.js", "maxSize": "96KB" },
77
{ "path": "./dist/vendors*.js", "maxSize": "30KB" },

packages/clerk-js/src/core/clerk.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ import {
8383
createAllowedRedirectOrigins,
8484
createBeforeUnloadTracker,
8585
createPageLifecycle,
86+
disabledCommerceFeature,
8687
disabledOrganizationsFeature,
8788
errorThrower,
8889
generateSignatureWithCoinbaseWallet,
@@ -921,6 +922,14 @@ export class Clerk implements ClerkInterface {
921922

922923
public __experimental_mountPricingTable = (node: HTMLDivElement, props?: __experimental_PricingTableProps): void => {
923924
this.assertComponentsReady(this.#componentControls);
925+
if (disabledCommerceFeature(this, this.environment)) {
926+
if (this.#instanceType === 'development') {
927+
throw new ClerkRuntimeError(warnings.cannotRenderAnyCommerceComponent('PricingTable'), {
928+
code: 'cannot_render_commerce_disabled',
929+
});
930+
}
931+
return;
932+
}
924933
void this.#componentControls.ensureMounted({ preloadHint: 'PricingTable' }).then(controls =>
925934
controls.mountComponent({
926935
name: 'PricingTable',

packages/clerk-js/src/core/modules/commerce/CommerceBilling.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,47 @@ import type {
33
__experimental_CommerceCheckoutJSON,
44
__experimental_CommercePlanResource,
55
__experimental_CommerceProductJSON,
6+
__experimental_CommerceSubscriptionJSON,
7+
__experimental_CommerceSubscriptionResource,
68
__experimental_CreateCheckoutParams,
79
__experimental_GetPlansParams,
810
ClerkPaginatedResponse,
911
} from '@clerk/types';
1012

11-
import { convertPageToOffsetSearchParams } from '../../../utils/convertPageToOffsetSearchParams';
12-
import { __experimental_CommerceCheckout, __experimental_CommercePlan, BaseResource } from '../../resources/internal';
13+
import {
14+
__experimental_CommerceCheckout,
15+
__experimental_CommercePlan,
16+
__experimental_CommerceSubscription,
17+
BaseResource,
18+
} from '../../resources/internal';
1319

1420
export class __experimental_CommerceBilling implements __experimental_CommerceBillingNamespace {
1521
getPlans = async (params?: __experimental_GetPlansParams): Promise<__experimental_CommercePlanResource[]> => {
1622
const { data: products } = (await BaseResource._fetch({
1723
path: `/commerce/products`,
1824
method: 'GET',
19-
search: convertPageToOffsetSearchParams(params),
25+
search: { payerType: params?.subscriberType || '' },
2026
})) as unknown as ClerkPaginatedResponse<__experimental_CommerceProductJSON>;
2127

2228
const defaultProduct = products.find(product => product.is_default);
2329
return defaultProduct?.plans.map(plan => new __experimental_CommercePlan(plan)) || [];
2430
};
2531

32+
getSubscriptions = async (): Promise<ClerkPaginatedResponse<__experimental_CommerceSubscriptionResource>> => {
33+
return await BaseResource._fetch({
34+
path: `/me/subscriptions`,
35+
method: 'GET',
36+
}).then(res => {
37+
const { data: subscriptions, total_count } =
38+
res?.response as unknown as ClerkPaginatedResponse<__experimental_CommerceSubscriptionJSON>;
39+
40+
return {
41+
total_count,
42+
data: subscriptions.map(subscription => new __experimental_CommerceSubscription(subscription)),
43+
};
44+
});
45+
};
46+
2647
startCheckout = async (params: __experimental_CreateCheckoutParams) => {
2748
const json = (
2849
await BaseResource._fetch<__experimental_CommerceCheckoutJSON>({

packages/clerk-js/src/core/resources/CommerceCheckout.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type {
22
__experimental_CommerceCheckoutJSON,
33
__experimental_CommerceCheckoutResource,
4+
__experimental_CommerceSubscriptionPlanPeriod,
45
__experimental_CommerceTotals,
56
__experimental_ConfirmCheckoutParams,
67
} from '@clerk/types';
@@ -23,7 +24,7 @@ export class __experimental_CommerceCheckout extends BaseResource implements __e
2324
invoice?: __experimental_CommerceInvoice;
2425
paymentSource?: __experimental_CommercePaymentSource;
2526
plan!: __experimental_CommercePlan;
26-
planPeriod!: string;
27+
planPeriod!: __experimental_CommerceSubscriptionPlanPeriod;
2728
status!: string;
2829
subscription?: __experimental_CommerceSubscription;
2930
totals!: __experimental_CommerceTotals;

packages/clerk-js/src/core/resources/CommercePlan.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ export class __experimental_CommercePlan extends BaseResource implements __exper
1212
currencySymbol!: string;
1313
currency!: string;
1414
description!: string;
15-
isActiveForPayer!: boolean;
1615
isRecurring!: boolean;
1716
hasBaseFee!: boolean;
1817
payerType!: string[];
1918
publiclyVisible!: boolean;
2019
slug!: string;
2120
avatarUrl!: string;
2221
features!: __experimental_CommerceFeature[];
22+
subscriptionIdForCurrentSubscriber: string | undefined;
2323

2424
constructor(data: __experimental_CommercePlanJSON) {
2525
super();
@@ -40,7 +40,6 @@ export class __experimental_CommercePlan extends BaseResource implements __exper
4040
this.currencySymbol = data.currency_symbol;
4141
this.currency = data.currency;
4242
this.description = data.description;
43-
this.isActiveForPayer = data.is_active_for_payer;
4443
this.isRecurring = data.is_recurring;
4544
this.hasBaseFee = data.has_base_fee;
4645
this.payerType = data.payer_type;

packages/clerk-js/src/core/resources/CommerceSettings.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { BaseResource } from './internal';
1111
*/
1212
export class __experimental_CommerceSettings extends BaseResource implements __experimental_CommerceSettingsResource {
1313
stripePublishableKey: string = '';
14+
enabled: boolean = false;
1415

1516
public constructor(
1617
data: __experimental_CommerceSettingsJSON | __experimental_CommerceSettingsJSONSnapshot | null = null,
@@ -26,12 +27,14 @@ export class __experimental_CommerceSettings extends BaseResource implements __e
2627
return this;
2728
}
2829
this.stripePublishableKey = data.stripe_publishable_key;
30+
this.enabled = data.enabled;
2931
return this;
3032
}
3133

3234
public __internal_toSnapshot(): __experimental_CommerceSettingsJSONSnapshot {
3335
return {
3436
stripe_publishable_key: this.stripePublishableKey,
37+
enabled: this.enabled,
3538
} as unknown as __experimental_CommerceSettingsJSONSnapshot;
3639
}
3740
}

packages/clerk-js/src/core/resources/CommerceSubscription.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import type {
22
__experimental_CommerceSubscriptionJSON,
3+
__experimental_CommerceSubscriptionPlanPeriod,
34
__experimental_CommerceSubscriptionResource,
5+
__experimental_CommerceSubscriptionStatus,
6+
DeletedObjectJSON,
47
} from '@clerk/types';
58

6-
import { __experimental_CommercePlan, BaseResource } from './internal';
9+
import { __experimental_CommercePlan, BaseResource, DeletedObject } from './internal';
710

811
export class __experimental_CommerceSubscription
912
extends BaseResource
@@ -12,8 +15,8 @@ export class __experimental_CommerceSubscription
1215
id!: string;
1316
paymentSourceId!: string;
1417
plan!: __experimental_CommercePlan;
15-
planPeriod!: string;
16-
status!: string;
18+
planPeriod!: __experimental_CommerceSubscriptionPlanPeriod;
19+
status!: __experimental_CommerceSubscriptionStatus;
1720

1821
constructor(data: __experimental_CommerceSubscriptionJSON) {
1922
super();
@@ -40,7 +43,8 @@ export class __experimental_CommerceSubscription
4043
path: `/me/commerce/subscriptions/${this.id}`,
4144
method: 'DELETE',
4245
})
43-
)?.response;
44-
return json;
46+
)?.response as unknown as DeletedObjectJSON;
47+
48+
return new DeletedObject(json);
4549
}
4650
}

packages/clerk-js/src/core/resources/Organization.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import type {
2+
__experimental_CommerceSubscriptionJSON,
3+
__experimental_CommerceSubscriptionResource,
4+
__experimental_GetSubscriptionsParams,
25
AddMemberParams,
36
ClerkPaginatedResponse,
47
ClerkResourceReloadParams,
@@ -28,7 +31,12 @@ import type {
2831

2932
import { convertPageToOffsetSearchParams } from '../../utils/convertPageToOffsetSearchParams';
3033
import { unixEpochToDate } from '../../utils/date';
31-
import { BaseResource, OrganizationInvitation, OrganizationMembership } from './internal';
34+
import {
35+
__experimental_CommerceSubscription,
36+
BaseResource,
37+
OrganizationInvitation,
38+
OrganizationMembership,
39+
} from './internal';
3240
import { OrganizationDomain } from './OrganizationDomain';
3341
import { OrganizationMembershipRequest } from './OrganizationMembershipRequest';
3442
import { Role } from './Role';
@@ -229,6 +237,29 @@ export class Organization extends BaseResource implements OrganizationResource {
229237
}).then(res => new OrganizationMembership(res?.response as OrganizationMembershipJSON));
230238
};
231239

240+
__experimental_getSubscriptions = async (
241+
getSubscriptionsParams?: __experimental_GetSubscriptionsParams,
242+
): Promise<ClerkPaginatedResponse<__experimental_CommerceSubscriptionResource>> => {
243+
return await BaseResource._fetch(
244+
{
245+
path: `/organizations/${this.id}/subscriptions`,
246+
method: 'GET',
247+
search: convertPageToOffsetSearchParams(getSubscriptionsParams),
248+
},
249+
{
250+
forceUpdateClient: true,
251+
},
252+
).then(res => {
253+
const { data: subscriptions, total_count } =
254+
res?.response as unknown as ClerkPaginatedResponse<__experimental_CommerceSubscriptionJSON>;
255+
256+
return {
257+
total_count,
258+
data: subscriptions.map(subscription => new __experimental_CommerceSubscription(subscription)),
259+
};
260+
});
261+
};
262+
232263
destroy = async (): Promise<void> => {
233264
return this._baseDelete();
234265
};

packages/clerk-js/src/core/resources/__tests__/__snapshots__/Environment.test.ts.snap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ exports[`Environment __internal_toSnapshot() 1`] = `
1010
"single_session_mode": true,
1111
},
1212
"commerce_settings": {
13+
"enabled": false,
1314
"stripe_publishable_key": "",
1415
},
1516
"display_config": {
@@ -271,6 +272,7 @@ exports[`Environment __internal_toSnapshot() 1`] = `
271272
exports[`Environment defaults values when instantiated without arguments 1`] = `
272273
Environment {
273274
"__experimental_commerceSettings": __experimental_CommerceSettings {
275+
"enabled": false,
274276
"pathRoot": "",
275277
"stripePublishableKey": "",
276278
},
@@ -497,6 +499,7 @@ Environment {
497499
exports[`Environment has the same initial properties 1`] = `
498500
Environment {
499501
"__experimental_commerceSettings": __experimental_CommerceSettings {
502+
"enabled": false,
500503
"pathRoot": "",
501504
"stripePublishableKey": "",
502505
},

0 commit comments

Comments
 (0)