@drawbridge/drawbridge-utils 0.0.103 → 0.0.104

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.js CHANGED
@@ -71,6 +71,11 @@ var connection = {
71
71
  error: "Plan does not include Mailchimp connection",
72
72
  feature: "Mailchimp connection"
73
73
  },
74
+ sender: {
75
+ key: "organization:connection:sender",
76
+ error: "Plan does not include a verified sending domain",
77
+ feature: "Sending domain connection"
78
+ },
74
79
  sendgrid: {
75
80
  key: "organization:connection:sendgrid",
76
81
  error: "Plan does not include SendGrid connection",
@@ -224,6 +229,15 @@ var featuresFor = (array = []) => Object.values({
224
229
  },
225
230
  { denied: {}, granted: {} }
226
231
  );
232
+ var overage = (actionCents) => ({
233
+ actionCents,
234
+ overages: { actions: String(actionCents) }
235
+ });
236
+ var unitAmountDecimal = (cents) => {
237
+ const value = Number(cents);
238
+ if (cents == null || !Number.isFinite(value)) throw new Error(`Invalid overage rate: ${cents}`);
239
+ return String(value);
240
+ };
227
241
  var all = {
228
242
  features: (array = []) => featuresFor([
229
243
  connection.mailchimp.key,
@@ -284,7 +298,11 @@ var free = {
284
298
  };
285
299
  var plans = {
286
300
  DB00002: {
287
- features: all.features([organization.members.key]),
301
+ // A verified sending domain is a PAID capability: free plans cannot send
302
+ // lead-facing email at all (the send path gates on an active
303
+ // subscription), so granting it there would offer a domain that can
304
+ // never send from.
305
+ features: all.features([connection.sender.key, organization.members.key]),
288
306
  limits: all.limits({ actions: 5e3, members: 3, storage: gigabyte * 10 }),
289
307
  marketing: {
290
308
  description: "Tools to fine-tune campaigns and improve lead quality.",
@@ -299,12 +317,13 @@ var plans = {
299
317
  ["Storage", "10GB"]
300
318
  ]
301
319
  },
302
- overages: { actions: "2.5" },
320
+ ...overage(2.5),
303
321
  title: "Starter",
304
322
  conversion: 2
305
323
  },
306
324
  DB00003: {
307
325
  features: all.features([
326
+ connection.sender.key,
308
327
  organization.advertisements.key,
309
328
  organization.analytics.key,
310
329
  organization.members.key,
@@ -329,12 +348,13 @@ var plans = {
329
348
  ["Storage", "20GB"]
330
349
  ]
331
350
  },
332
- overages: { actions: "2" },
351
+ ...overage(2),
333
352
  title: "Pro",
334
353
  conversion: 1.5
335
354
  },
336
355
  DB00004: {
337
356
  features: all.features([
357
+ connection.sender.key,
338
358
  organization.advertisements.key,
339
359
  organization.analytics.key,
340
360
  organization.members.key,
@@ -359,12 +379,13 @@ var plans = {
359
379
  ["Storage", "50GB"]
360
380
  ]
361
381
  },
362
- overages: { actions: "1.85" },
382
+ ...overage(1.85),
363
383
  title: "Premium",
364
384
  conversion: 1
365
385
  },
366
386
  DB00005: {
367
387
  features: all.features([
388
+ connection.sender.key,
368
389
  organization.advertisements.key,
369
390
  organization.analytics.key,
370
391
  organization.members.key,
@@ -389,7 +410,7 @@ var plans = {
389
410
  ["Storage", "100GB"]
390
411
  ]
391
412
  },
392
- overages: { actions: "1.5" },
413
+ ...overage(1.5),
393
414
  title: "Elite",
394
415
  conversion: 0.5
395
416
  }
@@ -405,8 +426,17 @@ var resolvePlan = (subscription) => {
405
426
  // infinite when a deal does not name it.
406
427
  conversion: custom.conversion ?? free.conversion,
407
428
  custom: true,
408
- features: all.features(((_a = custom.features) == null ? void 0 : _a.granted) || []),
429
+ // A custom plan is a negotiated PAID deal, so it carries the paid-tier
430
+ // baseline whether or not the deal thought to name it. Today that is the
431
+ // sending domain: every catalog paid tier grants it, and a custom plan
432
+ // silently lacking it would be a support ticket, not a pricing decision.
433
+ features: all.features([connection.sender.key, ...((_a = custom.features) == null ? void 0 : _a.granted) || []]),
409
434
  limits: all.limits(((_b = custom.limits) == null ? void 0 : _b.organization) || {}),
435
+ // A custom plan stores its overage BARE on `custom.overages` — a different
436
+ // shape from the catalog's nested one. Number() so a deal stored as a string
437
+ // still resolves to cents-per-action; an unnamed overage stays undefined
438
+ // (it bills nothing) rather than becoming NaN.
439
+ actionCents: custom.overages == null ? void 0 : Number(custom.overages),
410
440
  overages: { actions: custom.overages },
411
441
  title: custom.title || "Custom"
412
442
  };
@@ -419,5 +449,6 @@ export {
419
449
  conversionRate,
420
450
  free,
421
451
  plans,
422
- resolvePlan
452
+ resolvePlan,
453
+ unitAmountDecimal
423
454
  };