@drawbridge/drawbridge-utils 0.0.146 → 0.0.148
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/connections/index.cjs +51 -9
- package/dist/connections/index.d.cts +79 -15
- package/dist/connections/index.d.ts +79 -15
- package/dist/connections/index.js +51 -9
- package/dist/providers.cjs +51 -9
- package/dist/providers.js +51 -9
- package/package.json +1 -1
|
@@ -2311,9 +2311,19 @@ var drawbridge_default2 = {
|
|
|
2311
2311
|
// either. Unset, it degrades to the account sender rather than
|
|
2312
2312
|
// refusing to start.
|
|
2313
2313
|
{ input: "email", key: "leadSender", credential: "SENDGRID_SEND_FROM_ADDRESS", label: "Lead sender", message: "The default for lead-facing mail when a merchant has not verified their own domain." },
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2314
|
+
// NOT required, the three of them together. SendGrid alone is enough to
|
|
2315
|
+
// run the platform — sign-in codes, notifications and every lead-facing
|
|
2316
|
+
// mail are email. Requiring Twilio here made the whole drawbridge
|
|
2317
|
+
// provider read not-live on a deployment that never sends SMS, over a
|
|
2318
|
+
// channel it was not using.
|
|
2319
|
+
//
|
|
2320
|
+
// Missing, SMS is LOCKED DOWN rather than broken: every send path
|
|
2321
|
+
// refuses cleanly (queue/notification.js cancels, the otc stream skips
|
|
2322
|
+
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2323
|
+
// hides the org's SMS settings entirely.
|
|
2324
|
+
{ input: "text", key: "smsFrom", credential: "TWILIO_ACCOUNT_FROM", label: "SMS number", message: "Without Twilio credentials, SMS is disabled across the platform." },
|
|
2325
|
+
{ input: "password", key: "smsSid", credential: "TWILIO_ACCOUNT_SID", label: "Twilio account SID", redact: true },
|
|
2326
|
+
{ input: "password", key: "smsToken", credential: "TWILIO_AUTH_TOKEN", label: "Twilio auth token", redact: true }
|
|
2317
2327
|
]
|
|
2318
2328
|
},
|
|
2319
2329
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -4137,7 +4147,7 @@ var shopify_default2 = {
|
|
|
4137
4147
|
// against the ones the app now needs, and queues a webhook
|
|
4138
4148
|
// reconciliation.
|
|
4139
4149
|
health: async ({ connection: connection2, workflow }, { adminToken, logger: logger2, read, reconcileScopes, resolveSettings, rotateToken, shopify } = {}) => {
|
|
4140
|
-
var _a, _b, _c;
|
|
4150
|
+
var _a, _b, _c, _d;
|
|
4141
4151
|
const request2 = {
|
|
4142
4152
|
connectionId: workflow.connection,
|
|
4143
4153
|
organizationId: workflow.organization,
|
|
@@ -4177,18 +4187,42 @@ var shopify_default2 = {
|
|
|
4177
4187
|
adminAccessToken,
|
|
4178
4188
|
domain: connection2.shop
|
|
4179
4189
|
});
|
|
4180
|
-
|
|
4181
|
-
|
|
4190
|
+
const usageLine = (_a = subscriptions.find((subscription) => subscription.usageLineItemId)) == null ? void 0 : _a.usageLineItemId;
|
|
4191
|
+
if (usageLine) metered = usageLine;
|
|
4192
|
+
const partnerRow = (read == null ? void 0 : read.get) ? await read.get({ collection: "provider", query: { slug: "shopify" } }) : null;
|
|
4193
|
+
const partner = (partnerRow == null ? void 0 : partnerRow.settings) ? decrypt(partnerRow.settings) : {};
|
|
4194
|
+
if (partner.partnerToken && partner.partnerOrgId && partner.partnerAppId && (source == null ? void 0 : source.id) && ((_b = shopify.partner) == null ? void 0 : _b.getUsageChargeEvents)) {
|
|
4195
|
+
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4196
|
+
appId: "gid://shopify/App/" + partner.partnerAppId,
|
|
4197
|
+
first: 1,
|
|
4198
|
+
occurredAtMin: new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString(),
|
|
4199
|
+
organizationId: partner.partnerOrgId,
|
|
4200
|
+
partnerToken: partner.partnerToken,
|
|
4201
|
+
shopId: "gid://shopify/Shop/" + source.id
|
|
4202
|
+
});
|
|
4203
|
+
if (accruals.length) {
|
|
4204
|
+
metered = String(accruals[0].chargeId || accruals[0].id);
|
|
4205
|
+
} else {
|
|
4206
|
+
const unaccrued = await read.get({
|
|
4207
|
+
collection: "order",
|
|
4208
|
+
query: {
|
|
4209
|
+
"billed.date": { $lt: new Date(Date.now() - 6 * 60 * 60 * 1e3) },
|
|
4210
|
+
organization: workflow.organization,
|
|
4211
|
+
"provider.slug": "shopify"
|
|
4212
|
+
}
|
|
4213
|
+
});
|
|
4214
|
+
if (unaccrued) metered = null;
|
|
4215
|
+
}
|
|
4182
4216
|
}
|
|
4183
4217
|
} catch (probeError) {
|
|
4184
4218
|
billingProbeFailed = true;
|
|
4185
|
-
(
|
|
4219
|
+
(_c = logger2 == null ? void 0 : logger2.warn) == null ? void 0 : _c.call(logger2, "shopify.health.billing.probe.failed", {
|
|
4186
4220
|
connectionId: connection2.id,
|
|
4187
4221
|
message: probeError == null ? void 0 : probeError.message,
|
|
4188
4222
|
shop: connection2.shop
|
|
4189
4223
|
});
|
|
4190
4224
|
}
|
|
4191
|
-
if (sourceRepaired || metered !== void 0 && metered !== (((
|
|
4225
|
+
if (sourceRepaired || metered !== void 0 && metered !== (((_d = connection2.source) == null ? void 0 : _d.metered) ?? void 0)) {
|
|
4192
4226
|
writes.push({
|
|
4193
4227
|
collection: "connection",
|
|
4194
4228
|
data: {
|
|
@@ -4410,7 +4444,15 @@ var shopify_default2 = {
|
|
|
4410
4444
|
// and classification against it is case-sensitive. Optional: empty
|
|
4411
4445
|
// means the default, and the sender still refuses any handle that
|
|
4412
4446
|
// disagrees with the transaction it minted.
|
|
4413
|
-
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true }
|
|
4447
|
+
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true },
|
|
4448
|
+
// The Partner API credential set — the ONE place meter billing is
|
|
4449
|
+
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
4450
|
+
// id come from the Partner Dashboard; the token from Settings →
|
|
4451
|
+
// Partner API clients (Manage-apps permission). All optional: the
|
|
4452
|
+
// accrual probe simply stays off until they exist.
|
|
4453
|
+
{ input: "text", key: "partnerOrgId", label: "Partner organization ID", required: false, setting: true },
|
|
4454
|
+
{ input: "text", key: "partnerAppId", label: "Partner app ID (numeric)", required: false, setting: true },
|
|
4455
|
+
{ input: "password", key: "partnerToken", label: "Partner API token", redact: true, required: false, setting: true }
|
|
4414
4456
|
]
|
|
4415
4457
|
},
|
|
4416
4458
|
// A pre-launch integration: it only surfaces once the App Store listing
|
|
@@ -2413,9 +2413,19 @@ var drawbridge = {
|
|
|
2413
2413
|
// either. Unset, it degrades to the account sender rather than
|
|
2414
2414
|
// refusing to start.
|
|
2415
2415
|
{ input : 'email', key : 'leadSender', credential : 'SENDGRID_SEND_FROM_ADDRESS', label : 'Lead sender', message : 'The default for lead-facing mail when a merchant has not verified their own domain.' },
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2416
|
+
// NOT required, the three of them together. SendGrid alone is enough to
|
|
2417
|
+
// run the platform — sign-in codes, notifications and every lead-facing
|
|
2418
|
+
// mail are email. Requiring Twilio here made the whole drawbridge
|
|
2419
|
+
// provider read not-live on a deployment that never sends SMS, over a
|
|
2420
|
+
// channel it was not using.
|
|
2421
|
+
//
|
|
2422
|
+
// Missing, SMS is LOCKED DOWN rather than broken: every send path
|
|
2423
|
+
// refuses cleanly (queue/notification.js cancels, the otc stream skips
|
|
2424
|
+
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2425
|
+
// hides the org's SMS settings entirely.
|
|
2426
|
+
{ input : 'text', key : 'smsFrom', credential : 'TWILIO_ACCOUNT_FROM', label : 'SMS number', message : 'Without Twilio credentials, SMS is disabled across the platform.' },
|
|
2427
|
+
{ input : 'password', key : 'smsSid', credential : 'TWILIO_ACCOUNT_SID', label : 'Twilio account SID', redact : true },
|
|
2428
|
+
{ input : 'password', key : 'smsToken', credential : 'TWILIO_AUTH_TOKEN', label : 'Twilio auth token', redact : true }
|
|
2419
2429
|
]
|
|
2420
2430
|
},
|
|
2421
2431
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -4943,18 +4953,64 @@ var shopify = {
|
|
|
4943
4953
|
domain : connection.shop
|
|
4944
4954
|
});
|
|
4945
4955
|
|
|
4946
|
-
//
|
|
4947
|
-
//
|
|
4948
|
-
//
|
|
4949
|
-
//
|
|
4950
|
-
//
|
|
4951
|
-
//
|
|
4952
|
-
// unmetered
|
|
4953
|
-
//
|
|
4954
|
-
//
|
|
4955
|
-
|
|
4956
|
+
// A usage line on the approval is POSITIVE evidence and gets
|
|
4957
|
+
// stamped. Its ABSENCE proves nothing: measured 2026-09-04
|
|
4958
|
+
// (both 2026-04 and unstable, against a plan whose meter
|
|
4959
|
+
// exists), managed-pricing App-Events meters never
|
|
4960
|
+
// materialize as subscription line items — AppUsagePricing is
|
|
4961
|
+
// the legacy usage-charge model. Reading absence as
|
|
4962
|
+
// "unmetered" flagged healthy stores, so absence is NO
|
|
4963
|
+
// VERDICT: the stamp, the Issue, the card and the
|
|
4964
|
+
// meter-missing pager all stay silent until a signal that can
|
|
4965
|
+
// actually observe the meter exists (Partner API
|
|
4966
|
+
// USAGE_CHARGE_APPLIED accrual events are that signal).
|
|
4967
|
+
const usageLine = subscriptions.find( ( subscription ) => subscription.usageLineItemId )?.usageLineItemId;
|
|
4968
|
+
|
|
4969
|
+
if( usageLine ) metered = usageLine;
|
|
4970
|
+
|
|
4971
|
+
// THE REAL METER SIGNAL — Partner API accrual. A CHARGE_USAGE
|
|
4972
|
+
// event for this shop is proof billing works: its charge id
|
|
4973
|
+
// becomes the stamp (overriding the line-item probe, which
|
|
4974
|
+
// managed pricing keeps blind). No accrual AND a billed order
|
|
4975
|
+
// old enough that one should exist is the HONEST unmetered
|
|
4976
|
+
// verdict — the null that re-arms the card, the Issue and the
|
|
4977
|
+
// pager on truth instead of the Admin API's silence. Off
|
|
4978
|
+
// entirely until the provider row carries the credentials.
|
|
4979
|
+
const partnerRow = read?.get ? await read.get({ collection : 'provider', query : { slug : 'shopify' } }) : null;
|
|
4980
|
+
const partner = partnerRow?.settings ? decrypt( partnerRow.settings ) : {};
|
|
4981
|
+
|
|
4982
|
+
if( partner.partnerToken && partner.partnerOrgId && partner.partnerAppId && source?.id && shopify.partner?.getUsageChargeEvents ){
|
|
4983
|
+
|
|
4984
|
+
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4985
|
+
appId : 'gid://shopify/App/' + partner.partnerAppId,
|
|
4986
|
+
first : 1,
|
|
4987
|
+
occurredAtMin : new Date( Date.now() - 30 * 24 * 60 * 60 * 1000 ).toISOString(),
|
|
4988
|
+
organizationId : partner.partnerOrgId,
|
|
4989
|
+
partnerToken : partner.partnerToken,
|
|
4990
|
+
shopId : 'gid://shopify/Shop/' + source.id
|
|
4991
|
+
});
|
|
4992
|
+
|
|
4993
|
+
if( accruals.length ){
|
|
4994
|
+
|
|
4995
|
+
metered = String( accruals[ 0 ].chargeId || accruals[ 0 ].id );
|
|
4996
|
+
|
|
4997
|
+
} else {
|
|
4956
4998
|
|
|
4957
|
-
|
|
4999
|
+
// Only a store that SHOULD have accrued gets the
|
|
5000
|
+
// unmetered verdict: an order stamped billed six-plus
|
|
5001
|
+
// hours ago with still no accrual event.
|
|
5002
|
+
const unaccrued = await read.get({
|
|
5003
|
+
collection : 'order',
|
|
5004
|
+
query : {
|
|
5005
|
+
'billed.date' : { $lt : new Date( Date.now() - 6 * 60 * 60 * 1000 ) },
|
|
5006
|
+
organization : workflow.organization,
|
|
5007
|
+
'provider.slug' : 'shopify'
|
|
5008
|
+
}
|
|
5009
|
+
});
|
|
5010
|
+
|
|
5011
|
+
if( unaccrued ) metered = null;
|
|
5012
|
+
|
|
5013
|
+
}
|
|
4958
5014
|
|
|
4959
5015
|
}
|
|
4960
5016
|
|
|
@@ -5265,7 +5321,15 @@ var shopify = {
|
|
|
5265
5321
|
// and classification against it is case-sensitive. Optional: empty
|
|
5266
5322
|
// means the default, and the sender still refuses any handle that
|
|
5267
5323
|
// disagrees with the transaction it minted.
|
|
5268
|
-
{ format : 'slug', input : 'text', key : 'orderEventHandle', label : 'Order event handle', required : false, setting : true }
|
|
5324
|
+
{ format : 'slug', input : 'text', key : 'orderEventHandle', label : 'Order event handle', required : false, setting : true },
|
|
5325
|
+
// The Partner API credential set — the ONE place meter billing is
|
|
5326
|
+
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
5327
|
+
// id come from the Partner Dashboard; the token from Settings →
|
|
5328
|
+
// Partner API clients (Manage-apps permission). All optional: the
|
|
5329
|
+
// accrual probe simply stays off until they exist.
|
|
5330
|
+
{ input : 'text', key : 'partnerOrgId', label : 'Partner organization ID', required : false, setting : true },
|
|
5331
|
+
{ input : 'text', key : 'partnerAppId', label : 'Partner app ID (numeric)', required : false, setting : true },
|
|
5332
|
+
{ input : 'password', key : 'partnerToken', label : 'Partner API token', redact : true, required : false, setting : true }
|
|
5269
5333
|
]
|
|
5270
5334
|
},
|
|
5271
5335
|
// A pre-launch integration: it only surfaces once the App Store listing
|
|
@@ -2413,9 +2413,19 @@ var drawbridge = {
|
|
|
2413
2413
|
// either. Unset, it degrades to the account sender rather than
|
|
2414
2414
|
// refusing to start.
|
|
2415
2415
|
{ input : 'email', key : 'leadSender', credential : 'SENDGRID_SEND_FROM_ADDRESS', label : 'Lead sender', message : 'The default for lead-facing mail when a merchant has not verified their own domain.' },
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2416
|
+
// NOT required, the three of them together. SendGrid alone is enough to
|
|
2417
|
+
// run the platform — sign-in codes, notifications and every lead-facing
|
|
2418
|
+
// mail are email. Requiring Twilio here made the whole drawbridge
|
|
2419
|
+
// provider read not-live on a deployment that never sends SMS, over a
|
|
2420
|
+
// channel it was not using.
|
|
2421
|
+
//
|
|
2422
|
+
// Missing, SMS is LOCKED DOWN rather than broken: every send path
|
|
2423
|
+
// refuses cleanly (queue/notification.js cancels, the otc stream skips
|
|
2424
|
+
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2425
|
+
// hides the org's SMS settings entirely.
|
|
2426
|
+
{ input : 'text', key : 'smsFrom', credential : 'TWILIO_ACCOUNT_FROM', label : 'SMS number', message : 'Without Twilio credentials, SMS is disabled across the platform.' },
|
|
2427
|
+
{ input : 'password', key : 'smsSid', credential : 'TWILIO_ACCOUNT_SID', label : 'Twilio account SID', redact : true },
|
|
2428
|
+
{ input : 'password', key : 'smsToken', credential : 'TWILIO_AUTH_TOKEN', label : 'Twilio auth token', redact : true }
|
|
2419
2429
|
]
|
|
2420
2430
|
},
|
|
2421
2431
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -4943,18 +4953,64 @@ var shopify = {
|
|
|
4943
4953
|
domain : connection.shop
|
|
4944
4954
|
});
|
|
4945
4955
|
|
|
4946
|
-
//
|
|
4947
|
-
//
|
|
4948
|
-
//
|
|
4949
|
-
//
|
|
4950
|
-
//
|
|
4951
|
-
//
|
|
4952
|
-
// unmetered
|
|
4953
|
-
//
|
|
4954
|
-
//
|
|
4955
|
-
|
|
4956
|
+
// A usage line on the approval is POSITIVE evidence and gets
|
|
4957
|
+
// stamped. Its ABSENCE proves nothing: measured 2026-09-04
|
|
4958
|
+
// (both 2026-04 and unstable, against a plan whose meter
|
|
4959
|
+
// exists), managed-pricing App-Events meters never
|
|
4960
|
+
// materialize as subscription line items — AppUsagePricing is
|
|
4961
|
+
// the legacy usage-charge model. Reading absence as
|
|
4962
|
+
// "unmetered" flagged healthy stores, so absence is NO
|
|
4963
|
+
// VERDICT: the stamp, the Issue, the card and the
|
|
4964
|
+
// meter-missing pager all stay silent until a signal that can
|
|
4965
|
+
// actually observe the meter exists (Partner API
|
|
4966
|
+
// USAGE_CHARGE_APPLIED accrual events are that signal).
|
|
4967
|
+
const usageLine = subscriptions.find( ( subscription ) => subscription.usageLineItemId )?.usageLineItemId;
|
|
4968
|
+
|
|
4969
|
+
if( usageLine ) metered = usageLine;
|
|
4970
|
+
|
|
4971
|
+
// THE REAL METER SIGNAL — Partner API accrual. A CHARGE_USAGE
|
|
4972
|
+
// event for this shop is proof billing works: its charge id
|
|
4973
|
+
// becomes the stamp (overriding the line-item probe, which
|
|
4974
|
+
// managed pricing keeps blind). No accrual AND a billed order
|
|
4975
|
+
// old enough that one should exist is the HONEST unmetered
|
|
4976
|
+
// verdict — the null that re-arms the card, the Issue and the
|
|
4977
|
+
// pager on truth instead of the Admin API's silence. Off
|
|
4978
|
+
// entirely until the provider row carries the credentials.
|
|
4979
|
+
const partnerRow = read?.get ? await read.get({ collection : 'provider', query : { slug : 'shopify' } }) : null;
|
|
4980
|
+
const partner = partnerRow?.settings ? decrypt( partnerRow.settings ) : {};
|
|
4981
|
+
|
|
4982
|
+
if( partner.partnerToken && partner.partnerOrgId && partner.partnerAppId && source?.id && shopify.partner?.getUsageChargeEvents ){
|
|
4983
|
+
|
|
4984
|
+
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4985
|
+
appId : 'gid://shopify/App/' + partner.partnerAppId,
|
|
4986
|
+
first : 1,
|
|
4987
|
+
occurredAtMin : new Date( Date.now() - 30 * 24 * 60 * 60 * 1000 ).toISOString(),
|
|
4988
|
+
organizationId : partner.partnerOrgId,
|
|
4989
|
+
partnerToken : partner.partnerToken,
|
|
4990
|
+
shopId : 'gid://shopify/Shop/' + source.id
|
|
4991
|
+
});
|
|
4992
|
+
|
|
4993
|
+
if( accruals.length ){
|
|
4994
|
+
|
|
4995
|
+
metered = String( accruals[ 0 ].chargeId || accruals[ 0 ].id );
|
|
4996
|
+
|
|
4997
|
+
} else {
|
|
4956
4998
|
|
|
4957
|
-
|
|
4999
|
+
// Only a store that SHOULD have accrued gets the
|
|
5000
|
+
// unmetered verdict: an order stamped billed six-plus
|
|
5001
|
+
// hours ago with still no accrual event.
|
|
5002
|
+
const unaccrued = await read.get({
|
|
5003
|
+
collection : 'order',
|
|
5004
|
+
query : {
|
|
5005
|
+
'billed.date' : { $lt : new Date( Date.now() - 6 * 60 * 60 * 1000 ) },
|
|
5006
|
+
organization : workflow.organization,
|
|
5007
|
+
'provider.slug' : 'shopify'
|
|
5008
|
+
}
|
|
5009
|
+
});
|
|
5010
|
+
|
|
5011
|
+
if( unaccrued ) metered = null;
|
|
5012
|
+
|
|
5013
|
+
}
|
|
4958
5014
|
|
|
4959
5015
|
}
|
|
4960
5016
|
|
|
@@ -5265,7 +5321,15 @@ var shopify = {
|
|
|
5265
5321
|
// and classification against it is case-sensitive. Optional: empty
|
|
5266
5322
|
// means the default, and the sender still refuses any handle that
|
|
5267
5323
|
// disagrees with the transaction it minted.
|
|
5268
|
-
{ format : 'slug', input : 'text', key : 'orderEventHandle', label : 'Order event handle', required : false, setting : true }
|
|
5324
|
+
{ format : 'slug', input : 'text', key : 'orderEventHandle', label : 'Order event handle', required : false, setting : true },
|
|
5325
|
+
// The Partner API credential set — the ONE place meter billing is
|
|
5326
|
+
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
5327
|
+
// id come from the Partner Dashboard; the token from Settings →
|
|
5328
|
+
// Partner API clients (Manage-apps permission). All optional: the
|
|
5329
|
+
// accrual probe simply stays off until they exist.
|
|
5330
|
+
{ input : 'text', key : 'partnerOrgId', label : 'Partner organization ID', required : false, setting : true },
|
|
5331
|
+
{ input : 'text', key : 'partnerAppId', label : 'Partner app ID (numeric)', required : false, setting : true },
|
|
5332
|
+
{ input : 'password', key : 'partnerToken', label : 'Partner API token', redact : true, required : false, setting : true }
|
|
5269
5333
|
]
|
|
5270
5334
|
},
|
|
5271
5335
|
// A pre-launch integration: it only surfaces once the App Store listing
|
|
@@ -2237,9 +2237,19 @@ var drawbridge_default2 = {
|
|
|
2237
2237
|
// either. Unset, it degrades to the account sender rather than
|
|
2238
2238
|
// refusing to start.
|
|
2239
2239
|
{ input: "email", key: "leadSender", credential: "SENDGRID_SEND_FROM_ADDRESS", label: "Lead sender", message: "The default for lead-facing mail when a merchant has not verified their own domain." },
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2240
|
+
// NOT required, the three of them together. SendGrid alone is enough to
|
|
2241
|
+
// run the platform — sign-in codes, notifications and every lead-facing
|
|
2242
|
+
// mail are email. Requiring Twilio here made the whole drawbridge
|
|
2243
|
+
// provider read not-live on a deployment that never sends SMS, over a
|
|
2244
|
+
// channel it was not using.
|
|
2245
|
+
//
|
|
2246
|
+
// Missing, SMS is LOCKED DOWN rather than broken: every send path
|
|
2247
|
+
// refuses cleanly (queue/notification.js cancels, the otc stream skips
|
|
2248
|
+
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2249
|
+
// hides the org's SMS settings entirely.
|
|
2250
|
+
{ input: "text", key: "smsFrom", credential: "TWILIO_ACCOUNT_FROM", label: "SMS number", message: "Without Twilio credentials, SMS is disabled across the platform." },
|
|
2251
|
+
{ input: "password", key: "smsSid", credential: "TWILIO_ACCOUNT_SID", label: "Twilio account SID", redact: true },
|
|
2252
|
+
{ input: "password", key: "smsToken", credential: "TWILIO_AUTH_TOKEN", label: "Twilio auth token", redact: true }
|
|
2243
2253
|
]
|
|
2244
2254
|
},
|
|
2245
2255
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -4063,7 +4073,7 @@ var shopify_default2 = {
|
|
|
4063
4073
|
// against the ones the app now needs, and queues a webhook
|
|
4064
4074
|
// reconciliation.
|
|
4065
4075
|
health: async ({ connection: connection2, workflow }, { adminToken, logger: logger2, read, reconcileScopes, resolveSettings, rotateToken, shopify } = {}) => {
|
|
4066
|
-
var _a, _b, _c;
|
|
4076
|
+
var _a, _b, _c, _d;
|
|
4067
4077
|
const request2 = {
|
|
4068
4078
|
connectionId: workflow.connection,
|
|
4069
4079
|
organizationId: workflow.organization,
|
|
@@ -4103,18 +4113,42 @@ var shopify_default2 = {
|
|
|
4103
4113
|
adminAccessToken,
|
|
4104
4114
|
domain: connection2.shop
|
|
4105
4115
|
});
|
|
4106
|
-
|
|
4107
|
-
|
|
4116
|
+
const usageLine = (_a = subscriptions.find((subscription) => subscription.usageLineItemId)) == null ? void 0 : _a.usageLineItemId;
|
|
4117
|
+
if (usageLine) metered = usageLine;
|
|
4118
|
+
const partnerRow = (read == null ? void 0 : read.get) ? await read.get({ collection: "provider", query: { slug: "shopify" } }) : null;
|
|
4119
|
+
const partner = (partnerRow == null ? void 0 : partnerRow.settings) ? decrypt(partnerRow.settings) : {};
|
|
4120
|
+
if (partner.partnerToken && partner.partnerOrgId && partner.partnerAppId && (source == null ? void 0 : source.id) && ((_b = shopify.partner) == null ? void 0 : _b.getUsageChargeEvents)) {
|
|
4121
|
+
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4122
|
+
appId: "gid://shopify/App/" + partner.partnerAppId,
|
|
4123
|
+
first: 1,
|
|
4124
|
+
occurredAtMin: new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString(),
|
|
4125
|
+
organizationId: partner.partnerOrgId,
|
|
4126
|
+
partnerToken: partner.partnerToken,
|
|
4127
|
+
shopId: "gid://shopify/Shop/" + source.id
|
|
4128
|
+
});
|
|
4129
|
+
if (accruals.length) {
|
|
4130
|
+
metered = String(accruals[0].chargeId || accruals[0].id);
|
|
4131
|
+
} else {
|
|
4132
|
+
const unaccrued = await read.get({
|
|
4133
|
+
collection: "order",
|
|
4134
|
+
query: {
|
|
4135
|
+
"billed.date": { $lt: new Date(Date.now() - 6 * 60 * 60 * 1e3) },
|
|
4136
|
+
organization: workflow.organization,
|
|
4137
|
+
"provider.slug": "shopify"
|
|
4138
|
+
}
|
|
4139
|
+
});
|
|
4140
|
+
if (unaccrued) metered = null;
|
|
4141
|
+
}
|
|
4108
4142
|
}
|
|
4109
4143
|
} catch (probeError) {
|
|
4110
4144
|
billingProbeFailed = true;
|
|
4111
|
-
(
|
|
4145
|
+
(_c = logger2 == null ? void 0 : logger2.warn) == null ? void 0 : _c.call(logger2, "shopify.health.billing.probe.failed", {
|
|
4112
4146
|
connectionId: connection2.id,
|
|
4113
4147
|
message: probeError == null ? void 0 : probeError.message,
|
|
4114
4148
|
shop: connection2.shop
|
|
4115
4149
|
});
|
|
4116
4150
|
}
|
|
4117
|
-
if (sourceRepaired || metered !== void 0 && metered !== (((
|
|
4151
|
+
if (sourceRepaired || metered !== void 0 && metered !== (((_d = connection2.source) == null ? void 0 : _d.metered) ?? void 0)) {
|
|
4118
4152
|
writes.push({
|
|
4119
4153
|
collection: "connection",
|
|
4120
4154
|
data: {
|
|
@@ -4336,7 +4370,15 @@ var shopify_default2 = {
|
|
|
4336
4370
|
// and classification against it is case-sensitive. Optional: empty
|
|
4337
4371
|
// means the default, and the sender still refuses any handle that
|
|
4338
4372
|
// disagrees with the transaction it minted.
|
|
4339
|
-
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true }
|
|
4373
|
+
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true },
|
|
4374
|
+
// The Partner API credential set — the ONE place meter billing is
|
|
4375
|
+
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
4376
|
+
// id come from the Partner Dashboard; the token from Settings →
|
|
4377
|
+
// Partner API clients (Manage-apps permission). All optional: the
|
|
4378
|
+
// accrual probe simply stays off until they exist.
|
|
4379
|
+
{ input: "text", key: "partnerOrgId", label: "Partner organization ID", required: false, setting: true },
|
|
4380
|
+
{ input: "text", key: "partnerAppId", label: "Partner app ID (numeric)", required: false, setting: true },
|
|
4381
|
+
{ input: "password", key: "partnerToken", label: "Partner API token", redact: true, required: false, setting: true }
|
|
4340
4382
|
]
|
|
4341
4383
|
},
|
|
4342
4384
|
// A pre-launch integration: it only surfaces once the App Store listing
|
package/dist/providers.cjs
CHANGED
|
@@ -2217,9 +2217,19 @@ var drawbridge_default2 = {
|
|
|
2217
2217
|
// either. Unset, it degrades to the account sender rather than
|
|
2218
2218
|
// refusing to start.
|
|
2219
2219
|
{ input: "email", key: "leadSender", credential: "SENDGRID_SEND_FROM_ADDRESS", label: "Lead sender", message: "The default for lead-facing mail when a merchant has not verified their own domain." },
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2220
|
+
// NOT required, the three of them together. SendGrid alone is enough to
|
|
2221
|
+
// run the platform — sign-in codes, notifications and every lead-facing
|
|
2222
|
+
// mail are email. Requiring Twilio here made the whole drawbridge
|
|
2223
|
+
// provider read not-live on a deployment that never sends SMS, over a
|
|
2224
|
+
// channel it was not using.
|
|
2225
|
+
//
|
|
2226
|
+
// Missing, SMS is LOCKED DOWN rather than broken: every send path
|
|
2227
|
+
// refuses cleanly (queue/notification.js cancels, the otc stream skips
|
|
2228
|
+
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2229
|
+
// hides the org's SMS settings entirely.
|
|
2230
|
+
{ input: "text", key: "smsFrom", credential: "TWILIO_ACCOUNT_FROM", label: "SMS number", message: "Without Twilio credentials, SMS is disabled across the platform." },
|
|
2231
|
+
{ input: "password", key: "smsSid", credential: "TWILIO_ACCOUNT_SID", label: "Twilio account SID", redact: true },
|
|
2232
|
+
{ input: "password", key: "smsToken", credential: "TWILIO_AUTH_TOKEN", label: "Twilio auth token", redact: true }
|
|
2223
2233
|
]
|
|
2224
2234
|
},
|
|
2225
2235
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -4062,7 +4072,7 @@ var shopify_default2 = {
|
|
|
4062
4072
|
// against the ones the app now needs, and queues a webhook
|
|
4063
4073
|
// reconciliation.
|
|
4064
4074
|
health: async ({ connection: connection2, workflow }, { adminToken, logger: logger2, read, reconcileScopes, resolveSettings, rotateToken, shopify } = {}) => {
|
|
4065
|
-
var _a, _b, _c;
|
|
4075
|
+
var _a, _b, _c, _d;
|
|
4066
4076
|
const request2 = {
|
|
4067
4077
|
connectionId: workflow.connection,
|
|
4068
4078
|
organizationId: workflow.organization,
|
|
@@ -4102,18 +4112,42 @@ var shopify_default2 = {
|
|
|
4102
4112
|
adminAccessToken,
|
|
4103
4113
|
domain: connection2.shop
|
|
4104
4114
|
});
|
|
4105
|
-
|
|
4106
|
-
|
|
4115
|
+
const usageLine = (_a = subscriptions.find((subscription) => subscription.usageLineItemId)) == null ? void 0 : _a.usageLineItemId;
|
|
4116
|
+
if (usageLine) metered = usageLine;
|
|
4117
|
+
const partnerRow = (read == null ? void 0 : read.get) ? await read.get({ collection: "provider", query: { slug: "shopify" } }) : null;
|
|
4118
|
+
const partner = (partnerRow == null ? void 0 : partnerRow.settings) ? decrypt(partnerRow.settings) : {};
|
|
4119
|
+
if (partner.partnerToken && partner.partnerOrgId && partner.partnerAppId && (source == null ? void 0 : source.id) && ((_b = shopify.partner) == null ? void 0 : _b.getUsageChargeEvents)) {
|
|
4120
|
+
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4121
|
+
appId: "gid://shopify/App/" + partner.partnerAppId,
|
|
4122
|
+
first: 1,
|
|
4123
|
+
occurredAtMin: new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString(),
|
|
4124
|
+
organizationId: partner.partnerOrgId,
|
|
4125
|
+
partnerToken: partner.partnerToken,
|
|
4126
|
+
shopId: "gid://shopify/Shop/" + source.id
|
|
4127
|
+
});
|
|
4128
|
+
if (accruals.length) {
|
|
4129
|
+
metered = String(accruals[0].chargeId || accruals[0].id);
|
|
4130
|
+
} else {
|
|
4131
|
+
const unaccrued = await read.get({
|
|
4132
|
+
collection: "order",
|
|
4133
|
+
query: {
|
|
4134
|
+
"billed.date": { $lt: new Date(Date.now() - 6 * 60 * 60 * 1e3) },
|
|
4135
|
+
organization: workflow.organization,
|
|
4136
|
+
"provider.slug": "shopify"
|
|
4137
|
+
}
|
|
4138
|
+
});
|
|
4139
|
+
if (unaccrued) metered = null;
|
|
4140
|
+
}
|
|
4107
4141
|
}
|
|
4108
4142
|
} catch (probeError) {
|
|
4109
4143
|
billingProbeFailed = true;
|
|
4110
|
-
(
|
|
4144
|
+
(_c = logger2 == null ? void 0 : logger2.warn) == null ? void 0 : _c.call(logger2, "shopify.health.billing.probe.failed", {
|
|
4111
4145
|
connectionId: connection2.id,
|
|
4112
4146
|
message: probeError == null ? void 0 : probeError.message,
|
|
4113
4147
|
shop: connection2.shop
|
|
4114
4148
|
});
|
|
4115
4149
|
}
|
|
4116
|
-
if (sourceRepaired || metered !== void 0 && metered !== (((
|
|
4150
|
+
if (sourceRepaired || metered !== void 0 && metered !== (((_d = connection2.source) == null ? void 0 : _d.metered) ?? void 0)) {
|
|
4117
4151
|
writes.push({
|
|
4118
4152
|
collection: "connection",
|
|
4119
4153
|
data: {
|
|
@@ -4335,7 +4369,15 @@ var shopify_default2 = {
|
|
|
4335
4369
|
// and classification against it is case-sensitive. Optional: empty
|
|
4336
4370
|
// means the default, and the sender still refuses any handle that
|
|
4337
4371
|
// disagrees with the transaction it minted.
|
|
4338
|
-
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true }
|
|
4372
|
+
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true },
|
|
4373
|
+
// The Partner API credential set — the ONE place meter billing is
|
|
4374
|
+
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
4375
|
+
// id come from the Partner Dashboard; the token from Settings →
|
|
4376
|
+
// Partner API clients (Manage-apps permission). All optional: the
|
|
4377
|
+
// accrual probe simply stays off until they exist.
|
|
4378
|
+
{ input: "text", key: "partnerOrgId", label: "Partner organization ID", required: false, setting: true },
|
|
4379
|
+
{ input: "text", key: "partnerAppId", label: "Partner app ID (numeric)", required: false, setting: true },
|
|
4380
|
+
{ input: "password", key: "partnerToken", label: "Partner API token", redact: true, required: false, setting: true }
|
|
4339
4381
|
]
|
|
4340
4382
|
},
|
|
4341
4383
|
// A pre-launch integration: it only surfaces once the App Store listing
|
package/dist/providers.js
CHANGED
|
@@ -2173,9 +2173,19 @@ var drawbridge_default2 = {
|
|
|
2173
2173
|
// either. Unset, it degrades to the account sender rather than
|
|
2174
2174
|
// refusing to start.
|
|
2175
2175
|
{ input: "email", key: "leadSender", credential: "SENDGRID_SEND_FROM_ADDRESS", label: "Lead sender", message: "The default for lead-facing mail when a merchant has not verified their own domain." },
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2176
|
+
// NOT required, the three of them together. SendGrid alone is enough to
|
|
2177
|
+
// run the platform — sign-in codes, notifications and every lead-facing
|
|
2178
|
+
// mail are email. Requiring Twilio here made the whole drawbridge
|
|
2179
|
+
// provider read not-live on a deployment that never sends SMS, over a
|
|
2180
|
+
// channel it was not using.
|
|
2181
|
+
//
|
|
2182
|
+
// Missing, SMS is LOCKED DOWN rather than broken: every send path
|
|
2183
|
+
// refuses cleanly (queue/notification.js cancels, the otc stream skips
|
|
2184
|
+
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2185
|
+
// hides the org's SMS settings entirely.
|
|
2186
|
+
{ input: "text", key: "smsFrom", credential: "TWILIO_ACCOUNT_FROM", label: "SMS number", message: "Without Twilio credentials, SMS is disabled across the platform." },
|
|
2187
|
+
{ input: "password", key: "smsSid", credential: "TWILIO_ACCOUNT_SID", label: "Twilio account SID", redact: true },
|
|
2188
|
+
{ input: "password", key: "smsToken", credential: "TWILIO_AUTH_TOKEN", label: "Twilio auth token", redact: true }
|
|
2179
2189
|
]
|
|
2180
2190
|
},
|
|
2181
2191
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -4018,7 +4028,7 @@ var shopify_default2 = {
|
|
|
4018
4028
|
// against the ones the app now needs, and queues a webhook
|
|
4019
4029
|
// reconciliation.
|
|
4020
4030
|
health: async ({ connection: connection2, workflow }, { adminToken, logger: logger2, read, reconcileScopes, resolveSettings, rotateToken, shopify } = {}) => {
|
|
4021
|
-
var _a, _b, _c;
|
|
4031
|
+
var _a, _b, _c, _d;
|
|
4022
4032
|
const request2 = {
|
|
4023
4033
|
connectionId: workflow.connection,
|
|
4024
4034
|
organizationId: workflow.organization,
|
|
@@ -4058,18 +4068,42 @@ var shopify_default2 = {
|
|
|
4058
4068
|
adminAccessToken,
|
|
4059
4069
|
domain: connection2.shop
|
|
4060
4070
|
});
|
|
4061
|
-
|
|
4062
|
-
|
|
4071
|
+
const usageLine = (_a = subscriptions.find((subscription) => subscription.usageLineItemId)) == null ? void 0 : _a.usageLineItemId;
|
|
4072
|
+
if (usageLine) metered = usageLine;
|
|
4073
|
+
const partnerRow = (read == null ? void 0 : read.get) ? await read.get({ collection: "provider", query: { slug: "shopify" } }) : null;
|
|
4074
|
+
const partner = (partnerRow == null ? void 0 : partnerRow.settings) ? decrypt(partnerRow.settings) : {};
|
|
4075
|
+
if (partner.partnerToken && partner.partnerOrgId && partner.partnerAppId && (source == null ? void 0 : source.id) && ((_b = shopify.partner) == null ? void 0 : _b.getUsageChargeEvents)) {
|
|
4076
|
+
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4077
|
+
appId: "gid://shopify/App/" + partner.partnerAppId,
|
|
4078
|
+
first: 1,
|
|
4079
|
+
occurredAtMin: new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString(),
|
|
4080
|
+
organizationId: partner.partnerOrgId,
|
|
4081
|
+
partnerToken: partner.partnerToken,
|
|
4082
|
+
shopId: "gid://shopify/Shop/" + source.id
|
|
4083
|
+
});
|
|
4084
|
+
if (accruals.length) {
|
|
4085
|
+
metered = String(accruals[0].chargeId || accruals[0].id);
|
|
4086
|
+
} else {
|
|
4087
|
+
const unaccrued = await read.get({
|
|
4088
|
+
collection: "order",
|
|
4089
|
+
query: {
|
|
4090
|
+
"billed.date": { $lt: new Date(Date.now() - 6 * 60 * 60 * 1e3) },
|
|
4091
|
+
organization: workflow.organization,
|
|
4092
|
+
"provider.slug": "shopify"
|
|
4093
|
+
}
|
|
4094
|
+
});
|
|
4095
|
+
if (unaccrued) metered = null;
|
|
4096
|
+
}
|
|
4063
4097
|
}
|
|
4064
4098
|
} catch (probeError) {
|
|
4065
4099
|
billingProbeFailed = true;
|
|
4066
|
-
(
|
|
4100
|
+
(_c = logger2 == null ? void 0 : logger2.warn) == null ? void 0 : _c.call(logger2, "shopify.health.billing.probe.failed", {
|
|
4067
4101
|
connectionId: connection2.id,
|
|
4068
4102
|
message: probeError == null ? void 0 : probeError.message,
|
|
4069
4103
|
shop: connection2.shop
|
|
4070
4104
|
});
|
|
4071
4105
|
}
|
|
4072
|
-
if (sourceRepaired || metered !== void 0 && metered !== (((
|
|
4106
|
+
if (sourceRepaired || metered !== void 0 && metered !== (((_d = connection2.source) == null ? void 0 : _d.metered) ?? void 0)) {
|
|
4073
4107
|
writes.push({
|
|
4074
4108
|
collection: "connection",
|
|
4075
4109
|
data: {
|
|
@@ -4291,7 +4325,15 @@ var shopify_default2 = {
|
|
|
4291
4325
|
// and classification against it is case-sensitive. Optional: empty
|
|
4292
4326
|
// means the default, and the sender still refuses any handle that
|
|
4293
4327
|
// disagrees with the transaction it minted.
|
|
4294
|
-
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true }
|
|
4328
|
+
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true },
|
|
4329
|
+
// The Partner API credential set — the ONE place meter billing is
|
|
4330
|
+
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
4331
|
+
// id come from the Partner Dashboard; the token from Settings →
|
|
4332
|
+
// Partner API clients (Manage-apps permission). All optional: the
|
|
4333
|
+
// accrual probe simply stays off until they exist.
|
|
4334
|
+
{ input: "text", key: "partnerOrgId", label: "Partner organization ID", required: false, setting: true },
|
|
4335
|
+
{ input: "text", key: "partnerAppId", label: "Partner app ID (numeric)", required: false, setting: true },
|
|
4336
|
+
{ input: "password", key: "partnerToken", label: "Partner API token", redact: true, required: false, setting: true }
|
|
4295
4337
|
]
|
|
4296
4338
|
},
|
|
4297
4339
|
// A pre-launch integration: it only surfaces once the App Store listing
|
package/package.json
CHANGED