@drawbridge/drawbridge-utils 0.0.105 → 0.0.107

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/pricing.d.ts CHANGED
@@ -74,21 +74,102 @@ import '@drawbridge/drawbridge-telemetry';
74
74
  // Pro 15,000 = 30%
75
75
  // Starter 5,000 = 10%
76
76
  //
77
- // As of 2026-08-30 we sell about 2x the email we buy. That is fine while real
78
- // usage sits far below the allowances, and it is not a margin problem at this
79
- // ceiling an email costs a fraction of a cent, far under the 1.5-2.5c overage.
80
- // It is a CAPACITY problem: running out does not cost a few dollars, it stops
81
- // every merchant's mail at once. Raising a tier's allowance moves this number
82
- // too, or the ceiling quietly becomes the real limit.
77
+ // As of 2026-08-30 we sell about 2x the email we buy, against real usage of
78
+ // ~622 sends a month so this is a shape to watch, not a fire.
79
+ //
80
+ // Exceeding the included volume does NOT stop sends. The provider bills
81
+ // overage per email (see overageCents), so the consequence is a bill and the
82
+ // question is only ever "is the next plan up cheaper than the overage yet".
83
+ // Both halves stay comfortable: at 0.133c of overage against 1.5-2.5c of
84
+ // action overage, email we send past the plan still earns more than ten times
85
+ // what it costs.
86
+ //
87
+ // Raising a tier's allowance should still move the plan below, or the included
88
+ // volume quietly becomes the number that decides the bill.
89
+ // The provider's plan ladder, so the ceiling is DERIVED from which plan we are
90
+ // on rather than being a loose number somebody has to remember to change. Read
91
+ // from the SendGrid Email API Plans page 2026-08-30.
92
+ //
93
+ // included EMAILS per calendar month before overage starts.
94
+ // overageCents CENTS per additional email. $0.00133 is 0.133 CENTS — the
95
+ // decimal is the whole reason this is not stored in dollars.
96
+ // monthly CENTS per month for the plan itself.
97
+ //
98
+ // Pro is not "cheaper email" — Pro 100K costs more per overage email than
99
+ // Essentials 100K. What Pro buys is a dedicated IP, subusers, regional data
100
+ // residency, and link branding. Move for those, not for the rate.
101
+ const emailPlans = {
102
+ essentials50k : {
103
+ included : 50000,
104
+ // The plan's own price is not shown in the console once you are on it —
105
+ // it reads "Your Current Plan" where the price would be. Left null rather
106
+ // than guessed; fill from an invoice. Nothing derives from it yet, and an
107
+ // invented figure would quietly become the basis of an upgrade decision.
108
+ monthly : null,
109
+ overageCents : 0.133,
110
+ title : 'Essentials 50K'
111
+ },
112
+ essentials100k : {
113
+ included : 100000,
114
+ monthly : 3495,
115
+ overageCents : 0.09,
116
+ title : 'Essentials 100K'
117
+ },
118
+ pro100k : {
119
+ included : 100000,
120
+ monthly : 8995,
121
+ overageCents : 0.11,
122
+ title : 'Pro 100K'
123
+ },
124
+ pro300k : {
125
+ included : 300000,
126
+ monthly : 24900,
127
+ overageCents : 0.091,
128
+ title : 'Pro 300K'
129
+ },
130
+ pro700k : {
131
+ included : 700000,
132
+ monthly : 49900,
133
+ overageCents : 0.078,
134
+ title : 'Pro 700K'
135
+ },
136
+ pro1500k : {
137
+ included : 1500000,
138
+ monthly : 79900,
139
+ overageCents : 0.059,
140
+ title : 'Pro 1.5 Million'
141
+ },
142
+ pro2500k : {
143
+ included : 2500000,
144
+ monthly : 109900,
145
+ overageCents : 0.047,
146
+ title : 'Pro 2.5 Million'
147
+ }
148
+ };
149
+
150
+ // THE ONE FIELD TO CHANGE when the provider plan changes. Everything else here
151
+ // follows from it.
152
+ const emailPlan = 'essentials50k';
153
+
83
154
  const sending = {
84
155
  email : {
85
- // Fraction of monthlyCeiling that raises the alarm. Far enough ahead of
86
- // the wall to act on, high enough not to fire on ordinary growth.
156
+ // Fraction of the included volume that raises the alarm. Far enough ahead
157
+ // to act on, high enough not to fire on ordinary growth.
158
+ //
159
+ // Crossing it is NOT an outage. The provider bills overage rather than
160
+ // stopping sends, so the alarm is a COST signal: past the included volume
161
+ // every email is charged at overageCents, and at some run rate the next
162
+ // plan up is cheaper than the overage. That is the decision it exists to
163
+ // prompt, and it is why nobody should be woken by it.
87
164
  alertThreshold : 0.8,
88
- // SendGrid Essentials 50K — emails per calendar month, PLATFORM-WIDE and
89
- // across every send path: lead-facing mail, workflow steps, and the sign-in
90
- // codes and account mail that no plan allowance meters.
91
- monthlyCeiling : 50000
165
+ // Emails per calendar month included, PLATFORM-WIDE and across every send
166
+ // path: lead-facing mail, workflow steps, and the sign-in codes and
167
+ // account mail that no plan allowance meters.
168
+ monthlyCeiling : emailPlans[ emailPlan ].included,
169
+ overageCents : emailPlans[ emailPlan ].overageCents,
170
+ plan : emailPlan,
171
+ plans : emailPlans,
172
+ title : emailPlans[ emailPlan ].title
92
173
  }
93
174
  };
