@drawbridge/drawbridge-utils 0.0.129 → 0.0.131

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.
@@ -4855,7 +4855,7 @@ var projectConnection = (record) => {
4855
4855
  var resolveConnection = (item, data2, env = {}) => {
4856
4856
  if (!item) return item;
4857
4857
  return Object.fromEntries(
4858
- Object.entries(item).filter(([key]) => !["auth", "enabled", "fields", "hooks", "inbound", "provider", "requires", "steps", "supports"].includes(key)).map(([key, value]) => [
4858
+ Object.entries(item).filter(([key]) => !["auth", "enabled", "fields", "hooks", "inbound", "provider", "requires", "status", "steps", "supports"].includes(key)).map(([key, value]) => [
4859
4859
  key,
4860
4860
  typeof value === "function" ? value(data2, env) : value
4861
4861
  ])
@@ -6033,7 +6033,14 @@ const resolveConnection = ( item, data, env = {} ) => {
6033
6033
  // PLATFORM configuration — which credentials an admin types in for this
6034
6034
  // vendor — and no merchant-facing resolution has any business carrying
6035
6035
  // it, even as bare descriptors.
6036
- .filter( ( [ key ] ) => ! [ 'auth', 'enabled', 'fields', 'hooks', 'inbound', 'provider', 'requires', 'steps', 'supports' ].includes( key ) )
6036
+ //
6037
+ // `status` is in it because the hook judges a STORED DOCUMENT, and
6038
+ // resolution runs over whatever data it is handed — including none.
6039
+ // Asked about an absent document, the hook answers 'pending', and that
6040
+ // answer baked a Pending badge into Klaviyo, Mailchimp and Attentive
6041
+ // cards nobody had connected. Status belongs to the caller's own
6042
+ // read-time pass (api's applyStatus), never to projection.
6043
+ .filter( ( [ key ] ) => ! [ 'auth', 'enabled', 'fields', 'hooks', 'inbound', 'provider', 'requires', 'status', 'steps', 'supports' ].includes( key ) )
6037
6044
  .map( ( [ key, value ] ) => [
6038
6045
  key,
6039
6046
  ( typeof value === 'function' ? value( data, env ) : value )
@@ -6033,7 +6033,14 @@ const resolveConnection = ( item, data, env = {} ) => {
6033
6033
  // PLATFORM configuration — which credentials an admin types in for this
6034
6034
  // vendor — and no merchant-facing resolution has any business carrying
6035
6035
  // it, even as bare descriptors.
6036
- .filter( ( [ key ] ) => ! [ 'auth', 'enabled', 'fields', 'hooks', 'inbound', 'provider', 'requires', 'steps', 'supports' ].includes( key ) )
6036
+ //
6037
+ // `status` is in it because the hook judges a STORED DOCUMENT, and
6038
+ // resolution runs over whatever data it is handed — including none.
6039
+ // Asked about an absent document, the hook answers 'pending', and that
6040
+ // answer baked a Pending badge into Klaviyo, Mailchimp and Attentive
6041
+ // cards nobody had connected. Status belongs to the caller's own
6042
+ // read-time pass (api's applyStatus), never to projection.
6043
+ .filter( ( [ key ] ) => ! [ 'auth', 'enabled', 'fields', 'hooks', 'inbound', 'provider', 'requires', 'status', 'steps', 'supports' ].includes( key ) )
6037
6044
  .map( ( [ key, value ] ) => [
6038
6045
  key,
6039
6046
  ( typeof value === 'function' ? value( data, env ) : value )
@@ -4781,7 +4781,7 @@ var projectConnection = (record) => {
4781
4781
  var resolveConnection = (item, data2, env = {}) => {
4782
4782
  if (!item) return item;
4783
4783
  return Object.fromEntries(
4784
- Object.entries(item).filter(([key]) => !["auth", "enabled", "fields", "hooks", "inbound", "provider", "requires", "steps", "supports"].includes(key)).map(([key, value]) => [
4784
+ Object.entries(item).filter(([key]) => !["auth", "enabled", "fields", "hooks", "inbound", "provider", "requires", "status", "steps", "supports"].includes(key)).map(([key, value]) => [
4785
4785
  key,
4786
4786
  typeof value === "function" ? value(data2, env) : value
4787
4787
  ])
package/dist/pricing.cjs CHANGED
@@ -886,7 +886,7 @@ var channels = {
886
886
  };
887
887
  var numbers = {
888
888
  sms: {
889
- monthlyCents: 500
889
+ monthlyCents: 1500
890
890
  }
891
891
  };
892
892
  // Annotate the CommonJS export names for ESM import in node:
@@ -194,12 +194,14 @@ const channels = {
194
194
  // joins the organization's subscription as its own line and leaves when the
195
195
  // number is released. CENTS per month, like every stored money value.
196
196
  //
197
- // The amount was not settled in the item-6 plan (only the mechanism was);
198
- // $5 covers the ~$1.15 carrier cost with room for A2P registration fees.
199
- // Changing it is this one line plus the matching Stripe Price.
197
+ // $15 was DECIDED in the platform-sender pricing session (2026-08-30): it
198
+ // covers the worst case of number rental (~$1-2) + carrier campaign fees
199
+ // (~$2-15) + amortized A2P registration, in line with what SMS platforms
200
+ // charge for a dedicated number. Changing it is this one line plus the
201
+ // matching Stripe Price.
200
202
  const numbers = {
201
203
  sms : {
202
- monthlyCents : 500
204
+ monthlyCents : 1500
203
205
  }
204
206
  };
205
207
 
package/dist/pricing.d.ts CHANGED
@@ -194,12 +194,14 @@ const channels = {
194
194
  // joins the organization's subscription as its own line and leaves when the
195
195
  // number is released. CENTS per month, like every stored money value.
196
196
  //
197
- // The amount was not settled in the item-6 plan (only the mechanism was);
198
- // $5 covers the ~$1.15 carrier cost with room for A2P registration fees.
199
- // Changing it is this one line plus the matching Stripe Price.
197
+ // $15 was DECIDED in the platform-sender pricing session (2026-08-30): it
198
+ // covers the worst case of number rental (~$1-2) + carrier campaign fees
199
+ // (~$2-15) + amortized A2P registration, in line with what SMS platforms
200
+ // charge for a dedicated number. Changing it is this one line plus the
201
+ // matching Stripe Price.
200
202
  const numbers = {
201
203
  sms : {
202
- monthlyCents : 500
204
+ monthlyCents : 1500
203
205
  }
204
206
  };
205
207
 
package/dist/pricing.js CHANGED
@@ -835,7 +835,7 @@ var channels = {
835
835
  };
836
836
  var numbers = {
837
837
  sms: {
838
- monthlyCents: 500
838
+ monthlyCents: 1500
839
839
  }
840
840
  };
841
841
  export {
package/dist/twilio.cjs CHANGED
@@ -113,8 +113,9 @@ var twilio = {
113
113
  // body: PhoneNumber (E.164), SmsUrl, SmsMethod
114
114
  // DELETE /2010-04-01/Accounts/{AccountSid}/IncomingPhoneNumbers/{Sid}.json
115
115
  // Basic auth throughout, like Messages.
116
- searchNumbers: async ({ accountSid, areaCode, authToken, contains, country = "US", limit = 10, request: request2 = request }) => {
116
+ searchNumbers: async ({ accountSid, areaCode, authToken, contains, country = "US", cursor, limit = 10, request: request2 = request }) => {
117
117
  if (!accountSid || !authToken) throw new Error("Twilio credentials missing \u2014 accountSid, authToken");
118
+ const [page, token] = String(cursor || "").split("~");
118
119
  const result = await request2({
119
120
  method: "GET",
120
121
  url: "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/AvailablePhoneNumbers/" + country + "/Local.json",
@@ -128,14 +129,20 @@ var twilio = {
128
129
  // `Contains` is the vendor's matching-pattern filter — digits
129
130
  // match anywhere in the number, so one search box serves "my
130
131
  // area code" and "ends in 7777" alike.
131
- ...contains && { Contains: contains }
132
+ ...contains && { Contains: contains },
133
+ ...token && { Page: page, PageToken: token }
132
134
  }
133
135
  });
134
- return ((result == null ? void 0 : result.available_phone_numbers) || []).map((entry) => ({
135
- friendly: entry.friendly_name,
136
- locality: entry.locality || entry.region || null,
137
- number: entry.phone_number
138
- }));
136
+ const nextQuery = (result == null ? void 0 : result.next_page_uri) ? new URLSearchParams(String(result.next_page_uri).split("?")[1] || "") : null;
137
+ const nextToken = nextQuery == null ? void 0 : nextQuery.get("PageToken");
138
+ return {
139
+ cursor: nextToken ? (nextQuery.get("Page") || "") + "~" + nextToken : null,
140
+ items: ((result == null ? void 0 : result.available_phone_numbers) || []).map((entry) => ({
141
+ friendly: entry.friendly_name,
142
+ locality: entry.locality || entry.region || null,
143
+ number: entry.phone_number
144
+ }))
145
+ };
139
146
  },
140
147
  purchaseNumber: async ({ accountSid, authToken, number, request: request2 = request, smsUrl }) => {
141
148
  if (!accountSid || !authToken) throw new Error("Twilio credentials missing \u2014 accountSid, authToken");
package/dist/twilio.d.cts CHANGED
@@ -77,10 +77,16 @@ const twilio = {
77
77
  // DELETE /2010-04-01/Accounts/{AccountSid}/IncomingPhoneNumbers/{Sid}.json
78
78
  // Basic auth throughout, like Messages.
79
79
 
80
- searchNumbers : async ({ accountSid, areaCode, authToken, contains, country = 'US', limit = 10, request: request$1 = request }) => {
80
+ searchNumbers : async ({ accountSid, areaCode, authToken, contains, country = 'US', cursor, limit = 10, request: request$1 = request }) => {
81
81
 
82
82
  if( ! accountSid || ! authToken ) throw new Error( 'Twilio credentials missing — accountSid, authToken' );
83
83
 
84
+ // The vendor pages with Page + PageToken and answers next_page_uri
85
+ // (AvailablePhoneNumbers resource docs). Ours is one opaque cursor —
86
+ // `<Page>~<PageToken>` — so the caller never learns the vendor's two
87
+ // halves and cannot recombine them wrong.
88
+ const [ page, token ] = String( cursor || '' ).split( '~' );
89
+
84
90
  const result = await request$1({
85
91
  method : 'GET',
86
92
  url : 'https://api.twilio.com/2010-04-01/Accounts/' + accountSid + '/AvailablePhoneNumbers/' + country + '/Local.json',
@@ -94,16 +100,26 @@ const twilio = {
94
100
  // `Contains` is the vendor's matching-pattern filter — digits
95
101
  // match anywhere in the number, so one search box serves "my
96
102
  // area code" and "ends in 7777" alike.
97
- ...( contains && { Contains : contains } )
103
+ ...( contains && { Contains : contains } ),
104
+ ...( token && { Page : page, PageToken : token } )
98
105
  }
99
106
  });
100
107
 
108
+ const nextQuery = result?.next_page_uri
109
+ ? new URLSearchParams( String( result.next_page_uri ).split( '?' )[ 1 ] || '' )
110
+ : null;
111
+
112
+ const nextToken = nextQuery?.get( 'PageToken' );
113
+
101
114
  // The caller-facing shape is ours; the vendor's field names stay here.
102
- return ( result?.available_phone_numbers || [] ).map( ( entry ) => ({
103
- friendly : entry.friendly_name,
104
- locality : entry.locality || entry.region || null,
105
- number : entry.phone_number
106
- }) );
115
+ return {
116
+ cursor : nextToken ? ( nextQuery.get( 'Page' ) || '' ) + '~' + nextToken : null,
117
+ items : ( result?.available_phone_numbers || [] ).map( ( entry ) => ({
118
+ friendly : entry.friendly_name,
119
+ locality : entry.locality || entry.region || null,
120
+ number : entry.phone_number
121
+ }) )
122
+ };
107
123
 
108
124
  },
109
125
 
package/dist/twilio.d.ts CHANGED
@@ -77,10 +77,16 @@ const twilio = {
77
77
  // DELETE /2010-04-01/Accounts/{AccountSid}/IncomingPhoneNumbers/{Sid}.json
78
78
  // Basic auth throughout, like Messages.
79
79
 
80
- searchNumbers : async ({ accountSid, areaCode, authToken, contains, country = 'US', limit = 10, request: request$1 = request }) => {
80
+ searchNumbers : async ({ accountSid, areaCode, authToken, contains, country = 'US', cursor, limit = 10, request: request$1 = request }) => {
81
81
 
82
82
  if( ! accountSid || ! authToken ) throw new Error( 'Twilio credentials missing — accountSid, authToken' );
83
83
 
84
+ // The vendor pages with Page + PageToken and answers next_page_uri
85
+ // (AvailablePhoneNumbers resource docs). Ours is one opaque cursor —
86
+ // `<Page>~<PageToken>` — so the caller never learns the vendor's two
87
+ // halves and cannot recombine them wrong.
88
+ const [ page, token ] = String( cursor || '' ).split( '~' );
89
+
84
90
  const result = await request$1({
85
91
  method : 'GET',
86
92
  url : 'https://api.twilio.com/2010-04-01/Accounts/' + accountSid + '/AvailablePhoneNumbers/' + country + '/Local.json',
@@ -94,16 +100,26 @@ const twilio = {
94
100
  // `Contains` is the vendor's matching-pattern filter — digits
95
101
  // match anywhere in the number, so one search box serves "my
96
102
  // area code" and "ends in 7777" alike.
97
- ...( contains && { Contains : contains } )
103
+ ...( contains && { Contains : contains } ),
104
+ ...( token && { Page : page, PageToken : token } )
98
105
  }
99
106
  });
100
107
 
108
+ const nextQuery = result?.next_page_uri
109
+ ? new URLSearchParams( String( result.next_page_uri ).split( '?' )[ 1 ] || '' )
110
+ : null;
111
+
112
+ const nextToken = nextQuery?.get( 'PageToken' );
113
+
101
114
  // The caller-facing shape is ours; the vendor's field names stay here.
102
- return ( result?.available_phone_numbers || [] ).map( ( entry ) => ({
103
- friendly : entry.friendly_name,
104
- locality : entry.locality || entry.region || null,
105
- number : entry.phone_number
106
- }) );
115
+ return {
116
+ cursor : nextToken ? ( nextQuery.get( 'Page' ) || '' ) + '~' + nextToken : null,
117
+ items : ( result?.available_phone_numbers || [] ).map( ( entry ) => ({
118
+ friendly : entry.friendly_name,
119
+ locality : entry.locality || entry.region || null,
120
+ number : entry.phone_number
121
+ }) )
122
+ };
107
123
 
108
124
  },
109
125
 
package/dist/twilio.js CHANGED
@@ -88,8 +88,9 @@ var twilio = {
88
88
  // body: PhoneNumber (E.164), SmsUrl, SmsMethod
89
89
  // DELETE /2010-04-01/Accounts/{AccountSid}/IncomingPhoneNumbers/{Sid}.json
90
90
  // Basic auth throughout, like Messages.
91
- searchNumbers: async ({ accountSid, areaCode, authToken, contains, country = "US", limit = 10, request: request2 = request }) => {
91
+ searchNumbers: async ({ accountSid, areaCode, authToken, contains, country = "US", cursor, limit = 10, request: request2 = request }) => {
92
92
  if (!accountSid || !authToken) throw new Error("Twilio credentials missing \u2014 accountSid, authToken");
93
+ const [page, token] = String(cursor || "").split("~");
93
94
  const result = await request2({
94
95
  method: "GET",
95
96
  url: "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/AvailablePhoneNumbers/" + country + "/Local.json",
@@ -103,14 +104,20 @@ var twilio = {
103
104
  // `Contains` is the vendor's matching-pattern filter — digits
104
105
  // match anywhere in the number, so one search box serves "my
105
106
  // area code" and "ends in 7777" alike.
106
- ...contains && { Contains: contains }
107
+ ...contains && { Contains: contains },
108
+ ...token && { Page: page, PageToken: token }
107
109
  }
108
110
  });
109
- return ((result == null ? void 0 : result.available_phone_numbers) || []).map((entry) => ({
110
- friendly: entry.friendly_name,
111
- locality: entry.locality || entry.region || null,
112
- number: entry.phone_number
113
- }));
111
+ const nextQuery = (result == null ? void 0 : result.next_page_uri) ? new URLSearchParams(String(result.next_page_uri).split("?")[1] || "") : null;
112
+ const nextToken = nextQuery == null ? void 0 : nextQuery.get("PageToken");
113
+ return {
114
+ cursor: nextToken ? (nextQuery.get("Page") || "") + "~" + nextToken : null,
115
+ items: ((result == null ? void 0 : result.available_phone_numbers) || []).map((entry) => ({
116
+ friendly: entry.friendly_name,
117
+ locality: entry.locality || entry.region || null,
118
+ number: entry.phone_number
119
+ }))
120
+ };
114
121
  },
115
122
  purchaseNumber: async ({ accountSid, authToken, number, request: request2 = request, smsUrl }) => {
116
123
  if (!accountSid || !authToken) throw new Error("Twilio credentials missing \u2014 accountSid, authToken");
package/package.json CHANGED
@@ -215,5 +215,5 @@
215
215
  "test": ". \"$HOME/.nvm/nvm.sh\" && nvm use && node --test"
216
216
  },
217
217
  "types": "dist/index.d.ts",
218
- "version": "0.0.129"
218
+ "version": "0.0.131"
219
219
  }