@drawbridge/drawbridge-utils 0.0.93 → 0.0.95
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/dist/plans.cjs +23 -59
- package/dist/plans.d.cts +42 -64
- package/dist/plans.d.ts +42 -64
- package/dist/plans.js +21 -58
- package/package.json +1 -1
package/dist/plans.cjs
CHANGED
|
@@ -31,7 +31,8 @@ var plans_exports = {};
|
|
|
31
31
|
__export(plans_exports, {
|
|
32
32
|
conversionRate: () => conversionRate,
|
|
33
33
|
free: () => free,
|
|
34
|
-
plans: () => plans
|
|
34
|
+
plans: () => plans,
|
|
35
|
+
resolvePlan: () => resolvePlan
|
|
35
36
|
});
|
|
36
37
|
module.exports = __toCommonJS(plans_exports);
|
|
37
38
|
|
|
@@ -420,70 +421,33 @@ var plans = {
|
|
|
420
421
|
overages: { actions: "1.5" },
|
|
421
422
|
title: "Elite",
|
|
422
423
|
conversion: 0.5
|
|
423
|
-
},
|
|
424
|
-
// Negotiated tier. Unlike the four sellable plans it has NO catalog price:
|
|
425
|
-
// each enterprise subscription bills from its own Stripe price, minted
|
|
426
|
-
// under STRIPE_PRODUCT_ENTERPRISE and recorded on items.plan.price.
|
|
427
|
-
//
|
|
428
|
-
// That absent price is the whole marker — this entry carries no flag of its
|
|
429
|
-
// own, deliberately. A plan with no stripePriceId cannot be sold self-serve
|
|
430
|
-
// because subscribe and change would hand Stripe `price : undefined`, so
|
|
431
|
-
// "is it selectable" reads straight off the thing that makes it true. Two
|
|
432
|
-
// flags were considered and dropped: `status : drafted | published` (it
|
|
433
|
-
// collides with subscription.status and organization.status, which extend.js
|
|
434
|
-
// attaches to the same payload) and `type : default | custom` (its one real
|
|
435
|
-
// job — catching a sellable plan whose STRIPE_PRICE_* env went missing — is
|
|
436
|
-
// already done by assertEnv at api boot). Negotiated-ness is recorded where
|
|
437
|
-
// it actually varies: subscription.type on the document, set by the admin.
|
|
438
|
-
//
|
|
439
|
-
// Every value below is a FALLBACK, not the deal. Real allowances come from
|
|
440
|
-
// subscription.overrides per customer. They deliberately mirror Elite
|
|
441
|
-
// rather than being infinite or zero: a half-configured enterprise
|
|
442
|
-
// subscription then degrades to the best sellable tier — a known-good,
|
|
443
|
-
// billable state — instead of billing nothing or granting everything.
|
|
444
|
-
//
|
|
445
|
-
// Placed LAST so the array-position direction logic in drawbridge-api
|
|
446
|
-
// (organization-subscription.js `plans.findIndex`) reads a move onto
|
|
447
|
-
// enterprise as an upgrade and a move off it as a downgrade.
|
|
448
|
-
DBENTERPRISE: {
|
|
449
|
-
features: all.features([
|
|
450
|
-
organization.advertisements.key,
|
|
451
|
-
organization.analytics.key,
|
|
452
|
-
organization.members.key,
|
|
453
|
-
organization.subdomain.key,
|
|
454
|
-
page.slug.key
|
|
455
|
-
]),
|
|
456
|
-
limits: all.limits({ actions: 1e5, members: infinite, storage: gigabyte * 100 }),
|
|
457
|
-
marketing: {
|
|
458
|
-
description: "Negotiated terms tailored to your organization.",
|
|
459
|
-
features: [
|
|
460
|
-
"Analytics",
|
|
461
|
-
"Custom subdomain / URLs",
|
|
462
|
-
"Confirmation page ads",
|
|
463
|
-
"Negotiated pricing and limits"
|
|
464
|
-
],
|
|
465
|
-
limits: [
|
|
466
|
-
["Actions per month", "Custom"],
|
|
467
|
-
["Affiliates", "Unlimited"],
|
|
468
|
-
["Brands", "Unlimited"],
|
|
469
|
-
["Campaigns", "Unlimited"],
|
|
470
|
-
["Pages", "Unlimited"],
|
|
471
|
-
["Members", "Custom"],
|
|
472
|
-
["Storage", "Custom"]
|
|
473
|
-
]
|
|
474
|
-
},
|
|
475
|
-
overages: { actions: "1.5" },
|
|
476
|
-
title: "Enterprise",
|
|
477
|
-
conversion: 0.5
|
|
478
424
|
}
|
|
479
425
|
};
|
|
480
|
-
var
|
|
426
|
+
var resolvePlan = (subscription) => {
|
|
481
427
|
var _a, _b;
|
|
482
|
-
|
|
428
|
+
const custom = subscription == null ? void 0 : subscription.custom;
|
|
429
|
+
if (!custom) return plans[subscription == null ? void 0 : subscription.plan] ?? free;
|
|
430
|
+
return {
|
|
431
|
+
// Reusing all.features / all.limits is what keeps a custom plan the same
|
|
432
|
+
// SHAPE as a catalog one: the base feature grants every plan carries, the
|
|
433
|
+
// campaign limits that are always infinite, and members defaulting to
|
|
434
|
+
// infinite when a deal does not name it.
|
|
435
|
+
conversion: custom.conversion ?? free.conversion,
|
|
436
|
+
custom: true,
|
|
437
|
+
features: all.features(((_a = custom.features) == null ? void 0 : _a.granted) || []),
|
|
438
|
+
limits: all.limits(((_b = custom.limits) == null ? void 0 : _b.organization) || {}),
|
|
439
|
+
overages: { actions: custom.overages },
|
|
440
|
+
title: custom.title || "Custom"
|
|
441
|
+
};
|
|
442
|
+
};
|
|
443
|
+
var conversionRate = (subscription) => {
|
|
444
|
+
var _a;
|
|
445
|
+
return ((_a = resolvePlan(subscription)) == null ? void 0 : _a.conversion) ?? free.conversion;
|
|
483
446
|
};
|
|
484
447
|
// Annotate the CommonJS export names for ESM import in node:
|
|
485
448
|
0 && (module.exports = {
|
|
486
449
|
conversionRate,
|
|
487
450
|
free,
|
|
488
|
-
plans
|
|
451
|
+
plans,
|
|
452
|
+
resolvePlan
|
|
489
453
|
});
|
package/dist/plans.d.cts
CHANGED
|
@@ -194,73 +194,51 @@ const plans = {
|
|
|
194
194
|
conversion : 0.5
|
|
195
195
|
},
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
marketing : {
|
|
231
|
-
description : 'Negotiated terms tailored to your organization.',
|
|
232
|
-
features : [
|
|
233
|
-
'Analytics',
|
|
234
|
-
'Custom subdomain / URLs',
|
|
235
|
-
'Confirmation page ads',
|
|
236
|
-
'Negotiated pricing and limits'
|
|
237
|
-
],
|
|
238
|
-
limits : [
|
|
239
|
-
[ 'Actions per month', 'Custom' ],
|
|
240
|
-
[ 'Affiliates', 'Unlimited' ],
|
|
241
|
-
[ 'Brands', 'Unlimited' ],
|
|
242
|
-
[ 'Campaigns', 'Unlimited' ],
|
|
243
|
-
[ 'Pages', 'Unlimited' ],
|
|
244
|
-
[ 'Members', 'Custom' ],
|
|
245
|
-
[ 'Storage', 'Custom' ]
|
|
246
|
-
]
|
|
247
|
-
},
|
|
248
|
-
overages : { actions : '1.5' },
|
|
249
|
-
title : 'Enterprise',
|
|
250
|
-
conversion : 0.5
|
|
251
|
-
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// The effective plan for a subscription.
|
|
200
|
+
//
|
|
201
|
+
// A CUSTOM plan is not in this catalog and never will be: it belongs to one
|
|
202
|
+
// organization, so it is stored on that organization's subscription and is
|
|
203
|
+
// self-describing. Everything a plan needs is built here from what it carries,
|
|
204
|
+
// which is why `subscription.plan` is empty for one.
|
|
205
|
+
//
|
|
206
|
+
// This is the single resolver. drawbridge-api mirrors it as an aggregation
|
|
207
|
+
// expression for the organization payload, and drawbridge-sync calls it
|
|
208
|
+
// directly on raw documents — sync never touches extend, so without this it
|
|
209
|
+
// would resolve `plans[ null ]`, bill every custom-plan cycle at $0 and charge
|
|
210
|
+
// the free 3% conversion rate. A parity test pins the two expressions together.
|
|
211
|
+
const resolvePlan = ( subscription ) => {
|
|
212
|
+
|
|
213
|
+
const custom = subscription?.custom;
|
|
214
|
+
|
|
215
|
+
if( ! custom ) return plans[ subscription?.plan ] ?? free;
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
// Reusing all.features / all.limits is what keeps a custom plan the same
|
|
219
|
+
// SHAPE as a catalog one: the base feature grants every plan carries, the
|
|
220
|
+
// campaign limits that are always infinite, and members defaulting to
|
|
221
|
+
// infinite when a deal does not name it.
|
|
222
|
+
conversion : custom.conversion ?? free.conversion,
|
|
223
|
+
custom : true,
|
|
224
|
+
features : all.features( custom.features?.granted || [] ),
|
|
225
|
+
limits : all.limits( custom.limits?.organization || {} ),
|
|
226
|
+
overages : { actions : custom.overages },
|
|
227
|
+
title : custom.title || 'Custom'
|
|
228
|
+
};
|
|
229
|
+
|
|
252
230
|
};
|
|
253
231
|
|
|
254
232
|
// Resolve the conversion-fee percentage for an order's owning org.
|
|
255
|
-
//
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
//
|
|
259
|
-
//
|
|
233
|
+
//
|
|
234
|
+
// The plan is the only source. A negotiated rate is not a per-subscription
|
|
235
|
+
// override any more — it is a custom plan, and `resolvePlan` reads that from
|
|
236
|
+
// `subscription.custom.conversion`. The catalog answers for everyone else.
|
|
237
|
+
//
|
|
238
|
+
// `??` not `||`, because a plan's 0 is a valid 0% rate. `subscription` is null
|
|
239
|
+
// for free orgs (they have no subscription document).
|
|
260
240
|
const conversionRate = ( subscription ) =>
|
|
261
|
-
subscription?.
|
|
262
|
-
?? subscription?.conversion
|
|
263
|
-
?? plans[ subscription?.plan ]?.conversion
|
|
241
|
+
resolvePlan( subscription )?.conversion
|
|
264
242
|
?? free.conversion;
|
|
265
243
|
|
|
266
|
-
export { conversionRate, free, plans };
|
|
244
|
+
export { conversionRate, free, plans, resolvePlan };
|
package/dist/plans.d.ts
CHANGED
|
@@ -194,73 +194,51 @@ const plans = {
|
|
|
194
194
|
conversion : 0.5
|
|
195
195
|
},
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
marketing : {
|
|
231
|
-
description : 'Negotiated terms tailored to your organization.',
|
|
232
|
-
features : [
|
|
233
|
-
'Analytics',
|
|
234
|
-
'Custom subdomain / URLs',
|
|
235
|
-
'Confirmation page ads',
|
|
236
|
-
'Negotiated pricing and limits'
|
|
237
|
-
],
|
|
238
|
-
limits : [
|
|
239
|
-
[ 'Actions per month', 'Custom' ],
|
|
240
|
-
[ 'Affiliates', 'Unlimited' ],
|
|
241
|
-
[ 'Brands', 'Unlimited' ],
|
|
242
|
-
[ 'Campaigns', 'Unlimited' ],
|
|
243
|
-
[ 'Pages', 'Unlimited' ],
|
|
244
|
-
[ 'Members', 'Custom' ],
|
|
245
|
-
[ 'Storage', 'Custom' ]
|
|
246
|
-
]
|
|
247
|
-
},
|
|
248
|
-
overages : { actions : '1.5' },
|
|
249
|
-
title : 'Enterprise',
|
|
250
|
-
conversion : 0.5
|
|
251
|
-
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// The effective plan for a subscription.
|
|
200
|
+
//
|
|
201
|
+
// A CUSTOM plan is not in this catalog and never will be: it belongs to one
|
|
202
|
+
// organization, so it is stored on that organization's subscription and is
|
|
203
|
+
// self-describing. Everything a plan needs is built here from what it carries,
|
|
204
|
+
// which is why `subscription.plan` is empty for one.
|
|
205
|
+
//
|
|
206
|
+
// This is the single resolver. drawbridge-api mirrors it as an aggregation
|
|
207
|
+
// expression for the organization payload, and drawbridge-sync calls it
|
|
208
|
+
// directly on raw documents — sync never touches extend, so without this it
|
|
209
|
+
// would resolve `plans[ null ]`, bill every custom-plan cycle at $0 and charge
|
|
210
|
+
// the free 3% conversion rate. A parity test pins the two expressions together.
|
|
211
|
+
const resolvePlan = ( subscription ) => {
|
|
212
|
+
|
|
213
|
+
const custom = subscription?.custom;
|
|
214
|
+
|
|
215
|
+
if( ! custom ) return plans[ subscription?.plan ] ?? free;
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
// Reusing all.features / all.limits is what keeps a custom plan the same
|
|
219
|
+
// SHAPE as a catalog one: the base feature grants every plan carries, the
|
|
220
|
+
// campaign limits that are always infinite, and members defaulting to
|
|
221
|
+
// infinite when a deal does not name it.
|
|
222
|
+
conversion : custom.conversion ?? free.conversion,
|
|
223
|
+
custom : true,
|
|
224
|
+
features : all.features( custom.features?.granted || [] ),
|
|
225
|
+
limits : all.limits( custom.limits?.organization || {} ),
|
|
226
|
+
overages : { actions : custom.overages },
|
|
227
|
+
title : custom.title || 'Custom'
|
|
228
|
+
};
|
|
229
|
+
|
|
252
230
|
};
|
|
253
231
|
|
|
254
232
|
// Resolve the conversion-fee percentage for an order's owning org.
|
|
255
|
-
//
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
//
|
|
259
|
-
//
|
|
233
|
+
//
|
|
234
|
+
// The plan is the only source. A negotiated rate is not a per-subscription
|
|
235
|
+
// override any more — it is a custom plan, and `resolvePlan` reads that from
|
|
236
|
+
// `subscription.custom.conversion`. The catalog answers for everyone else.
|
|
237
|
+
//
|
|
238
|
+
// `??` not `||`, because a plan's 0 is a valid 0% rate. `subscription` is null
|
|
239
|
+
// for free orgs (they have no subscription document).
|
|
260
240
|
const conversionRate = ( subscription ) =>
|
|
261
|
-
subscription?.
|
|
262
|
-
?? subscription?.conversion
|
|
263
|
-
?? plans[ subscription?.plan ]?.conversion
|
|
241
|
+
resolvePlan( subscription )?.conversion
|
|
264
242
|
?? free.conversion;
|
|
265
243
|
|
|
266
|
-
export { conversionRate, free, plans };
|
|
244
|
+
export { conversionRate, free, plans, resolvePlan };
|
package/dist/plans.js
CHANGED
|
@@ -383,69 +383,32 @@ var plans = {
|
|
|
383
383
|
overages: { actions: "1.5" },
|
|
384
384
|
title: "Elite",
|
|
385
385
|
conversion: 0.5
|
|
386
|
-
},
|
|
387
|
-
// Negotiated tier. Unlike the four sellable plans it has NO catalog price:
|
|
388
|
-
// each enterprise subscription bills from its own Stripe price, minted
|
|
389
|
-
// under STRIPE_PRODUCT_ENTERPRISE and recorded on items.plan.price.
|
|
390
|
-
//
|
|
391
|
-
// That absent price is the whole marker — this entry carries no flag of its
|
|
392
|
-
// own, deliberately. A plan with no stripePriceId cannot be sold self-serve
|
|
393
|
-
// because subscribe and change would hand Stripe `price : undefined`, so
|
|
394
|
-
// "is it selectable" reads straight off the thing that makes it true. Two
|
|
395
|
-
// flags were considered and dropped: `status : drafted | published` (it
|
|
396
|
-
// collides with subscription.status and organization.status, which extend.js
|
|
397
|
-
// attaches to the same payload) and `type : default | custom` (its one real
|
|
398
|
-
// job — catching a sellable plan whose STRIPE_PRICE_* env went missing — is
|
|
399
|
-
// already done by assertEnv at api boot). Negotiated-ness is recorded where
|
|
400
|
-
// it actually varies: subscription.type on the document, set by the admin.
|
|
401
|
-
//
|
|
402
|
-
// Every value below is a FALLBACK, not the deal. Real allowances come from
|
|
403
|
-
// subscription.overrides per customer. They deliberately mirror Elite
|
|
404
|
-
// rather than being infinite or zero: a half-configured enterprise
|
|
405
|
-
// subscription then degrades to the best sellable tier — a known-good,
|
|
406
|
-
// billable state — instead of billing nothing or granting everything.
|
|
407
|
-
//
|
|
408
|
-
// Placed LAST so the array-position direction logic in drawbridge-api
|
|
409
|
-
// (organization-subscription.js `plans.findIndex`) reads a move onto
|
|
410
|
-
// enterprise as an upgrade and a move off it as a downgrade.
|
|
411
|
-
DBENTERPRISE: {
|
|
412
|
-
features: all.features([
|
|
413
|
-
organization.advertisements.key,
|
|
414
|
-
organization.analytics.key,
|
|
415
|
-
organization.members.key,
|
|
416
|
-
organization.subdomain.key,
|
|
417
|
-
page.slug.key
|
|
418
|
-
]),
|
|
419
|
-
limits: all.limits({ actions: 1e5, members: infinite, storage: gigabyte * 100 }),
|
|
420
|
-
marketing: {
|
|
421
|
-
description: "Negotiated terms tailored to your organization.",
|
|
422
|
-
features: [
|
|
423
|
-
"Analytics",
|
|
424
|
-
"Custom subdomain / URLs",
|
|
425
|
-
"Confirmation page ads",
|
|
426
|
-
"Negotiated pricing and limits"
|
|
427
|
-
],
|
|
428
|
-
limits: [
|
|
429
|
-
["Actions per month", "Custom"],
|
|
430
|
-
["Affiliates", "Unlimited"],
|
|
431
|
-
["Brands", "Unlimited"],
|
|
432
|
-
["Campaigns", "Unlimited"],
|
|
433
|
-
["Pages", "Unlimited"],
|
|
434
|
-
["Members", "Custom"],
|
|
435
|
-
["Storage", "Custom"]
|
|
436
|
-
]
|
|
437
|
-
},
|
|
438
|
-
overages: { actions: "1.5" },
|
|
439
|
-
title: "Enterprise",
|
|
440
|
-
conversion: 0.5
|
|
441
386
|
}
|
|
442
387
|
};
|
|
443
|
-
var
|
|
388
|
+
var resolvePlan = (subscription) => {
|
|
444
389
|
var _a, _b;
|
|
445
|
-
|
|
390
|
+
const custom = subscription == null ? void 0 : subscription.custom;
|
|
391
|
+
if (!custom) return plans[subscription == null ? void 0 : subscription.plan] ?? free;
|
|
392
|
+
return {
|
|
393
|
+
// Reusing all.features / all.limits is what keeps a custom plan the same
|
|
394
|
+
// SHAPE as a catalog one: the base feature grants every plan carries, the
|
|
395
|
+
// campaign limits that are always infinite, and members defaulting to
|
|
396
|
+
// infinite when a deal does not name it.
|
|
397
|
+
conversion: custom.conversion ?? free.conversion,
|
|
398
|
+
custom: true,
|
|
399
|
+
features: all.features(((_a = custom.features) == null ? void 0 : _a.granted) || []),
|
|
400
|
+
limits: all.limits(((_b = custom.limits) == null ? void 0 : _b.organization) || {}),
|
|
401
|
+
overages: { actions: custom.overages },
|
|
402
|
+
title: custom.title || "Custom"
|
|
403
|
+
};
|
|
404
|
+
};
|
|
405
|
+
var conversionRate = (subscription) => {
|
|
406
|
+
var _a;
|
|
407
|
+
return ((_a = resolvePlan(subscription)) == null ? void 0 : _a.conversion) ?? free.conversion;
|
|
446
408
|
};
|
|
447
409
|
export {
|
|
448
410
|
conversionRate,
|
|
449
411
|
free,
|
|
450
|
-
plans
|
|
412
|
+
plans,
|
|
413
|
+
resolvePlan
|
|
451
414
|
};
|
package/package.json
CHANGED