@drawbridge/drawbridge-utils 0.0.148 → 0.0.150

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.
@@ -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,14 +4194,15 @@ 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: 1,
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
- if (accruals.length) {
4204
- metered = String(accruals[0].chargeId || accruals[0].id);
4203
+ const accrued = accruals.find((event) => Number(event.usageQuantity) > 0);
4204
+ if (accrued) {
4205
+ metered = String(accrued.chargeId || accrued.id);
4205
4206
  } else {
4206
4207
  const unaccrued = await read.get({
4207
4208
  collection: "order",
@@ -4433,10 +4434,10 @@ var shopify_default2 = {
4433
4434
  // never go live from the admin screen.
4434
4435
  provider: {
4435
4436
  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 },
4437
+ { 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 },
4438
+ { 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 },
4439
+ { 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 },
4440
+ { 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
4441
  // The usage meter's event handle, when the plan config's meter ever
4441
4442
  // changes: stored value overrides the built-in default
4442
4443
  // (events.order.handle) at the mint point, and `format : 'slug'`
@@ -4444,15 +4445,15 @@ var shopify_default2 = {
4444
4445
  // and classification against it is case-sensitive. Optional: empty
4445
4446
  // means the default, and the sender still refuses any handle that
4446
4447
  // disagrees with the transaction it minted.
4447
- { format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true },
4448
+ { 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
4449
  // The Partner API credential set — the ONE place meter billing is
4449
4450
  // observable (CHARGE_USAGE accrual events). Org id and numeric app
4450
4451
  // id come from the Partner Dashboard; the token from Settings →
4451
4452
  // Partner API clients (Manage-apps permission). All optional: the
4452
4453
  // 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 }
4454
+ { 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 },
4455
+ { 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 },
4456
+ { 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
4457
  ]
4457
4458
  },
4458
4459
  // 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,16 +4983,21 @@ var shopify = {
4983
4983
 
4984
4984
  const accruals = await shopify.partner.getUsageChargeEvents({
4985
4985
  appId : 'gid://shopify/App/' + partner.partnerAppId,
4986
- first : 1,
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
- if( accruals.length ){
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
- metered = String( accruals[ 0 ].chargeId || accruals[ 0 ].id );
4998
+ if( accrued ){
4999
+
5000
+ metered = String( accrued.chargeId || accrued.id );
4996
5001
 
4997
5002
  } else {
4998
5003
 
@@ -5310,10 +5315,10 @@ var shopify = {
5310
5315
  // never go live from the admin screen.
5311
5316
  provider : {
5312
5317
  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 },
5318
+ { input : 'text', key : 'apiKey', credential : 'SHOPIFY_API_KEY', label : 'API key', message : 'The app\'s Client ID — Dev Dashboard, the app, Settings.', required : true },
5319
+ { 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 },
5320
+ { 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 },
5321
+ { 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
5322
  // The usage meter's event handle, when the plan config's meter ever
5318
5323
  // changes: stored value overrides the built-in default
5319
5324
  // (events.order.handle) at the mint point, and `format : 'slug'`
@@ -5321,15 +5326,15 @@ var shopify = {
5321
5326
  // and classification against it is case-sensitive. Optional: empty
5322
5327
  // means the default, and the sender still refuses any handle that
5323
5328
  // disagrees with the transaction it minted.
5324
- { format : 'slug', input : 'text', key : 'orderEventHandle', label : 'Order event handle', required : false, setting : true },
5329
+ { 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
5330
  // The Partner API credential set — the ONE place meter billing is
5326
5331
  // observable (CHARGE_USAGE accrual events). Org id and numeric app
5327
5332
  // id come from the Partner Dashboard; the token from Settings →
5328
5333
  // Partner API clients (Manage-apps permission). All optional: the
5329
5334
  // 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 }
5335
+ { 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 },
5336
+ { 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 },
5337
+ { 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
5338
  ]
5334
5339
  },
5335
5340
  // 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,16 +4983,21 @@ var shopify = {
4983
4983
 
4984
4984
  const accruals = await shopify.partner.getUsageChargeEvents({
4985
4985
  appId : 'gid://shopify/App/' + partner.partnerAppId,
4986
- first : 1,
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
- if( accruals.length ){
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
- metered = String( accruals[ 0 ].chargeId || accruals[ 0 ].id );
4998
+ if( accrued ){
4999
+
5000
+ metered = String( accrued.chargeId || accrued.id );
4996
5001
 
4997
5002
  } else {
4998
5003
 
@@ -5310,10 +5315,10 @@ var shopify = {
5310
5315
  // never go live from the admin screen.
5311
5316
  provider : {
5312
5317
  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 },
5318
+ { input : 'text', key : 'apiKey', credential : 'SHOPIFY_API_KEY', label : 'API key', message : 'The app\'s Client ID — Dev Dashboard, the app, Settings.', required : true },
5319
+ { 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 },
5320
+ { 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 },
5321
+ { 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
5322
  // The usage meter's event handle, when the plan config's meter ever
5318
5323
  // changes: stored value overrides the built-in default
5319
5324
  // (events.order.handle) at the mint point, and `format : 'slug'`
@@ -5321,15 +5326,15 @@ var shopify = {
5321
5326
  // and classification against it is case-sensitive. Optional: empty
5322
5327
  // means the default, and the sender still refuses any handle that
5323
5328
  // disagrees with the transaction it minted.
5324
- { format : 'slug', input : 'text', key : 'orderEventHandle', label : 'Order event handle', required : false, setting : true },
5329
+ { 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
5330
  // The Partner API credential set — the ONE place meter billing is
5326
5331
  // observable (CHARGE_USAGE accrual events). Org id and numeric app
5327
5332
  // id come from the Partner Dashboard; the token from Settings →
5328
5333
  // Partner API clients (Manage-apps permission). All optional: the
5329
5334
  // 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 }
5335
+ { 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 },
5336
+ { 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 },
5337
+ { 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
5338
  ]
5334
5339
  },
5335
5340
  // 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,14 +4120,15 @@ 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: 1,
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
- if (accruals.length) {
4130
- metered = String(accruals[0].chargeId || accruals[0].id);
4129
+ const accrued = accruals.find((event) => Number(event.usageQuantity) > 0);
4130
+ if (accrued) {
4131
+ metered = String(accrued.chargeId || accrued.id);
4131
4132
  } else {
4132
4133
  const unaccrued = await read.get({
4133
4134
  collection: "order",
@@ -4359,10 +4360,10 @@ var shopify_default2 = {
4359
4360
  // never go live from the admin screen.
4360
4361
  provider: {
4361
4362
  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 },
4363
+ { 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 },
4364
+ { 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 },
4365
+ { 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 },
4366
+ { 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
4367
  // The usage meter's event handle, when the plan config's meter ever
4367
4368
  // changes: stored value overrides the built-in default
4368
4369
  // (events.order.handle) at the mint point, and `format : 'slug'`
@@ -4370,15 +4371,15 @@ var shopify_default2 = {
4370
4371
  // and classification against it is case-sensitive. Optional: empty
4371
4372
  // means the default, and the sender still refuses any handle that
4372
4373
  // disagrees with the transaction it minted.
4373
- { format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true },
4374
+ { 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
4375
  // The Partner API credential set — the ONE place meter billing is
4375
4376
  // observable (CHARGE_USAGE accrual events). Org id and numeric app
4376
4377
  // id come from the Partner Dashboard; the token from Settings →
4377
4378
  // Partner API clients (Manage-apps permission). All optional: the
4378
4379
  // 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 }
4380
+ { 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 },
4381
+ { 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 },
4382
+ { 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
4383
  ]
4383
4384
  },
4384
4385
  // A pre-launch integration: it only surfaces once the App Store listing
@@ -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,14 +4119,15 @@ 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: 1,
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
- if (accruals.length) {
4129
- metered = String(accruals[0].chargeId || accruals[0].id);
4128
+ const accrued = accruals.find((event) => Number(event.usageQuantity) > 0);
4129
+ if (accrued) {
4130
+ metered = String(accrued.chargeId || accrued.id);
4130
4131
  } else {
4131
4132
  const unaccrued = await read.get({
4132
4133
  collection: "order",
@@ -4358,10 +4359,10 @@ var shopify_default2 = {
4358
4359
  // never go live from the admin screen.
4359
4360
  provider: {
4360
4361
  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 },
4362
+ { 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 },
4363
+ { 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 },
4364
+ { 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 },
4365
+ { 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
4366
  // The usage meter's event handle, when the plan config's meter ever
4366
4367
  // changes: stored value overrides the built-in default
4367
4368
  // (events.order.handle) at the mint point, and `format : 'slug'`
@@ -4369,15 +4370,15 @@ var shopify_default2 = {
4369
4370
  // and classification against it is case-sensitive. Optional: empty
4370
4371
  // means the default, and the sender still refuses any handle that
4371
4372
  // disagrees with the transaction it minted.
4372
- { 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", 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
4374
  // The Partner API credential set — the ONE place meter billing is
4374
4375
  // observable (CHARGE_USAGE accrual events). Org id and numeric app
4375
4376
  // id come from the Partner Dashboard; the token from Settings →
4376
4377
  // Partner API clients (Manage-apps permission). All optional: the
4377
4378
  // 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 }
4379
+ { 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 },
4380
+ { 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 },
4381
+ { 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
4382
  ]
4382
4383
  },
4383
4384
  // 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,14 +4075,15 @@ 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: 1,
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
- if (accruals.length) {
4085
- metered = String(accruals[0].chargeId || accruals[0].id);
4084
+ const accrued = accruals.find((event) => Number(event.usageQuantity) > 0);
4085
+ if (accrued) {
4086
+ metered = String(accrued.chargeId || accrued.id);
4086
4087
  } else {
4087
4088
  const unaccrued = await read.get({
4088
4089
  collection: "order",
@@ -4314,10 +4315,10 @@ var shopify_default2 = {
4314
4315
  // never go live from the admin screen.
4315
4316
  provider: {
4316
4317
  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 },
4318
+ { 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 },
4319
+ { 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 },
4320
+ { 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 },
4321
+ { 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
4322
  // The usage meter's event handle, when the plan config's meter ever
4322
4323
  // changes: stored value overrides the built-in default
4323
4324
  // (events.order.handle) at the mint point, and `format : 'slug'`
@@ -4325,15 +4326,15 @@ var shopify_default2 = {
4325
4326
  // and classification against it is case-sensitive. Optional: empty
4326
4327
  // means the default, and the sender still refuses any handle that
4327
4328
  // disagrees with the transaction it minted.
4328
- { format: "slug", input: "text", key: "orderEventHandle", label: "Order event handle", required: false, setting: true },
4329
+ { 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
4330
  // The Partner API credential set — the ONE place meter billing is
4330
4331
  // observable (CHARGE_USAGE accrual events). Org id and numeric app
4331
4332
  // id come from the Partner Dashboard; the token from Settings →
4332
4333
  // Partner API clients (Manage-apps permission). All optional: the
4333
4334
  // 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 }
4335
+ { 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 },
4336
+ { 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 },
4337
+ { 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
4338
  ]
4338
4339
  },
4339
4340
  // A pre-launch integration: it only surfaces once the App Store listing
package/package.json CHANGED
@@ -216,5 +216,5 @@
216
216
  "prepublishOnly": ". \"$HOME/.nvm/nvm.sh\" && nvm use && tsup && node --test"
217
217
  },
218
218
  "types": "dist/index.d.ts",
219
- "version": "0.0.148"
219
+ "version": "0.0.150"
220
220
  }