@drawbridge/drawbridge-utils 0.0.149 → 0.0.151
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 +32 -24
- package/dist/connections/index.d.cts +53 -28
- package/dist/connections/index.d.ts +53 -28
- package/dist/connections/index.js +32 -24
- package/dist/providers.cjs +32 -24
- package/dist/providers.js +32 -24
- package/package.json +1 -1
|
@@ -860,8 +860,8 @@ var attentive_default2 = {
|
|
|
860
860
|
// keep the stored value. `required` drives the live check.
|
|
861
861
|
provider: {
|
|
862
862
|
fields: [
|
|
863
|
-
{ input: "text", key: "clientId", credential: "ATTENTIVE_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
864
|
-
{ input: "password", key: "clientSecret", credential: "ATTENTIVE_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
863
|
+
{ input: "text", key: "clientId", credential: "ATTENTIVE_OAUTH_CLIENT_ID", label: "Client ID", message: "From our app's registration in the Attentive developer portal.", required: true },
|
|
864
|
+
{ input: "password", key: "clientSecret", credential: "ATTENTIVE_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID in the Attentive developer portal.", redact: true, required: true }
|
|
865
865
|
]
|
|
866
866
|
},
|
|
867
867
|
requires: [
|
|
@@ -2302,7 +2302,7 @@ var drawbridge_default2 = {
|
|
|
2302
2302
|
provider: {
|
|
2303
2303
|
fields: [
|
|
2304
2304
|
{ input: "email", key: "accountSender", credential: "SENDGRID_FROM_ADDRESS", label: "Account sender", message: "Verification codes and security alerts send from here.", required: true },
|
|
2305
|
-
{ input: "password", key: "apiKey", credential: "SENDGRID_API_KEY", label: "SendGrid API key", redact: true, required: true },
|
|
2305
|
+
{ input: "password", key: "apiKey", credential: "SENDGRID_API_KEY", label: "SendGrid API key", message: "SendGrid dashboard, Settings, API Keys \u2014 full access for sends.", redact: true, required: true },
|
|
2306
2306
|
// NOT required. The CRM sync is best-effort internal tooling and no-ops
|
|
2307
2307
|
// without a token — requiring it would make the whole drawbridge provider
|
|
2308
2308
|
// read not-live over something no merchant ever sees.
|
|
@@ -2322,8 +2322,8 @@ var drawbridge_default2 = {
|
|
|
2322
2322
|
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2323
2323
|
// hides the org's SMS settings entirely.
|
|
2324
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 }
|
|
2325
|
+
{ input: "password", key: "smsSid", credential: "TWILIO_ACCOUNT_SID", label: "Twilio account SID", message: "Twilio console home \u2014 the AC\u2026 identifier on the account dashboard.", redact: true },
|
|
2326
|
+
{ input: "password", key: "smsToken", credential: "TWILIO_AUTH_TOKEN", label: "Twilio auth token", message: "Beside the account SID on the Twilio console dashboard.", redact: true }
|
|
2327
2327
|
]
|
|
2328
2328
|
},
|
|
2329
2329
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -2913,8 +2913,8 @@ var klaviyo_default2 = {
|
|
|
2913
2913
|
// `requires` that names the same variables.
|
|
2914
2914
|
provider: {
|
|
2915
2915
|
fields: [
|
|
2916
|
-
{ input: "text", key: "clientId", credential: "KLAVIYO_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
2917
|
-
{ input: "password", key: "clientSecret", credential: "KLAVIYO_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
2916
|
+
{ input: "text", key: "clientId", credential: "KLAVIYO_OAUTH_CLIENT_ID", label: "Client ID", message: "From our app in the Klaviyo developer portal (developers.klaviyo.com).", required: true },
|
|
2917
|
+
{ input: "password", key: "clientSecret", credential: "KLAVIYO_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID on the Klaviyo app.", redact: true, required: true }
|
|
2918
2918
|
]
|
|
2919
2919
|
},
|
|
2920
2920
|
requires: [
|
|
@@ -3259,8 +3259,8 @@ var mailchimp_default2 = {
|
|
|
3259
3259
|
// same variables.
|
|
3260
3260
|
provider: {
|
|
3261
3261
|
fields: [
|
|
3262
|
-
{ input: "text", key: "clientId", credential: "MAILCHIMP_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
3263
|
-
{ input: "password", key: "clientSecret", credential: "MAILCHIMP_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
3262
|
+
{ input: "text", key: "clientId", credential: "MAILCHIMP_OAUTH_CLIENT_ID", label: "Client ID", message: "From our registered app \u2014 Mailchimp account, Extras, Registered apps.", required: true },
|
|
3263
|
+
{ input: "password", key: "clientSecret", credential: "MAILCHIMP_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID on the registered app.", redact: true, required: true }
|
|
3264
3264
|
]
|
|
3265
3265
|
},
|
|
3266
3266
|
// The OAuth client this deployment registered. Without both, the vendor drops
|
|
@@ -4194,24 +4194,32 @@ var shopify_default2 = {
|
|
|
4194
4194
|
if (partner.partnerToken && partner.partnerOrgId && partner.partnerAppId && (source == null ? void 0 : source.id) && ((_b = shopify.partner) == null ? void 0 : _b.getUsageChargeEvents)) {
|
|
4195
4195
|
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4196
4196
|
appId: "gid://shopify/App/" + partner.partnerAppId,
|
|
4197
|
-
first:
|
|
4197
|
+
first: 5,
|
|
4198
4198
|
occurredAtMin: new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString(),
|
|
4199
4199
|
organizationId: partner.partnerOrgId,
|
|
4200
4200
|
partnerToken: partner.partnerToken,
|
|
4201
4201
|
shopId: "gid://shopify/Shop/" + source.id
|
|
4202
4202
|
});
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4203
|
+
const accrued = accruals.find((event) => Number(event.usageQuantity) > 0);
|
|
4204
|
+
if (accrued) {
|
|
4205
|
+
metered = String(accrued.chargeId || accrued.id);
|
|
4206
|
+
writes.push({
|
|
4207
4207
|
collection: "order",
|
|
4208
|
+
data: {
|
|
4209
|
+
$set: { "billed.receipt": metered }
|
|
4210
|
+
},
|
|
4211
|
+
// Top-level, not an option — the controller takes
|
|
4212
|
+
// `multiple` beside `options`, and the shell
|
|
4213
|
+
// forwards it as such.
|
|
4214
|
+
multiple: true,
|
|
4215
|
+
operation: "update",
|
|
4208
4216
|
query: {
|
|
4209
|
-
"billed.date": { $
|
|
4217
|
+
"billed.date": { $gte: new Date(accrued.occurredAt || 0) },
|
|
4218
|
+
"billed.receipt": { $in: [null] },
|
|
4210
4219
|
organization: workflow.organization,
|
|
4211
4220
|
"provider.slug": "shopify"
|
|
4212
4221
|
}
|
|
4213
4222
|
});
|
|
4214
|
-
if (unaccrued) metered = null;
|
|
4215
4223
|
}
|
|
4216
4224
|
}
|
|
4217
4225
|
} catch (probeError) {
|
|
@@ -4433,10 +4441,10 @@ var shopify_default2 = {
|
|
|
4433
4441
|
// never go live from the admin screen.
|
|
4434
4442
|
provider: {
|
|
4435
4443
|
fields: [
|
|
4436
|
-
{ input: "text", key: "apiKey", credential: "SHOPIFY_API_KEY", label: "API key", required: true },
|
|
4437
|
-
{ input: "password", key: "apiSecret", credential: "SHOPIFY_API_SECRET", label: "API secret", redact: true, required: true },
|
|
4438
|
-
{ input: "text", key: "appHandle", credential: "SHOPIFY_APP_HANDLE", label: "App handle", required: true },
|
|
4439
|
-
{ input: "text", key: "listingUrl", credential: "SHOPIFY_APP_LISTING_URL", label: "App listing URL", required: true },
|
|
4444
|
+
{ input: "text", key: "apiKey", credential: "SHOPIFY_API_KEY", label: "API key", message: "The app's Client ID \u2014 Dev Dashboard, the app, Settings.", required: true },
|
|
4445
|
+
{ input: "password", key: "apiSecret", credential: "SHOPIFY_API_SECRET", label: "API secret", message: "The app's Client secret, beside the Client ID in the app's settings.", redact: true, required: true },
|
|
4446
|
+
{ input: "text", key: "appHandle", credential: "SHOPIFY_APP_HANDLE", label: "App handle", message: "The app's URL handle (for example drawbridge-development), from the app's configuration.", required: true },
|
|
4447
|
+
{ input: "text", key: "listingUrl", credential: "SHOPIFY_APP_LISTING_URL", label: "App listing URL", message: 'Where "View on the Shopify App Store" sends merchants \u2014 the public listing, or the Dev Dashboard install link for the dev app.', required: true },
|
|
4440
4448
|
// The usage meter's event handle, when the plan config's meter ever
|
|
4441
4449
|
// changes: stored value overrides the built-in default
|
|
4442
4450
|
// (events.order.handle) at the mint point, and `format : 'slug'`
|
|
@@ -4444,15 +4452,15 @@ var shopify_default2 = {
|
|
|
4444
4452
|
// and classification against it is case-sensitive. Optional: empty
|
|
4445
4453
|
// means the default, and the sender still refuses any handle that
|
|
4446
4454
|
// disagrees with the transaction it minted.
|
|
4447
|
-
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true },
|
|
4455
|
+
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", message: "Must match the usage meter's Handle field on the plan exactly \u2014 lowercase and hyphens. Leave empty to use drawbridge-orders.", required: false, setting: true },
|
|
4448
4456
|
// The Partner API credential set — the ONE place meter billing is
|
|
4449
4457
|
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
4450
4458
|
// id come from the Partner Dashboard; the token from Settings →
|
|
4451
4459
|
// Partner API clients (Manage-apps permission). All optional: the
|
|
4452
4460
|
// 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 }
|
|
4461
|
+
{ input: "text", key: "partnerOrgId", label: "Partner organization ID", message: "The number in the Partner Dashboard URL \u2014 partners.shopify.com/<this number>/\u2026 \u2014 NOT the admin organization_id from the app listing link.", required: false, setting: true },
|
|
4462
|
+
{ input: "text", key: "partnerAppId", label: "Partner app ID (numeric)", message: "The numeric id in the app's Partner Dashboard URL \u2014 not the Client ID.", required: false, setting: true },
|
|
4463
|
+
{ input: "password", key: "partnerToken", label: "Partner API token", message: "Partner Dashboard, Settings, Partner API clients \u2014 create one with Manage apps and paste the prtapi_ token.", redact: true, required: false, setting: true }
|
|
4456
4464
|
]
|
|
4457
4465
|
},
|
|
4458
4466
|
// A pre-launch integration: it only surfaces once the App Store listing
|
|
@@ -1193,8 +1193,8 @@ var attentive = {
|
|
|
1193
1193
|
// keep the stored value. `required` drives the live check.
|
|
1194
1194
|
provider : {
|
|
1195
1195
|
fields : [
|
|
1196
|
-
{ input : 'text', key : 'clientId', credential : 'ATTENTIVE_OAUTH_CLIENT_ID', label : 'Client ID', required : true },
|
|
1197
|
-
{ input : 'password', key : 'clientSecret', credential : 'ATTENTIVE_OAUTH_CLIENT_SECRET', label : 'Client secret', redact : true, required : true }
|
|
1196
|
+
{ input : 'text', key : 'clientId', credential : 'ATTENTIVE_OAUTH_CLIENT_ID', label : 'Client ID', message : 'From our app\'s registration in the Attentive developer portal.', required : true },
|
|
1197
|
+
{ input : 'password', key : 'clientSecret', credential : 'ATTENTIVE_OAUTH_CLIENT_SECRET', label : 'Client secret', message : 'Beside the Client ID in the Attentive developer portal.', redact : true, required : true }
|
|
1198
1198
|
]
|
|
1199
1199
|
},
|
|
1200
1200
|
requires : [
|
|
@@ -2404,7 +2404,7 @@ var drawbridge = {
|
|
|
2404
2404
|
provider : {
|
|
2405
2405
|
fields : [
|
|
2406
2406
|
{ input : 'email', key : 'accountSender', credential : 'SENDGRID_FROM_ADDRESS', label : 'Account sender', message : 'Verification codes and security alerts send from here.', required : true },
|
|
2407
|
-
{ input : 'password', key : 'apiKey', credential : 'SENDGRID_API_KEY', label : 'SendGrid API key', redact : true, required : true },
|
|
2407
|
+
{ input : 'password', key : 'apiKey', credential : 'SENDGRID_API_KEY', label : 'SendGrid API key', message : 'SendGrid dashboard, Settings, API Keys — full access for sends.', redact : true, required : true },
|
|
2408
2408
|
// NOT required. The CRM sync is best-effort internal tooling and no-ops
|
|
2409
2409
|
// without a token — requiring it would make the whole drawbridge provider
|
|
2410
2410
|
// read not-live over something no merchant ever sees.
|
|
@@ -2424,8 +2424,8 @@ var drawbridge = {
|
|
|
2424
2424
|
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2425
2425
|
// hides the org's SMS settings entirely.
|
|
2426
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 }
|
|
2427
|
+
{ input : 'password', key : 'smsSid', credential : 'TWILIO_ACCOUNT_SID', label : 'Twilio account SID', message : 'Twilio console home — the AC… identifier on the account dashboard.', redact : true },
|
|
2428
|
+
{ input : 'password', key : 'smsToken', credential : 'TWILIO_AUTH_TOKEN', label : 'Twilio auth token', message : 'Beside the account SID on the Twilio console dashboard.', redact : true }
|
|
2429
2429
|
]
|
|
2430
2430
|
},
|
|
2431
2431
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -3179,8 +3179,8 @@ var klaviyo = {
|
|
|
3179
3179
|
// `requires` that names the same variables.
|
|
3180
3180
|
provider : {
|
|
3181
3181
|
fields : [
|
|
3182
|
-
{ input : 'text', key : 'clientId', credential : 'KLAVIYO_OAUTH_CLIENT_ID', label : 'Client ID', required : true },
|
|
3183
|
-
{ input : 'password', key : 'clientSecret', credential : 'KLAVIYO_OAUTH_CLIENT_SECRET', label : 'Client secret', redact : true, required : true }
|
|
3182
|
+
{ input : 'text', key : 'clientId', credential : 'KLAVIYO_OAUTH_CLIENT_ID', label : 'Client ID', message : 'From our app in the Klaviyo developer portal (developers.klaviyo.com).', required : true },
|
|
3183
|
+
{ input : 'password', key : 'clientSecret', credential : 'KLAVIYO_OAUTH_CLIENT_SECRET', label : 'Client secret', message : 'Beside the Client ID on the Klaviyo app.', redact : true, required : true }
|
|
3184
3184
|
]
|
|
3185
3185
|
},
|
|
3186
3186
|
requires : [
|
|
@@ -3643,8 +3643,8 @@ var mailchimp = {
|
|
|
3643
3643
|
// same variables.
|
|
3644
3644
|
provider : {
|
|
3645
3645
|
fields : [
|
|
3646
|
-
{ input : 'text', key : 'clientId', credential : 'MAILCHIMP_OAUTH_CLIENT_ID', label : 'Client ID', required : true },
|
|
3647
|
-
{ input : 'password', key : 'clientSecret', credential : 'MAILCHIMP_OAUTH_CLIENT_SECRET', label : 'Client secret', redact : true, required : true }
|
|
3646
|
+
{ input : 'text', key : 'clientId', credential : 'MAILCHIMP_OAUTH_CLIENT_ID', label : 'Client ID', message : 'From our registered app — Mailchimp account, Extras, Registered apps.', required : true },
|
|
3647
|
+
{ input : 'password', key : 'clientSecret', credential : 'MAILCHIMP_OAUTH_CLIENT_SECRET', label : 'Client secret', message : 'Beside the Client ID on the registered app.', redact : true, required : true }
|
|
3648
3648
|
]
|
|
3649
3649
|
},
|
|
3650
3650
|
// The OAuth client this deployment registered. Without both, the vendor drops
|
|
@@ -4983,35 +4983,60 @@ var shopify = {
|
|
|
4983
4983
|
|
|
4984
4984
|
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4985
4985
|
appId : 'gid://shopify/App/' + partner.partnerAppId,
|
|
4986
|
-
first :
|
|
4986
|
+
first : 5,
|
|
4987
4987
|
occurredAtMin : new Date( Date.now() - 30 * 24 * 60 * 60 * 1000 ).toISOString(),
|
|
4988
4988
|
organizationId : partner.partnerOrgId,
|
|
4989
4989
|
partnerToken : partner.partnerToken,
|
|
4990
4990
|
shopId : 'gid://shopify/Shop/' + source.id
|
|
4991
4991
|
});
|
|
4992
4992
|
|
|
4993
|
-
|
|
4993
|
+
// A usage ROW exists per subscription even before anything
|
|
4994
|
+
// accrues (measured: a pre-meter approval shows qty 0), so
|
|
4995
|
+
// the row is not the proof — a POSITIVE usageQuantity is.
|
|
4996
|
+
const accrued = accruals.find( ( event ) => Number( event.usageQuantity ) > 0 );
|
|
4994
4997
|
|
|
4995
|
-
|
|
4998
|
+
if( accrued ){
|
|
4996
4999
|
|
|
4997
|
-
|
|
5000
|
+
metered = String( accrued.chargeId || accrued.id );
|
|
4998
5001
|
|
|
4999
|
-
//
|
|
5000
|
-
//
|
|
5001
|
-
//
|
|
5002
|
-
|
|
5002
|
+
// THE BUCKET STAMPS ITS ORDERS. Partner accrual rows
|
|
5003
|
+
// are per-subscription, not per-order, so the charge id
|
|
5004
|
+
// is the invoice bucket every order billed since that
|
|
5005
|
+
// subscription's approval rolled into — written onto
|
|
5006
|
+
// billed.receipt (many-update; $in [null] matches both
|
|
5007
|
+
// null and never-stamped). Orders billed before the
|
|
5008
|
+
// window belong to earlier, possibly unbillable
|
|
5009
|
+
// approvals and honestly stay unstamped.
|
|
5010
|
+
writes.push({
|
|
5003
5011
|
collection : 'order',
|
|
5012
|
+
data : {
|
|
5013
|
+
$set : { 'billed.receipt' : metered }
|
|
5014
|
+
},
|
|
5015
|
+
// Top-level, not an option — the controller takes
|
|
5016
|
+
// `multiple` beside `options`, and the shell
|
|
5017
|
+
// forwards it as such.
|
|
5018
|
+
multiple : true,
|
|
5019
|
+
operation : 'update',
|
|
5004
5020
|
query : {
|
|
5005
|
-
'billed.date' : { $
|
|
5021
|
+
'billed.date' : { $gte : new Date( accrued.occurredAt || 0 ) },
|
|
5022
|
+
'billed.receipt' : { $in : [ null ] },
|
|
5006
5023
|
organization : workflow.organization,
|
|
5007
5024
|
'provider.slug' : 'shopify'
|
|
5008
5025
|
}
|
|
5009
5026
|
});
|
|
5010
5027
|
|
|
5011
|
-
if( unaccrued ) metered = null;
|
|
5012
|
-
|
|
5013
5028
|
}
|
|
5014
5029
|
|
|
5030
|
+
// NO negative verdict from an empty ledger: measured
|
|
5031
|
+
// 2026-09-04, CHARGE_USAGE rows only materialize at
|
|
5032
|
+
// BILLING moments (cycle end, cancellation/replacement)
|
|
5033
|
+
// — usage accrues invisibly between them, so a
|
|
5034
|
+
// first-cycle store with billed orders and no row is
|
|
5035
|
+
// the NORMAL state, not an unmetered one. The honest
|
|
5036
|
+
// negative is a boundary reconciliation (a charge-out
|
|
5037
|
+
// row whose quantity falls short of the window's billed
|
|
5038
|
+
// sum) — until that exists, absence stays a no-verdict.
|
|
5039
|
+
|
|
5015
5040
|
}
|
|
5016
5041
|
|
|
5017
5042
|
} catch ( probeError ) {
|
|
@@ -5310,10 +5335,10 @@ var shopify = {
|
|
|
5310
5335
|
// never go live from the admin screen.
|
|
5311
5336
|
provider : {
|
|
5312
5337
|
fields : [
|
|
5313
|
-
{ input : 'text', key : 'apiKey', credential : 'SHOPIFY_API_KEY', label : 'API key', required : true },
|
|
5314
|
-
{ input : 'password', key : 'apiSecret', credential : 'SHOPIFY_API_SECRET', label : 'API secret', redact : true, required : true },
|
|
5315
|
-
{ input : 'text', key : 'appHandle', credential : 'SHOPIFY_APP_HANDLE', label : 'App handle', required : true },
|
|
5316
|
-
{ input : 'text', key : 'listingUrl', credential : 'SHOPIFY_APP_LISTING_URL', label : 'App listing URL', required : true },
|
|
5338
|
+
{ input : 'text', key : 'apiKey', credential : 'SHOPIFY_API_KEY', label : 'API key', message : 'The app\'s Client ID — Dev Dashboard, the app, Settings.', required : true },
|
|
5339
|
+
{ input : 'password', key : 'apiSecret', credential : 'SHOPIFY_API_SECRET', label : 'API secret', message : 'The app\'s Client secret, beside the Client ID in the app\'s settings.', redact : true, required : true },
|
|
5340
|
+
{ input : 'text', key : 'appHandle', credential : 'SHOPIFY_APP_HANDLE', label : 'App handle', message : 'The app\'s URL handle (for example drawbridge-development), from the app\'s configuration.', required : true },
|
|
5341
|
+
{ input : 'text', key : 'listingUrl', credential : 'SHOPIFY_APP_LISTING_URL', label : 'App listing URL', message : 'Where "View on the Shopify App Store" sends merchants — the public listing, or the Dev Dashboard install link for the dev app.', required : true },
|
|
5317
5342
|
// The usage meter's event handle, when the plan config's meter ever
|
|
5318
5343
|
// changes: stored value overrides the built-in default
|
|
5319
5344
|
// (events.order.handle) at the mint point, and `format : 'slug'`
|
|
@@ -5321,15 +5346,15 @@ var shopify = {
|
|
|
5321
5346
|
// and classification against it is case-sensitive. Optional: empty
|
|
5322
5347
|
// means the default, and the sender still refuses any handle that
|
|
5323
5348
|
// disagrees with the transaction it minted.
|
|
5324
|
-
{ format : 'slug', input : 'text', key : 'orderEventHandle', label : 'Order event handle', required : false, setting : true },
|
|
5349
|
+
{ format : 'slug', input : 'text', key : 'orderEventHandle', label : 'Order event handle', message : 'Must match the usage meter\'s Handle field on the plan exactly — lowercase and hyphens. Leave empty to use drawbridge-orders.', required : false, setting : true },
|
|
5325
5350
|
// The Partner API credential set — the ONE place meter billing is
|
|
5326
5351
|
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
5327
5352
|
// id come from the Partner Dashboard; the token from Settings →
|
|
5328
5353
|
// Partner API clients (Manage-apps permission). All optional: the
|
|
5329
5354
|
// 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 }
|
|
5355
|
+
{ input : 'text', key : 'partnerOrgId', label : 'Partner organization ID', message : 'The number in the Partner Dashboard URL — partners.shopify.com/<this number>/… — NOT the admin organization_id from the app listing link.', required : false, setting : true },
|
|
5356
|
+
{ input : 'text', key : 'partnerAppId', label : 'Partner app ID (numeric)', message : 'The numeric id in the app\'s Partner Dashboard URL — not the Client ID.', required : false, setting : true },
|
|
5357
|
+
{ input : 'password', key : 'partnerToken', label : 'Partner API token', message : 'Partner Dashboard, Settings, Partner API clients — create one with Manage apps and paste the prtapi_ token.', redact : true, required : false, setting : true }
|
|
5333
5358
|
]
|
|
5334
5359
|
},
|
|
5335
5360
|
// A pre-launch integration: it only surfaces once the App Store listing
|
|
@@ -1193,8 +1193,8 @@ var attentive = {
|
|
|
1193
1193
|
// keep the stored value. `required` drives the live check.
|
|
1194
1194
|
provider : {
|
|
1195
1195
|
fields : [
|
|
1196
|
-
{ input : 'text', key : 'clientId', credential : 'ATTENTIVE_OAUTH_CLIENT_ID', label : 'Client ID', required : true },
|
|
1197
|
-
{ input : 'password', key : 'clientSecret', credential : 'ATTENTIVE_OAUTH_CLIENT_SECRET', label : 'Client secret', redact : true, required : true }
|
|
1196
|
+
{ input : 'text', key : 'clientId', credential : 'ATTENTIVE_OAUTH_CLIENT_ID', label : 'Client ID', message : 'From our app\'s registration in the Attentive developer portal.', required : true },
|
|
1197
|
+
{ input : 'password', key : 'clientSecret', credential : 'ATTENTIVE_OAUTH_CLIENT_SECRET', label : 'Client secret', message : 'Beside the Client ID in the Attentive developer portal.', redact : true, required : true }
|
|
1198
1198
|
]
|
|
1199
1199
|
},
|
|
1200
1200
|
requires : [
|
|
@@ -2404,7 +2404,7 @@ var drawbridge = {
|
|
|
2404
2404
|
provider : {
|
|
2405
2405
|
fields : [
|
|
2406
2406
|
{ input : 'email', key : 'accountSender', credential : 'SENDGRID_FROM_ADDRESS', label : 'Account sender', message : 'Verification codes and security alerts send from here.', required : true },
|
|
2407
|
-
{ input : 'password', key : 'apiKey', credential : 'SENDGRID_API_KEY', label : 'SendGrid API key', redact : true, required : true },
|
|
2407
|
+
{ input : 'password', key : 'apiKey', credential : 'SENDGRID_API_KEY', label : 'SendGrid API key', message : 'SendGrid dashboard, Settings, API Keys — full access for sends.', redact : true, required : true },
|
|
2408
2408
|
// NOT required. The CRM sync is best-effort internal tooling and no-ops
|
|
2409
2409
|
// without a token — requiring it would make the whole drawbridge provider
|
|
2410
2410
|
// read not-live over something no merchant ever sees.
|
|
@@ -2424,8 +2424,8 @@ var drawbridge = {
|
|
|
2424
2424
|
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2425
2425
|
// hides the org's SMS settings entirely.
|
|
2426
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 }
|
|
2427
|
+
{ input : 'password', key : 'smsSid', credential : 'TWILIO_ACCOUNT_SID', label : 'Twilio account SID', message : 'Twilio console home — the AC… identifier on the account dashboard.', redact : true },
|
|
2428
|
+
{ input : 'password', key : 'smsToken', credential : 'TWILIO_AUTH_TOKEN', label : 'Twilio auth token', message : 'Beside the account SID on the Twilio console dashboard.', redact : true }
|
|
2429
2429
|
]
|
|
2430
2430
|
},
|
|
2431
2431
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -3179,8 +3179,8 @@ var klaviyo = {
|
|
|
3179
3179
|
// `requires` that names the same variables.
|
|
3180
3180
|
provider : {
|
|
3181
3181
|
fields : [
|
|
3182
|
-
{ input : 'text', key : 'clientId', credential : 'KLAVIYO_OAUTH_CLIENT_ID', label : 'Client ID', required : true },
|
|
3183
|
-
{ input : 'password', key : 'clientSecret', credential : 'KLAVIYO_OAUTH_CLIENT_SECRET', label : 'Client secret', redact : true, required : true }
|
|
3182
|
+
{ input : 'text', key : 'clientId', credential : 'KLAVIYO_OAUTH_CLIENT_ID', label : 'Client ID', message : 'From our app in the Klaviyo developer portal (developers.klaviyo.com).', required : true },
|
|
3183
|
+
{ input : 'password', key : 'clientSecret', credential : 'KLAVIYO_OAUTH_CLIENT_SECRET', label : 'Client secret', message : 'Beside the Client ID on the Klaviyo app.', redact : true, required : true }
|
|
3184
3184
|
]
|
|
3185
3185
|
},
|
|
3186
3186
|
requires : [
|
|
@@ -3643,8 +3643,8 @@ var mailchimp = {
|
|
|
3643
3643
|
// same variables.
|
|
3644
3644
|
provider : {
|
|
3645
3645
|
fields : [
|
|
3646
|
-
{ input : 'text', key : 'clientId', credential : 'MAILCHIMP_OAUTH_CLIENT_ID', label : 'Client ID', required : true },
|
|
3647
|
-
{ input : 'password', key : 'clientSecret', credential : 'MAILCHIMP_OAUTH_CLIENT_SECRET', label : 'Client secret', redact : true, required : true }
|
|
3646
|
+
{ input : 'text', key : 'clientId', credential : 'MAILCHIMP_OAUTH_CLIENT_ID', label : 'Client ID', message : 'From our registered app — Mailchimp account, Extras, Registered apps.', required : true },
|
|
3647
|
+
{ input : 'password', key : 'clientSecret', credential : 'MAILCHIMP_OAUTH_CLIENT_SECRET', label : 'Client secret', message : 'Beside the Client ID on the registered app.', redact : true, required : true }
|
|
3648
3648
|
]
|
|
3649
3649
|
},
|
|
3650
3650
|
// The OAuth client this deployment registered. Without both, the vendor drops
|
|
@@ -4983,35 +4983,60 @@ var shopify = {
|
|
|
4983
4983
|
|
|
4984
4984
|
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4985
4985
|
appId : 'gid://shopify/App/' + partner.partnerAppId,
|
|
4986
|
-
first :
|
|
4986
|
+
first : 5,
|
|
4987
4987
|
occurredAtMin : new Date( Date.now() - 30 * 24 * 60 * 60 * 1000 ).toISOString(),
|
|
4988
4988
|
organizationId : partner.partnerOrgId,
|
|
4989
4989
|
partnerToken : partner.partnerToken,
|
|
4990
4990
|
shopId : 'gid://shopify/Shop/' + source.id
|
|
4991
4991
|
});
|
|
4992
4992
|
|
|
4993
|
-
|
|
4993
|
+
// A usage ROW exists per subscription even before anything
|
|
4994
|
+
// accrues (measured: a pre-meter approval shows qty 0), so
|
|
4995
|
+
// the row is not the proof — a POSITIVE usageQuantity is.
|
|
4996
|
+
const accrued = accruals.find( ( event ) => Number( event.usageQuantity ) > 0 );
|
|
4994
4997
|
|
|
4995
|
-
|
|
4998
|
+
if( accrued ){
|
|
4996
4999
|
|
|
4997
|
-
|
|
5000
|
+
metered = String( accrued.chargeId || accrued.id );
|
|
4998
5001
|
|
|
4999
|
-
//
|
|
5000
|
-
//
|
|
5001
|
-
//
|
|
5002
|
-
|
|
5002
|
+
// THE BUCKET STAMPS ITS ORDERS. Partner accrual rows
|
|
5003
|
+
// are per-subscription, not per-order, so the charge id
|
|
5004
|
+
// is the invoice bucket every order billed since that
|
|
5005
|
+
// subscription's approval rolled into — written onto
|
|
5006
|
+
// billed.receipt (many-update; $in [null] matches both
|
|
5007
|
+
// null and never-stamped). Orders billed before the
|
|
5008
|
+
// window belong to earlier, possibly unbillable
|
|
5009
|
+
// approvals and honestly stay unstamped.
|
|
5010
|
+
writes.push({
|
|
5003
5011
|
collection : 'order',
|
|
5012
|
+
data : {
|
|
5013
|
+
$set : { 'billed.receipt' : metered }
|
|
5014
|
+
},
|
|
5015
|
+
// Top-level, not an option — the controller takes
|
|
5016
|
+
// `multiple` beside `options`, and the shell
|
|
5017
|
+
// forwards it as such.
|
|
5018
|
+
multiple : true,
|
|
5019
|
+
operation : 'update',
|
|
5004
5020
|
query : {
|
|
5005
|
-
'billed.date' : { $
|
|
5021
|
+
'billed.date' : { $gte : new Date( accrued.occurredAt || 0 ) },
|
|
5022
|
+
'billed.receipt' : { $in : [ null ] },
|
|
5006
5023
|
organization : workflow.organization,
|
|
5007
5024
|
'provider.slug' : 'shopify'
|
|
5008
5025
|
}
|
|
5009
5026
|
});
|
|
5010
5027
|
|
|
5011
|
-
if( unaccrued ) metered = null;
|
|
5012
|
-
|
|
5013
5028
|
}
|
|
5014
5029
|
|
|
5030
|
+
// NO negative verdict from an empty ledger: measured
|
|
5031
|
+
// 2026-09-04, CHARGE_USAGE rows only materialize at
|
|
5032
|
+
// BILLING moments (cycle end, cancellation/replacement)
|
|
5033
|
+
// — usage accrues invisibly between them, so a
|
|
5034
|
+
// first-cycle store with billed orders and no row is
|
|
5035
|
+
// the NORMAL state, not an unmetered one. The honest
|
|
5036
|
+
// negative is a boundary reconciliation (a charge-out
|
|
5037
|
+
// row whose quantity falls short of the window's billed
|
|
5038
|
+
// sum) — until that exists, absence stays a no-verdict.
|
|
5039
|
+
|
|
5015
5040
|
}
|
|
5016
5041
|
|
|
5017
5042
|
} catch ( probeError ) {
|
|
@@ -5310,10 +5335,10 @@ var shopify = {
|
|
|
5310
5335
|
// never go live from the admin screen.
|
|
5311
5336
|
provider : {
|
|
5312
5337
|
fields : [
|
|
5313
|
-
{ input : 'text', key : 'apiKey', credential : 'SHOPIFY_API_KEY', label : 'API key', required : true },
|
|
5314
|
-
{ input : 'password', key : 'apiSecret', credential : 'SHOPIFY_API_SECRET', label : 'API secret', redact : true, required : true },
|
|
5315
|
-
{ input : 'text', key : 'appHandle', credential : 'SHOPIFY_APP_HANDLE', label : 'App handle', required : true },
|
|
5316
|
-
{ input : 'text', key : 'listingUrl', credential : 'SHOPIFY_APP_LISTING_URL', label : 'App listing URL', required : true },
|
|
5338
|
+
{ input : 'text', key : 'apiKey', credential : 'SHOPIFY_API_KEY', label : 'API key', message : 'The app\'s Client ID — Dev Dashboard, the app, Settings.', required : true },
|
|
5339
|
+
{ input : 'password', key : 'apiSecret', credential : 'SHOPIFY_API_SECRET', label : 'API secret', message : 'The app\'s Client secret, beside the Client ID in the app\'s settings.', redact : true, required : true },
|
|
5340
|
+
{ input : 'text', key : 'appHandle', credential : 'SHOPIFY_APP_HANDLE', label : 'App handle', message : 'The app\'s URL handle (for example drawbridge-development), from the app\'s configuration.', required : true },
|
|
5341
|
+
{ input : 'text', key : 'listingUrl', credential : 'SHOPIFY_APP_LISTING_URL', label : 'App listing URL', message : 'Where "View on the Shopify App Store" sends merchants — the public listing, or the Dev Dashboard install link for the dev app.', required : true },
|
|
5317
5342
|
// The usage meter's event handle, when the plan config's meter ever
|
|
5318
5343
|
// changes: stored value overrides the built-in default
|
|
5319
5344
|
// (events.order.handle) at the mint point, and `format : 'slug'`
|
|
@@ -5321,15 +5346,15 @@ var shopify = {
|
|
|
5321
5346
|
// and classification against it is case-sensitive. Optional: empty
|
|
5322
5347
|
// means the default, and the sender still refuses any handle that
|
|
5323
5348
|
// disagrees with the transaction it minted.
|
|
5324
|
-
{ format : 'slug', input : 'text', key : 'orderEventHandle', label : 'Order event handle', required : false, setting : true },
|
|
5349
|
+
{ format : 'slug', input : 'text', key : 'orderEventHandle', label : 'Order event handle', message : 'Must match the usage meter\'s Handle field on the plan exactly — lowercase and hyphens. Leave empty to use drawbridge-orders.', required : false, setting : true },
|
|
5325
5350
|
// The Partner API credential set — the ONE place meter billing is
|
|
5326
5351
|
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
5327
5352
|
// id come from the Partner Dashboard; the token from Settings →
|
|
5328
5353
|
// Partner API clients (Manage-apps permission). All optional: the
|
|
5329
5354
|
// 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 }
|
|
5355
|
+
{ input : 'text', key : 'partnerOrgId', label : 'Partner organization ID', message : 'The number in the Partner Dashboard URL — partners.shopify.com/<this number>/… — NOT the admin organization_id from the app listing link.', required : false, setting : true },
|
|
5356
|
+
{ input : 'text', key : 'partnerAppId', label : 'Partner app ID (numeric)', message : 'The numeric id in the app\'s Partner Dashboard URL — not the Client ID.', required : false, setting : true },
|
|
5357
|
+
{ input : 'password', key : 'partnerToken', label : 'Partner API token', message : 'Partner Dashboard, Settings, Partner API clients — create one with Manage apps and paste the prtapi_ token.', redact : true, required : false, setting : true }
|
|
5333
5358
|
]
|
|
5334
5359
|
},
|
|
5335
5360
|
// A pre-launch integration: it only surfaces once the App Store listing
|
|
@@ -786,8 +786,8 @@ var attentive_default2 = {
|
|
|
786
786
|
// keep the stored value. `required` drives the live check.
|
|
787
787
|
provider: {
|
|
788
788
|
fields: [
|
|
789
|
-
{ input: "text", key: "clientId", credential: "ATTENTIVE_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
790
|
-
{ input: "password", key: "clientSecret", credential: "ATTENTIVE_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
789
|
+
{ input: "text", key: "clientId", credential: "ATTENTIVE_OAUTH_CLIENT_ID", label: "Client ID", message: "From our app's registration in the Attentive developer portal.", required: true },
|
|
790
|
+
{ input: "password", key: "clientSecret", credential: "ATTENTIVE_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID in the Attentive developer portal.", redact: true, required: true }
|
|
791
791
|
]
|
|
792
792
|
},
|
|
793
793
|
requires: [
|
|
@@ -2228,7 +2228,7 @@ var drawbridge_default2 = {
|
|
|
2228
2228
|
provider: {
|
|
2229
2229
|
fields: [
|
|
2230
2230
|
{ input: "email", key: "accountSender", credential: "SENDGRID_FROM_ADDRESS", label: "Account sender", message: "Verification codes and security alerts send from here.", required: true },
|
|
2231
|
-
{ input: "password", key: "apiKey", credential: "SENDGRID_API_KEY", label: "SendGrid API key", redact: true, required: true },
|
|
2231
|
+
{ input: "password", key: "apiKey", credential: "SENDGRID_API_KEY", label: "SendGrid API key", message: "SendGrid dashboard, Settings, API Keys \u2014 full access for sends.", redact: true, required: true },
|
|
2232
2232
|
// NOT required. The CRM sync is best-effort internal tooling and no-ops
|
|
2233
2233
|
// without a token — requiring it would make the whole drawbridge provider
|
|
2234
2234
|
// read not-live over something no merchant ever sees.
|
|
@@ -2248,8 +2248,8 @@ var drawbridge_default2 = {
|
|
|
2248
2248
|
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2249
2249
|
// hides the org's SMS settings entirely.
|
|
2250
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 }
|
|
2251
|
+
{ input: "password", key: "smsSid", credential: "TWILIO_ACCOUNT_SID", label: "Twilio account SID", message: "Twilio console home \u2014 the AC\u2026 identifier on the account dashboard.", redact: true },
|
|
2252
|
+
{ input: "password", key: "smsToken", credential: "TWILIO_AUTH_TOKEN", label: "Twilio auth token", message: "Beside the account SID on the Twilio console dashboard.", redact: true }
|
|
2253
2253
|
]
|
|
2254
2254
|
},
|
|
2255
2255
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -2839,8 +2839,8 @@ var klaviyo_default2 = {
|
|
|
2839
2839
|
// `requires` that names the same variables.
|
|
2840
2840
|
provider: {
|
|
2841
2841
|
fields: [
|
|
2842
|
-
{ input: "text", key: "clientId", credential: "KLAVIYO_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
2843
|
-
{ input: "password", key: "clientSecret", credential: "KLAVIYO_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
2842
|
+
{ input: "text", key: "clientId", credential: "KLAVIYO_OAUTH_CLIENT_ID", label: "Client ID", message: "From our app in the Klaviyo developer portal (developers.klaviyo.com).", required: true },
|
|
2843
|
+
{ input: "password", key: "clientSecret", credential: "KLAVIYO_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID on the Klaviyo app.", redact: true, required: true }
|
|
2844
2844
|
]
|
|
2845
2845
|
},
|
|
2846
2846
|
requires: [
|
|
@@ -3185,8 +3185,8 @@ var mailchimp_default2 = {
|
|
|
3185
3185
|
// same variables.
|
|
3186
3186
|
provider: {
|
|
3187
3187
|
fields: [
|
|
3188
|
-
{ input: "text", key: "clientId", credential: "MAILCHIMP_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
3189
|
-
{ input: "password", key: "clientSecret", credential: "MAILCHIMP_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
3188
|
+
{ input: "text", key: "clientId", credential: "MAILCHIMP_OAUTH_CLIENT_ID", label: "Client ID", message: "From our registered app \u2014 Mailchimp account, Extras, Registered apps.", required: true },
|
|
3189
|
+
{ input: "password", key: "clientSecret", credential: "MAILCHIMP_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID on the registered app.", redact: true, required: true }
|
|
3190
3190
|
]
|
|
3191
3191
|
},
|
|
3192
3192
|
// The OAuth client this deployment registered. Without both, the vendor drops
|
|
@@ -4120,24 +4120,32 @@ var shopify_default2 = {
|
|
|
4120
4120
|
if (partner.partnerToken && partner.partnerOrgId && partner.partnerAppId && (source == null ? void 0 : source.id) && ((_b = shopify.partner) == null ? void 0 : _b.getUsageChargeEvents)) {
|
|
4121
4121
|
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4122
4122
|
appId: "gid://shopify/App/" + partner.partnerAppId,
|
|
4123
|
-
first:
|
|
4123
|
+
first: 5,
|
|
4124
4124
|
occurredAtMin: new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString(),
|
|
4125
4125
|
organizationId: partner.partnerOrgId,
|
|
4126
4126
|
partnerToken: partner.partnerToken,
|
|
4127
4127
|
shopId: "gid://shopify/Shop/" + source.id
|
|
4128
4128
|
});
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4129
|
+
const accrued = accruals.find((event) => Number(event.usageQuantity) > 0);
|
|
4130
|
+
if (accrued) {
|
|
4131
|
+
metered = String(accrued.chargeId || accrued.id);
|
|
4132
|
+
writes.push({
|
|
4133
4133
|
collection: "order",
|
|
4134
|
+
data: {
|
|
4135
|
+
$set: { "billed.receipt": metered }
|
|
4136
|
+
},
|
|
4137
|
+
// Top-level, not an option — the controller takes
|
|
4138
|
+
// `multiple` beside `options`, and the shell
|
|
4139
|
+
// forwards it as such.
|
|
4140
|
+
multiple: true,
|
|
4141
|
+
operation: "update",
|
|
4134
4142
|
query: {
|
|
4135
|
-
"billed.date": { $
|
|
4143
|
+
"billed.date": { $gte: new Date(accrued.occurredAt || 0) },
|
|
4144
|
+
"billed.receipt": { $in: [null] },
|
|
4136
4145
|
organization: workflow.organization,
|
|
4137
4146
|
"provider.slug": "shopify"
|
|
4138
4147
|
}
|
|
4139
4148
|
});
|
|
4140
|
-
if (unaccrued) metered = null;
|
|
4141
4149
|
}
|
|
4142
4150
|
}
|
|
4143
4151
|
} catch (probeError) {
|
|
@@ -4359,10 +4367,10 @@ var shopify_default2 = {
|
|
|
4359
4367
|
// never go live from the admin screen.
|
|
4360
4368
|
provider: {
|
|
4361
4369
|
fields: [
|
|
4362
|
-
{ input: "text", key: "apiKey", credential: "SHOPIFY_API_KEY", label: "API key", required: true },
|
|
4363
|
-
{ input: "password", key: "apiSecret", credential: "SHOPIFY_API_SECRET", label: "API secret", redact: true, required: true },
|
|
4364
|
-
{ input: "text", key: "appHandle", credential: "SHOPIFY_APP_HANDLE", label: "App handle", required: true },
|
|
4365
|
-
{ input: "text", key: "listingUrl", credential: "SHOPIFY_APP_LISTING_URL", label: "App listing URL", required: true },
|
|
4370
|
+
{ input: "text", key: "apiKey", credential: "SHOPIFY_API_KEY", label: "API key", message: "The app's Client ID \u2014 Dev Dashboard, the app, Settings.", required: true },
|
|
4371
|
+
{ input: "password", key: "apiSecret", credential: "SHOPIFY_API_SECRET", label: "API secret", message: "The app's Client secret, beside the Client ID in the app's settings.", redact: true, required: true },
|
|
4372
|
+
{ input: "text", key: "appHandle", credential: "SHOPIFY_APP_HANDLE", label: "App handle", message: "The app's URL handle (for example drawbridge-development), from the app's configuration.", required: true },
|
|
4373
|
+
{ input: "text", key: "listingUrl", credential: "SHOPIFY_APP_LISTING_URL", label: "App listing URL", message: 'Where "View on the Shopify App Store" sends merchants \u2014 the public listing, or the Dev Dashboard install link for the dev app.', required: true },
|
|
4366
4374
|
// The usage meter's event handle, when the plan config's meter ever
|
|
4367
4375
|
// changes: stored value overrides the built-in default
|
|
4368
4376
|
// (events.order.handle) at the mint point, and `format : 'slug'`
|
|
@@ -4370,15 +4378,15 @@ var shopify_default2 = {
|
|
|
4370
4378
|
// and classification against it is case-sensitive. Optional: empty
|
|
4371
4379
|
// means the default, and the sender still refuses any handle that
|
|
4372
4380
|
// disagrees with the transaction it minted.
|
|
4373
|
-
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true },
|
|
4381
|
+
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", message: "Must match the usage meter's Handle field on the plan exactly \u2014 lowercase and hyphens. Leave empty to use drawbridge-orders.", required: false, setting: true },
|
|
4374
4382
|
// The Partner API credential set — the ONE place meter billing is
|
|
4375
4383
|
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
4376
4384
|
// id come from the Partner Dashboard; the token from Settings →
|
|
4377
4385
|
// Partner API clients (Manage-apps permission). All optional: the
|
|
4378
4386
|
// 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 }
|
|
4387
|
+
{ input: "text", key: "partnerOrgId", label: "Partner organization ID", message: "The number in the Partner Dashboard URL \u2014 partners.shopify.com/<this number>/\u2026 \u2014 NOT the admin organization_id from the app listing link.", required: false, setting: true },
|
|
4388
|
+
{ input: "text", key: "partnerAppId", label: "Partner app ID (numeric)", message: "The numeric id in the app's Partner Dashboard URL \u2014 not the Client ID.", required: false, setting: true },
|
|
4389
|
+
{ input: "password", key: "partnerToken", label: "Partner API token", message: "Partner Dashboard, Settings, Partner API clients \u2014 create one with Manage apps and paste the prtapi_ token.", redact: true, required: false, setting: true }
|
|
4382
4390
|
]
|
|
4383
4391
|
},
|
|
4384
4392
|
// A pre-launch integration: it only surfaces once the App Store listing
|
package/dist/providers.cjs
CHANGED
|
@@ -766,8 +766,8 @@ var attentive_default2 = {
|
|
|
766
766
|
// keep the stored value. `required` drives the live check.
|
|
767
767
|
provider: {
|
|
768
768
|
fields: [
|
|
769
|
-
{ input: "text", key: "clientId", credential: "ATTENTIVE_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
770
|
-
{ input: "password", key: "clientSecret", credential: "ATTENTIVE_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
769
|
+
{ input: "text", key: "clientId", credential: "ATTENTIVE_OAUTH_CLIENT_ID", label: "Client ID", message: "From our app's registration in the Attentive developer portal.", required: true },
|
|
770
|
+
{ input: "password", key: "clientSecret", credential: "ATTENTIVE_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID in the Attentive developer portal.", redact: true, required: true }
|
|
771
771
|
]
|
|
772
772
|
},
|
|
773
773
|
requires: [
|
|
@@ -2208,7 +2208,7 @@ var drawbridge_default2 = {
|
|
|
2208
2208
|
provider: {
|
|
2209
2209
|
fields: [
|
|
2210
2210
|
{ input: "email", key: "accountSender", credential: "SENDGRID_FROM_ADDRESS", label: "Account sender", message: "Verification codes and security alerts send from here.", required: true },
|
|
2211
|
-
{ input: "password", key: "apiKey", credential: "SENDGRID_API_KEY", label: "SendGrid API key", redact: true, required: true },
|
|
2211
|
+
{ input: "password", key: "apiKey", credential: "SENDGRID_API_KEY", label: "SendGrid API key", message: "SendGrid dashboard, Settings, API Keys \u2014 full access for sends.", redact: true, required: true },
|
|
2212
2212
|
// NOT required. The CRM sync is best-effort internal tooling and no-ops
|
|
2213
2213
|
// without a token — requiring it would make the whole drawbridge provider
|
|
2214
2214
|
// read not-live over something no merchant ever sees.
|
|
@@ -2228,8 +2228,8 @@ var drawbridge_default2 = {
|
|
|
2228
2228
|
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2229
2229
|
// hides the org's SMS settings entirely.
|
|
2230
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 }
|
|
2231
|
+
{ input: "password", key: "smsSid", credential: "TWILIO_ACCOUNT_SID", label: "Twilio account SID", message: "Twilio console home \u2014 the AC\u2026 identifier on the account dashboard.", redact: true },
|
|
2232
|
+
{ input: "password", key: "smsToken", credential: "TWILIO_AUTH_TOKEN", label: "Twilio auth token", message: "Beside the account SID on the Twilio console dashboard.", redact: true }
|
|
2233
2233
|
]
|
|
2234
2234
|
},
|
|
2235
2235
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -2819,8 +2819,8 @@ var klaviyo_default2 = {
|
|
|
2819
2819
|
// `requires` that names the same variables.
|
|
2820
2820
|
provider: {
|
|
2821
2821
|
fields: [
|
|
2822
|
-
{ input: "text", key: "clientId", credential: "KLAVIYO_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
2823
|
-
{ input: "password", key: "clientSecret", credential: "KLAVIYO_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
2822
|
+
{ input: "text", key: "clientId", credential: "KLAVIYO_OAUTH_CLIENT_ID", label: "Client ID", message: "From our app in the Klaviyo developer portal (developers.klaviyo.com).", required: true },
|
|
2823
|
+
{ input: "password", key: "clientSecret", credential: "KLAVIYO_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID on the Klaviyo app.", redact: true, required: true }
|
|
2824
2824
|
]
|
|
2825
2825
|
},
|
|
2826
2826
|
requires: [
|
|
@@ -3165,8 +3165,8 @@ var mailchimp_default2 = {
|
|
|
3165
3165
|
// same variables.
|
|
3166
3166
|
provider: {
|
|
3167
3167
|
fields: [
|
|
3168
|
-
{ input: "text", key: "clientId", credential: "MAILCHIMP_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
3169
|
-
{ input: "password", key: "clientSecret", credential: "MAILCHIMP_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
3168
|
+
{ input: "text", key: "clientId", credential: "MAILCHIMP_OAUTH_CLIENT_ID", label: "Client ID", message: "From our registered app \u2014 Mailchimp account, Extras, Registered apps.", required: true },
|
|
3169
|
+
{ input: "password", key: "clientSecret", credential: "MAILCHIMP_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID on the registered app.", redact: true, required: true }
|
|
3170
3170
|
]
|
|
3171
3171
|
},
|
|
3172
3172
|
// The OAuth client this deployment registered. Without both, the vendor drops
|
|
@@ -4119,24 +4119,32 @@ var shopify_default2 = {
|
|
|
4119
4119
|
if (partner.partnerToken && partner.partnerOrgId && partner.partnerAppId && (source == null ? void 0 : source.id) && ((_b = shopify.partner) == null ? void 0 : _b.getUsageChargeEvents)) {
|
|
4120
4120
|
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4121
4121
|
appId: "gid://shopify/App/" + partner.partnerAppId,
|
|
4122
|
-
first:
|
|
4122
|
+
first: 5,
|
|
4123
4123
|
occurredAtMin: new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString(),
|
|
4124
4124
|
organizationId: partner.partnerOrgId,
|
|
4125
4125
|
partnerToken: partner.partnerToken,
|
|
4126
4126
|
shopId: "gid://shopify/Shop/" + source.id
|
|
4127
4127
|
});
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4128
|
+
const accrued = accruals.find((event) => Number(event.usageQuantity) > 0);
|
|
4129
|
+
if (accrued) {
|
|
4130
|
+
metered = String(accrued.chargeId || accrued.id);
|
|
4131
|
+
writes.push({
|
|
4132
4132
|
collection: "order",
|
|
4133
|
+
data: {
|
|
4134
|
+
$set: { "billed.receipt": metered }
|
|
4135
|
+
},
|
|
4136
|
+
// Top-level, not an option — the controller takes
|
|
4137
|
+
// `multiple` beside `options`, and the shell
|
|
4138
|
+
// forwards it as such.
|
|
4139
|
+
multiple: true,
|
|
4140
|
+
operation: "update",
|
|
4133
4141
|
query: {
|
|
4134
|
-
"billed.date": { $
|
|
4142
|
+
"billed.date": { $gte: new Date(accrued.occurredAt || 0) },
|
|
4143
|
+
"billed.receipt": { $in: [null] },
|
|
4135
4144
|
organization: workflow.organization,
|
|
4136
4145
|
"provider.slug": "shopify"
|
|
4137
4146
|
}
|
|
4138
4147
|
});
|
|
4139
|
-
if (unaccrued) metered = null;
|
|
4140
4148
|
}
|
|
4141
4149
|
}
|
|
4142
4150
|
} catch (probeError) {
|
|
@@ -4358,10 +4366,10 @@ var shopify_default2 = {
|
|
|
4358
4366
|
// never go live from the admin screen.
|
|
4359
4367
|
provider: {
|
|
4360
4368
|
fields: [
|
|
4361
|
-
{ input: "text", key: "apiKey", credential: "SHOPIFY_API_KEY", label: "API key", required: true },
|
|
4362
|
-
{ input: "password", key: "apiSecret", credential: "SHOPIFY_API_SECRET", label: "API secret", redact: true, required: true },
|
|
4363
|
-
{ input: "text", key: "appHandle", credential: "SHOPIFY_APP_HANDLE", label: "App handle", required: true },
|
|
4364
|
-
{ input: "text", key: "listingUrl", credential: "SHOPIFY_APP_LISTING_URL", label: "App listing URL", required: true },
|
|
4369
|
+
{ input: "text", key: "apiKey", credential: "SHOPIFY_API_KEY", label: "API key", message: "The app's Client ID \u2014 Dev Dashboard, the app, Settings.", required: true },
|
|
4370
|
+
{ input: "password", key: "apiSecret", credential: "SHOPIFY_API_SECRET", label: "API secret", message: "The app's Client secret, beside the Client ID in the app's settings.", redact: true, required: true },
|
|
4371
|
+
{ input: "text", key: "appHandle", credential: "SHOPIFY_APP_HANDLE", label: "App handle", message: "The app's URL handle (for example drawbridge-development), from the app's configuration.", required: true },
|
|
4372
|
+
{ input: "text", key: "listingUrl", credential: "SHOPIFY_APP_LISTING_URL", label: "App listing URL", message: 'Where "View on the Shopify App Store" sends merchants \u2014 the public listing, or the Dev Dashboard install link for the dev app.', required: true },
|
|
4365
4373
|
// The usage meter's event handle, when the plan config's meter ever
|
|
4366
4374
|
// changes: stored value overrides the built-in default
|
|
4367
4375
|
// (events.order.handle) at the mint point, and `format : 'slug'`
|
|
@@ -4369,15 +4377,15 @@ var shopify_default2 = {
|
|
|
4369
4377
|
// and classification against it is case-sensitive. Optional: empty
|
|
4370
4378
|
// means the default, and the sender still refuses any handle that
|
|
4371
4379
|
// disagrees with the transaction it minted.
|
|
4372
|
-
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true },
|
|
4380
|
+
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", message: "Must match the usage meter's Handle field on the plan exactly \u2014 lowercase and hyphens. Leave empty to use drawbridge-orders.", required: false, setting: true },
|
|
4373
4381
|
// The Partner API credential set — the ONE place meter billing is
|
|
4374
4382
|
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
4375
4383
|
// id come from the Partner Dashboard; the token from Settings →
|
|
4376
4384
|
// Partner API clients (Manage-apps permission). All optional: the
|
|
4377
4385
|
// 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 }
|
|
4386
|
+
{ input: "text", key: "partnerOrgId", label: "Partner organization ID", message: "The number in the Partner Dashboard URL \u2014 partners.shopify.com/<this number>/\u2026 \u2014 NOT the admin organization_id from the app listing link.", required: false, setting: true },
|
|
4387
|
+
{ input: "text", key: "partnerAppId", label: "Partner app ID (numeric)", message: "The numeric id in the app's Partner Dashboard URL \u2014 not the Client ID.", required: false, setting: true },
|
|
4388
|
+
{ input: "password", key: "partnerToken", label: "Partner API token", message: "Partner Dashboard, Settings, Partner API clients \u2014 create one with Manage apps and paste the prtapi_ token.", redact: true, required: false, setting: true }
|
|
4381
4389
|
]
|
|
4382
4390
|
},
|
|
4383
4391
|
// A pre-launch integration: it only surfaces once the App Store listing
|
package/dist/providers.js
CHANGED
|
@@ -722,8 +722,8 @@ var attentive_default2 = {
|
|
|
722
722
|
// keep the stored value. `required` drives the live check.
|
|
723
723
|
provider: {
|
|
724
724
|
fields: [
|
|
725
|
-
{ input: "text", key: "clientId", credential: "ATTENTIVE_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
726
|
-
{ input: "password", key: "clientSecret", credential: "ATTENTIVE_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
725
|
+
{ input: "text", key: "clientId", credential: "ATTENTIVE_OAUTH_CLIENT_ID", label: "Client ID", message: "From our app's registration in the Attentive developer portal.", required: true },
|
|
726
|
+
{ input: "password", key: "clientSecret", credential: "ATTENTIVE_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID in the Attentive developer portal.", redact: true, required: true }
|
|
727
727
|
]
|
|
728
728
|
},
|
|
729
729
|
requires: [
|
|
@@ -2164,7 +2164,7 @@ var drawbridge_default2 = {
|
|
|
2164
2164
|
provider: {
|
|
2165
2165
|
fields: [
|
|
2166
2166
|
{ input: "email", key: "accountSender", credential: "SENDGRID_FROM_ADDRESS", label: "Account sender", message: "Verification codes and security alerts send from here.", required: true },
|
|
2167
|
-
{ input: "password", key: "apiKey", credential: "SENDGRID_API_KEY", label: "SendGrid API key", redact: true, required: true },
|
|
2167
|
+
{ input: "password", key: "apiKey", credential: "SENDGRID_API_KEY", label: "SendGrid API key", message: "SendGrid dashboard, Settings, API Keys \u2014 full access for sends.", redact: true, required: true },
|
|
2168
2168
|
// NOT required. The CRM sync is best-effort internal tooling and no-ops
|
|
2169
2169
|
// without a token — requiring it would make the whole drawbridge provider
|
|
2170
2170
|
// read not-live over something no merchant ever sees.
|
|
@@ -2184,8 +2184,8 @@ var drawbridge_default2 = {
|
|
|
2184
2184
|
// and logs), the number-purchase routes deny, and identityDefaults.sms
|
|
2185
2185
|
// hides the org's SMS settings entirely.
|
|
2186
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 }
|
|
2187
|
+
{ input: "password", key: "smsSid", credential: "TWILIO_ACCOUNT_SID", label: "Twilio account SID", message: "Twilio console home \u2014 the AC\u2026 identifier on the account dashboard.", redact: true },
|
|
2188
|
+
{ input: "password", key: "smsToken", credential: "TWILIO_AUTH_TOKEN", label: "Twilio auth token", message: "Beside the account SID on the Twilio console dashboard.", redact: true }
|
|
2189
2189
|
]
|
|
2190
2190
|
},
|
|
2191
2191
|
// NOTHING, and HUBSPOT_ACCESS_TOKEN in particular must not be here.
|
|
@@ -2775,8 +2775,8 @@ var klaviyo_default2 = {
|
|
|
2775
2775
|
// `requires` that names the same variables.
|
|
2776
2776
|
provider: {
|
|
2777
2777
|
fields: [
|
|
2778
|
-
{ input: "text", key: "clientId", credential: "KLAVIYO_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
2779
|
-
{ input: "password", key: "clientSecret", credential: "KLAVIYO_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
2778
|
+
{ input: "text", key: "clientId", credential: "KLAVIYO_OAUTH_CLIENT_ID", label: "Client ID", message: "From our app in the Klaviyo developer portal (developers.klaviyo.com).", required: true },
|
|
2779
|
+
{ input: "password", key: "clientSecret", credential: "KLAVIYO_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID on the Klaviyo app.", redact: true, required: true }
|
|
2780
2780
|
]
|
|
2781
2781
|
},
|
|
2782
2782
|
requires: [
|
|
@@ -3121,8 +3121,8 @@ var mailchimp_default2 = {
|
|
|
3121
3121
|
// same variables.
|
|
3122
3122
|
provider: {
|
|
3123
3123
|
fields: [
|
|
3124
|
-
{ input: "text", key: "clientId", credential: "MAILCHIMP_OAUTH_CLIENT_ID", label: "Client ID", required: true },
|
|
3125
|
-
{ input: "password", key: "clientSecret", credential: "MAILCHIMP_OAUTH_CLIENT_SECRET", label: "Client secret", redact: true, required: true }
|
|
3124
|
+
{ input: "text", key: "clientId", credential: "MAILCHIMP_OAUTH_CLIENT_ID", label: "Client ID", message: "From our registered app \u2014 Mailchimp account, Extras, Registered apps.", required: true },
|
|
3125
|
+
{ input: "password", key: "clientSecret", credential: "MAILCHIMP_OAUTH_CLIENT_SECRET", label: "Client secret", message: "Beside the Client ID on the registered app.", redact: true, required: true }
|
|
3126
3126
|
]
|
|
3127
3127
|
},
|
|
3128
3128
|
// The OAuth client this deployment registered. Without both, the vendor drops
|
|
@@ -4075,24 +4075,32 @@ var shopify_default2 = {
|
|
|
4075
4075
|
if (partner.partnerToken && partner.partnerOrgId && partner.partnerAppId && (source == null ? void 0 : source.id) && ((_b = shopify.partner) == null ? void 0 : _b.getUsageChargeEvents)) {
|
|
4076
4076
|
const accruals = await shopify.partner.getUsageChargeEvents({
|
|
4077
4077
|
appId: "gid://shopify/App/" + partner.partnerAppId,
|
|
4078
|
-
first:
|
|
4078
|
+
first: 5,
|
|
4079
4079
|
occurredAtMin: new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString(),
|
|
4080
4080
|
organizationId: partner.partnerOrgId,
|
|
4081
4081
|
partnerToken: partner.partnerToken,
|
|
4082
4082
|
shopId: "gid://shopify/Shop/" + source.id
|
|
4083
4083
|
});
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4084
|
+
const accrued = accruals.find((event) => Number(event.usageQuantity) > 0);
|
|
4085
|
+
if (accrued) {
|
|
4086
|
+
metered = String(accrued.chargeId || accrued.id);
|
|
4087
|
+
writes.push({
|
|
4088
4088
|
collection: "order",
|
|
4089
|
+
data: {
|
|
4090
|
+
$set: { "billed.receipt": metered }
|
|
4091
|
+
},
|
|
4092
|
+
// Top-level, not an option — the controller takes
|
|
4093
|
+
// `multiple` beside `options`, and the shell
|
|
4094
|
+
// forwards it as such.
|
|
4095
|
+
multiple: true,
|
|
4096
|
+
operation: "update",
|
|
4089
4097
|
query: {
|
|
4090
|
-
"billed.date": { $
|
|
4098
|
+
"billed.date": { $gte: new Date(accrued.occurredAt || 0) },
|
|
4099
|
+
"billed.receipt": { $in: [null] },
|
|
4091
4100
|
organization: workflow.organization,
|
|
4092
4101
|
"provider.slug": "shopify"
|
|
4093
4102
|
}
|
|
4094
4103
|
});
|
|
4095
|
-
if (unaccrued) metered = null;
|
|
4096
4104
|
}
|
|
4097
4105
|
}
|
|
4098
4106
|
} catch (probeError) {
|
|
@@ -4314,10 +4322,10 @@ var shopify_default2 = {
|
|
|
4314
4322
|
// never go live from the admin screen.
|
|
4315
4323
|
provider: {
|
|
4316
4324
|
fields: [
|
|
4317
|
-
{ input: "text", key: "apiKey", credential: "SHOPIFY_API_KEY", label: "API key", required: true },
|
|
4318
|
-
{ input: "password", key: "apiSecret", credential: "SHOPIFY_API_SECRET", label: "API secret", redact: true, required: true },
|
|
4319
|
-
{ input: "text", key: "appHandle", credential: "SHOPIFY_APP_HANDLE", label: "App handle", required: true },
|
|
4320
|
-
{ input: "text", key: "listingUrl", credential: "SHOPIFY_APP_LISTING_URL", label: "App listing URL", required: true },
|
|
4325
|
+
{ input: "text", key: "apiKey", credential: "SHOPIFY_API_KEY", label: "API key", message: "The app's Client ID \u2014 Dev Dashboard, the app, Settings.", required: true },
|
|
4326
|
+
{ input: "password", key: "apiSecret", credential: "SHOPIFY_API_SECRET", label: "API secret", message: "The app's Client secret, beside the Client ID in the app's settings.", redact: true, required: true },
|
|
4327
|
+
{ input: "text", key: "appHandle", credential: "SHOPIFY_APP_HANDLE", label: "App handle", message: "The app's URL handle (for example drawbridge-development), from the app's configuration.", required: true },
|
|
4328
|
+
{ input: "text", key: "listingUrl", credential: "SHOPIFY_APP_LISTING_URL", label: "App listing URL", message: 'Where "View on the Shopify App Store" sends merchants \u2014 the public listing, or the Dev Dashboard install link for the dev app.', required: true },
|
|
4321
4329
|
// The usage meter's event handle, when the plan config's meter ever
|
|
4322
4330
|
// changes: stored value overrides the built-in default
|
|
4323
4331
|
// (events.order.handle) at the mint point, and `format : 'slug'`
|
|
@@ -4325,15 +4333,15 @@ var shopify_default2 = {
|
|
|
4325
4333
|
// and classification against it is case-sensitive. Optional: empty
|
|
4326
4334
|
// means the default, and the sender still refuses any handle that
|
|
4327
4335
|
// disagrees with the transaction it minted.
|
|
4328
|
-
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true },
|
|
4336
|
+
{ format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", message: "Must match the usage meter's Handle field on the plan exactly \u2014 lowercase and hyphens. Leave empty to use drawbridge-orders.", required: false, setting: true },
|
|
4329
4337
|
// The Partner API credential set — the ONE place meter billing is
|
|
4330
4338
|
// observable (CHARGE_USAGE accrual events). Org id and numeric app
|
|
4331
4339
|
// id come from the Partner Dashboard; the token from Settings →
|
|
4332
4340
|
// Partner API clients (Manage-apps permission). All optional: the
|
|
4333
4341
|
// 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 }
|
|
4342
|
+
{ input: "text", key: "partnerOrgId", label: "Partner organization ID", message: "The number in the Partner Dashboard URL \u2014 partners.shopify.com/<this number>/\u2026 \u2014 NOT the admin organization_id from the app listing link.", required: false, setting: true },
|
|
4343
|
+
{ input: "text", key: "partnerAppId", label: "Partner app ID (numeric)", message: "The numeric id in the app's Partner Dashboard URL \u2014 not the Client ID.", required: false, setting: true },
|
|
4344
|
+
{ input: "password", key: "partnerToken", label: "Partner API token", message: "Partner Dashboard, Settings, Partner API clients \u2014 create one with Manage apps and paste the prtapi_ token.", redact: true, required: false, setting: true }
|
|
4337
4345
|
]
|
|
4338
4346
|
},
|
|
4339
4347
|
// A pre-launch integration: it only surfaces once the App Store listing
|
package/package.json
CHANGED