@delopay/sdk 0.247.0 → 0.255.0

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/index.cjs CHANGED
@@ -41,6 +41,7 @@ __export(index_exports, {
41
41
  AvailabilityOverrides: () => AvailabilityOverrides,
42
42
  BRANDING_EXPORT_FORMAT: () => BRANDING_EXPORT_FORMAT,
43
43
  BRANDING_EXPORT_VERSION: () => BRANDING_EXPORT_VERSION,
44
+ BUILTIN_PAYMENT_ICON_KEYS: () => BUILTIN_PAYMENT_ICON_KEYS,
44
45
  BuyerBlocklist: () => BuyerBlocklist,
45
46
  CARD_FIELD_CHROMES: () => CARD_FIELD_CHROMES,
46
47
  CARD_FIELD_FONT_SIZES: () => CARD_FIELD_FONT_SIZES,
@@ -102,7 +103,9 @@ __export(index_exports, {
102
103
  PANE_ICON_KEYS: () => PANE_ICON_KEYS,
103
104
  PAYPAL_CARD_LAYOUTS: () => PAYPAL_CARD_LAYOUTS,
104
105
  PAYPAL_LABEL_STYLES: () => PAYPAL_LABEL_STYLES,
106
+ PRESENTATION_CONTRACT_VERSION: () => PRESENTATION_CONTRACT_VERSION,
105
107
  PaypalDisputes: () => PaypalDisputes,
108
+ PresentationCache: () => PresentationCache,
106
109
  ProcessorCosts: () => ProcessorCosts,
107
110
  Products: () => Products,
108
111
  RTL_CHECKOUT_LOCALES: () => RTL_CHECKOUT_LOCALES,
@@ -156,6 +159,8 @@ __export(index_exports, {
156
159
  applyBrandingVariables: () => applyBrandingVariables,
157
160
  asAirwallexCardPreset: () => asAirwallexCardPreset,
158
161
  buildBrandingExport: () => buildBrandingExport,
162
+ builtinPaymentIconDataUri: () => builtinPaymentIconDataUri,
163
+ builtinPaymentIconSvg: () => builtinPaymentIconSvg,
159
164
  buttonPadValue: () => buttonPadValue,
160
165
  canonicalSectionId: () => canonicalSectionId,
161
166
  cardFieldFontPx: () => cardFieldFontPx,
@@ -213,6 +218,7 @@ __export(index_exports, {
213
218
  isNoticeIcon: () => isNoticeIcon,
214
219
  isSubscriptionDisputeWebhook: () => isSubscriptionDisputeWebhook,
215
220
  isSubscriptionLifecycleWebhook: () => isSubscriptionLifecycleWebhook,
221
+ isSupportedPresentation: () => isSupportedPresentation,
216
222
  knownSectionLabelKey: () => knownSectionLabelKey,
217
223
  leaf: () => leaf,
218
224
  logoDimensions: () => logoDimensions,
@@ -230,6 +236,9 @@ __export(index_exports, {
230
236
  parseCustomFieldsLoose: () => parseCustomFieldsLoose,
231
237
  parseImportedBranding: () => parseImportedBranding,
232
238
  parseNoticesLoose: () => parseNoticesLoose,
239
+ presentationIconDataUri: () => presentationIconDataUri,
240
+ presentationIconSrc: () => presentationIconSrc,
241
+ presentationTiers: () => presentationTiers,
233
242
  programToTree: () => programToTree,
234
243
  radiusValue: () => radiusValue,
235
244
  readableInkOn: () => readableInkOn,
@@ -244,6 +253,7 @@ __export(index_exports, {
244
253
  sanitizeCustomCss: () => sanitizeCustomCss,
245
254
  sectionLabel: () => sectionLabel,
246
255
  sectionOrderOf: () => sectionOrderOf,
256
+ selectableEntries: () => selectableEntries,
247
257
  shadowFor: () => shadowFor,
248
258
  shownNotices: () => shownNotices,
249
259
  stripeSpacingValues: () => stripeSpacingValues,
@@ -1227,11 +1237,92 @@ var Connectors = class {
1227
1237
  { body: params }
1228
1238
  );
1229
1239
  }
1240
+ /**
1241
+ * Every webhook the connector's payment provider lists for its credentials
1242
+ * in one environment: Delopay's own, other connector accounts', former
1243
+ * addresses' and other integrations'.
1244
+ * `GET /account/{merchantId}/connectors/webhooks/{connectorId}/provider`
1245
+ *
1246
+ * Available for Stripe, PayPal, Airwallex, Whop and Adyen. Destinations are
1247
+ * masked; `capabilities` says which changes the provider allows and
1248
+ * `editable` whether the caller may make them.
1249
+ */
1250
+ async listProviderWebhooks(merchantId, connectorId, environment) {
1251
+ return this.request("GET", providerWebhooksPath(merchantId, connectorId), {
1252
+ query: { environment }
1253
+ });
1254
+ }
1255
+ /**
1256
+ * Create a webhook at the provider for the merchant's own systems.
1257
+ * `POST /account/{merchantId}/connectors/webhooks/{connectorId}/provider`
1258
+ *
1259
+ * The URL must be `https` and outside Delopay; Delopay's own webhook is
1260
+ * registered with `registerWebhook`. A returned `signing_secret` is not kept
1261
+ * by Delopay and cannot be read again.
1262
+ */
1263
+ async createProviderWebhook(merchantId, connectorId, params) {
1264
+ return this.request("POST", providerWebhooksPath(merchantId, connectorId), { body: params });
1265
+ }
1266
+ /**
1267
+ * Change one webhook at the provider.
1268
+ * `PATCH /account/{merchantId}/connectors/webhooks/{connectorId}/provider/{webhookId}`
1269
+ *
1270
+ * Refused once the webhook changed since `fingerprint`, and for Delopay's
1271
+ * own webhooks.
1272
+ */
1273
+ async updateProviderWebhook(merchantId, connectorId, webhookId, params) {
1274
+ return this.request(
1275
+ "PATCH",
1276
+ `${providerWebhooksPath(merchantId, connectorId)}/${encodeURIComponent(webhookId)}`,
1277
+ { body: params }
1278
+ );
1279
+ }
1280
+ /**
1281
+ * Delete one webhook at the provider.
1282
+ * `POST /account/{merchantId}/connectors/webhooks/{connectorId}/provider/{webhookId}/delete`
1283
+ *
1284
+ * Refused once the webhook changed since `fingerprint`. Deleting Delopay's
1285
+ * own webhook needs `confirm_managed: true`; another connector account's is
1286
+ * never deleted from here.
1287
+ */
1288
+ async deleteProviderWebhook(merchantId, connectorId, webhookId, params) {
1289
+ return this.request(
1290
+ "POST",
1291
+ `${providerWebhooksPath(merchantId, connectorId)}/${encodeURIComponent(webhookId)}/delete`,
1292
+ { body: params }
1293
+ );
1294
+ }
1295
+ /**
1296
+ * What "replace all" would delete and keep. Nothing is changed.
1297
+ * `GET /account/{merchantId}/connectors/webhooks/{connectorId}/provider/replace`
1298
+ */
1299
+ async previewProviderWebhookReplace(merchantId, connectorId, environment) {
1300
+ return this.request("GET", `${providerWebhooksPath(merchantId, connectorId)}/replace`, {
1301
+ query: { environment }
1302
+ });
1303
+ }
1304
+ /**
1305
+ * Keep only Delopay's webhook: delete exactly the confirmed webhooks of the
1306
+ * preview, after registering Delopay's own unless `sequence` is
1307
+ * `delete_first`.
1308
+ * `POST /account/{merchantId}/connectors/webhooks/{connectorId}/provider/replace`
1309
+ *
1310
+ * A list that changed since the preview answers `scope_changed` and deletes
1311
+ * nothing. A second replacement while one runs is refused as busy (`HE_00`).
1312
+ */
1313
+ async replaceProviderWebhooks(merchantId, connectorId, params) {
1314
+ return this.request("POST", `${providerWebhooksPath(merchantId, connectorId)}/replace`, {
1315
+ body: params
1316
+ });
1317
+ }
1230
1318
  /** List available payment methods. `GET /account/payment-methods` */
1231
1319
  async listPaymentMethods() {
1232
1320
  return this.request("GET", "/account/payment-methods");
1233
1321
  }
1234
1322
  };
1323
+ function providerWebhooksPath(merchantId, connectorId) {
1324
+ return `/account/${encodeURIComponent(merchantId)}/connectors/webhooks/${encodeURIComponent(connectorId)}/provider`;
1325
+ }
1235
1326
 
1236
1327
  // src/resources/customers.ts
1237
1328
  function toQuery(params) {
@@ -2404,6 +2495,44 @@ var PaymentMethods = class {
2404
2495
  query: params
2405
2496
  });
2406
2497
  }
2498
+ /**
2499
+ * The shop's payment buttons as the hosted checkout draws them: order,
2500
+ * labels in the shop's or caller's language, artwork, and what selecting
2501
+ * each one does. For rendering payment buttons on your own site without a
2502
+ * local table of provider names and icons.
2503
+ *
2504
+ * With a secret key, name the shop (`profile_id`) and optionally the
2505
+ * environment and a buyer context; the answer may be reused for
2506
+ * `cache.max_age_seconds` — {@link PresentationCache} does that. With a
2507
+ * publishable key, pass the payment's `client_secret` (or use
2508
+ * `CheckoutSession.paymentMethodPresentation`); that answer is never reused.
2509
+ *
2510
+ * A displayed entry is not a promise: the payment is confirmed against the
2511
+ * current configuration.
2512
+ *
2513
+ * `GET /account/payment-methods/presentation`
2514
+ *
2515
+ * @example
2516
+ * ```typescript
2517
+ * const buttons = await delopay.paymentMethods.presentation({
2518
+ * profile_id: 'pro_123',
2519
+ * country: 'DE',
2520
+ * currency: 'EUR',
2521
+ * amount: 4999,
2522
+ * locale: 'de',
2523
+ * });
2524
+ * for (const entry of buttons.entries) {
2525
+ * if (entry.kind === 'heading') renderHeading(entry.label);
2526
+ * else renderButton(entry.label, entry.sublabel, presentationIconSrc(entry));
2527
+ * }
2528
+ * ```
2529
+ */
2530
+ async presentation(params, options) {
2531
+ return this.request("GET", "/account/payment-methods/presentation", {
2532
+ query: params,
2533
+ ...options
2534
+ });
2535
+ }
2407
2536
  /**
2408
2537
  * List all saved payment methods for a customer, optionally filtered.
2409
2538
  *
@@ -7246,7 +7375,7 @@ var BuyerAccount = class {
7246
7375
  constructor(request) {
7247
7376
  this.request = request;
7248
7377
  }
7249
- /** Whether buyers can sign in by email on this platform, and how. */
7378
+ /** Whether buyers can sign in on this platform, and which methods are offered. */
7250
7379
  async availability(options) {
7251
7380
  return this.request("GET", "/buyer-account/availability", { ...options });
7252
7381
  }
@@ -12375,6 +12504,37 @@ var CheckoutSession = class {
12375
12504
  headers: this.bearerHeaders(options?.headers)
12376
12505
  });
12377
12506
  }
12507
+ /**
12508
+ * Remove one of the buyer's saved cards, named by its `payment_token` from
12509
+ * {@link vaultSavedCards}: from the customer's saved cards and from the
12510
+ * shop's vault, with every saved copy of the same card. Only a card of the
12511
+ * payment's own customer that the shop's vault holds can be removed, and
12512
+ * only within the payment's session.
12513
+ *
12514
+ * Refusals throw a `DelopayError`:
12515
+ *
12516
+ * - `400` with code `IR_16` and `data.reason` set to a
12517
+ * {@link VaultSavedCardRemovalRefusal}: the card stays listed.
12518
+ * `saved_card_in_use` means a subscription or agreement still charges it,
12519
+ * `saved_card_payment_in_progress` a payment with it is in flight, and
12520
+ * `saved_card_removal_unavailable` that the shop cannot remove cards here.
12521
+ * - `404`: the card is not one this buyer can remove, for example because it
12522
+ * is already gone.
12523
+ * - `422` with code `IR_29`: the token is no longer held. Read
12524
+ * {@link vaultSavedCards} again and remove the card by its new token.
12525
+ *
12526
+ * `DELETE /payment-link/{merchantId}/{paymentId}/vault/saved-cards/{paymentToken}`
12527
+ */
12528
+ async vaultRemoveSavedCard(paymentToken, options) {
12529
+ await this.client.request(
12530
+ "DELETE",
12531
+ `${this.linkBase}/vault/saved-cards/${encodeURIComponent(paymentToken)}`,
12532
+ {
12533
+ ...options,
12534
+ headers: this.bearerHeaders(options?.headers)
12535
+ }
12536
+ );
12537
+ }
12378
12538
  /**
12379
12539
  * Mint the security-code form for a saved card, on a shop whose vault keeps
12380
12540
  * the code itself (Enigma Vault). The buyer re-enters the code into the
@@ -12603,7 +12763,195 @@ var CheckoutSession = class {
12603
12763
  headers: this.pkHeaders(options?.headers)
12604
12764
  });
12605
12765
  }
12766
+ /**
12767
+ * This payment's checkout buttons, as the hosted checkout draws them: order,
12768
+ * labels, artwork, and what selecting each one does. The shop, environment,
12769
+ * currency and amount are the payment's. Ask again when the cart changes;
12770
+ * an answer is never reused for another payment.
12771
+ *
12772
+ * `GET /account/payment-methods/presentation` (publishable key + client secret)
12773
+ *
12774
+ * @param params - `country` outranks the billing address and IP
12775
+ * geolocation; `locale` names the language of the labels.
12776
+ */
12777
+ async paymentMethodPresentation(params, options) {
12778
+ return this.client.request("GET", "/account/payment-methods/presentation", {
12779
+ query: {
12780
+ client_secret: this.requireClientSecret(),
12781
+ country: params?.country,
12782
+ locale: params?.locale,
12783
+ contract_version: params?.contract_version
12784
+ },
12785
+ ...options,
12786
+ headers: this.pkHeaders(options?.headers)
12787
+ });
12788
+ }
12789
+ };
12790
+
12791
+ // src/paymentPresentation.ts
12792
+ var PRESENTATION_CONTRACT_VERSION = 1;
12793
+ var BUILTIN_PAYMENT_ICON_KEYS = [
12794
+ "wallet",
12795
+ "card",
12796
+ "bank",
12797
+ "apple",
12798
+ "google",
12799
+ "bnpl",
12800
+ "cash",
12801
+ "paypal",
12802
+ "klarna",
12803
+ "crypto"
12804
+ ];
12805
+ var SVG_OPEN = '<svg xmlns="http://www.w3.org/2000/svg"';
12806
+ function glyph(key, color) {
12807
+ const line = (body) => `${SVG_OPEN} viewBox="0 0 24 24" fill="none" stroke="${color}" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">${body}</svg>`;
12808
+ switch (key) {
12809
+ case "card":
12810
+ return line('<rect x="2" y="5" width="20" height="14" rx="2"/><path d="M2 10h20"/>');
12811
+ case "bank":
12812
+ return line(
12813
+ '<path d="M3 10h18"/><path d="m12 3 9 5H3l9-5Z"/><path d="M6 10v7M10 10v7M14 10v7M18 10v7"/><path d="M3 20h18"/>'
12814
+ );
12815
+ case "bnpl":
12816
+ return line(
12817
+ '<rect x="2" y="6" width="20" height="12" rx="2"/><path d="M6 12h4"/><path d="M14 10v4"/><path d="M18 10v4"/>'
12818
+ );
12819
+ case "cash":
12820
+ return line(
12821
+ '<rect x="2" y="6" width="20" height="12" rx="2"/><circle cx="12" cy="12" r="2.5"/><path d="M6 12h.01M18 12h.01"/>'
12822
+ );
12823
+ case "apple":
12824
+ return `${SVG_OPEN} viewBox="0 0 384 512" fill="${color}"><path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/></svg>`;
12825
+ case "google":
12826
+ return `${SVG_OPEN} viewBox="0 0 48 48"><path fill="#4285F4" d="M45.12 24.5c0-1.56-.14-3.06-.4-4.5H24v8.51h11.84c-.51 2.75-2.06 5.08-4.39 6.64v5.52h7.11c4.16-3.83 6.56-9.47 6.56-16.17z"/><path fill="#34A853" d="M24 46c5.94 0 10.92-1.97 14.56-5.33l-7.11-5.52c-1.97 1.32-4.49 2.1-7.45 2.1-5.73 0-10.58-3.87-12.31-9.07H4.34v5.7C7.96 41.07 15.4 46 24 46z"/><path fill="#FBBC05" d="M11.69 28.18C11.25 26.86 11 25.45 11 24s.25-2.86.69-4.18v-5.7H4.34C2.85 17.09 2 20.45 2 24s.85 6.91 2.34 9.88l7.35-5.7z"/><path fill="#EA4335" d="M24 10.75c3.23 0 6.13 1.11 8.41 3.29l6.31-6.31C34.91 4.18 29.93 2 24 2 15.4 2 7.96 6.93 4.34 14.12l7.35 5.7c1.73-5.2 6.58-9.07 12.31-9.07z"/></svg>`;
12827
+ case "paypal":
12828
+ return `${SVG_OPEN} viewBox="0 0 32 32"><path d="M9 4h7.2c3.4 0 6 2.4 5.6 5.8-.4 3.6-3.5 6-7.1 6h-3.2L10.4 23H6.7L9 4z" fill="#003087"/><path d="M13 8.5h7.2c3.4 0 6 2.4 5.6 5.8-.4 3.6-3.5 6-7.1 6h-3.2L14.4 27.5H10.7L13 8.5z" fill="#009cde"/></svg>`;
12829
+ case "klarna":
12830
+ return `${SVG_OPEN} viewBox="0 0 24 24"><rect width="24" height="24" rx="6" fill="#FFA8CD"/><path fill="#0B051D" d="M8 6h2.7v12H8V6zm6.5 0h2.5c-.4 2.7-1.5 5-3 6.6 1.6 1.6 2.7 3.6 3.2 5.4h-2.7c-.5-1.6-1.4-3-2.7-4.2v4.2H10V12c2.1-1 3.8-3.2 4.5-6z"/></svg>`;
12831
+ case "crypto":
12832
+ return `${SVG_OPEN} viewBox="0 0 64 64"><path fill="#F7931A" d="m63.033,39.744c-4.274,17.143-21.637,27.576-38.782,23.301-17.138-4.274-27.571-21.638-23.295-38.78,4.272-17.145,21.635-27.579,38.775-23.305,17.144,4.274,27.576,21.64,23.302,38.784z"/><path fill="#FFF" d="m46.103,27.444c0.637-4.258-2.605-6.547-7.038-8.074l1.438-5.768-3.511-0.875-1.4,5.616c-0.923-0.23-1.871-0.447-2.813-0.662l1.41-5.653-3.509-0.875-1.439,5.766c-0.764-0.174-1.514-0.346-2.242-0.527l0.004-0.018-4.842-1.209-0.934,3.75s2.605,0.597,2.55,0.634c1.422,0.355,1.679,1.296,1.636,2.042l-1.638,6.571c0.098,0.025,0.225,0.061,0.365,0.117-0.117-0.029-0.242-0.061-0.371-0.092l-2.296,9.205c-0.174,0.432-0.615,1.08-1.609,0.834,0.035,0.051-2.552-0.637-2.552-0.637l-1.743,4.019,4.569,1.139c0.85,0.213,1.683,0.436,2.503,0.646l-1.453,5.834,3.507,0.875,1.439-5.772c0.958,0.26,1.888,0.5,2.798,0.726l-1.434,5.745,3.511,0.875,1.453-5.823c5.987,1.133,10.489,0.676,12.384-4.739,1.527-4.36-0.076-6.875-3.226-8.515,2.294-0.529,4.022-2.038,4.483-5.155zm-8.022,11.249c-1.085,4.36-8.426,2.003-10.806,1.412l1.928-7.729c2.38,0.594,10.012,1.77,8.878,6.317zm1.086-11.312c-0.99,3.966-7.1,1.951-9.082,1.457l1.748-7.01c1.982,0.494,8.365,1.416,7.334,5.553z"/></svg>`;
12833
+ case "wallet":
12834
+ return line(
12835
+ '<path d="M3 7a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2"/><rect x="3" y="7" width="18" height="12" rx="2"/><path d="M16 13h3"/>'
12836
+ );
12837
+ }
12838
+ }
12839
+ function isBuiltinKey(key) {
12840
+ return BUILTIN_PAYMENT_ICON_KEYS.includes(key);
12841
+ }
12842
+ function builtinPaymentIconSvg(key, color = "#1f2937") {
12843
+ return glyph(isBuiltinKey(key) ? key : "wallet", color);
12844
+ }
12845
+ function builtinPaymentIconDataUri(key, color) {
12846
+ return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(builtinPaymentIconSvg(key, color))}`;
12847
+ }
12848
+ function presentationIconDataUri(icon, color) {
12849
+ return icon.type === "svg" ? icon.data_uri : builtinPaymentIconDataUri(icon.key, color);
12850
+ }
12851
+ function presentationIconSrc(entry, color) {
12852
+ if (entry.icon) return presentationIconDataUri(entry.icon, color);
12853
+ if (entry.fallback_icon) return builtinPaymentIconDataUri(entry.fallback_icon, color);
12854
+ return null;
12855
+ }
12856
+ function isSupportedPresentation(response) {
12857
+ return response.contract_version === PRESENTATION_CONTRACT_VERSION;
12858
+ }
12859
+ function presentationTiers(response) {
12860
+ const out = { express: [], normal: [], alternative: [] };
12861
+ for (const entry of response.entries) {
12862
+ if (entry.tier === "express") {
12863
+ const row = entry.row ?? 0;
12864
+ while (out.express.length <= row) out.express.push([]);
12865
+ out.express[row]?.push(entry);
12866
+ } else {
12867
+ out[entry.tier].push(entry);
12868
+ }
12869
+ }
12870
+ out.express = out.express.filter((row) => row.length > 0);
12871
+ return out;
12872
+ }
12873
+ function selectableEntries(response) {
12874
+ return response.entries.filter((entry) => entry.action !== void 0);
12875
+ }
12876
+ var PresentationCache = class _PresentationCache {
12877
+ constructor(options) {
12878
+ this.slots = /* @__PURE__ */ new Map();
12879
+ this.load = options.load;
12880
+ this.now = options.now ?? Date.now;
12881
+ this.maxEntries = options.maxEntries ?? 500;
12882
+ }
12883
+ /** The key two requests share exactly when DeloPay would answer them alike. */
12884
+ static keyOf(params) {
12885
+ return JSON.stringify([
12886
+ params.profile_id ?? null,
12887
+ params.environment ?? "live",
12888
+ params.locale?.toLowerCase() ?? null,
12889
+ params.country?.toUpperCase() ?? null,
12890
+ params.currency ?? null,
12891
+ params.amount ?? null,
12892
+ params.contract_version ?? PRESENTATION_CONTRACT_VERSION
12893
+ ]);
12894
+ }
12895
+ async get(params) {
12896
+ const request = {
12897
+ ...params,
12898
+ contract_version: params.contract_version ?? PRESENTATION_CONTRACT_VERSION
12899
+ };
12900
+ if (request.client_secret) {
12901
+ return { response: await this.load(request, {}), stale: false };
12902
+ }
12903
+ const key = _PresentationCache.keyOf(request);
12904
+ const slot = this.slots.get(key);
12905
+ const now = this.now();
12906
+ if (slot && now - slot.fetchedAt < slot.response.cache.max_age_seconds * 1e3) {
12907
+ return { response: slot.response, stale: false };
12908
+ }
12909
+ try {
12910
+ const response = await this.load(
12911
+ request,
12912
+ slot ? { headers: { "If-None-Match": `"${slot.response.revision}"` } } : {}
12913
+ );
12914
+ this.store(key, response, now);
12915
+ return { response, stale: false };
12916
+ } catch (error) {
12917
+ if (slot && error instanceof DelopayError && error.status === 304) {
12918
+ this.store(key, slot.response, now);
12919
+ return { response: slot.response, stale: false };
12920
+ }
12921
+ const policy = slot?.response.cache;
12922
+ const usableUntil = slot ? slot.fetchedAt + ((policy?.max_age_seconds ?? 0) + (policy?.stale_if_error_seconds ?? 0)) * 1e3 : 0;
12923
+ if (slot && isUnavailable(error) && now < usableUntil) {
12924
+ return { response: slot.response, stale: true };
12925
+ }
12926
+ if (slot && isRefusal(error)) this.slots.delete(key);
12927
+ throw error;
12928
+ }
12929
+ }
12930
+ /** Forget every answer, e.g. after the merchant changes the checkout editor. */
12931
+ clear() {
12932
+ this.slots.clear();
12933
+ }
12934
+ store(key, response, now) {
12935
+ if (response.cache.max_age_seconds <= 0) {
12936
+ this.slots.delete(key);
12937
+ return;
12938
+ }
12939
+ this.slots.delete(key);
12940
+ this.slots.set(key, { response, fetchedAt: now });
12941
+ while (this.slots.size > this.maxEntries) {
12942
+ const oldest = this.slots.keys().next().value;
12943
+ if (oldest === void 0) break;
12944
+ this.slots.delete(oldest);
12945
+ }
12946
+ }
12606
12947
  };
12948
+ function isRefusal(error) {
12949
+ return error instanceof DelopayError && error.status >= 400 && error.status < 500 && error.status !== 429;
12950
+ }
12951
+ function isUnavailable(error) {
12952
+ if (!(error instanceof DelopayError)) return false;
12953
+ return error.status === 0 || error.status === 429 || error.status >= 500;
12954
+ }
12607
12955
 
12608
12956
  // src/panes.ts
12609
12957
  var PANE_VISIBILITIES = ["always", "embedded_only", "external_only"];
@@ -13033,6 +13381,7 @@ var encodeNativePanes = encodePanes;
13033
13381
  AvailabilityOverrides,
13034
13382
  BRANDING_EXPORT_FORMAT,
13035
13383
  BRANDING_EXPORT_VERSION,
13384
+ BUILTIN_PAYMENT_ICON_KEYS,
13036
13385
  BuyerBlocklist,
13037
13386
  CARD_FIELD_CHROMES,
13038
13387
  CARD_FIELD_FONT_SIZES,
@@ -13094,7 +13443,9 @@ var encodeNativePanes = encodePanes;
13094
13443
  PANE_ICON_KEYS,
13095
13444
  PAYPAL_CARD_LAYOUTS,
13096
13445
  PAYPAL_LABEL_STYLES,
13446
+ PRESENTATION_CONTRACT_VERSION,
13097
13447
  PaypalDisputes,
13448
+ PresentationCache,
13098
13449
  ProcessorCosts,
13099
13450
  Products,
13100
13451
  RTL_CHECKOUT_LOCALES,
@@ -13148,6 +13499,8 @@ var encodeNativePanes = encodePanes;
13148
13499
  applyBrandingVariables,
13149
13500
  asAirwallexCardPreset,
13150
13501
  buildBrandingExport,
13502
+ builtinPaymentIconDataUri,
13503
+ builtinPaymentIconSvg,
13151
13504
  buttonPadValue,
13152
13505
  canonicalSectionId,
13153
13506
  cardFieldFontPx,
@@ -13205,6 +13558,7 @@ var encodeNativePanes = encodePanes;
13205
13558
  isNoticeIcon,
13206
13559
  isSubscriptionDisputeWebhook,
13207
13560
  isSubscriptionLifecycleWebhook,
13561
+ isSupportedPresentation,
13208
13562
  knownSectionLabelKey,
13209
13563
  leaf,
13210
13564
  logoDimensions,
@@ -13222,6 +13576,9 @@ var encodeNativePanes = encodePanes;
13222
13576
  parseCustomFieldsLoose,
13223
13577
  parseImportedBranding,
13224
13578
  parseNoticesLoose,
13579
+ presentationIconDataUri,
13580
+ presentationIconSrc,
13581
+ presentationTiers,
13225
13582
  programToTree,
13226
13583
  radiusValue,
13227
13584
  readableInkOn,
@@ -13236,6 +13593,7 @@ var encodeNativePanes = encodePanes;
13236
13593
  sanitizeCustomCss,
13237
13594
  sectionLabel,
13238
13595
  sectionOrderOf,
13596
+ selectableEntries,
13239
13597
  shadowFor,
13240
13598
  shownNotices,
13241
13599
  stripeSpacingValues,