@drawbridge/drawbridge-utils 0.0.136 → 0.0.139
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 +175 -29
- package/dist/connections/index.d.cts +230 -15
- package/dist/connections/index.d.ts +230 -15
- package/dist/connections/index.js +175 -29
- package/dist/providers.cjs +181 -35
- package/dist/providers.d.cts +2 -0
- package/dist/providers.d.ts +2 -0
- package/dist/providers.js +181 -35
- package/package.json +1 -1
package/dist/providers.js
CHANGED
|
@@ -501,6 +501,9 @@ var attentive_default2 = {
|
|
|
501
501
|
},
|
|
502
502
|
// A contact destination, like Klaviyo and Mailchimp — a merchant could
|
|
503
503
|
// reasonably keep several up to date at once.
|
|
504
|
+
// No vendor-facing event identities — declared empty so the contract stays
|
|
505
|
+
// explicit: a vendor that gains one adds it here, never as a side channel.
|
|
506
|
+
events: {},
|
|
504
507
|
exclusive: false,
|
|
505
508
|
feature: "organization:connection:attentive",
|
|
506
509
|
fields: [
|
|
@@ -1681,6 +1684,9 @@ var drawbridge_default2 = {
|
|
|
1681
1684
|
"Nothing to do. These steps are available in every workflow builder."
|
|
1682
1685
|
]
|
|
1683
1686
|
},
|
|
1687
|
+
// No vendor-facing event identities — declared empty so the contract stays
|
|
1688
|
+
// explicit: a vendor that gains one adds it here, never as a side channel.
|
|
1689
|
+
events: {},
|
|
1684
1690
|
exclusive: false,
|
|
1685
1691
|
fields: [],
|
|
1686
1692
|
group: "developer",
|
|
@@ -2465,6 +2471,9 @@ var klaviyo_default2 = {
|
|
|
2465
2471
|
// current — so the exclusivity that once applied when these were SENDERS is
|
|
2466
2472
|
// deliberately gone. That was removed once already; declaring it out loud is
|
|
2467
2473
|
// what stops it coming back by inference.
|
|
2474
|
+
// No vendor-facing event identities — declared empty so the contract stays
|
|
2475
|
+
// explicit: a vendor that gains one adds it here, never as a side channel.
|
|
2476
|
+
events: {},
|
|
2468
2477
|
exclusive: false,
|
|
2469
2478
|
feature: "organization:connection:klaviyo",
|
|
2470
2479
|
fields: [
|
|
@@ -2941,6 +2950,9 @@ var mailchimp_default2 = {
|
|
|
2941
2950
|
// picking two providers to send the same mail was meaningless. As contact
|
|
2942
2951
|
// syncs they are destinations, and a merchant could reasonably keep several
|
|
2943
2952
|
// up to date, so the exclusivity is gone.
|
|
2953
|
+
// No vendor-facing event identities — declared empty so the contract stays
|
|
2954
|
+
// explicit: a vendor that gains one adds it here, never as a side channel.
|
|
2955
|
+
events: {},
|
|
2944
2956
|
exclusive: false,
|
|
2945
2957
|
feature: "organization:connection:mailchimp",
|
|
2946
2958
|
fields: [
|
|
@@ -3216,6 +3228,22 @@ var toCanonicalEmail = (value) => {
|
|
|
3216
3228
|
return local + "@" + domain;
|
|
3217
3229
|
};
|
|
3218
3230
|
|
|
3231
|
+
// lib/slugify.js
|
|
3232
|
+
import slug from "slugify";
|
|
3233
|
+
var slugify = (value, nochars = false) => {
|
|
3234
|
+
const remove = nochars ? /[-?*+~.()'"!:@#^_{}\[\];,/\\]/g : /[?*+~.()'"!:@#^_{}\[\];,/\\]/g;
|
|
3235
|
+
const replacement = nochars ? "" : "-";
|
|
3236
|
+
return slug(
|
|
3237
|
+
value,
|
|
3238
|
+
{
|
|
3239
|
+
remove,
|
|
3240
|
+
replacement,
|
|
3241
|
+
lower: true,
|
|
3242
|
+
trim: true
|
|
3243
|
+
}
|
|
3244
|
+
);
|
|
3245
|
+
};
|
|
3246
|
+
|
|
3219
3247
|
// lib/connections/providers/shopify.js
|
|
3220
3248
|
var toLine = ({
|
|
3221
3249
|
price,
|
|
@@ -3251,6 +3279,7 @@ var attributeLineItems = (lineItems = []) => lineItems.reduce(
|
|
|
3251
3279
|
{ attrMap: {}, attributedGross: 0, attributedLines: [] }
|
|
3252
3280
|
);
|
|
3253
3281
|
var generateDiscountCode = customAlphabet2("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 8);
|
|
3282
|
+
var ORDER_EVENT_HANDLE = slugify("drawbridge-orders");
|
|
3254
3283
|
var REFRESH_TOKEN_FRESHNESS_BUFFER_MS = 5 * 24 * 60 * 60 * 1e3;
|
|
3255
3284
|
var OAUTH_ERROR_SOURCE = "oauth";
|
|
3256
3285
|
var OAUTH_GRANT_REVOKED_CODES = ["application_cannot_be_found", "invalid_grant"];
|
|
@@ -3308,7 +3337,7 @@ var shopify_default2 = {
|
|
|
3308
3337
|
guide: [
|
|
3309
3338
|
"Open the Drawbridge listing on the Shopify App Store.",
|
|
3310
3339
|
"Install the app on the store you want to connect. It opens in Shopify admin and stays there.",
|
|
3311
|
-
"
|
|
3340
|
+
"Approve the Drawbridge plan when prompted \u2014 during install, or from the connection page here. The connection shows Pending until you do, then Active.",
|
|
3312
3341
|
"Come back here \u2014 the connections list updates on its own once the install lands."
|
|
3313
3342
|
],
|
|
3314
3343
|
// Names where the link GOES rather than what it does: installing happens on
|
|
@@ -3322,6 +3351,29 @@ var shopify_default2 = {
|
|
|
3322
3351
|
// ONE STORE PER ORGANIZATION. Two Shopify stores on one org would give every
|
|
3323
3352
|
// attributed order two possible sources.
|
|
3324
3353
|
exclusive: true,
|
|
3354
|
+
// VENDOR-FACING EVENT IDENTITY, published so readers outside this package
|
|
3355
|
+
// (drawbridge-sync's usage queue, an operator checking the Dev Dashboard)
|
|
3356
|
+
// see the same handle the order hook mints into transactions and enqueues.
|
|
3357
|
+
events: {
|
|
3358
|
+
order: {
|
|
3359
|
+
handle: ORDER_EVENT_HANDLE,
|
|
3360
|
+
// THE SUBSCRIPTION THE APP MINTS FOR ITSELF (Billing API, not the
|
|
3361
|
+
// managed-pricing meter system): a $0 recurring line plus this usage
|
|
3362
|
+
// line, approved by the org owner at Shopify's confirmation screen.
|
|
3363
|
+
// `terms` is the merchant-visible consent copy; "up to" because the
|
|
3364
|
+
// actual rate is plan-derived (conversionRate) and must never exceed
|
|
3365
|
+
// what was approved. cappedAmount bounds one 30-day cycle's usage
|
|
3366
|
+
// charges — a record beyond it errors until the merchant raises it.
|
|
3367
|
+
// ponytail: $1,000 cap ≈ $66k attributed revenue/cycle at 1.5%; raise
|
|
3368
|
+
// via a re-approved subscription when a merchant outgrows it.
|
|
3369
|
+
pricing: {
|
|
3370
|
+
cappedAmount: 1e3,
|
|
3371
|
+
currency: "usd",
|
|
3372
|
+
name: "Drawbridge Orders",
|
|
3373
|
+
terms: "Up to 1.5% of revenue from orders attributed to Drawbridge campaigns"
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
},
|
|
3325
3377
|
feature: "organization:connection:shopify",
|
|
3326
3378
|
fields: [
|
|
3327
3379
|
{
|
|
@@ -3507,7 +3559,7 @@ var shopify_default2 = {
|
|
|
3507
3559
|
// for one purchase. The hook used to loop for this itself; describing
|
|
3508
3560
|
// the writes moved the retry to the queue, with the same guarantee.
|
|
3509
3561
|
order: async ({ connection: connection2, context }, { logger: logger2, mintId, read } = {}) => {
|
|
3510
|
-
var _a, _b, _c, _d, _e, _f;
|
|
3562
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
3511
3563
|
const {
|
|
3512
3564
|
advertisement,
|
|
3513
3565
|
created_at: createdAt,
|
|
@@ -3749,8 +3801,26 @@ var shopify_default2 = {
|
|
|
3749
3801
|
});
|
|
3750
3802
|
}
|
|
3751
3803
|
}
|
|
3752
|
-
const
|
|
3804
|
+
const billable = (org == null ? void 0 : org.billingProvider) === "shopify" && fee > 0 && !backfill;
|
|
3805
|
+
if (billable && !((_f = connection2 == null ? void 0 : connection2.source) == null ? void 0 : _f.id)) {
|
|
3806
|
+
(_g = logger2 == null ? void 0 : logger2.error) == null ? void 0 : _g.call(logger2, new Error(
|
|
3807
|
+
"shopify.usage.billing.skipped on order " + orderId + ": " + Math.round(fee * 100) + " cents not billed \u2014 connection " + (connection2 == null ? void 0 : connection2.id) + " has no source.id"
|
|
3808
|
+
), {
|
|
3809
|
+
extra: {
|
|
3810
|
+
connectionId: connection2 == null ? void 0 : connection2.id,
|
|
3811
|
+
fee,
|
|
3812
|
+
orderDocId,
|
|
3813
|
+
orderId: String(orderId)
|
|
3814
|
+
}
|
|
3815
|
+
});
|
|
3816
|
+
}
|
|
3817
|
+
const enqueues = billable && ((_h = connection2 == null ? void 0 : connection2.source) == null ? void 0 : _h.id) ? [{
|
|
3753
3818
|
data: {
|
|
3819
|
+
// The meter handle travels WITH the job so the sender can
|
|
3820
|
+
// verify it against the transaction prefix and refuse a
|
|
3821
|
+
// drifted pair — idempotency keys are permanent, so a
|
|
3822
|
+
// mistraceable event can never be resent under its own key.
|
|
3823
|
+
handle: ORDER_EVENT_HANDLE,
|
|
3754
3824
|
idempotencyKey: String(orderId),
|
|
3755
3825
|
orderDocId,
|
|
3756
3826
|
orderId: String(orderId),
|
|
@@ -3760,7 +3830,7 @@ var shopify_default2 = {
|
|
|
3760
3830
|
// here — the event handle plus the order id — and sent as the
|
|
3761
3831
|
// event's `reference`. queue/usage.js stamps the same id onto
|
|
3762
3832
|
// the order as billed.transaction.
|
|
3763
|
-
transaction: "
|
|
3833
|
+
transaction: ORDER_EVENT_HANDLE + "." + orderId,
|
|
3764
3834
|
value: Math.round(fee * 100)
|
|
3765
3835
|
},
|
|
3766
3836
|
name: "billing",
|
|
@@ -3903,7 +3973,8 @@ var shopify_default2 = {
|
|
|
3903
3973
|
// access token still works, reconciles the scopes the store granted
|
|
3904
3974
|
// against the ones the app now needs, and queues a webhook
|
|
3905
3975
|
// reconciliation.
|
|
3906
|
-
health: async ({ connection: connection2, workflow }, { adminToken, read, reconcileScopes, resolveSettings, rotateToken, shopify } = {}) => {
|
|
3976
|
+
health: async ({ connection: connection2, workflow }, { adminToken, logger: logger2, read, reconcileScopes, resolveSettings, rotateToken, shopify } = {}) => {
|
|
3977
|
+
var _a, _b;
|
|
3907
3978
|
const request2 = {
|
|
3908
3979
|
connectionId: workflow.connection,
|
|
3909
3980
|
organizationId: workflow.organization,
|
|
@@ -3922,7 +3993,50 @@ var shopify_default2 = {
|
|
|
3922
3993
|
}
|
|
3923
3994
|
await shopify.oauth.ping({ adminAccessToken, domain: connection2.shop });
|
|
3924
3995
|
const scopesMissing = await reconcileScopes({ shop: connection2.shop });
|
|
3996
|
+
const writes = [];
|
|
3997
|
+
let source = connection2.source || null;
|
|
3998
|
+
let sourceRepaired = false;
|
|
3999
|
+
let metered = (source == null ? void 0 : source.metered) ?? null;
|
|
4000
|
+
let shopCurrency = null;
|
|
4001
|
+
let billingProbeFailed = false;
|
|
4002
|
+
try {
|
|
4003
|
+
if (!(source == null ? void 0 : source.id)) {
|
|
4004
|
+
const shopData = await shopify.oauth.getShop({ adminAccessToken, shop: connection2.shop });
|
|
4005
|
+
source = {
|
|
4006
|
+
domain: shopData.myshopifyDomain,
|
|
4007
|
+
id: String(shopData.id),
|
|
4008
|
+
label: shopData.name
|
|
4009
|
+
};
|
|
4010
|
+
shopCurrency = String(shopData.currency || "").toLowerCase() || null;
|
|
4011
|
+
sourceRepaired = true;
|
|
4012
|
+
}
|
|
4013
|
+
const { subscriptions } = await shopify.admin.getActiveAppSubscriptions({
|
|
4014
|
+
adminAccessToken,
|
|
4015
|
+
domain: connection2.shop
|
|
4016
|
+
});
|
|
4017
|
+
if (subscriptions.length && subscriptions.every((subscription) => typeof subscription.metered === "boolean")) {
|
|
4018
|
+
metered = subscriptions.some((subscription) => subscription.metered);
|
|
4019
|
+
}
|
|
4020
|
+
} catch (probeError) {
|
|
4021
|
+
billingProbeFailed = true;
|
|
4022
|
+
(_a = logger2 == null ? void 0 : logger2.warn) == null ? void 0 : _a.call(logger2, "shopify.health.billing.probe.failed", {
|
|
4023
|
+
connectionId: connection2.id,
|
|
4024
|
+
message: probeError == null ? void 0 : probeError.message,
|
|
4025
|
+
shop: connection2.shop
|
|
4026
|
+
});
|
|
4027
|
+
}
|
|
4028
|
+
if (sourceRepaired || metered !== null && metered !== (((_b = connection2.source) == null ? void 0 : _b.metered) ?? null)) {
|
|
4029
|
+
writes.push({
|
|
4030
|
+
collection: "connection",
|
|
4031
|
+
data: {
|
|
4032
|
+
$set: sourceRepaired ? { source: { ...source, ...metered !== null && { metered } } } : { "source.metered": metered }
|
|
4033
|
+
},
|
|
4034
|
+
operation: "update",
|
|
4035
|
+
query: { id: connection2.id }
|
|
4036
|
+
});
|
|
4037
|
+
}
|
|
3925
4038
|
return {
|
|
4039
|
+
writes,
|
|
3926
4040
|
enqueues: [{
|
|
3927
4041
|
data: {
|
|
3928
4042
|
data: {
|
|
@@ -3935,13 +4049,19 @@ var shopify_default2 = {
|
|
|
3935
4049
|
options: { jobId: "connection.update.register." + workflow.connection + "." + randomUUID() },
|
|
3936
4050
|
queue: "connection"
|
|
3937
4051
|
}],
|
|
3938
|
-
message: (scopesMissing == null ? void 0 : scopesMissing.length) ? "Health check: ping ok, webhooks reconciled \u2014 connection errored, granted scopes are missing: " + scopesMissing.join(", ") + "." : refreshTokenRotated ? "Health check passed \u2014 refresh token rotated, ping ok, webhooks reconciled." : "Health check passed \u2014 ping ok, webhooks reconciled.",
|
|
4052
|
+
message: ((scopesMissing == null ? void 0 : scopesMissing.length) ? "Health check: ping ok, webhooks reconciled \u2014 connection errored, granted scopes are missing: " + scopesMissing.join(", ") + "." : refreshTokenRotated ? "Health check passed \u2014 refresh token rotated, ping ok, webhooks reconciled." : "Health check passed \u2014 ping ok, webhooks reconciled.") + (sourceRepaired ? " Billing source repaired from the live shop." : "") + (metered === false ? " No usage line on the store's approved plan \u2014 order billing needs the merchant to approve the updated plan." : ""),
|
|
3939
4053
|
request: request2,
|
|
3940
4054
|
response: {
|
|
4055
|
+
billingProbeFailed,
|
|
4056
|
+
metered,
|
|
3941
4057
|
pingedAt: /* @__PURE__ */ new Date(),
|
|
3942
4058
|
refreshTokenExpiresAt: refreshTokenExpiresAt || null,
|
|
3943
4059
|
refreshTokenRotated,
|
|
3944
4060
|
scopesMissing,
|
|
4061
|
+
// The live settlement currency, for an operator — never
|
|
4062
|
+
// written, see above.
|
|
4063
|
+
...shopCurrency && { shopCurrency },
|
|
4064
|
+
sourceRepaired,
|
|
3945
4065
|
webhookReconciliationQueued: true
|
|
3946
4066
|
}
|
|
3947
4067
|
};
|
|
@@ -4209,12 +4329,35 @@ var shopify_default2 = {
|
|
|
4209
4329
|
//
|
|
4210
4330
|
// Scope drift is NOT here: drawbridge-sync writes it onto the connection
|
|
4211
4331
|
// document, and the document's own warnings render beside these.
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4332
|
+
// Both cards carry `action : 'billing'`: the dashboard renders it as a real
|
|
4333
|
+
// button that mints the corrective subscription (POST .../billing) and sends
|
|
4334
|
+
// the owner to Shopify's confirmation screen — the fix lives in OUR
|
|
4335
|
+
// dashboard, and the one Shopify-hosted step is the charge consent no app
|
|
4336
|
+
// can perform for a merchant.
|
|
4337
|
+
tasks: (data2) => {
|
|
4338
|
+
var _a;
|
|
4339
|
+
return [
|
|
4340
|
+
...(data2 == null ? void 0 : data2.status) === "pending" ? [
|
|
4341
|
+
{
|
|
4342
|
+
action: "billing",
|
|
4343
|
+
message: "Approve the Drawbridge plan to activate this connection. You'll confirm the pricing on Shopify, then everything else happens here.",
|
|
4344
|
+
title: "Approve your plan"
|
|
4345
|
+
}
|
|
4346
|
+
] : [],
|
|
4347
|
+
// The store's ACTIVE approval carries no usage component — stamped by
|
|
4348
|
+
// the daily health check and the approval webhook (`source.metered`).
|
|
4349
|
+
// Approved pricing is never retroactive, so the fix is a fresh approval.
|
|
4350
|
+
// Gated on an EXPLICIT false — a connection the probe hasn't reached
|
|
4351
|
+
// (or couldn't read) shows nothing rather than nagging on silence.
|
|
4352
|
+
...(data2 == null ? void 0 : data2.status) === "active" && ((_a = data2 == null ? void 0 : data2.source) == null ? void 0 : _a.metered) === false ? [
|
|
4353
|
+
{
|
|
4354
|
+
action: "billing",
|
|
4355
|
+
message: "Order billing isn't set up for this store, so campaign-attributed orders aren't being charged. Approve the updated plan to fix it \u2014 one click here, one confirmation on Shopify.",
|
|
4356
|
+
title: "Fix order billing"
|
|
4357
|
+
}
|
|
4358
|
+
] : []
|
|
4359
|
+
];
|
|
4360
|
+
},
|
|
4218
4361
|
title: "Shopify"
|
|
4219
4362
|
};
|
|
4220
4363
|
|
|
@@ -4388,6 +4531,9 @@ var webhook_default = {
|
|
|
4388
4531
|
// Nothing to be exclusive with — there is no second webhook vendor, and a
|
|
4389
4532
|
// merchant with two endpoints is a step-level choice rather than a second
|
|
4390
4533
|
// connection.
|
|
4534
|
+
// No vendor-facing event identities — declared empty so the contract stays
|
|
4535
|
+
// explicit: a vendor that gains one adds it here, never as a side channel.
|
|
4536
|
+
events: {},
|
|
4391
4537
|
exclusive: false,
|
|
4392
4538
|
feature: "organization:connection:webhook",
|
|
4393
4539
|
fields: [
|
|
@@ -4674,22 +4820,22 @@ var connections = Object.freeze({
|
|
|
4674
4820
|
(() => {
|
|
4675
4821
|
var _a;
|
|
4676
4822
|
const routes = {};
|
|
4677
|
-
for (const [
|
|
4823
|
+
for (const [slug2, manifest] of Object.entries(connections)) {
|
|
4678
4824
|
for (const [name, step] of leaves(manifest.steps)) {
|
|
4679
4825
|
const type = "step." + name;
|
|
4680
4826
|
const queue = (_a = step({})) == null ? void 0 : _a.queue;
|
|
4681
4827
|
if (routes[type] && routes[type].queue !== queue) {
|
|
4682
4828
|
throw new Error(
|
|
4683
|
-
"Step " + type + " routes to " + routes[type].queue + " for " + routes[type].slug + " and " + queue + " for " +
|
|
4829
|
+
"Step " + type + " routes to " + routes[type].queue + " for " + routes[type].slug + " and " + queue + " for " + slug2 + " \u2014 one of them would be enqueued nowhere"
|
|
4684
4830
|
);
|
|
4685
4831
|
}
|
|
4686
|
-
routes[type] = { queue, slug };
|
|
4832
|
+
routes[type] = { queue, slug: slug2 };
|
|
4687
4833
|
}
|
|
4688
4834
|
}
|
|
4689
4835
|
})();
|
|
4690
4836
|
var publicSettingsBySlug = Object.fromEntries(
|
|
4691
|
-
Object.entries(connections).map(([
|
|
4692
|
-
|
|
4837
|
+
Object.entries(connections).map(([slug2, manifest]) => [
|
|
4838
|
+
slug2,
|
|
4693
4839
|
manifest.fields.filter((field2) => !field2.redact).map((field2) => field2.key)
|
|
4694
4840
|
])
|
|
4695
4841
|
);
|
|
@@ -4777,13 +4923,13 @@ var decrypt = (value) => {
|
|
|
4777
4923
|
};
|
|
4778
4924
|
|
|
4779
4925
|
// lib/providers.js
|
|
4780
|
-
var providerFields = (
|
|
4926
|
+
var providerFields = (slug2) => {
|
|
4781
4927
|
var _a;
|
|
4782
|
-
return Object.hasOwn(connections,
|
|
4928
|
+
return Object.hasOwn(connections, slug2) ? ((_a = connections[slug2].provider) == null ? void 0 : _a.fields) || [] : [];
|
|
4783
4929
|
};
|
|
4784
|
-
var providerSlugs = () => Object.keys(connections).filter((
|
|
4785
|
-
var isLive = (
|
|
4786
|
-
const fields2 = providerFields(
|
|
4930
|
+
var providerSlugs = () => Object.keys(connections).filter((slug2) => connections[slug2].provider).sort();
|
|
4931
|
+
var isLive = (slug2, settings) => {
|
|
4932
|
+
const fields2 = providerFields(slug2);
|
|
4787
4933
|
if (!fields2.length) return false;
|
|
4788
4934
|
return fields2.filter((field2) => field2.required).every((field2) => Boolean(settings == null ? void 0 : settings[field2.key]));
|
|
4789
4935
|
};
|
|
@@ -4795,23 +4941,23 @@ var mask = (value) => {
|
|
|
4795
4941
|
var providerMemo = /* @__PURE__ */ new Map();
|
|
4796
4942
|
var MEMO_TTL_MS = 60 * 1e3;
|
|
4797
4943
|
var clearProviderMemo = () => providerMemo.clear();
|
|
4798
|
-
var providerSettings = async ({ controller, slug }) => {
|
|
4799
|
-
const memoized = providerMemo.get(
|
|
4944
|
+
var providerSettings = async ({ controller, slug: slug2 }) => {
|
|
4945
|
+
const memoized = providerMemo.get(slug2);
|
|
4800
4946
|
if (memoized && Date.now() - memoized.at < MEMO_TTL_MS) return memoized.value;
|
|
4801
4947
|
const row = await controller.get({
|
|
4802
4948
|
collection: "provider",
|
|
4803
|
-
query: { slug }
|
|
4949
|
+
query: { slug: slug2 }
|
|
4804
4950
|
});
|
|
4805
4951
|
const value = (row == null ? void 0 : row.settings) ? decrypt(row.settings) : {};
|
|
4806
|
-
providerMemo.set(
|
|
4952
|
+
providerMemo.set(slug2, { at: Date.now(), value });
|
|
4807
4953
|
return value;
|
|
4808
4954
|
};
|
|
4809
|
-
var saveProviderSettings = async ({ authenticated, clear, controller, settings, slug }) => {
|
|
4810
|
-
const fields2 = providerFields(
|
|
4955
|
+
var saveProviderSettings = async ({ authenticated, clear, controller, settings, slug: slug2 }) => {
|
|
4956
|
+
const fields2 = providerFields(slug2);
|
|
4811
4957
|
if (!fields2.length) return null;
|
|
4812
4958
|
const existing = await controller.get({
|
|
4813
4959
|
collection: "provider",
|
|
4814
|
-
query: { slug }
|
|
4960
|
+
query: { slug: slug2 }
|
|
4815
4961
|
});
|
|
4816
4962
|
const stored = (existing == null ? void 0 : existing.settings) ? decrypt(existing.settings) : {};
|
|
4817
4963
|
const pasted = (value) => typeof value === "string" ? value.trim().replace(/^['"]+|['"]+$/g, "") : value;
|
|
@@ -4833,20 +4979,20 @@ var saveProviderSettings = async ({ authenticated, clear, controller, settings,
|
|
|
4833
4979
|
options: {
|
|
4834
4980
|
upsert: true
|
|
4835
4981
|
},
|
|
4836
|
-
query: { slug }
|
|
4982
|
+
query: { slug: slug2 }
|
|
4837
4983
|
});
|
|
4838
|
-
providerMemo.delete(
|
|
4984
|
+
providerMemo.delete(slug2);
|
|
4839
4985
|
return result;
|
|
4840
4986
|
};
|
|
4841
4987
|
var providerEnvNames = () => new Set(
|
|
4842
|
-
providerSlugs().flatMap((
|
|
4988
|
+
providerSlugs().flatMap((slug2) => providerFields(slug2)).map((field2) => field2.credential).filter(Boolean)
|
|
4843
4989
|
);
|
|
4844
4990
|
var providerCredentials = async ({ controller }) => {
|
|
4845
4991
|
const credentials2 = {};
|
|
4846
|
-
for (const
|
|
4992
|
+
for (const slug2 of providerSlugs()) {
|
|
4847
4993
|
try {
|
|
4848
|
-
const settings = await providerSettings({ controller, slug });
|
|
4849
|
-
for (const field2 of providerFields(
|
|
4994
|
+
const settings = await providerSettings({ controller, slug: slug2 });
|
|
4995
|
+
for (const field2 of providerFields(slug2)) {
|
|
4850
4996
|
const value = settings == null ? void 0 : settings[field2.key];
|
|
4851
4997
|
if (field2.credential && value) credentials2[field2.credential] = value;
|
|
4852
4998
|
}
|
package/package.json
CHANGED