@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.cjs
CHANGED
|
@@ -545,6 +545,9 @@ var attentive_default2 = {
|
|
|
545
545
|
},
|
|
546
546
|
// A contact destination, like Klaviyo and Mailchimp — a merchant could
|
|
547
547
|
// reasonably keep several up to date at once.
|
|
548
|
+
// No vendor-facing event identities — declared empty so the contract stays
|
|
549
|
+
// explicit: a vendor that gains one adds it here, never as a side channel.
|
|
550
|
+
events: {},
|
|
548
551
|
exclusive: false,
|
|
549
552
|
feature: "organization:connection:attentive",
|
|
550
553
|
fields: [
|
|
@@ -1725,6 +1728,9 @@ var drawbridge_default2 = {
|
|
|
1725
1728
|
"Nothing to do. These steps are available in every workflow builder."
|
|
1726
1729
|
]
|
|
1727
1730
|
},
|
|
1731
|
+
// No vendor-facing event identities — declared empty so the contract stays
|
|
1732
|
+
// explicit: a vendor that gains one adds it here, never as a side channel.
|
|
1733
|
+
events: {},
|
|
1728
1734
|
exclusive: false,
|
|
1729
1735
|
fields: [],
|
|
1730
1736
|
group: "developer",
|
|
@@ -2509,6 +2515,9 @@ var klaviyo_default2 = {
|
|
|
2509
2515
|
// current — so the exclusivity that once applied when these were SENDERS is
|
|
2510
2516
|
// deliberately gone. That was removed once already; declaring it out loud is
|
|
2511
2517
|
// what stops it coming back by inference.
|
|
2518
|
+
// No vendor-facing event identities — declared empty so the contract stays
|
|
2519
|
+
// explicit: a vendor that gains one adds it here, never as a side channel.
|
|
2520
|
+
events: {},
|
|
2512
2521
|
exclusive: false,
|
|
2513
2522
|
feature: "organization:connection:klaviyo",
|
|
2514
2523
|
fields: [
|
|
@@ -2985,6 +2994,9 @@ var mailchimp_default2 = {
|
|
|
2985
2994
|
// picking two providers to send the same mail was meaningless. As contact
|
|
2986
2995
|
// syncs they are destinations, and a merchant could reasonably keep several
|
|
2987
2996
|
// up to date, so the exclusivity is gone.
|
|
2997
|
+
// No vendor-facing event identities — declared empty so the contract stays
|
|
2998
|
+
// explicit: a vendor that gains one adds it here, never as a side channel.
|
|
2999
|
+
events: {},
|
|
2988
3000
|
exclusive: false,
|
|
2989
3001
|
feature: "organization:connection:mailchimp",
|
|
2990
3002
|
fields: [
|
|
@@ -3260,6 +3272,22 @@ var toCanonicalEmail = (value) => {
|
|
|
3260
3272
|
return local + "@" + domain;
|
|
3261
3273
|
};
|
|
3262
3274
|
|
|
3275
|
+
// lib/slugify.js
|
|
3276
|
+
var import_slugify = __toESM(require("slugify"), 1);
|
|
3277
|
+
var slugify = (value, nochars = false) => {
|
|
3278
|
+
const remove = nochars ? /[-?*+~.()'"!:@#^_{}\[\];,/\\]/g : /[?*+~.()'"!:@#^_{}\[\];,/\\]/g;
|
|
3279
|
+
const replacement = nochars ? "" : "-";
|
|
3280
|
+
return (0, import_slugify.default)(
|
|
3281
|
+
value,
|
|
3282
|
+
{
|
|
3283
|
+
remove,
|
|
3284
|
+
replacement,
|
|
3285
|
+
lower: true,
|
|
3286
|
+
trim: true
|
|
3287
|
+
}
|
|
3288
|
+
);
|
|
3289
|
+
};
|
|
3290
|
+
|
|
3263
3291
|
// lib/connections/providers/shopify.js
|
|
3264
3292
|
var toLine = ({
|
|
3265
3293
|
price,
|
|
@@ -3295,6 +3323,7 @@ var attributeLineItems = (lineItems = []) => lineItems.reduce(
|
|
|
3295
3323
|
{ attrMap: {}, attributedGross: 0, attributedLines: [] }
|
|
3296
3324
|
);
|
|
3297
3325
|
var generateDiscountCode = (0, import_nanoid2.customAlphabet)("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 8);
|
|
3326
|
+
var ORDER_EVENT_HANDLE = slugify("drawbridge-orders");
|
|
3298
3327
|
var REFRESH_TOKEN_FRESHNESS_BUFFER_MS = 5 * 24 * 60 * 60 * 1e3;
|
|
3299
3328
|
var OAUTH_ERROR_SOURCE = "oauth";
|
|
3300
3329
|
var OAUTH_GRANT_REVOKED_CODES = ["application_cannot_be_found", "invalid_grant"];
|
|
@@ -3352,7 +3381,7 @@ var shopify_default2 = {
|
|
|
3352
3381
|
guide: [
|
|
3353
3382
|
"Open the Drawbridge listing on the Shopify App Store.",
|
|
3354
3383
|
"Install the app on the store you want to connect. It opens in Shopify admin and stays there.",
|
|
3355
|
-
"
|
|
3384
|
+
"Approve the Drawbridge plan when prompted \u2014 during install, or from the connection page here. The connection shows Pending until you do, then Active.",
|
|
3356
3385
|
"Come back here \u2014 the connections list updates on its own once the install lands."
|
|
3357
3386
|
],
|
|
3358
3387
|
// Names where the link GOES rather than what it does: installing happens on
|
|
@@ -3366,6 +3395,29 @@ var shopify_default2 = {
|
|
|
3366
3395
|
// ONE STORE PER ORGANIZATION. Two Shopify stores on one org would give every
|
|
3367
3396
|
// attributed order two possible sources.
|
|
3368
3397
|
exclusive: true,
|
|
3398
|
+
// VENDOR-FACING EVENT IDENTITY, published so readers outside this package
|
|
3399
|
+
// (drawbridge-sync's usage queue, an operator checking the Dev Dashboard)
|
|
3400
|
+
// see the same handle the order hook mints into transactions and enqueues.
|
|
3401
|
+
events: {
|
|
3402
|
+
order: {
|
|
3403
|
+
handle: ORDER_EVENT_HANDLE,
|
|
3404
|
+
// THE SUBSCRIPTION THE APP MINTS FOR ITSELF (Billing API, not the
|
|
3405
|
+
// managed-pricing meter system): a $0 recurring line plus this usage
|
|
3406
|
+
// line, approved by the org owner at Shopify's confirmation screen.
|
|
3407
|
+
// `terms` is the merchant-visible consent copy; "up to" because the
|
|
3408
|
+
// actual rate is plan-derived (conversionRate) and must never exceed
|
|
3409
|
+
// what was approved. cappedAmount bounds one 30-day cycle's usage
|
|
3410
|
+
// charges — a record beyond it errors until the merchant raises it.
|
|
3411
|
+
// ponytail: $1,000 cap ≈ $66k attributed revenue/cycle at 1.5%; raise
|
|
3412
|
+
// via a re-approved subscription when a merchant outgrows it.
|
|
3413
|
+
pricing: {
|
|
3414
|
+
cappedAmount: 1e3,
|
|
3415
|
+
currency: "usd",
|
|
3416
|
+
name: "Drawbridge Orders",
|
|
3417
|
+
terms: "Up to 1.5% of revenue from orders attributed to Drawbridge campaigns"
|
|
3418
|
+
}
|
|
3419
|
+
}
|
|
3420
|
+
},
|
|
3369
3421
|
feature: "organization:connection:shopify",
|
|
3370
3422
|
fields: [
|
|
3371
3423
|
{
|
|
@@ -3551,7 +3603,7 @@ var shopify_default2 = {
|
|
|
3551
3603
|
// for one purchase. The hook used to loop for this itself; describing
|
|
3552
3604
|
// the writes moved the retry to the queue, with the same guarantee.
|
|
3553
3605
|
order: async ({ connection: connection2, context }, { logger: logger2, mintId, read } = {}) => {
|
|
3554
|
-
var _a, _b, _c, _d, _e, _f;
|
|
3606
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
3555
3607
|
const {
|
|
3556
3608
|
advertisement,
|
|
3557
3609
|
created_at: createdAt,
|
|
@@ -3793,8 +3845,26 @@ var shopify_default2 = {
|
|
|
3793
3845
|
});
|
|
3794
3846
|
}
|
|
3795
3847
|
}
|
|
3796
|
-
const
|
|
3848
|
+
const billable = (org == null ? void 0 : org.billingProvider) === "shopify" && fee > 0 && !backfill;
|
|
3849
|
+
if (billable && !((_f = connection2 == null ? void 0 : connection2.source) == null ? void 0 : _f.id)) {
|
|
3850
|
+
(_g = logger2 == null ? void 0 : logger2.error) == null ? void 0 : _g.call(logger2, new Error(
|
|
3851
|
+
"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"
|
|
3852
|
+
), {
|
|
3853
|
+
extra: {
|
|
3854
|
+
connectionId: connection2 == null ? void 0 : connection2.id,
|
|
3855
|
+
fee,
|
|
3856
|
+
orderDocId,
|
|
3857
|
+
orderId: String(orderId)
|
|
3858
|
+
}
|
|
3859
|
+
});
|
|
3860
|
+
}
|
|
3861
|
+
const enqueues = billable && ((_h = connection2 == null ? void 0 : connection2.source) == null ? void 0 : _h.id) ? [{
|
|
3797
3862
|
data: {
|
|
3863
|
+
// The meter handle travels WITH the job so the sender can
|
|
3864
|
+
// verify it against the transaction prefix and refuse a
|
|
3865
|
+
// drifted pair — idempotency keys are permanent, so a
|
|
3866
|
+
// mistraceable event can never be resent under its own key.
|
|
3867
|
+
handle: ORDER_EVENT_HANDLE,
|
|
3798
3868
|
idempotencyKey: String(orderId),
|
|
3799
3869
|
orderDocId,
|
|
3800
3870
|
orderId: String(orderId),
|
|
@@ -3804,7 +3874,7 @@ var shopify_default2 = {
|
|
|
3804
3874
|
// here — the event handle plus the order id — and sent as the
|
|
3805
3875
|
// event's `reference`. queue/usage.js stamps the same id onto
|
|
3806
3876
|
// the order as billed.transaction.
|
|
3807
|
-
transaction: "
|
|
3877
|
+
transaction: ORDER_EVENT_HANDLE + "." + orderId,
|
|
3808
3878
|
value: Math.round(fee * 100)
|
|
3809
3879
|
},
|
|
3810
3880
|
name: "billing",
|
|
@@ -3947,7 +4017,8 @@ var shopify_default2 = {
|
|
|
3947
4017
|
// access token still works, reconciles the scopes the store granted
|
|
3948
4018
|
// against the ones the app now needs, and queues a webhook
|
|
3949
4019
|
// reconciliation.
|
|
3950
|
-
health: async ({ connection: connection2, workflow }, { adminToken, read, reconcileScopes, resolveSettings, rotateToken, shopify } = {}) => {
|
|
4020
|
+
health: async ({ connection: connection2, workflow }, { adminToken, logger: logger2, read, reconcileScopes, resolveSettings, rotateToken, shopify } = {}) => {
|
|
4021
|
+
var _a, _b;
|
|
3951
4022
|
const request2 = {
|
|
3952
4023
|
connectionId: workflow.connection,
|
|
3953
4024
|
organizationId: workflow.organization,
|
|
@@ -3966,7 +4037,50 @@ var shopify_default2 = {
|
|
|
3966
4037
|
}
|
|
3967
4038
|
await shopify.oauth.ping({ adminAccessToken, domain: connection2.shop });
|
|
3968
4039
|
const scopesMissing = await reconcileScopes({ shop: connection2.shop });
|
|
4040
|
+
const writes = [];
|
|
4041
|
+
let source = connection2.source || null;
|
|
4042
|
+
let sourceRepaired = false;
|
|
4043
|
+
let metered = (source == null ? void 0 : source.metered) ?? null;
|
|
4044
|
+
let shopCurrency = null;
|
|
4045
|
+
let billingProbeFailed = false;
|
|
4046
|
+
try {
|
|
4047
|
+
if (!(source == null ? void 0 : source.id)) {
|
|
4048
|
+
const shopData = await shopify.oauth.getShop({ adminAccessToken, shop: connection2.shop });
|
|
4049
|
+
source = {
|
|
4050
|
+
domain: shopData.myshopifyDomain,
|
|
4051
|
+
id: String(shopData.id),
|
|
4052
|
+
label: shopData.name
|
|
4053
|
+
};
|
|
4054
|
+
shopCurrency = String(shopData.currency || "").toLowerCase() || null;
|
|
4055
|
+
sourceRepaired = true;
|
|
4056
|
+
}
|
|
4057
|
+
const { subscriptions } = await shopify.admin.getActiveAppSubscriptions({
|
|
4058
|
+
adminAccessToken,
|
|
4059
|
+
domain: connection2.shop
|
|
4060
|
+
});
|
|
4061
|
+
if (subscriptions.length && subscriptions.every((subscription) => typeof subscription.metered === "boolean")) {
|
|
4062
|
+
metered = subscriptions.some((subscription) => subscription.metered);
|
|
4063
|
+
}
|
|
4064
|
+
} catch (probeError) {
|
|
4065
|
+
billingProbeFailed = true;
|
|
4066
|
+
(_a = logger2 == null ? void 0 : logger2.warn) == null ? void 0 : _a.call(logger2, "shopify.health.billing.probe.failed", {
|
|
4067
|
+
connectionId: connection2.id,
|
|
4068
|
+
message: probeError == null ? void 0 : probeError.message,
|
|
4069
|
+
shop: connection2.shop
|
|
4070
|
+
});
|
|
4071
|
+
}
|
|
4072
|
+
if (sourceRepaired || metered !== null && metered !== (((_b = connection2.source) == null ? void 0 : _b.metered) ?? null)) {
|
|
4073
|
+
writes.push({
|
|
4074
|
+
collection: "connection",
|
|
4075
|
+
data: {
|
|
4076
|
+
$set: sourceRepaired ? { source: { ...source, ...metered !== null && { metered } } } : { "source.metered": metered }
|
|
4077
|
+
},
|
|
4078
|
+
operation: "update",
|
|
4079
|
+
query: { id: connection2.id }
|
|
4080
|
+
});
|
|
4081
|
+
}
|
|
3969
4082
|
return {
|
|
4083
|
+
writes,
|
|
3970
4084
|
enqueues: [{
|
|
3971
4085
|
data: {
|
|
3972
4086
|
data: {
|
|
@@ -3979,13 +4093,19 @@ var shopify_default2 = {
|
|
|
3979
4093
|
options: { jobId: "connection.update.register." + workflow.connection + "." + (0, import_node_crypto5.randomUUID)() },
|
|
3980
4094
|
queue: "connection"
|
|
3981
4095
|
}],
|
|
3982
|
-
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.",
|
|
4096
|
+
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." : ""),
|
|
3983
4097
|
request: request2,
|
|
3984
4098
|
response: {
|
|
4099
|
+
billingProbeFailed,
|
|
4100
|
+
metered,
|
|
3985
4101
|
pingedAt: /* @__PURE__ */ new Date(),
|
|
3986
4102
|
refreshTokenExpiresAt: refreshTokenExpiresAt || null,
|
|
3987
4103
|
refreshTokenRotated,
|
|
3988
4104
|
scopesMissing,
|
|
4105
|
+
// The live settlement currency, for an operator — never
|
|
4106
|
+
// written, see above.
|
|
4107
|
+
...shopCurrency && { shopCurrency },
|
|
4108
|
+
sourceRepaired,
|
|
3989
4109
|
webhookReconciliationQueued: true
|
|
3990
4110
|
}
|
|
3991
4111
|
};
|
|
@@ -4253,12 +4373,35 @@ var shopify_default2 = {
|
|
|
4253
4373
|
//
|
|
4254
4374
|
// Scope drift is NOT here: drawbridge-sync writes it onto the connection
|
|
4255
4375
|
// document, and the document's own warnings render beside these.
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4376
|
+
// Both cards carry `action : 'billing'`: the dashboard renders it as a real
|
|
4377
|
+
// button that mints the corrective subscription (POST .../billing) and sends
|
|
4378
|
+
// the owner to Shopify's confirmation screen — the fix lives in OUR
|
|
4379
|
+
// dashboard, and the one Shopify-hosted step is the charge consent no app
|
|
4380
|
+
// can perform for a merchant.
|
|
4381
|
+
tasks: (data2) => {
|
|
4382
|
+
var _a;
|
|
4383
|
+
return [
|
|
4384
|
+
...(data2 == null ? void 0 : data2.status) === "pending" ? [
|
|
4385
|
+
{
|
|
4386
|
+
action: "billing",
|
|
4387
|
+
message: "Approve the Drawbridge plan to activate this connection. You'll confirm the pricing on Shopify, then everything else happens here.",
|
|
4388
|
+
title: "Approve your plan"
|
|
4389
|
+
}
|
|
4390
|
+
] : [],
|
|
4391
|
+
// The store's ACTIVE approval carries no usage component — stamped by
|
|
4392
|
+
// the daily health check and the approval webhook (`source.metered`).
|
|
4393
|
+
// Approved pricing is never retroactive, so the fix is a fresh approval.
|
|
4394
|
+
// Gated on an EXPLICIT false — a connection the probe hasn't reached
|
|
4395
|
+
// (or couldn't read) shows nothing rather than nagging on silence.
|
|
4396
|
+
...(data2 == null ? void 0 : data2.status) === "active" && ((_a = data2 == null ? void 0 : data2.source) == null ? void 0 : _a.metered) === false ? [
|
|
4397
|
+
{
|
|
4398
|
+
action: "billing",
|
|
4399
|
+
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.",
|
|
4400
|
+
title: "Fix order billing"
|
|
4401
|
+
}
|
|
4402
|
+
] : []
|
|
4403
|
+
];
|
|
4404
|
+
},
|
|
4262
4405
|
title: "Shopify"
|
|
4263
4406
|
};
|
|
4264
4407
|
|
|
@@ -4432,6 +4575,9 @@ var webhook_default = {
|
|
|
4432
4575
|
// Nothing to be exclusive with — there is no second webhook vendor, and a
|
|
4433
4576
|
// merchant with two endpoints is a step-level choice rather than a second
|
|
4434
4577
|
// connection.
|
|
4578
|
+
// No vendor-facing event identities — declared empty so the contract stays
|
|
4579
|
+
// explicit: a vendor that gains one adds it here, never as a side channel.
|
|
4580
|
+
events: {},
|
|
4435
4581
|
exclusive: false,
|
|
4436
4582
|
feature: "organization:connection:webhook",
|
|
4437
4583
|
fields: [
|
|
@@ -4718,22 +4864,22 @@ var connections = Object.freeze({
|
|
|
4718
4864
|
(() => {
|
|
4719
4865
|
var _a;
|
|
4720
4866
|
const routes = {};
|
|
4721
|
-
for (const [
|
|
4867
|
+
for (const [slug2, manifest] of Object.entries(connections)) {
|
|
4722
4868
|
for (const [name, step] of leaves(manifest.steps)) {
|
|
4723
4869
|
const type = "step." + name;
|
|
4724
4870
|
const queue = (_a = step({})) == null ? void 0 : _a.queue;
|
|
4725
4871
|
if (routes[type] && routes[type].queue !== queue) {
|
|
4726
4872
|
throw new Error(
|
|
4727
|
-
"Step " + type + " routes to " + routes[type].queue + " for " + routes[type].slug + " and " + queue + " for " +
|
|
4873
|
+
"Step " + type + " routes to " + routes[type].queue + " for " + routes[type].slug + " and " + queue + " for " + slug2 + " \u2014 one of them would be enqueued nowhere"
|
|
4728
4874
|
);
|
|
4729
4875
|
}
|
|
4730
|
-
routes[type] = { queue, slug };
|
|
4876
|
+
routes[type] = { queue, slug: slug2 };
|
|
4731
4877
|
}
|
|
4732
4878
|
}
|
|
4733
4879
|
})();
|
|
4734
4880
|
var publicSettingsBySlug = Object.fromEntries(
|
|
4735
|
-
Object.entries(connections).map(([
|
|
4736
|
-
|
|
4881
|
+
Object.entries(connections).map(([slug2, manifest]) => [
|
|
4882
|
+
slug2,
|
|
4737
4883
|
manifest.fields.filter((field2) => !field2.redact).map((field2) => field2.key)
|
|
4738
4884
|
])
|
|
4739
4885
|
);
|
|
@@ -4821,13 +4967,13 @@ var decrypt = (value) => {
|
|
|
4821
4967
|
};
|
|
4822
4968
|
|
|
4823
4969
|
// lib/providers.js
|
|
4824
|
-
var providerFields = (
|
|
4970
|
+
var providerFields = (slug2) => {
|
|
4825
4971
|
var _a;
|
|
4826
|
-
return Object.hasOwn(connections,
|
|
4972
|
+
return Object.hasOwn(connections, slug2) ? ((_a = connections[slug2].provider) == null ? void 0 : _a.fields) || [] : [];
|
|
4827
4973
|
};
|
|
4828
|
-
var providerSlugs = () => Object.keys(connections).filter((
|
|
4829
|
-
var isLive = (
|
|
4830
|
-
const fields2 = providerFields(
|
|
4974
|
+
var providerSlugs = () => Object.keys(connections).filter((slug2) => connections[slug2].provider).sort();
|
|
4975
|
+
var isLive = (slug2, settings) => {
|
|
4976
|
+
const fields2 = providerFields(slug2);
|
|
4831
4977
|
if (!fields2.length) return false;
|
|
4832
4978
|
return fields2.filter((field2) => field2.required).every((field2) => Boolean(settings == null ? void 0 : settings[field2.key]));
|
|
4833
4979
|
};
|
|
@@ -4839,23 +4985,23 @@ var mask = (value) => {
|
|
|
4839
4985
|
var providerMemo = /* @__PURE__ */ new Map();
|
|
4840
4986
|
var MEMO_TTL_MS = 60 * 1e3;
|
|
4841
4987
|
var clearProviderMemo = () => providerMemo.clear();
|
|
4842
|
-
var providerSettings = async ({ controller, slug }) => {
|
|
4843
|
-
const memoized = providerMemo.get(
|
|
4988
|
+
var providerSettings = async ({ controller, slug: slug2 }) => {
|
|
4989
|
+
const memoized = providerMemo.get(slug2);
|
|
4844
4990
|
if (memoized && Date.now() - memoized.at < MEMO_TTL_MS) return memoized.value;
|
|
4845
4991
|
const row = await controller.get({
|
|
4846
4992
|
collection: "provider",
|
|
4847
|
-
query: { slug }
|
|
4993
|
+
query: { slug: slug2 }
|
|
4848
4994
|
});
|
|
4849
4995
|
const value = (row == null ? void 0 : row.settings) ? decrypt(row.settings) : {};
|
|
4850
|
-
providerMemo.set(
|
|
4996
|
+
providerMemo.set(slug2, { at: Date.now(), value });
|
|
4851
4997
|
return value;
|
|
4852
4998
|
};
|
|
4853
|
-
var saveProviderSettings = async ({ authenticated, clear, controller, settings, slug }) => {
|
|
4854
|
-
const fields2 = providerFields(
|
|
4999
|
+
var saveProviderSettings = async ({ authenticated, clear, controller, settings, slug: slug2 }) => {
|
|
5000
|
+
const fields2 = providerFields(slug2);
|
|
4855
5001
|
if (!fields2.length) return null;
|
|
4856
5002
|
const existing = await controller.get({
|
|
4857
5003
|
collection: "provider",
|
|
4858
|
-
query: { slug }
|
|
5004
|
+
query: { slug: slug2 }
|
|
4859
5005
|
});
|
|
4860
5006
|
const stored = (existing == null ? void 0 : existing.settings) ? decrypt(existing.settings) : {};
|
|
4861
5007
|
const pasted = (value) => typeof value === "string" ? value.trim().replace(/^['"]+|['"]+$/g, "") : value;
|
|
@@ -4877,20 +5023,20 @@ var saveProviderSettings = async ({ authenticated, clear, controller, settings,
|
|
|
4877
5023
|
options: {
|
|
4878
5024
|
upsert: true
|
|
4879
5025
|
},
|
|
4880
|
-
query: { slug }
|
|
5026
|
+
query: { slug: slug2 }
|
|
4881
5027
|
});
|
|
4882
|
-
providerMemo.delete(
|
|
5028
|
+
providerMemo.delete(slug2);
|
|
4883
5029
|
return result;
|
|
4884
5030
|
};
|
|
4885
5031
|
var providerEnvNames = () => new Set(
|
|
4886
|
-
providerSlugs().flatMap((
|
|
5032
|
+
providerSlugs().flatMap((slug2) => providerFields(slug2)).map((field2) => field2.credential).filter(Boolean)
|
|
4887
5033
|
);
|
|
4888
5034
|
var providerCredentials = async ({ controller }) => {
|
|
4889
5035
|
const credentials2 = {};
|
|
4890
|
-
for (const
|
|
5036
|
+
for (const slug2 of providerSlugs()) {
|
|
4891
5037
|
try {
|
|
4892
|
-
const settings = await providerSettings({ controller, slug });
|
|
4893
|
-
for (const field2 of providerFields(
|
|
5038
|
+
const settings = await providerSettings({ controller, slug: slug2 });
|
|
5039
|
+
for (const field2 of providerFields(slug2)) {
|
|
4894
5040
|
const value = settings == null ? void 0 : settings[field2.key];
|
|
4895
5041
|
if (field2.credential && value) credentials2[field2.credential] = value;
|
|
4896
5042
|
}
|
package/dist/providers.d.cts
CHANGED