@drawbridge/drawbridge-utils 0.0.175 → 0.0.177

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.
Files changed (73) hide show
  1. package/dist/admin-B9ZaLvan.d.cts +697 -0
  2. package/dist/admin-C3HtEM6h.d.ts +697 -0
  3. package/dist/billing-Bc4yo9XG.d.cts +175 -0
  4. package/dist/billing-mNsKflmQ.d.ts +175 -0
  5. package/dist/billing.d.cts +1 -1
  6. package/dist/billing.d.ts +1 -1
  7. package/dist/connections/index.cjs +5928 -1920
  8. package/dist/connections/index.d.cts +20 -9163
  9. package/dist/connections/index.d.ts +20 -9163
  10. package/dist/connections/index.js +5917 -1921
  11. package/dist/connections/oauth.cjs +4 -4
  12. package/dist/connections/oauth.d.cts +10 -8
  13. package/dist/connections/oauth.d.ts +10 -8
  14. package/dist/connections/oauth.js +4 -4
  15. package/dist/features.cjs +10260 -42
  16. package/dist/features.d.cts +55 -42
  17. package/dist/features.d.ts +55 -42
  18. package/dist/features.js +10254 -42
  19. package/dist/http.cjs +10 -1
  20. package/dist/http.d.cts +10 -1
  21. package/dist/http.d.ts +10 -1
  22. package/dist/http.js +10 -1
  23. package/dist/index-B546oDNo.d.ts +13809 -0
  24. package/dist/index-C59xHago.d.cts +13809 -0
  25. package/dist/oauth/index.d.cts +1 -1
  26. package/dist/oauth/index.d.ts +1 -1
  27. package/dist/oauth-BJDh0sdM.d.cts +527 -0
  28. package/dist/oauth-DveZMLHx.d.ts +527 -0
  29. package/dist/partner-BOZltuh2.d.ts +94 -0
  30. package/dist/partner-ed2OfW1J.d.cts +94 -0
  31. package/dist/plans.cjs +10256 -51
  32. package/dist/plans.d.cts +37 -10
  33. package/dist/plans.d.ts +37 -10
  34. package/dist/plans.js +10262 -51
  35. package/dist/pricing.cjs +10401 -209
  36. package/dist/pricing.d.cts +34 -17
  37. package/dist/pricing.d.ts +34 -17
  38. package/dist/pricing.js +10407 -209
  39. package/dist/providers.cjs +5433 -1755
  40. package/dist/providers.d.cts +13 -15
  41. package/dist/providers.d.ts +13 -15
  42. package/dist/providers.js +5436 -1752
  43. package/dist/sendgrid.cjs +10 -1
  44. package/dist/sendgrid.js +10 -1
  45. package/dist/shopify/admin.cjs +562 -0
  46. package/dist/shopify/admin.d.cts +3 -0
  47. package/dist/shopify/admin.d.ts +3 -0
  48. package/dist/shopify/admin.js +528 -0
  49. package/dist/shopify/billing.cjs +166 -0
  50. package/dist/shopify/billing.d.cts +3 -0
  51. package/dist/shopify/billing.d.ts +3 -0
  52. package/dist/shopify/billing.js +140 -0
  53. package/dist/shopify/constants.cjs +63 -0
  54. package/dist/shopify/constants.d.cts +58 -0
  55. package/dist/shopify/constants.d.ts +58 -0
  56. package/dist/shopify/constants.js +32 -0
  57. package/dist/shopify/oauth.cjs +509 -0
  58. package/dist/shopify/oauth.d.cts +7 -0
  59. package/dist/shopify/oauth.d.ts +7 -0
  60. package/dist/shopify/oauth.js +466 -0
  61. package/dist/shopify/partner.cjs +156 -0
  62. package/dist/shopify/partner.d.cts +3 -0
  63. package/dist/shopify/partner.d.ts +3 -0
  64. package/dist/shopify/partner.js +130 -0
  65. package/dist/shopify/storefront.cjs +611 -0
  66. package/dist/shopify/storefront.d.cts +3 -0
  67. package/dist/shopify/storefront.d.ts +3 -0
  68. package/dist/shopify/storefront.js +576 -0
  69. package/dist/storefront-C8FKOGeD.d.cts +659 -0
  70. package/dist/storefront-DJFGLqPl.d.ts +659 -0
  71. package/dist/twilio.cjs +10 -1
  72. package/dist/twilio.js +10 -1
  73. package/package.json +98 -68