94
175
 
package/dist/pricing.js CHANGED
@@ -71,11 +71,6 @@ 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
- },
79
74
  sendgrid: {
80
75
  key: "organization:connection:sendgrid",
81
76
  error: "Plan does not include SendGrid connection",
@@ -118,6 +113,19 @@ var organization = {
118
113
  error: "Your plan does not include brands",
119
114
  feature: "Organization brands management"
120
115
  },
116
+ // Gates the Networking section as a whole — a verified sending domain today,
117
+ // the SMS number and a custom page domain as they land. One key rather than
118
+ // one per type: they are the same capability to a merchant, and splitting
119
+ // them would mean a plan could grant half a section.
120
+ //
121
+ // It replaces `connection.sender`, which named a connection this stopped
122
+ // being. Free organizations cannot send lead-facing email at all, so a
123
+ // sending identity there is one they could never send from.
124
+ networking: {
125
+ key: "organization:networking",
126
+ error: "Your plan does not include a custom sending identity",
127
+ feature: "Organization networking"
128
+ },
121
129
  members: {
122
130
  key: "organization:members",
123
131
  error: "Your plan does not include team members",
@@ -302,7 +310,7 @@ var plans = {
302
310
  // lead-facing email at all (the send path gates on an active
303
311
  // subscription), so granting it there would offer a domain that can
304
312
  // never send from.
305
- features: all.features([connection.sender.key, organization.members.key]),
313
+ features: all.features([organization.networking.key, organization.members.key]),
306
314
  limits: all.limits({ actions: 5e3, members: 3, storage: gigabyte * 10 }),
307
315
  marketing: {
308
316
  description: "Tools to fine-tune campaigns and improve lead quality.",
@@ -323,7 +331,7 @@ var plans = {
323
331
  },
324
332
  DB00003: {
325
333
  features: all.features([
326
- connection.sender.key,
334
+ organization.networking.key,
327
335
  organization.advertisements.key,
328
336
  organization.analytics.key,
329
337
  organization.members.key,
@@ -354,7 +362,7 @@ var plans = {
354
362
  },
355
363
  DB00004: {
356
364
  features: all.features([
357
- connection.sender.key,
365
+ organization.networking.key,
358
366
  organization.advertisements.key,
359
367
  organization.analytics.key,
360
368
  organization.members.key,
@@ -385,7 +393,7 @@ var plans = {
385
393
  },
386
394
  DB00005: {
387
395
  features: all.features([
388
- connection.sender.key,
396
+ organization.networking.key,
389
397
  organization.advertisements.key,
390
398
  organization.analytics.key,
391
399
  organization.members.key,
@@ -430,7 +438,7 @@ var resolvePlan = (subscription) => {
430
438
  // baseline whether or not the deal thought to name it. Today that is the
431
439
  // sending domain: every catalog paid tier grants it, and a custom plan
432
440
  // 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) || []]),
441
+ features: all.features([organization.networking.key, ...((_a = custom.features) == null ? void 0 : _a.granted) || []]),
434
442
  limits: all.limits(((_b = custom.limits) == null ? void 0 : _b.organization) || {}),
435
443
  // A custom plan stores its overage BARE on `custom.overages` — a different
436
444
  // shape from the catalog's nested one. Number() so a deal stored as a string
@@ -725,15 +733,74 @@ var scrape = {
725
733
  };
726
734
 
727
735
  // lib/pricing.js
736
+ var emailPlans = {
737
+ essentials50k: {
738
+ included: 5e4,
739
+ // The plan's own price is not shown in the console once you are on it —
740
+ // it reads "Your Current Plan" where the price would be. Left null rather
741
+ // than guessed; fill from an invoice. Nothing derives from it yet, and an
742
+ // invented figure would quietly become the basis of an upgrade decision.
743
+ monthly: null,
744
+ overageCents: 0.133,
745
+ title: "Essentials 50K"
746
+ },
747
+ essentials100k: {
748
+ included: 1e5,
749
+ monthly: 3495,
750
+ overageCents: 0.09,
751
+ title: "Essentials 100K"
752
+ },
753
+ pro100k: {
754
+ included: 1e5,
755
+ monthly: 8995,
756
+ overageCents: 0.11,
757
+ title: "Pro 100K"
758
+ },
759
+ pro300k: {
760
+ included: 3e5,
761
+ monthly: 24900,
762
+ overageCents: 0.091,
763
+ title: "Pro 300K"
764
+ },
765
+ pro700k: {
766
+ included: 7e5,
767
+ monthly: 49900,
768
+ overageCents: 0.078,
769
+ title: "Pro 700K"
770
+ },
771
+ pro1500k: {
772
+ included: 15e5,
773
+ monthly: 79900,
774
+ overageCents: 0.059,
775
+ title: "Pro 1.5 Million"
776
+ },
777
+ pro2500k: {
778
+ included: 25e5,
779
+ monthly: 109900,
780
+ overageCents: 0.047,
781
+ title: "Pro 2.5 Million"
782
+ }
783
+ };
784
+ var emailPlan = "essentials50k";
728
785
  var sending = {
729
786
  email: {
730
- // Fraction of monthlyCeiling that raises the alarm. Far enough ahead of
731
- // the wall to act on, high enough not to fire on ordinary growth.
787
+ // Fraction of the included volume that raises the alarm. Far enough ahead
788
+ // to act on, high enough not to fire on ordinary growth.
789
+ //
790
+ // Crossing it is NOT an outage. The provider bills overage rather than
791
+ // stopping sends, so the alarm is a COST signal: past the included volume
792
+ // every email is charged at overageCents, and at some run rate the next
793
+ // plan up is cheaper than the overage. That is the decision it exists to
794
+ // prompt, and it is why nobody should be woken by it.
732
795
  alertThreshold: 0.8,
733
- // SendGrid Essentials 50K — emails per calendar month, PLATFORM-WIDE and
734
- // across every send path: lead-facing mail, workflow steps, and the sign-in
735
- // codes and account mail that no plan allowance meters.
736
- monthlyCeiling: 5e4
796
+ // Emails per calendar month included, PLATFORM-WIDE and across every send
797
+ // path: lead-facing mail, workflow steps, and the sign-in codes and
798
+ // account mail that no plan allowance meters.
799
+ monthlyCeiling: emailPlans[emailPlan].included,
800
+ overageCents: emailPlans[emailPlan].overageCents,
801
+ plan: emailPlan,
802
+ plans: emailPlans,
803
+ title: emailPlans[emailPlan].title
737
804
  }
738
805
  };
739
806
  var channels = {
package/package.json CHANGED
@@ -172,6 +172,16 @@
172
172
  "types": "./dist/fields-validate.d.ts",
173
173
  "import": "./dist/fields-validate.js",
174
174
  "require": "./dist/fields-validate.cjs"
175
+ },
176
+ "./connections": {
177
+ "types": "./dist/connections/index.d.ts",
178
+ "import": "./dist/connections/index.js",
179
+ "require": "./dist/connections/index.cjs"
180
+ },
181
+ "./connections/oauth": {
182
+ "types": "./dist/connections/oauth.d.ts",
183
+ "import": "./dist/connections/oauth.js",
184
+ "require": "./dist/connections/oauth.cjs"
175
185
  }
176
186
  },
177
187
  "files": [
@@ -190,5 +200,5 @@
190
200
  "test": ". \"$HOME/.nvm/nvm.sh\" && nvm use && node --test"
191
201
  },
192
202
  "types": "dist/index.d.ts",
193
- "version": "0.0.105"
203
+ "version": "0.0.107"
194
204
  }