@swell/apps-sdk 1.0.162 → 1.0.164

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
@@ -7320,6 +7320,7 @@ var DEFAULT_OPTIONS = Object.freeze({
7320
7320
  });
7321
7321
  var NULL_VALUE = "__NULL__";
7322
7322
  var SWR_PROMISE_MAP = /* @__PURE__ */ new Map();
7323
+ var FETCH_PROMISE_MAP = /* @__PURE__ */ new Map();
7323
7324
  var Cache = class {
7324
7325
  client;
7325
7326
  workerCtx;
@@ -7332,8 +7333,30 @@ var Cache = class {
7332
7333
  ...options
7333
7334
  });
7334
7335
  }
7335
- async fetch(key, fetchFn, ttl) {
7336
- return this.client.wrap(key, fetchFn, ttl);
7336
+ /**
7337
+ * Always fetches fresh data and updates cache
7338
+ * Deduplicates concurrent requests with the same key
7339
+ *
7340
+ * @param key Cache key
7341
+ * @param fetchFn Function to fetch fresh data
7342
+ * @param ttl Time to live in milliseconds (default: DEFAULT_SWR_TTL)
7343
+ * @param isCacheable Whether to store result in cache (default: true)
7344
+ */
7345
+ async fetch(key, fetchFn, ttl = DEFAULT_SWR_TTL, isCacheable = true) {
7346
+ let promise = FETCH_PROMISE_MAP.get(key);
7347
+ if (!promise) {
7348
+ promise = Promise.resolve().then(fetchFn).then(resolveAsyncResources).then(async (value) => {
7349
+ const isNull = value === null || value === void 0;
7350
+ if (isCacheable) {
7351
+ await this.client.set(key, isNull ? NULL_VALUE : value, ttl);
7352
+ }
7353
+ return value;
7354
+ }).finally(() => {
7355
+ FETCH_PROMISE_MAP.delete(key);
7356
+ });
7357
+ FETCH_PROMISE_MAP.set(key, promise);
7358
+ }
7359
+ return await promise;
7337
7360
  }
7338
7361
  /**
7339
7362
  * Fetch cache using SWR (stale-while-revalidate)
@@ -8441,18 +8464,24 @@ var Swell = class _Swell {
8441
8464
  }
8442
8465
  return params;
8443
8466
  }
8467
+ /**
8468
+ * Checks if cache bypass is requested via X-Cache-Bypass header
8469
+ */
8470
+ shouldBypassCache() {
8471
+ return this.headers?.["x-cache-bypass"] === "revalidation";
8472
+ }
8444
8473
  /**
8445
8474
  * Fetches a resource.
8446
8475
  * First attempts to fetch from cache.
8447
8476
  */
8448
8477
  async getCachedResource(key, args, handler, isCacheble = true) {
8449
8478
  const cacheKey = getCacheKey(key, [this.instanceId, args]);
8450
- return this.getResourceCache().fetchSWR(
8451
- cacheKey,
8452
- handler,
8453
- void 0,
8454
- isCacheble
8455
- );
8479
+ const cache = this.getResourceCache();
8480
+ if (this.shouldBypassCache()) {
8481
+ return cache.fetch(cacheKey, handler, void 0, isCacheble);
8482
+ } else {
8483
+ return cache.fetchSWR(cacheKey, handler, void 0, isCacheble);
8484
+ }
8456
8485
  }
8457
8486
  async getAppSettings() {
8458
8487
  const settings = await this.get(
@@ -8619,11 +8648,17 @@ var Swell = class _Swell {
8619
8648
  data,
8620
8649
  opt
8621
8650
  ]);
8622
- return this.getRequestCache().fetchSWR(key, () => {
8651
+ const cache = this.getRequestCache();
8652
+ const fetchFn = () => {
8623
8653
  const requestUrl = id ? `${url}/${id}` : url;
8624
8654
  logger.debug("[SDK] Cacheable API request", { url: requestUrl, key });
8625
8655
  return storefrontRequest(method, url, id, data, opt);
8626
- });
8656
+ };
8657
+ if (this.shouldBypassCache()) {
8658
+ return cache.fetch(key, fetchFn);
8659
+ } else {
8660
+ return cache.fetchSWR(key, fetchFn);
8661
+ }
8627
8662
  }
8628
8663
  switch (method) {
8629
8664
  case "delete":
@@ -16022,7 +16057,7 @@ function ShopifyAddress(instance, address, account) {
16022
16057
  function joinAddressLines(...props) {
16023
16058
  return props.filter(Boolean).join("\n");
16024
16059
  }
16025
- function ShopifyCountry(_instance2, countryCode) {
16060
+ function ShopifyCountry(_instance, countryCode) {
16026
16061
  const currencyCode = getCurrencyByCountry(countryCode) || "USD";
16027
16062
  return new ShopifyResource(
16028
16063
  {
@@ -16355,7 +16390,7 @@ async function resolveLastOrder(instance, account) {
16355
16390
  }
16356
16391
 
16357
16392
  // src/compatibility/shopify-objects/font.ts
16358
- function ShopifyFont(_instance2, font) {
16393
+ function ShopifyFont(_instance, font) {
16359
16394
  if (font instanceof ShopifyResource) {
16360
16395
  return font.clone();
16361
16396
  }
@@ -16366,7 +16401,7 @@ function ShopifyFont(_instance2, font) {
16366
16401
  family: font.family,
16367
16402
  style: font.style,
16368
16403
  "system?": font.system,
16369
- variants: font.variants.map((variant) => ShopifyFont(_instance2, variant)),
16404
+ variants: font.variants.map((variant) => ShopifyFont(_instance, variant)),
16370
16405
  weight: font.weight
16371
16406
  });
16372
16407
  }
@@ -16379,7 +16414,7 @@ var SHOPIFY_FORMS = {
16379
16414
  })
16380
16415
  }
16381
16416
  };
16382
- function ShopifyForm(_instance2, form) {
16417
+ function ShopifyForm(_instance, form) {
16383
16418
  if (form instanceof ShopifyResource) {
16384
16419
  return form.clone();
16385
16420
  }
@@ -16676,7 +16711,7 @@ function ShopifyRecommendations(instance, product) {
16676
16711
  }
16677
16712
 
16678
16713
  // src/compatibility/shopify-objects/page.ts
16679
- function ShopifyPage(_instance2, page) {
16714
+ function ShopifyPage(_instance, page) {
16680
16715
  if (page instanceof ShopifyResource) {
16681
16716
  return page.clone();
16682
16717
  }
@@ -17888,7 +17923,7 @@ ${injects.join("\n")}</script>`;
17888
17923
  };
17889
17924
 
17890
17925
  // src/compatibility/shopify-objects/template.ts
17891
- function ShopifyTemplate(_instance2, template) {
17926
+ function ShopifyTemplate(_instance, template) {
17892
17927
  return new ShopifyResource(
17893
17928
  {
17894
17929
  directory: template.path,
@@ -22465,9 +22500,7 @@ var DEFAULT_CACHE_RULES = {
22465
22500
  preview: { ttl: 10, swr: 60 * 60 * 24 * 7 }
22466
22501
  // 10s TTL, 1 week SWR
22467
22502
  },
22468
- pathRules: [
22469
- { path: "/checkout/*", skip: true }
22470
- ]
22503
+ pathRules: [{ path: "/checkout/*", skip: true }]
22471
22504
  };
22472
22505
  var HtmlCache = class {
22473
22506
  epoch;
@@ -22557,6 +22590,16 @@ var HtmlCache = class {
22557
22590
  const ttl = this.getTTLForRequest(request);
22558
22591
  const swr = this.getSWRForRequest(request);
22559
22592
  const body = await response.text();
22593
+ if (!body || body.trim().length === 0) {
22594
+ logger.warn(
22595
+ "[SDK Html-cache] put skipped, empty or minimal response body",
22596
+ {
22597
+ trace,
22598
+ bodyLength: body.length
22599
+ }
22600
+ );
22601
+ return;
22602
+ }
22560
22603
  const cacheTimeISO = (/* @__PURE__ */ new Date()).toISOString();
22561
22604
  const headers = this.normalizeHeaders(response.headers);
22562
22605
  const entry = {
@@ -22614,7 +22657,7 @@ var HtmlCache = class {
22614
22657
  }
22615
22658
  buildClientResponse(entry, isStale, age) {
22616
22659
  const headers = new Headers(entry.headers);
22617
- headers.set("Cache-Control", "public, max-age=0, must-revalidate");
22660
+ headers.set("Cache-Control", "public, max-age=1, must-revalidate");
22618
22661
  headers.set(
22619
22662
  "Cloudflare-CDN-Cache-Control",
22620
22663
  `public, s-maxage=${entry.ttl}, stale-while-revalidate=${entry.swr}, stale-if-error=60`
@@ -22709,7 +22752,7 @@ var HtmlCache = class {
22709
22752
  const accept = headers.get("accept") || "";
22710
22753
  const versionFactors = {
22711
22754
  store: headers.get("swell-storefront-id") || "",
22712
- app: (headers.get("swell-app-id") || "") + "@" + (swellData["swell-app-version"] || ""),
22755
+ app: (headers.get("swell-app-id") || "") + "@" + (headers.get("host") || ""),
22713
22756
  auth: headers.get("swell-access-token") || "",
22714
22757
  theme: headers.get("swell-theme-version-hash") || "",
22715
22758
  modified: headers.get("swell-cache-modified") || "",
@@ -22975,7 +23018,6 @@ var WorkerCacheBackend = class {
22975
23018
  statusText: entry.statusText,
22976
23019
  headers
22977
23020
  });
22978
- await cache.delete(request);
22979
23021
  await cache.put(request, response);
22980
23022
  }
22981
23023
  async delete(key) {
@@ -22986,19 +23028,15 @@ var WorkerCacheBackend = class {
22986
23028
  };
22987
23029
 
22988
23030
  // src/cache/html-cache/html-cache-factory.ts
22989
- var _instance = null;
22990
23031
  function getHtmlCache(env, cacheRules) {
22991
23032
  const epoch = env?.HTML_CACHE_EPOCH;
22992
23033
  if (typeof epoch !== "string" || !epoch) return null;
22993
- if (_instance) return _instance;
22994
23034
  const kv = env?.NAMESPACE;
22995
23035
  const rules = cacheRules || env?.HTML_CACHE_RULES;
22996
23036
  if (env?.HTML_CACHE_BACKEND !== "worker" && kv) {
22997
- _instance = new HtmlCache(epoch, new KVCacheBackend(kv), rules);
22998
- return _instance;
23037
+ return new HtmlCache(epoch, new KVCacheBackend(kv), rules);
22999
23038
  }
23000
- _instance = new HtmlCache(epoch, new WorkerCacheBackend(epoch), rules);
23001
- return _instance;
23039
+ return new HtmlCache(epoch, new WorkerCacheBackend(epoch), rules);
23002
23040
  }
23003
23041
  // Annotate the CommonJS export names for ESM import in node:
23004
23042
  0 && (module.exports = {