@@ -0,0 +1,576 @@
1
+ // lib/http.js
2
+ var DEFAULT_TIMEOUT_MS = 15e3;
3
+ var request = async ({
4
+ body,
5
+ // THE TRANSPORT, injectable and defaulted to the real one.
6
+ //
7
+ // Every other vendor client in this package takes a `fetcher` — it is how
8
+ // klaviyo, mailchimp and attentive are tested without a network, and it is a
9
+ // declared HOOK_OPTION. The Shopify client had no seam at all, so the only way
10
+ // to test a hook that used it was to inject the whole SDK namespace; that
11
+ // injection existed to work around an import cycle, and when the cycle went
12
+ // the tests lost their only hold. This is the seam they should have had.
13
+ fetcher = fetch,
14
+ headers = {},
15
+ method = "GET",
16
+ query,
17
+ timeout = DEFAULT_TIMEOUT_MS,
18
+ type = "json",
19
+ url
20
+ }) => {
21
+ const fullUrl = new URL(url);
22
+ if (query) {
23
+ Object.entries(query).forEach(([k, v]) => fullUrl.searchParams.set(k, v));
24
+ }
25
+ ;
26
+ const isForm = type === "form";
27
+ const response = await fetcher(fullUrl.toString(), {
28
+ method,
29
+ headers: {
30
+ "Content-Type": isForm ? "application/x-www-form-urlencoded" : "application/json",
31
+ ...headers
32
+ },
33
+ signal: AbortSignal.timeout(timeout),
34
+ ...body !== void 0 && {
35
+ body: isForm ? new URLSearchParams(body).toString() : JSON.stringify(body)
36
+ }
37
+ });
38
+ if (!response.ok) {
39
+ const text2 = await response.text().catch(() => "");
40
+ const error = new Error(text2 || response.statusText);
41
+ error.status = response.status;
42
+ throw error;
43
+ }
44
+ ;
45
+ const text = await response.text();
46
+ try {
47
+ return text ? JSON.parse(text) : null;
48
+ } catch {
49
+ return null;
50
+ }
51
+ };
52
+
53
+ // lib/shopify/constants.js
54
+ var SHOPIFY_STOREFRONT_API_VERSION = "2025-01";
55
+ var REFRESH_TOKEN_LIFETIME_MS = 90 * 24 * 60 * 60 * 1e3;
56
+ var ACCESS_TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
57
+ var PARTNER_API_VERSION = process.env.SHOPIFY_PARTNER_API_VERSION || "2026-07";
58
+
59
+ // lib/shopify/storefront.js
60
+ var SORT_KEY_MAP = {
61
+ bestSelling: "BEST_SELLING",
62
+ createdAt: "CREATED_AT",
63
+ id: "ID",
64
+ price: "PRICE",
65
+ productType: "PRODUCT_TYPE",
66
+ title: "TITLE",
67
+ updatedAt: "UPDATED_AT",
68
+ vendor: "VENDOR"
69
+ };
70
+ var resolveProductSort = (sort) => {
71
+ const entry = sort && Object.entries(sort)[0];
72
+ if (!entry) return null;
73
+ const [field, direction] = entry;
74
+ const sortKey = SORT_KEY_MAP[field];
75
+ if (!sortKey) return null;
76
+ return {
77
+ sortKey,
78
+ reverse: Number(direction) < 0
79
+ };
80
+ };
81
+ var storefrontUrl = (domain) => `https://${domain}/api/${SHOPIFY_STOREFRONT_API_VERSION}/graphql.json`;
82
+ var storefrontFetch = async ({ fetcher, domain, storefrontAccessToken, query, variables }) => {
83
+ return request({
84
+ method: "POST",
85
+ url: storefrontUrl(domain),
86
+ headers: {
87
+ "X-Shopify-Storefront-Access-Token": storefrontAccessToken
88
+ },
89
+ body: {
90
+ query,
91
+ ...variables && { variables }
92
+ }
93
+ });
94
+ };
95
+ var shopCountryCache = {};
96
+ var getShopCountry = async ({ domain, fetcher, storefrontAccessToken }) => {
97
+ var _a, _b;
98
+ if (shopCountryCache[domain]) return shopCountryCache[domain];
99
+ const { data } = await storefrontFetch({
100
+ fetcher,
101
+ domain,
102
+ storefrontAccessToken,
103
+ query: `{
104
+ shop {
105
+ paymentSettings {
106
+ countryCode
107
+ }
108
+ }
109
+ }`
110
+ });
111
+ const countryCode = ((_b = (_a = data == null ? void 0 : data.shop) == null ? void 0 : _a.paymentSettings) == null ? void 0 : _b.countryCode) || null;
112
+ if (countryCode) shopCountryCache[domain] = countryCode;
113
+ return countryCode;
114
+ };
115
+ var OUT_OF_STOCK_WARNING_CODES = [
116
+ "MERCHANDISE_OUT_OF_STOCK",
117
+ "MERCHANDISE_NOT_ENOUGH_STOCK"
118
+ ];
119
+ var probeVariantsOutOfStock = async ({ fetcher, domain, storefrontAccessToken, variantIds, countryCode }) => {
120
+ var _a, _b;
121
+ if (!(variantIds == null ? void 0 : variantIds.length)) return [];
122
+ const resolvedCountry = countryCode || await getShopCountry({ domain, fetcher, storefrontAccessToken });
123
+ const { data, errors } = await storefrontFetch({
124
+ fetcher,
125
+ domain,
126
+ storefrontAccessToken,
127
+ query: `
128
+ mutation probe( $input : CartInput! ){
129
+ cartCreate( input : $input ){
130
+ cart {
131
+ lines( first : 250 ){
132
+ edges {
133
+ node {
134
+ id
135
+ merchandise {
136
+ ... on ProductVariant {
137
+ id
138
+ }
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+ warnings {
145
+ code
146
+ message
147
+ target
148
+ }
149
+ }
150
+ }
151
+ `,
152
+ variables: {
153
+ input: {
154
+ lines: variantIds.map((merchandiseId) => ({
155
+ merchandiseId,
156
+ quantity: 1
157
+ })),
158
+ ...resolvedCountry && {
159
+ buyerIdentity: {
160
+ countryCode: resolvedCountry
161
+ }
162
+ }
163
+ }
164
+ }
165
+ });
166
+ if (errors) return [];
167
+ const payload = data == null ? void 0 : data.cartCreate;
168
+ const soldOut = new Set(
169
+ ((payload == null ? void 0 : payload.warnings) || []).filter((warning) => OUT_OF_STOCK_WARNING_CODES.includes(warning == null ? void 0 : warning.code) && (warning == null ? void 0 : warning.target)).map((warning) => warning.target)
170
+ );
171
+ return (((_b = (_a = payload == null ? void 0 : payload.cart) == null ? void 0 : _a.lines) == null ? void 0 : _b.edges) || []).filter(({ node }) => soldOut.has(node.id)).map(({ node }) => {
172
+ var _a2;
173
+ return (_a2 = node == null ? void 0 : node.merchandise) == null ? void 0 : _a2.id;
174
+ }).filter(Boolean);
175
+ };
176
+ var productsQuery = (search, cursor, limit, sort) => {
177
+ const resolved = resolveProductSort(sort);
178
+ const sortArgs = resolved ? `, sortKey: ${resolved.sortKey}, reverse: ${resolved.reverse}` : "";
179
+ return `{
180
+ products(first: ${limit}${search ? `, query: "title:*${search}*"` : ""}${cursor ? `, after: "${cursor}"` : ""}${sortArgs}) {
181
+ edges {
182
+ node {
183
+ id
184
+ title
185
+ description
186
+ handle
187
+ productType
188
+ featuredImage {
189
+ url
190
+ }
191
+ variants(first: 10) {
192
+ edges {
193
+ node {
194
+ id
195
+ title
196
+ image {
197
+ url
198
+ }
199
+ price {
200
+ amount
201
+ currencyCode
202
+ }
203
+ compareAtPrice {
204
+ amount
205
+ currencyCode
206
+ }
207
+ availableForSale
208
+ requiresShipping
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ pageInfo {
215
+ endCursor
216
+ hasNextPage
217
+ hasPreviousPage
218
+ startCursor
219
+ }
220
+ }
221
+ }`;
222
+ };
223
+ var productQuery = (productId) => `{
224
+ product(id: "${productId}") {
225
+ id
226
+ title
227
+ description
228
+ handle
229
+ productType
230
+ featuredImage {
231
+ url
232
+ }
233
+ variants(first: 10) {
234
+ edges {
235
+ node {
236
+ id
237
+ title
238
+ image {
239
+ url
240
+ }
241
+ price {
242
+ amount
243
+ currencyCode
244
+ }
245
+ compareAtPrice {
246
+ amount
247
+ currencyCode
248
+ }
249
+ availableForSale
250
+ requiresShipping
251
+ }
252
+ }
253
+ }
254
+ }
255
+ }`;
256
+ var variantsQuery = (productId, cursor) => `{
257
+ product(id: "${productId}") {
258
+ variants(first: 250${cursor ? `, after: "${cursor}"` : ""}) {
259
+ edges {
260
+ node {
261
+ id
262
+ title
263
+ image {
264
+ url
265
+ }
266
+ price {
267
+ amount
268
+ currencyCode
269
+ }
270
+ compareAtPrice {
271
+ amount
272
+ currencyCode
273
+ }
274
+ availableForSale
275
+ requiresShipping
276
+ }
277
+ }
278
+ pageInfo {
279
+ hasNextPage
280
+ endCursor
281
+ }
282
+ }
283
+ }
284
+ }`;
285
+ var getProducts = async ({ fetcher, domain, storefrontAccessToken, search, cursor, limit, sort }) => {
286
+ const { data, errors } = await storefrontFetch({
287
+ fetcher,
288
+ domain,
289
+ storefrontAccessToken,
290
+ query: productsQuery(search, cursor, limit, sort)
291
+ });
292
+ if (errors) {
293
+ throw new Error("Failed to fetch Shopify products");
294
+ }
295
+ ;
296
+ return data == null ? void 0 : data.products;
297
+ };
298
+ var getProduct = async ({ fetcher, domain, storefrontAccessToken, productId }) => {
299
+ var _a;
300
+ const { data, errors } = await storefrontFetch({
301
+ fetcher,
302
+ domain,
303
+ storefrontAccessToken,
304
+ query: productQuery(productId)
305
+ });
306
+ if (errors) {
307
+ throw new Error("Shopify storefront error: " + ((_a = errors[0]) == null ? void 0 : _a.message));
308
+ }
309
+ ;
310
+ if (!(data == null ? void 0 : data.product)) {
311
+ throw new Error("Shopify product not found");
312
+ }
313
+ ;
314
+ return data.product;
315
+ };
316
+ var getProductVariantsPage = async ({ fetcher, domain, storefrontAccessToken, productId, cursor }) => {
317
+ var _a;
318
+ const { data, errors } = await storefrontFetch({
319
+ fetcher,
320
+ domain,
321
+ storefrontAccessToken,
322
+ query: variantsQuery(productId, cursor)
323
+ });
324
+ if (errors) {
325
+ throw new Error("Shopify storefront error: " + ((_a = errors[0]) == null ? void 0 : _a.message));
326
+ }
327
+ ;
328
+ if (!(data == null ? void 0 : data.product)) {
329
+ throw new Error("Shopify product not found");
330
+ }
331
+ ;
332
+ return data.product.variants;
333
+ };
334
+ var CART_FIELDS = `
335
+ id
336
+ checkoutUrl
337
+ lines(first: 100) {
338
+ edges {
339
+ node {
340
+ id
341
+ quantity
342
+ merchandise {
343
+ ... on ProductVariant {
344
+ id
345
+ title
346
+ availableForSale
347
+ image {
348
+ url
349
+ }
350
+ price {
351
+ amount
352
+ currencyCode
353
+ }
354
+ product {
355
+ title
356
+ }
357
+ }
358
+ }
359
+ }
360
+ }
361
+ }
362
+ `;
363
+ var mapCart = (cart) => {
364
+ var _a;
365
+ if (!cart) return null;
366
+ return {
367
+ checkoutUrl: cart.checkoutUrl,
368
+ id: cart.id,
369
+ lines: (((_a = cart.lines) == null ? void 0 : _a.edges) || []).map(({ node }) => {
370
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
371
+ return {
372
+ availableForSale: ((_a2 = node == null ? void 0 : node.merchandise) == null ? void 0 : _a2.availableForSale) ?? true,
373
+ currency: ((_c = (_b = node == null ? void 0 : node.merchandise) == null ? void 0 : _b.price) == null ? void 0 : _c.currencyCode) || null,
374
+ id: node.id,
375
+ image: ((_e = (_d = node == null ? void 0 : node.merchandise) == null ? void 0 : _d.image) == null ? void 0 : _e.url) || null,
376
+ price: ((_g = (_f = node == null ? void 0 : node.merchandise) == null ? void 0 : _f.price) == null ? void 0 : _g.amount) || null,
377
+ productTitle: ((_i = (_h = node == null ? void 0 : node.merchandise) == null ? void 0 : _h.product) == null ? void 0 : _i.title) || null,
378
+ quantity: node.quantity,
379
+ variantId: (_j = node == null ? void 0 : node.merchandise) == null ? void 0 : _j.id,
380
+ variantTitle: ((_k = node == null ? void 0 : node.merchandise) == null ? void 0 : _k.title) || null
381
+ };
382
+ })
383
+ };
384
+ };
385
+ var firstUserError = (userErrors) => {
386
+ const error = userErrors == null ? void 0 : userErrors[0];
387
+ if (!error) return null;
388
+ const message = new Error(error.message || "Shopify cart error");
389
+ message.userError = true;
390
+ return message;
391
+ };
392
+ var createCheckoutToken = async ({ fetcher, clientId, clientSecret } = {}) => {
393
+ if (!clientId || !clientSecret) {
394
+ throw new Error("createCheckoutToken requires clientId and clientSecret");
395
+ }
396
+ ;
397
+ const response = await request({
398
+ fetcher,
399
+ method: "POST",
400
+ url: "https://api.shopify.com/auth/access_token",
401
+ body: {
402
+ client_id: clientId,
403
+ client_secret: clientSecret,
404
+ grant_type: "client_credentials"
405
+ }
406
+ });
407
+ const token = response == null ? void 0 : response.access_token;
408
+ if (!token) {
409
+ throw new Error("Failed to create Shopify checkout token");
410
+ }
411
+ ;
412
+ return token;
413
+ };
414
+ var cartCreate = async ({ fetcher, domain, storefrontAccessToken, lines }) => {
415
+ var _a, _b;
416
+ const { data, errors } = await storefrontFetch({
417
+ fetcher,
418
+ domain,
419
+ storefrontAccessToken,
420
+ query: `
421
+ mutation cartCreate($input: CartInput!) {
422
+ cartCreate(input: $input) {
423
+ cart {
424
+ ${CART_FIELDS}
425
+ }
426
+ userErrors {
427
+ field
428
+ message
429
+ }
430
+ }
431
+ }
432
+ `,
433
+ variables: {
434
+ input: {
435
+ lines
436
+ }
437
+ }
438
+ });
439
+ if (errors) {
440
+ throw new Error("Failed to create Shopify cart");
441
+ }
442
+ ;
443
+ const userError = firstUserError((_a = data == null ? void 0 : data.cartCreate) == null ? void 0 : _a.userErrors);
444
+ if (userError) throw userError;
445
+ return mapCart((_b = data == null ? void 0 : data.cartCreate) == null ? void 0 : _b.cart);
446
+ };
447
+ var cartGet = async ({ fetcher, domain, storefrontAccessToken, cartId }) => {
448
+ const { data, errors } = await storefrontFetch({
449
+ fetcher,
450
+ domain,
451
+ storefrontAccessToken,
452
+ query: `
453
+ query cart($id: ID!) {
454
+ cart(id: $id) {
455
+ ${CART_FIELDS}
456
+ }
457
+ }
458
+ `,
459
+ variables: {
460
+ id: cartId
461
+ }
462
+ });
463
+ if (errors) {
464
+ throw new Error("Failed to fetch Shopify cart");
465
+ }
466
+ ;
467
+ return mapCart(data == null ? void 0 : data.cart);
468
+ };
469
+ var cartLinesAdd = async ({ fetcher, domain, storefrontAccessToken, cartId, lines }) => {
470
+ var _a, _b;
471
+ const { data, errors } = await storefrontFetch({
472
+ fetcher,
473
+ domain,
474
+ storefrontAccessToken,
475
+ query: `
476
+ mutation cartLinesAdd($cartId: ID!, $lines: [CartLineInput!]!) {
477
+ cartLinesAdd(cartId: $cartId, lines: $lines) {
478
+ cart {
479
+ ${CART_FIELDS}
480
+ }
481
+ userErrors {
482
+ field
483
+ message
484
+ }
485
+ }
486
+ }
487
+ `,
488
+ variables: {
489
+ cartId,
490
+ lines
491
+ }
492
+ });
493
+ if (errors) {
494
+ throw new Error("Failed to add Shopify cart lines");
495
+ }
496
+ ;
497
+ const userError = firstUserError((_a = data == null ? void 0 : data.cartLinesAdd) == null ? void 0 : _a.userErrors);
498
+ if (userError) throw userError;
499
+ return mapCart((_b = data == null ? void 0 : data.cartLinesAdd) == null ? void 0 : _b.cart);
500
+ };
501
+ var cartLinesRemove = async ({ fetcher, domain, storefrontAccessToken, cartId, lineIds }) => {
502
+ var _a, _b;
503
+ const { data, errors } = await storefrontFetch({
504
+ fetcher,
505
+ domain,
506
+ storefrontAccessToken,
507
+ query: `
508
+ mutation cartLinesRemove($cartId: ID!, $lineIds: [ID!]!) {
509
+ cartLinesRemove(cartId: $cartId, lineIds: $lineIds) {
510
+ cart {
511
+ ${CART_FIELDS}
512
+ }
513
+ userErrors {
514
+ field
515
+ message
516
+ }
517
+ }
518
+ }
519
+ `,
520
+ variables: {
521
+ cartId,
522
+ lineIds
523
+ }
524
+ });
525
+ if (errors) {
526
+ throw new Error("Failed to remove Shopify cart lines");
527
+ }
528
+ ;
529
+ const userError = firstUserError((_a = data == null ? void 0 : data.cartLinesRemove) == null ? void 0 : _a.userErrors);
530
+ if (userError) throw userError;
531
+ return mapCart((_b = data == null ? void 0 : data.cartLinesRemove) == null ? void 0 : _b.cart);
532
+ };
533
+ var cartLinesUpdate = async ({ fetcher, domain, storefrontAccessToken, cartId, lines }) => {
534
+ var _a, _b;
535
+ const { data, errors } = await storefrontFetch({
536
+ fetcher,
537
+ domain,
538
+ storefrontAccessToken,
539
+ query: `
540
+ mutation cartLinesUpdate($cartId: ID!, $lines: [CartLineUpdateInput!]!) {
541
+ cartLinesUpdate(cartId: $cartId, lines: $lines) {
542
+ cart {
543
+ ${CART_FIELDS}
544
+ }
545
+ userErrors {
546
+ field
547
+ message
548
+ }
549
+ }
550
+ }
551
+ `,
552
+ variables: {
553
+ cartId,
554
+ lines
555
+ }
556
+ });
557
+ if (errors) {
558
+ throw new Error("Failed to update Shopify cart lines");
559
+ }
560
+ ;
561
+ const userError = firstUserError((_a = data == null ? void 0 : data.cartLinesUpdate) == null ? void 0 : _a.userErrors);
562
+ if (userError) throw userError;
563
+ return mapCart((_b = data == null ? void 0 : data.cartLinesUpdate) == null ? void 0 : _b.cart);
564
+ };
565
+ export {
566
+ cartCreate,
567
+ cartGet,
568
+ cartLinesAdd,
569
+ cartLinesRemove,
570
+ cartLinesUpdate,
571
+ createCheckoutToken,
572
+ getProduct,
573
+ getProductVariantsPage,
574
+ getProducts,
575
+ probeVariantsOutOfStock
576
+ };