@todesktop/shared 7.188.65 → 7.188.67

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/src/plans.ts CHANGED
@@ -1,126 +1,722 @@
1
- function pick<T, K extends keyof T>(objectInput: T, ...keys: K[]): Pick<T, K> {
2
- const objectOutput = {} as Pick<T, K>;
3
- keys.forEach((key) => {
4
- objectOutput[key] = objectInput[key];
5
- });
6
- return objectOutput;
7
- }
1
+ import { Subscription } from './base';
8
2
 
9
- export const devPlanIds = {
10
- startup: 'plan_Fe8BzLp7k71eGD',
11
- business: 'plan_Fe8CUkZfXasFtB',
12
- essential: 'plan_FpljxNuZtNFFbm',
13
- growth: 'plan_FplOshrr1w3Mvu',
14
- essential_new: 'plan_GYXmTA3EdfCv4q',
15
- professional: 'plan_GYXoIkvwVKyfF2',
16
- professional_annual: 'price_1KHU70IewCKA2h0IR87yXOQ2',
17
- cli_founder: 'plan_Gq0FzdmoTJshQL',
18
- cli_founder_30: 'plan_GsL7NZskOY0TC9',
19
- cli_founder_50: 'plan_GsL6VYAshfh7c4',
20
- cli_performance: 'price_1L821UIewCKA2h0IUwRhicyo',
21
- cli_scale: 'price_1L821wIewCKA2h0IMLUmjulL',
22
- builder_essential: 'price_1M4o9XIewCKA2h0IVfGrid8E',
23
- builder_professional: 'price_1M4o9vIewCKA2h0IHREokdD8',
24
- enterprise: 'price_1H2v6JIewCKA2h0IgUwsuctb',
3
+ export type PriceKey = `${'monthly' | 'yearly'}_${string}`;
4
+ export type Price = {
5
+ id: string;
6
+ status: 'active' | 'inactive';
7
+ period: 'monthly' | 'yearly';
8
+ amount: number;
25
9
  };
26
10
 
27
- export const prodPlanIds = {
28
- startup: 'plan_FdmDAUN7JGD8pR',
29
- business: 'plan_FdmE8akq9ukxiY',
30
- essential: 'plan_FohJzCujA6vvt4',
31
- growth: 'plan_FohKGuWis5ocsi',
32
- essential_new: 'plan_GYXn2cnPl5dy7j',
33
- professional: 'plan_GYXoKsa2j0yURg',
34
- professional_annual: 'price_1KHTgaIewCKA2h0I81TVg85r',
35
- professional_annual_full_price: 'price_1KLT32IewCKA2h0IFeJOAgG5',
36
- cli_founder: 'plan_GpzWZLfsOzjrvI',
37
- cli_founder_30: 'plan_GsL1IRUwpj5CIF',
38
- cli_founder_50: 'plan_GsL1IRUwpj5CIF',
39
- cli_performance: 'price_1L822LIewCKA2h0I5JYyOG1p',
40
- cli_scale: 'price_1L822RIewCKA2h0IPt9f2nZM',
41
- builder_essential: 'price_1M4oA4IewCKA2h0IWgfbSJBe',
42
- builder_professional: 'price_1MIDxtIewCKA2h0IvWi5weJL',
43
- enterprise: 'plan_GuGICX6nRtDthN',
11
+ export type Product<T extends PriceKey = any> = {
12
+ id: string;
13
+ prices: Record<T, Price>;
44
14
  };
45
15
 
46
- export type PlanIds = typeof prodPlanIds;
47
-
48
- export const getPlanEnvironment = (stage: 'dev' | 'prod') =>
49
- stage === 'prod' ? prodPlanIds : devPlanIds;
50
-
51
- /* ToDesktop CLI Plans */
52
- export const getCLIPlanIds = (stage: 'dev' | 'prod') => {
53
- const planIds = getPlanEnvironment(stage);
54
- return pick(
55
- planIds,
56
- 'cli_founder',
57
- 'cli_founder_30',
58
- 'cli_founder_50',
59
- 'cli_performance',
60
- 'cli_scale'
61
- );
16
+ export type PlanTier = 'basic' | 'legacy_pro' | 'pro' | 'scale';
17
+ export type Plan = {
18
+ tier: PlanTier;
19
+ label: string;
20
+ eligiblePlanTiers: PlanTier[];
21
+ products: Record<'dev' | 'prod', Product[]>;
62
22
  };
63
23
 
64
- export const getCLIFounderPlanIds = (stage: 'dev' | 'prod') => {
65
- const planIds = getPlanEnvironment(stage);
66
- return pick(planIds, 'cli_founder', 'cli_founder_30', 'cli_founder_50');
24
+ export type Configuration = {
25
+ default_return_url: string;
26
+ business_profile: {
27
+ headline: string;
28
+ privacy_policy_url: string;
29
+ terms_of_service_url: string;
30
+ };
31
+ metadata: { [name: string]: string | number | null };
32
+ features: {
33
+ payment_method_update: {
34
+ enabled: boolean;
35
+ };
36
+ subscription_update: {
37
+ enabled: boolean;
38
+ default_allowed_updates: ('price' | 'promotion_code' | 'quantity')[];
39
+ products: { product: string; prices: string[] }[];
40
+ };
41
+ };
67
42
  };
68
43
 
69
- export const getCLIPerformancePlanIds = (stage: 'dev' | 'prod') => {
70
- const planIds = getPlanEnvironment(stage);
71
- return pick(planIds, 'cli_performance');
72
- };
44
+ export enum PortalConfigKey {
45
+ CLIUpdateDev = 'cli_update_dev',
46
+ CLIUpdateProd = 'cli_update_prod',
47
+ CLIUpgradeDev = 'cli_upgrade_dev',
48
+ CLIUpgradeProd = 'cli_upgrade_prod',
49
+ BuilderUpdateDev = 'builder_update_dev',
50
+ BuilderUpdateProd = 'builder_update_prod',
51
+ BuilderUpgradeDev = 'builder_upgrade_dev',
52
+ BuilderUpgradeProd = 'builder_upgrade_prod',
53
+ }
73
54
 
74
- export const getCLIScalePlanIds = (stage: 'dev' | 'prod') => {
75
- const planIds = getPlanEnvironment(stage);
76
- return pick(planIds, 'cli_scale');
55
+ // --- factory functions ---
56
+ const createPrice = (id: string, price: Omit<Price, 'id'>): Price => {
57
+ return { id, ...price };
77
58
  };
78
59
 
79
- /* ToDesktop Builder Plans */
80
- export const getBuilderPlanIds = (stage: 'dev' | 'prod') => {
81
- const planIds = getPlanEnvironment(stage);
82
- return pick(planIds, 'builder_essential', 'builder_professional');
60
+ const createProduct = <T extends PriceKey>(
61
+ id: string,
62
+ prices: Record<T, Price>
63
+ ): Product<T> => ({ id, prices });
64
+
65
+ const createPlan = (
66
+ tier: PlanTier,
67
+ products: { dev: Product[]; prod: Product[] }
68
+ ): Plan => {
69
+ const record: Record<PlanTier, { label: string; tiers: PlanTier[] }> = {
70
+ basic: { label: 'Basic', tiers: ['basic', 'legacy_pro', 'pro', 'scale'] },
71
+ legacy_pro: { label: 'Pro', tiers: ['legacy_pro', 'pro', 'scale'] },
72
+ pro: { label: 'Pro', tiers: ['pro', 'scale'] },
73
+ scale: { label: 'Scale', tiers: ['scale'] },
74
+ };
75
+
76
+ const { label, tiers } = record[tier];
77
+ return {
78
+ tier,
79
+ label,
80
+ eligiblePlanTiers: tiers,
81
+ products: { dev: products.dev, prod: products.prod },
82
+ };
83
83
  };
84
84
 
85
- export const getBuilderEssentialPlanIds = (stage: 'dev' | 'prod') => {
86
- const planIds = getPlanEnvironment(stage);
87
- return pick(planIds, 'builder_essential');
85
+ const PORTAL_VERSION = 1; // increment this value to force Stripe to update the portal configurations
86
+ const createPortalConfig = (
87
+ key: PortalConfigKey,
88
+ products: Product[]
89
+ ): Configuration => {
90
+ return {
91
+ default_return_url: 'https://app.todesktop.com',
92
+ business_profile: {
93
+ headline: 'ToDesktop Billing Portal',
94
+ privacy_policy_url: 'https://www.todesktop.com/privacy-policy',
95
+ terms_of_service_url: 'https://www.todesktop.com/terms',
96
+ },
97
+ metadata: { key, version: PORTAL_VERSION },
98
+ features: {
99
+ payment_method_update: { enabled: true },
100
+ subscription_update: {
101
+ enabled: true,
102
+ default_allowed_updates: ['price'],
103
+ products: products.map((product) => {
104
+ return {
105
+ product: product.id,
106
+ prices: Object.values(product.prices)
107
+ .filter((price) => price.status === 'active')
108
+ .map((price) => price.id),
109
+ };
110
+ }),
111
+ },
112
+ },
113
+ };
88
114
  };
89
115
 
90
- export const getBuilderProfessionalPlanIds = (stage: 'dev' | 'prod') => {
91
- const planIds = getPlanEnvironment(stage);
92
- return pick(planIds, 'builder_professional');
116
+ // --- products ---
117
+ export const products = {
118
+ dev: {
119
+ builder: {
120
+ essential: createProduct('prod_MoR1S4o0nLv00y', {
121
+ monthly_99: createPrice('price_1M4o9XIewCKA2h0IVfGrid8E', {
122
+ status: 'inactive',
123
+ amount: 99,
124
+ period: 'monthly',
125
+ }),
126
+ monthly_125: createPrice('price_1PuuAqIewCKA2h0Iw4judQNj', {
127
+ status: 'active',
128
+ amount: 125,
129
+ period: 'monthly',
130
+ }),
131
+ yearly_1200: createPrice('price_1PuvdgIewCKA2h0IisTKqjFN', {
132
+ status: 'active',
133
+ amount: 1200,
134
+ period: 'yearly',
135
+ }),
136
+ }),
137
+ professional: createProduct('prod_MoR1SchsRDAIgY', {
138
+ monthly_199: createPrice('price_1M4o9vIewCKA2h0IHREokdD8', {
139
+ status: 'inactive',
140
+ amount: 199,
141
+ period: 'monthly',
142
+ }),
143
+ monthly_240: createPrice('price_1M4o9vIewCKA2h0IHREokdD8', {
144
+ status: 'inactive',
145
+ amount: 240,
146
+ period: 'monthly',
147
+ }),
148
+ monthly_300: createPrice('price_1PuuHrIewCKA2h0IQfEZ4Wog', {
149
+ status: 'active',
150
+ amount: 300,
151
+ period: 'monthly',
152
+ }),
153
+ yearly_2880: createPrice('price_1PuuJAIewCKA2h0IibpUIhf9', {
154
+ status: 'active',
155
+ amount: 2880,
156
+ period: 'yearly',
157
+ }),
158
+ }),
159
+ },
160
+ cli: {
161
+ founder30: createProduct('prod_GsL6LaRo4NFD5n', {
162
+ monthly_30: createPrice('plan_GsL7NZskOY0TC9', {
163
+ status: 'active',
164
+ amount: 30,
165
+ period: 'monthly',
166
+ }),
167
+ }),
168
+ founder50: createProduct('prod_GsL5O1PdbxOrxJ', {
169
+ monthly_50: createPrice('plan_GsL6VYAshfh7c4', {
170
+ status: 'active',
171
+ amount: 50,
172
+ period: 'monthly',
173
+ }),
174
+ monthly_90: createPrice('plan_GsL6VYAshfh7c4', {
175
+ status: 'inactive',
176
+ amount: 90,
177
+ period: 'monthly',
178
+ }),
179
+ }),
180
+ founder: createProduct('prod_Gq0E8nbTYHtkPl', {
181
+ monthly_100: createPrice('plan_Gq0FzdmoTJshQL', {
182
+ status: 'inactive',
183
+ amount: 100,
184
+ period: 'monthly',
185
+ }),
186
+ monthly_125: createPrice('price_1PuuMRIewCKA2h0IrggfwCwA', {
187
+ status: 'active',
188
+ amount: 125,
189
+ period: 'monthly',
190
+ }),
191
+ yearly_1200: createPrice('price_1PuuMkIewCKA2h0IRxhkDpmk', {
192
+ status: 'active',
193
+ amount: 1200,
194
+ period: 'yearly',
195
+ }),
196
+ }),
197
+ performance: createProduct('prod_LphQku6BNkzCga', {
198
+ monthly_300: createPrice('price_1L821UIewCKA2h0IUwRhicyo', {
199
+ status: 'inactive',
200
+ amount: 300,
201
+ period: 'monthly',
202
+ }),
203
+ monthly_375: createPrice('price_1PuuO7IewCKA2h0IOK9ivzS0', {
204
+ status: 'active',
205
+ amount: 375,
206
+ period: 'monthly',
207
+ }),
208
+ yearly_3600: createPrice('price_1PuuOKIewCKA2h0IrcVvJkgG', {
209
+ status: 'active',
210
+ amount: 3600,
211
+ period: 'yearly',
212
+ }),
213
+ }),
214
+ scale: createProduct('prod_LphQxNgfUIxVfA', {
215
+ monthly_1200: createPrice('price_1L821wIewCKA2h0IMLUmjulL', {
216
+ status: 'inactive',
217
+ amount: 1200,
218
+ period: 'monthly',
219
+ }),
220
+ monthly_1500: createPrice('price_1PuuPFIewCKA2h0IbPmKdsJr', {
221
+ status: 'active',
222
+ amount: 1500,
223
+ period: 'monthly',
224
+ }),
225
+ yearly_14400: createPrice('price_1PuuPaIewCKA2h0IhLfSlRFj', {
226
+ status: 'active',
227
+ amount: 14400,
228
+ period: 'yearly',
229
+ }),
230
+ }),
231
+ },
232
+ legacy: {
233
+ essential: createProduct('prod_FplN7CkqFRH0ye', {
234
+ monthly_58: createPrice('plan_FpljxNuZtNFFbm', {
235
+ status: 'active',
236
+ amount: 58,
237
+ period: 'monthly',
238
+ }),
239
+ }),
240
+ essentialNew: createProduct('prod_GYXm5X66hM1Ywj', {
241
+ monthly_58: createPrice('plan_GYXmTA3EdfCv4q', {
242
+ status: 'active',
243
+ amount: 58,
244
+ period: 'monthly',
245
+ }),
246
+ yearly_580: createPrice('plan_GYXmTA3EdfCv4q', {
247
+ status: 'active',
248
+ amount: 580,
249
+ period: 'yearly',
250
+ }),
251
+ }),
252
+ professional: createProduct('prod_GYXo54YK5kga12', {
253
+ monthly_199: createPrice('plan_GYXoIkvwVKyfF2', {
254
+ status: 'active',
255
+ amount: 199,
256
+ period: 'monthly',
257
+ }),
258
+ yearly_1990: createPrice('price_1KHU70IewCKA2h0IR87yXOQ2', {
259
+ status: 'inactive',
260
+ amount: 1990,
261
+ period: 'yearly',
262
+ }),
263
+ yearly_2388: createPrice('price_1KHU70IewCKA2h0IR87yXOQ2', {
264
+ status: 'active',
265
+ amount: 2388,
266
+ period: 'yearly',
267
+ }),
268
+ }),
269
+ startup: createProduct('prod_Fe8BTslXbdylxV', {
270
+ monthly_49: createPrice('plan_Fe8BzLp7k71eGD', {
271
+ status: 'active',
272
+ amount: 49,
273
+ period: 'monthly',
274
+ }),
275
+ yearly_200: createPrice('plan_Fe8BzLp7k71eGD', {
276
+ status: 'active',
277
+ amount: 200,
278
+ period: 'yearly',
279
+ }),
280
+ }),
281
+ growth: createProduct('prod_FplOSDbBmxba94', {
282
+ monthly_199: createPrice('plan_FplOshrr1w3Mvu', {
283
+ status: 'active',
284
+ amount: 199,
285
+ period: 'monthly',
286
+ }),
287
+ }),
288
+ business: createProduct('prod_Fe8CbCE2wGJIWr', {
289
+ monthly_199: createPrice('plan_Fe8CUkZfXasFtB', {
290
+ status: 'active',
291
+ amount: 199,
292
+ period: 'monthly',
293
+ }),
294
+ }),
295
+ enterprise: createProduct('prod_Hc9PMnHUmHvOlw', {
296
+ monthly_700: createPrice('price_1H2v6JIewCKA2h0IgUwsuctb', {
297
+ status: 'active',
298
+ amount: 700,
299
+ period: 'monthly',
300
+ }),
301
+ }),
302
+ },
303
+ },
304
+ prod: {
305
+ builder: {
306
+ essential: createProduct('prod_MoR2Ldm5PJpJZJ', {
307
+ monthly_99: createPrice('price_1M4oA4IewCKA2h0IWgfbSJBe', {
308
+ status: 'inactive',
309
+ amount: 99,
310
+ period: 'monthly',
311
+ }),
312
+ monthly_125: createPrice('price_1PuuU1IewCKA2h0IUSAcuUUb', {
313
+ status: 'active',
314
+ amount: 125,
315
+ period: 'monthly',
316
+ }),
317
+ yearly_1200: createPrice('price_1PuuUZIewCKA2h0IDMNwNqQl', {
318
+ status: 'active',
319
+ amount: 1200,
320
+ period: 'yearly',
321
+ }),
322
+ }),
323
+ professional: createProduct('prod_MoR2h0Nf16hhgb', {
324
+ monthly_199: createPrice('price_1M4oABIewCKA2h0INkbaCbIS', {
325
+ status: 'inactive',
326
+ amount: 199,
327
+ period: 'monthly',
328
+ }),
329
+ monthly_240: createPrice('price_1MIDxtIewCKA2h0IvWi5weJL', {
330
+ status: 'inactive',
331
+ amount: 240,
332
+ period: 'monthly',
333
+ }),
334
+ monthly_300: createPrice('price_1PuuVSIewCKA2h0IETsLUwF9', {
335
+ status: 'active',
336
+ amount: 300,
337
+ period: 'monthly',
338
+ }),
339
+ yearly_2880: createPrice('price_1PuuVmIewCKA2h0I37dMpqI5', {
340
+ status: 'active',
341
+ amount: 2880,
342
+ period: 'yearly',
343
+ }),
344
+ }),
345
+ },
346
+ cli: {
347
+ founder30: createProduct('prod_GrHtZKuUDvLZOF', {
348
+ monthly_30: createPrice('plan_GrHuyGjzYN0XN2', {
349
+ status: 'active',
350
+ amount: 30,
351
+ period: 'monthly',
352
+ }),
353
+ }),
354
+ founder50: createProduct('prod_GsL0ntimYpTTwD', {
355
+ monthly_50: createPrice('plan_GsL1IRUwpj5CIF', {
356
+ status: 'active',
357
+ amount: 50,
358
+ period: 'monthly',
359
+ }),
360
+ monthly_90: createPrice('price_1JMHNnIewCKA2h0II5RGjVtk', {
361
+ status: 'inactive',
362
+ amount: 90,
363
+ period: 'monthly',
364
+ }),
365
+ }),
366
+ founder: createProduct('prod_GpzVRVsBgluoef', {
367
+ monthly_100: createPrice('plan_GpzWZLfsOzjrvI', {
368
+ status: 'inactive',
369
+ amount: 100,
370
+ period: 'monthly',
371
+ }),
372
+ monthly_125: createPrice('price_1PuuXFIewCKA2h0IVHSyfFsd', {
373
+ status: 'active',
374
+ amount: 125,
375
+ period: 'monthly',
376
+ }),
377
+ yearly_1200: createPrice('price_1PuuXYIewCKA2h0IAsygBajd', {
378
+ status: 'active',
379
+ amount: 1200,
380
+ period: 'yearly',
381
+ }),
382
+ }),
383
+ performance: createProduct('prod_LphRn5Rfuq3CMh', {
384
+ monthly_300: createPrice('price_1L822LIewCKA2h0I5JYyOG1p', {
385
+ status: 'inactive',
386
+ amount: 300,
387
+ period: 'monthly',
388
+ }),
389
+ monthly_375: createPrice('price_1PuuYKIewCKA2h0IWBJ4cyRQ', {
390
+ status: 'active',
391
+ amount: 375,
392
+ period: 'monthly',
393
+ }),
394
+ yearly_3600: createPrice('price_1PuuYcIewCKA2h0IzeU1xWbQ', {
395
+ status: 'active',
396
+ amount: 3600,
397
+ period: 'yearly',
398
+ }),
399
+ }),
400
+ scale: createProduct('prod_LphRKSuMLjQriP', {
401
+ monthly_1200: createPrice('price_1L822RIewCKA2h0IPt9f2nZM', {
402
+ status: 'inactive',
403
+ amount: 1200,
404
+ period: 'monthly',
405
+ }),
406
+ monthly_1500: createPrice('price_1PuuarIewCKA2h0IEONPcFU5', {
407
+ status: 'active',
408
+ amount: 1500,
409
+ period: 'monthly',
410
+ }),
411
+ yearly_14400: createPrice('price_1Puub5IewCKA2h0IMJ3CQ58r', {
412
+ status: 'active',
413
+ amount: 14400,
414
+ period: 'yearly',
415
+ }),
416
+ }),
417
+ },
418
+ legacy: {
419
+ essential: createProduct('prod_FohIP5aSMWWGyY', {
420
+ monthly_58: createPrice('plan_FohJzCujA6vvt4', {
421
+ status: 'active',
422
+ amount: 58,
423
+ period: 'monthly',
424
+ }),
425
+ }),
426
+ essentialNew: createProduct('prod_GYXn73zcoJKsF8', {
427
+ monthly_58: createPrice('plan_GYXn2cnPl5dy7j', {
428
+ status: 'active',
429
+ amount: 58,
430
+ period: 'monthly',
431
+ }),
432
+ yearly_580: createPrice('price_1Gqb24IewCKA2h0ILP5rxTnT', {
433
+ status: 'active',
434
+ amount: 580,
435
+ period: 'yearly',
436
+ }),
437
+ }),
438
+ professional: createProduct('prod_GYXouE5K7vuitU', {
439
+ monthly_199: createPrice('plan_GYXoKsa2j0yURg', {
440
+ status: 'active',
441
+ amount: 199,
442
+ period: 'monthly',
443
+ }),
444
+ yearly_1990: createPrice('price_1KHTgaIewCKA2h0I81TVg85r', {
445
+ status: 'inactive',
446
+ amount: 1990,
447
+ period: 'yearly',
448
+ }),
449
+ yearly_2388: createPrice('price_1KLT32IewCKA2h0IFeJOAgG5', {
450
+ status: 'active',
451
+ amount: 2388,
452
+ period: 'yearly',
453
+ }),
454
+ }),
455
+ startup: createProduct('prod_FdmCGcrX2IETUH', {
456
+ monthly_49: createPrice('plan_FdmDAUN7JGD8pR', {
457
+ status: 'active',
458
+ amount: 49,
459
+ period: 'monthly',
460
+ }),
461
+ yearly_200: createPrice('plan_Ft8qvk401twwrW', {
462
+ status: 'active',
463
+ amount: 200,
464
+ period: 'yearly',
465
+ }),
466
+ }),
467
+ growth: createProduct('prod_FohKfjLOlJNm1W', {
468
+ monthly_199: createPrice('plan_FohKGuWis5ocsi', {
469
+ status: 'active',
470
+ amount: 199,
471
+ period: 'monthly',
472
+ }),
473
+ }),
474
+ business: createProduct('prod_FdmEvAgT7ZtVEw', {
475
+ monthly_199: createPrice('plan_FdmE8akq9ukxiY', {
476
+ status: 'active',
477
+ amount: 199,
478
+ period: 'monthly',
479
+ }),
480
+ }),
481
+ enterprise: createProduct('prod_GuGGWeMQ3SCuE9', {
482
+ monthly_700: createPrice('plan_GuGICX6nRtDthN', {
483
+ status: 'active',
484
+ amount: 700,
485
+ period: 'monthly',
486
+ }),
487
+ }),
488
+ },
489
+ },
490
+ } as const;
491
+
492
+ const { dev, prod } = products;
493
+
494
+ // --- plans ---
495
+ export const basicPlan = createPlan('basic', {
496
+ dev: [
497
+ dev.builder.essential,
498
+ dev.cli.founder30,
499
+ dev.cli.founder50,
500
+ dev.cli.founder,
501
+ dev.legacy.essential,
502
+ dev.legacy.essentialNew,
503
+ dev.legacy.startup,
504
+ ],
505
+ prod: [
506
+ prod.builder.essential,
507
+ prod.cli.founder30,
508
+ prod.cli.founder50,
509
+ prod.cli.founder,
510
+ prod.legacy.essential,
511
+ prod.legacy.essentialNew,
512
+ prod.legacy.startup,
513
+ ],
514
+ });
515
+
516
+ export const legacyProPlan = createPlan('legacy_pro', {
517
+ dev: [
518
+ dev.builder.professional,
519
+ dev.cli.founder,
520
+ dev.cli.founder30,
521
+ dev.cli.founder50,
522
+ dev.cli.performance,
523
+ dev.cli.scale,
524
+ dev.legacy.professional,
525
+ dev.legacy.growth,
526
+ dev.legacy.business,
527
+ ],
528
+ prod: [
529
+ prod.builder.professional,
530
+ prod.cli.founder,
531
+ prod.cli.founder30,
532
+ prod.cli.founder50,
533
+ prod.cli.performance,
534
+ prod.cli.scale,
535
+ prod.legacy.professional,
536
+ prod.legacy.growth,
537
+ prod.legacy.business,
538
+ ],
539
+ });
540
+
541
+ export const proPlan = createPlan('pro', {
542
+ dev: [
543
+ dev.builder.professional,
544
+ dev.cli.performance,
545
+ dev.legacy.professional,
546
+ dev.legacy.growth,
547
+ dev.legacy.business,
548
+ ],
549
+ prod: [
550
+ prod.builder.professional,
551
+ prod.cli.performance,
552
+ prod.legacy.professional,
553
+ prod.legacy.growth,
554
+ prod.legacy.business,
555
+ ],
556
+ });
557
+
558
+ export const scalePlan = createPlan('scale', {
559
+ dev: [dev.cli.scale, dev.legacy.enterprise],
560
+ prod: [prod.cli.scale, prod.legacy.enterprise],
561
+ });
562
+
563
+ // --- configurations ---
564
+ export const configurations = {
565
+ dev: {
566
+ builder: {
567
+ update: createPortalConfig(PortalConfigKey.BuilderUpdateDev, [
568
+ dev.builder.essential,
569
+ dev.builder.professional,
570
+ ]),
571
+ upgrade: createPortalConfig(PortalConfigKey.BuilderUpgradeDev, [
572
+ dev.builder.professional,
573
+ ]),
574
+ },
575
+ cli: {
576
+ update: createPortalConfig(PortalConfigKey.CLIUpdateDev, [
577
+ dev.cli.founder,
578
+ dev.cli.performance,
579
+ dev.cli.scale,
580
+ ]),
581
+ upgrade: createPortalConfig(PortalConfigKey.CLIUpgradeDev, [
582
+ dev.cli.performance,
583
+ dev.cli.scale,
584
+ ]),
585
+ },
586
+ },
587
+ prod: {
588
+ builder: {
589
+ update: createPortalConfig(PortalConfigKey.BuilderUpdateProd, [
590
+ prod.builder.essential,
591
+ prod.builder.professional,
592
+ ]),
593
+ upgrade: createPortalConfig(PortalConfigKey.BuilderUpgradeProd, [
594
+ prod.builder.professional,
595
+ ]),
596
+ },
597
+ cli: {
598
+ update: createPortalConfig(PortalConfigKey.CLIUpdateProd, [
599
+ prod.cli.founder,
600
+ prod.cli.performance,
601
+ prod.cli.scale,
602
+ ]),
603
+ upgrade: createPortalConfig(PortalConfigKey.CLIUpgradeProd, [
604
+ prod.cli.performance,
605
+ prod.cli.scale,
606
+ ]),
607
+ },
608
+ },
93
609
  };
94
610
 
95
- /* ToDesktop Web Plans */
96
- export const getEssentialPlanIds = (stage: 'dev' | 'prod') => {
97
- const planIds = getPlanEnvironment(stage);
98
- return pick(planIds, 'startup', 'essential', 'essential_new');
611
+ // --- utilities ---
612
+
613
+ export const hasActiveSub = (sub?: Subscription) => {
614
+ return sub && (sub.status === 'active' || sub.status === 'trialing')
615
+ ? true
616
+ : false;
99
617
  };
100
618
 
101
- export const getProfessionalPlanIds = (stage: 'dev' | 'prod') => {
102
- const planIds = getPlanEnvironment(stage);
103
- return pick(
104
- planIds,
105
- 'business',
106
- 'growth',
107
- 'professional',
108
- 'professional_annual'
109
- );
619
+ export const hasPlan = (plan: Plan, sub?: Subscription) => {
620
+ if (!sub || !hasActiveSub(sub)) return false;
621
+ const plans = [basicPlan, legacyProPlan, proPlan, scalePlan];
622
+
623
+ // find the plans that are eligible to be tested
624
+ const eligiblePlans = plans.filter((eligiblePlan) => {
625
+ return plan.eligiblePlanTiers.includes(eligiblePlan.tier);
626
+ });
627
+
628
+ // test if any of those plans contains the current subscription
629
+ for (const { products } of eligiblePlans) {
630
+ for (const { id, prices } of [...products.dev, ...products.prod]) {
631
+ if (sub?.productId && sub?.productId === id) {
632
+ return true;
633
+ } else if (
634
+ Object.values(prices).some((price) => price.id === sub?.planId)
635
+ ) {
636
+ return true;
637
+ }
638
+ }
639
+ }
640
+
641
+ return false;
110
642
  };
111
643
 
112
- export const getEnterprisePlanIds = (stage: 'dev' | 'prod') => {
113
- const planIds = getPlanEnvironment(stage);
114
- return pick(planIds, 'enterprise');
644
+ export const getPlan = (
645
+ sub?: Pick<Subscription, 'productId' | 'planId'>
646
+ ): Plan | null => {
647
+ const plans = [basicPlan, legacyProPlan, proPlan, scalePlan];
648
+
649
+ for (const plan of plans) {
650
+ const { products } = plan;
651
+ for (const { id, prices } of [...products.dev, ...products.prod]) {
652
+ if (sub?.productId && sub?.productId === id) {
653
+ return plan;
654
+ } else if (
655
+ Object.values(prices).some((price) => price.id === sub?.planId)
656
+ ) {
657
+ return plan;
658
+ }
659
+ }
660
+ }
661
+
662
+ return null;
115
663
  };
116
664
 
117
- export enum PortalConfigKey {
118
- CLIUpdateDev = 'cli_update_dev',
119
- CLIUpdateProd = 'cli_update_prod',
120
- CLIUpgradeDev = 'cli_upgrade_dev',
121
- CLIUpgradeProd = 'cli_upgrade_prod',
122
- BuilderUpdateDev = 'builder_update_dev',
123
- BuilderUpdateProd = 'builder_update_prod',
124
- BuilderUpgradeDev = 'builder_upgrade_dev',
125
- BuilderUpgradeProd = 'builder_upgrade_prod',
126
- }
665
+ // --- legacy support for createStripeCheckoutSession - delete when no longer needed ---
666
+ export type LegacyProductKey =
667
+ | 'startup'
668
+ | 'business'
669
+ | 'essential'
670
+ | 'growth'
671
+ | 'essential_new'
672
+ | 'professional'
673
+ | 'professional_annual'
674
+ | 'professional_annual_full_price'
675
+ | 'cli_founder'
676
+ | 'cli_founder_30'
677
+ | 'cli_founder_50'
678
+ | 'cli_performance'
679
+ | 'cli_scale'
680
+ | 'builder_essential'
681
+ | 'builder_professional'
682
+ | 'enterprise';
683
+
684
+ export const LegacyProductRecord: Record<
685
+ LegacyProductKey,
686
+ Record<'dev' | 'prod', Product>
687
+ > = {
688
+ startup: { dev: dev.legacy.startup, prod: prod.legacy.startup },
689
+ business: { dev: dev.legacy.business, prod: prod.legacy.business },
690
+ essential: { dev: dev.legacy.essential, prod: prod.legacy.essential },
691
+ growth: { dev: dev.legacy.growth, prod: prod.legacy.growth },
692
+ essential_new: {
693
+ dev: dev.legacy.essentialNew,
694
+ prod: prod.legacy.essentialNew,
695
+ },
696
+ professional: {
697
+ dev: dev.legacy.professional,
698
+ prod: prod.legacy.professional,
699
+ },
700
+ professional_annual: {
701
+ dev: dev.legacy.professional,
702
+ prod: prod.legacy.professional,
703
+ },
704
+ professional_annual_full_price: {
705
+ dev: dev.legacy.professional,
706
+ prod: prod.legacy.professional,
707
+ },
708
+ cli_founder: { dev: dev.cli.founder, prod: prod.cli.founder },
709
+ cli_founder_30: { dev: dev.cli.founder30, prod: prod.cli.founder30 },
710
+ cli_founder_50: { dev: dev.cli.founder50, prod: prod.cli.founder50 },
711
+ cli_performance: { dev: dev.cli.performance, prod: prod.cli.performance },
712
+ cli_scale: { dev: dev.cli.scale, prod: prod.cli.scale },
713
+ builder_essential: {
714
+ dev: dev.builder.essential,
715
+ prod: prod.builder.essential,
716
+ },
717
+ builder_professional: {
718
+ dev: dev.builder.professional,
719
+ prod: prod.builder.professional,
720
+ },
721
+ enterprise: { dev: dev.legacy.enterprise, prod: prod.legacy.enterprise },
722
+ };