@swell/apps-sdk 1.0.151 → 1.0.153

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
@@ -94,6 +94,7 @@ __export(index_exports, {
94
94
  ThemeFont: () => ThemeFont,
95
95
  ThemeForm: () => ThemeForm,
96
96
  ThemeFormErrors: () => ThemeFormErrors,
97
+ WorkerHtmlCache: () => WorkerHtmlCache,
97
98
  adaptShopifyFontData: () => adaptShopifyFontData,
98
99
  adaptShopifyFormData: () => adaptShopifyFormData,
99
100
  adaptShopifyMenuData: () => adaptShopifyMenuData,
@@ -160,72 +161,6 @@ var import_qs2 = __toESM(require("qs"), 1);
160
161
  var import_keyv = require("keyv");
161
162
  var import_cache_manager = require("cache-manager");
162
163
 
163
- // src/cache/cf-worker-kv-keyv-adapter.ts
164
- var CFWorkerKVKeyvAdapter = class {
165
- store;
166
- namespace;
167
- // magically passed in from Keyv
168
- opts;
169
- constructor(store) {
170
- this.store = store;
171
- this.opts = null;
172
- this.namespace = "dummy";
173
- }
174
- async has(key) {
175
- const stream = await this.store.get(key, "stream");
176
- if (stream !== null) {
177
- await stream.cancel();
178
- return true;
179
- }
180
- return false;
181
- }
182
- async get(key) {
183
- const value = await this.store.get(key);
184
- return value !== null ? value : void 0;
185
- }
186
- set(key, value, ttl) {
187
- if (typeof ttl === "number") {
188
- ttl = Math.max(60, ttl / 1e3);
189
- }
190
- return this.store.put(key, value, { expirationTtl: ttl });
191
- }
192
- async delete(key) {
193
- await this.store.delete(key);
194
- return true;
195
- }
196
- async clear() {
197
- let cursor = "";
198
- let complete = false;
199
- const prefix = `${this.namespace}:`;
200
- do {
201
- const response = await this.store.list({
202
- prefix,
203
- cursor: cursor || void 0
204
- });
205
- cursor = response.cursor ?? "";
206
- complete = response.list_complete;
207
- if (response.keys.length > 0) {
208
- await Promise.all(
209
- response.keys.map((key) => {
210
- return this.store.delete(key.name);
211
- })
212
- );
213
- }
214
- } while (!complete);
215
- }
216
- on(_event, _listener) {
217
- return this;
218
- }
219
- };
220
-
221
- // src/utils/index.ts
222
- var import_qs = __toESM(require("qs"), 1);
223
- var import_lodash_es3 = require("lodash-es");
224
- var import_json52 = __toESM(require("json5"), 1);
225
-
226
- // src/resources.ts
227
- var import_lodash_es2 = require("lodash-es");
228
-
229
164
  // src/utils/logger.ts
230
165
  var logLevels = {
231
166
  error: 0,
@@ -317,6 +252,80 @@ function createTraceId(data) {
317
252
  return (hash >>> 0).toString(16);
318
253
  }
319
254
 
255
+ // src/cache/cf-worker-kv-keyv-adapter.ts
256
+ var CFWorkerKVKeyvAdapter = class {
257
+ store;
258
+ namespace;
259
+ // magically passed in from Keyv
260
+ opts;
261
+ constructor(store) {
262
+ this.store = store;
263
+ this.opts = null;
264
+ this.namespace = "dummy";
265
+ }
266
+ async has(key) {
267
+ const stream = await this.store.get(key, "stream");
268
+ if (stream !== null) {
269
+ await stream.cancel();
270
+ return true;
271
+ }
272
+ return false;
273
+ }
274
+ async get(key) {
275
+ const trace = createTraceId();
276
+ logger.debug("[SDK] kv.get", { key, trace });
277
+ const value = await this.store.get(key);
278
+ const result = value !== null ? value : void 0;
279
+ logger.debug(`[SDK] kv.get ${value !== null ? "HIT" : "MISS"}`, {
280
+ key,
281
+ trace
282
+ });
283
+ return result;
284
+ }
285
+ set(key, value, ttl) {
286
+ if (typeof ttl === "number") {
287
+ ttl = Math.max(60, ttl / 1e3);
288
+ }
289
+ logger.debug("[SDK] kv.set", { key });
290
+ return this.store.put(key, value, { expirationTtl: ttl });
291
+ }
292
+ async delete(key) {
293
+ await this.store.delete(key);
294
+ return true;
295
+ }
296
+ async clear() {
297
+ let cursor = "";
298
+ let complete = false;
299
+ const prefix = `${this.namespace}:`;
300
+ do {
301
+ const response = await this.store.list({
302
+ prefix,
303
+ cursor: cursor || void 0
304
+ });
305
+ cursor = response.cursor ?? "";
306
+ complete = response.list_complete;
307
+ if (response.keys.length > 0) {
308
+ await Promise.all(
309
+ response.keys.map((key) => {
310
+ return this.store.delete(key.name);
311
+ })
312
+ );
313
+ }
314
+ } while (!complete);
315
+ }
316
+ on(_event, _listener) {
317
+ return this;
318
+ }
319
+ };
320
+
321
+ // src/utils/index.ts
322
+ var import_qs = __toESM(require("qs"), 1);
323
+ var import_lodash_es3 = require("lodash-es");
324
+ var import_json52 = __toESM(require("json5"), 1);
325
+
326
+ // src/resources.ts
327
+ var import_lodash_es2 = require("lodash-es");
328
+
320
329
  // src/liquid/utils.ts
321
330
  var import_liquidjs = require("liquidjs");
322
331
 
@@ -960,6 +969,7 @@ var SwellStorefrontCollection = class _SwellStorefrontCollection extends SwellSt
960
969
  this._collection,
961
970
  this._query,
962
971
  this._swell.queryParams,
972
+ // TODO: consider to exlcude
963
973
  this._getterHash
964
974
  ],
965
975
  getter,
@@ -1088,6 +1098,7 @@ var SwellStorefrontRecord = class extends SwellStorefrontResource {
1088
1098
  this._id,
1089
1099
  this._query,
1090
1100
  this._swell.queryParams,
1101
+ // TODO: consider to exlcude
1091
1102
  this._getterHash
1092
1103
  ],
1093
1104
  getter,
@@ -7316,8 +7327,6 @@ var Cache = class {
7316
7327
  * This will always return the cached value immediately if exists
7317
7328
  */
7318
7329
  async fetchSWR(key, fetchFn, ttl = DEFAULT_SWR_TTL, isCacheble = true) {
7319
- const trace = createTraceId();
7320
- logger.debug("[SDK] Cache fetch start", { key, trace });
7321
7330
  const cacheValue = isCacheble ? await this.client.get(key) : void 0;
7322
7331
  let promise = SWR_PROMISE_MAP.get(key);
7323
7332
  if (promise === void 0) {
@@ -7325,7 +7334,6 @@ var Cache = class {
7325
7334
  const isNull = value === null || value === void 0;
7326
7335
  if (isCacheble) {
7327
7336
  await this.client.set(key, isNull ? NULL_VALUE : value, ttl);
7328
- logger.debug("[SDK] Cache update done", { key, trace });
7329
7337
  }
7330
7338
  return value;
7331
7339
  }).finally(() => {
@@ -7337,12 +7345,9 @@ var Cache = class {
7337
7345
  this.workerCtx.waitUntil(promise);
7338
7346
  }
7339
7347
  if (cacheValue !== void 0) {
7340
- logger.debug("[SDK] Cache check done", { status: "HIT", key, trace });
7341
7348
  return cacheValue === NULL_VALUE ? null : cacheValue;
7342
7349
  }
7343
- logger.debug("[SDK] Cache check done", { status: "MISS", key, trace });
7344
7350
  const result = await promise;
7345
- logger.debug("[SDK] Cache fetch end", { key, trace });
7346
7351
  return result;
7347
7352
  }
7348
7353
  async get(key) {
@@ -7849,6 +7854,384 @@ var WorkerCacheProxy = class {
7849
7854
  }
7850
7855
  };
7851
7856
 
7857
+ // src/cache/worker-html-cache.ts
7858
+ var CACHE_NAME2 = "swell-html-v1";
7859
+ var CACHE_KEY_ORIGIN2 = "https://cache.swell.store";
7860
+ var TTL_CONFIG = {
7861
+ LIVE: {
7862
+ DEFAULT: 300,
7863
+ // 5 minutes
7864
+ HOME: 300,
7865
+ // 5 minutes
7866
+ PRODUCT: 600,
7867
+ // 10 minutes
7868
+ COLLECTION: 900,
7869
+ // 15 minutes
7870
+ PAGE: 3600,
7871
+ // 1 hour
7872
+ BLOG: 1800,
7873
+ // 30 minutes
7874
+ SWR: 3600
7875
+ // 1 hour stale-while-revalidate
7876
+ },
7877
+ PREVIEW: {
7878
+ DEFAULT: 5,
7879
+ // 1 minute - faster updates in preview
7880
+ HOME: 5,
7881
+ // 1 minute
7882
+ PRODUCT: 5,
7883
+ // 2 minutes
7884
+ COLLECTION: 5,
7885
+ // 3 minutes
7886
+ PAGE: 5,
7887
+ // 5 minutes
7888
+ BLOG: 5,
7889
+ // 5 minutes
7890
+ SWR: 600
7891
+ // 10 minutes stale-while-revalidate
7892
+ }
7893
+ };
7894
+ var WorkerHtmlCache = class {
7895
+ epoch;
7896
+ constructor(epoch) {
7897
+ this.epoch = epoch;
7898
+ }
7899
+ async get(request) {
7900
+ const trace = createTraceId();
7901
+ if (request.method !== "GET") {
7902
+ logger.debug("[SDK Html-cache] non-cacheable", { trace });
7903
+ return { found: false, cacheable: false };
7904
+ }
7905
+ if (!this.isCacheable(request)) {
7906
+ logger.debug("[SDK Html-cache] non-cacheable", { trace });
7907
+ return { found: false, cacheable: false };
7908
+ }
7909
+ try {
7910
+ const cache = await caches.open(CACHE_NAME2 + this.epoch);
7911
+ const cacheKey = this.buildCacheKey(request);
7912
+ const cached = await cache.match(cacheKey);
7913
+ if (!cached) {
7914
+ logger.debug("[SDK Html-cache] cacheable, MISS", { trace });
7915
+ return { found: false, cacheable: true };
7916
+ }
7917
+ const age = this.getResponseAge(cached);
7918
+ const ttl = parseInt(cached.headers.get("X-Original-TTL") || "") || this.getTTLForRequest(request);
7919
+ const swr = parseInt(cached.headers.get("X-Original-SWR") || "") || this.getSWRForRequest(request);
7920
+ const isStale = age >= ttl;
7921
+ const isExpired = age >= ttl + swr;
7922
+ if (!isExpired) {
7923
+ logger.debug("[SDK Html-cache] cacheable, HIT", {
7924
+ stale: isStale,
7925
+ age,
7926
+ trace
7927
+ });
7928
+ const clientResponse = this.buildClientResponse(
7929
+ cached,
7930
+ ttl,
7931
+ swr,
7932
+ isStale,
7933
+ age
7934
+ );
7935
+ return {
7936
+ found: true,
7937
+ stale: isStale,
7938
+ response: clientResponse,
7939
+ cacheable: true,
7940
+ age: Math.floor(age)
7941
+ };
7942
+ }
7943
+ logger.debug("[SDK Html-cache] cacheable, hit, expired", { trace });
7944
+ return { found: false, cacheable: true };
7945
+ } catch (_) {
7946
+ logger.warn("[SDK Html-cache] no get support", { trace });
7947
+ return null;
7948
+ }
7949
+ }
7950
+ // 304 support
7951
+ async getWithConditionals(request) {
7952
+ const result = await this.get(request);
7953
+ if (!result?.found || result.stale) {
7954
+ return result;
7955
+ }
7956
+ const ifModifiedSince = request.headers.get("If-Modified-Since");
7957
+ const ifNoneMatch = request.headers.get("If-None-Match");
7958
+ if ((ifModifiedSince || ifNoneMatch) && result.response) {
7959
+ const lastModified = result.response.headers.get("Last-Modified");
7960
+ const etag = result.response.headers.get("ETag");
7961
+ if (this.checkNotModified(ifModifiedSince, ifNoneMatch, lastModified, etag)) {
7962
+ result.notModified = true;
7963
+ result.conditional304 = new Response(null, {
7964
+ status: 304,
7965
+ headers: {
7966
+ "Last-Modified": lastModified || "",
7967
+ ETag: etag || "",
7968
+ "Cache-Control": result.response.headers.get("Cache-Control") || "",
7969
+ "Cloudflare-CDN-Cache-Control": result.response.headers.get("Cloudflare-CDN-Cache-Control") || "",
7970
+ "X-Cache-Status": "HIT-304"
7971
+ }
7972
+ });
7973
+ }
7974
+ }
7975
+ return result;
7976
+ }
7977
+ checkNotModified(ifModifiedSince, ifNoneMatch, lastModified, etag) {
7978
+ if (ifNoneMatch && etag) {
7979
+ return ifNoneMatch === etag;
7980
+ }
7981
+ if (ifModifiedSince && lastModified) {
7982
+ const ifModDate = new Date(ifModifiedSince);
7983
+ const lastModDate = new Date(lastModified);
7984
+ return !isNaN(ifModDate.getTime()) && !isNaN(lastModDate.getTime()) && ifModDate >= lastModDate;
7985
+ }
7986
+ return false;
7987
+ }
7988
+ createRevalidationRequest(request) {
7989
+ const headers = new Headers(request.headers);
7990
+ headers.set("X-Cache-Bypass", "revalidation");
7991
+ headers.delete("If-None-Match");
7992
+ headers.delete("If-Modified-Since");
7993
+ headers.delete("Cache-Control");
7994
+ headers.delete("Pragma");
7995
+ return new Request(request.url, {
7996
+ method: "GET",
7997
+ headers
7998
+ });
7999
+ }
8000
+ async put(request, response) {
8001
+ const trace = createTraceId();
8002
+ if (request.method !== "GET" || !response.ok) {
8003
+ logger.debug("[SDK Html-cache] put skipped", { trace });
8004
+ return;
8005
+ }
8006
+ if (!this.isCacheable(request) || !this.isResponseCacheable(response)) {
8007
+ logger.debug("[SDK Html-cache] put skipped, non-cacheable", {
8008
+ trace
8009
+ });
8010
+ return;
8011
+ }
8012
+ try {
8013
+ const cache = await caches.open(CACHE_NAME2 + this.epoch);
8014
+ const cacheKey = this.buildCacheKey(request);
8015
+ await cache.delete(cacheKey);
8016
+ const ttl = this.getTTLForRequest(request);
8017
+ const swr = this.getSWRForRequest(request);
8018
+ const headers = new Headers(response.headers);
8019
+ const existingCacheControl = response.headers.get("Cache-Control");
8020
+ if (!existingCacheControl || existingCacheControl === "public") {
8021
+ const internalMaxAge = ttl + swr;
8022
+ headers.set("Cache-Control", `public, max-age=${internalMaxAge}`);
8023
+ }
8024
+ const cacheTime = (/* @__PURE__ */ new Date()).toISOString();
8025
+ headers.set("X-Cache-Time", cacheTime);
8026
+ headers.set("X-Original-TTL", ttl.toString());
8027
+ headers.set("X-Original-SWR", swr.toString());
8028
+ if (!headers.get("Last-Modified")) {
8029
+ headers.set("Last-Modified", new Date(cacheTime).toUTCString());
8030
+ }
8031
+ const cacheableResponse = new Response(response.body, {
8032
+ status: response.status,
8033
+ statusText: response.statusText,
8034
+ headers
8035
+ });
8036
+ await cache.put(cacheKey, cacheableResponse);
8037
+ logger.debug("[SDK Html-cache] put done", { trace });
8038
+ } catch (_) {
8039
+ logger.warn("[SDK Html-cache] no put support", { trace });
8040
+ }
8041
+ }
8042
+ buildClientResponse(cachedResponse, ttl, swr, isStale, age) {
8043
+ const headers = new Headers(cachedResponse.headers);
8044
+ headers.set(
8045
+ "Cache-Control",
8046
+ `public, max-age=${ttl}, stale-while-revalidate=${swr}`
8047
+ );
8048
+ headers.set(
8049
+ "Cloudflare-CDN-Cache-Control",
8050
+ `public, s-maxage=${ttl}, stale-while-revalidate=${swr}, stale-if-error=60`
8051
+ );
8052
+ const cacheTime = headers.get("X-Cache-Time");
8053
+ if (cacheTime) {
8054
+ const lastModified = new Date(cacheTime).toUTCString();
8055
+ headers.set("Last-Modified", lastModified);
8056
+ }
8057
+ headers.set("X-Cache-Status", isStale ? "STALE" : "HIT");
8058
+ headers.set("X-Cache-Age", Math.floor(age).toString());
8059
+ headers.delete("X-Original-TTL");
8060
+ headers.delete("X-Original-SWR");
8061
+ headers.delete("X-Cache-Time");
8062
+ return new Response(cachedResponse.body, {
8063
+ status: cachedResponse.status,
8064
+ statusText: cachedResponse.statusText,
8065
+ headers
8066
+ });
8067
+ }
8068
+ buildCacheKey(request) {
8069
+ const url = new URL(request.url);
8070
+ const versionHash = this.generateVersionHash(request.headers);
8071
+ const normalizedQuery = this.normalizeSearchParams(url.searchParams);
8072
+ const cacheKeyPath = `${versionHash}${url.pathname}`;
8073
+ const keyUrl = new URL(`${CACHE_KEY_ORIGIN2}${cacheKeyPath}`);
8074
+ if (normalizedQuery) {
8075
+ keyUrl.search = `?${normalizedQuery}`;
8076
+ }
8077
+ const sanitizedHeaders = this.sanitizeHeaders(request.headers);
8078
+ return new Request(keyUrl.toString(), {
8079
+ method: "GET",
8080
+ headers: sanitizedHeaders
8081
+ });
8082
+ }
8083
+ sanitizeHeaders(originalHeaders) {
8084
+ const CACHE_RELEVANT_HEADERS = [
8085
+ // Content negotiation (affects response format)
8086
+ "accept",
8087
+ "accept-language"
8088
+ ];
8089
+ const sanitized = new Headers();
8090
+ CACHE_RELEVANT_HEADERS.forEach((header) => {
8091
+ const value = originalHeaders.get(header);
8092
+ if (value) {
8093
+ sanitized.set(header, value);
8094
+ }
8095
+ });
8096
+ return sanitized;
8097
+ }
8098
+ generateVersionHash(headers) {
8099
+ const swellData = this.extractSwellData(headers);
8100
+ const versionFactors = {
8101
+ store: headers.get("swell-storefront-id") || "",
8102
+ auth: headers.get("swell-access-token") || "",
8103
+ theme: headers.get("swell-theme-version-hash") || "",
8104
+ modified: headers.get("swell-cache-modified") || "",
8105
+ currency: swellData["swell-currency"] || "USD",
8106
+ locale: headers.get("x-locale") || headers.get("accept-language")?.split(",")[0] || "default",
8107
+ context: headers.get("swell-storefront-context"),
8108
+ epoch: this.epoch
8109
+ };
8110
+ return md5(JSON.stringify(versionFactors));
8111
+ }
8112
+ extractSwellData(headers) {
8113
+ const cookie = headers.get("cookie");
8114
+ if (!cookie) return {};
8115
+ const swellDataMatch = cookie.match(/swell-data=([^;]+)/);
8116
+ if (!swellDataMatch) return {};
8117
+ try {
8118
+ const parsed = JSON.parse(decodeURIComponent(swellDataMatch[1]));
8119
+ if (typeof parsed === "object" && parsed !== null) {
8120
+ return parsed;
8121
+ }
8122
+ return {};
8123
+ } catch {
8124
+ return {};
8125
+ }
8126
+ }
8127
+ isCacheable(request) {
8128
+ const url = new URL(request.url);
8129
+ const headers = request.headers;
8130
+ if (headers.get("swell-deployment-mode") === "editor") {
8131
+ return false;
8132
+ }
8133
+ const skipPaths = ["/checkout"];
8134
+ if (skipPaths.some((path) => url.pathname.startsWith(path))) {
8135
+ return false;
8136
+ }
8137
+ if (headers.get("cache-control")?.includes("no-cache")) {
8138
+ return false;
8139
+ }
8140
+ return true;
8141
+ }
8142
+ isResponseCacheable(response) {
8143
+ const contentType = response.headers.get("content-type");
8144
+ if (!contentType?.includes("text/html")) {
8145
+ return false;
8146
+ }
8147
+ if (response.headers.get("set-cookie")) {
8148
+ return false;
8149
+ }
8150
+ const cacheControl = response.headers.get("cache-control");
8151
+ if (cacheControl?.includes("no-store") || cacheControl?.includes("private")) {
8152
+ return false;
8153
+ }
8154
+ return true;
8155
+ }
8156
+ getDeploymentMode(headers) {
8157
+ const mode = headers.get("swell-deployment-mode");
8158
+ if (mode === "preview" || mode === "editor") {
8159
+ return mode;
8160
+ }
8161
+ return "live";
8162
+ }
8163
+ getTTLForRequest(request) {
8164
+ const url = new URL(request.url);
8165
+ const path = url.pathname;
8166
+ const mode = this.getDeploymentMode(request.headers);
8167
+ if (mode === "editor") {
8168
+ return 0;
8169
+ }
8170
+ const config = mode === "preview" ? TTL_CONFIG.PREVIEW : TTL_CONFIG.LIVE;
8171
+ if (path === "/") {
8172
+ return config.HOME;
8173
+ }
8174
+ if (path.startsWith("/products/")) {
8175
+ return config.PRODUCT;
8176
+ }
8177
+ if (path.startsWith("/categories/")) {
8178
+ return config.COLLECTION;
8179
+ }
8180
+ if (path.startsWith("/pages/")) {
8181
+ return config.PAGE;
8182
+ }
8183
+ if (path.startsWith("/blogs/")) {
8184
+ return config.BLOG;
8185
+ }
8186
+ return config.DEFAULT;
8187
+ }
8188
+ getSWRForRequest(request) {
8189
+ const mode = this.getDeploymentMode(request.headers);
8190
+ if (mode === "editor") {
8191
+ return 0;
8192
+ }
8193
+ return mode === "preview" ? TTL_CONFIG.PREVIEW.SWR : TTL_CONFIG.LIVE.SWR;
8194
+ }
8195
+ getResponseAge(response) {
8196
+ const cacheTime = response.headers.get("X-Cache-Time");
8197
+ if (!cacheTime) {
8198
+ return Infinity;
8199
+ }
8200
+ const cacheDate = new Date(cacheTime);
8201
+ if (isNaN(cacheDate.getTime())) {
8202
+ return Infinity;
8203
+ }
8204
+ const age = (Date.now() - cacheDate.getTime()) / 1e3;
8205
+ return Math.max(0, age);
8206
+ }
8207
+ normalizeSearchParams(searchParams) {
8208
+ const ignoredParams = [
8209
+ "utm_source",
8210
+ "utm_medium",
8211
+ "utm_campaign",
8212
+ "utm_content",
8213
+ "utm_term",
8214
+ "fbclid",
8215
+ "gclid",
8216
+ "gbraid",
8217
+ "wbraid",
8218
+ "ref",
8219
+ "source",
8220
+ "mc_cid",
8221
+ "mc_eid"
8222
+ ];
8223
+ const relevantParams = [];
8224
+ searchParams.forEach((value, key) => {
8225
+ if (!ignoredParams.includes(key)) {
8226
+ relevantParams.push(
8227
+ `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
8228
+ );
8229
+ }
8230
+ });
8231
+ return relevantParams.sort().join("&");
8232
+ }
8233
+ };
8234
+
7852
8235
  // src/resources/addresses.ts
7853
8236
  var SwellAddresses = class extends SwellStorefrontCollection {
7854
8237
  constructor(swell, query) {
@@ -8676,13 +9059,19 @@ var Swell = class _Swell {
8676
9059
  const storefrontRequest = storefront.request;
8677
9060
  return (method, url, id, data, opt) => {
8678
9061
  if (this.isStorefrontRequestCacheable(method, url, opt)) {
8679
- return this.getRequestCache().fetchSWR(
8680
- getCacheKey("request", [this.instanceId, method, url, id, data, opt]),
8681
- () => {
8682
- logger.info("[SDK] Storefront request", { method, url, id, data });
8683
- return storefrontRequest(method, url, id, data, opt);
8684
- }
8685
- );
9062
+ const key = getCacheKey("request", [
9063
+ this.instanceId,
9064
+ method,
9065
+ url,
9066
+ id,
9067
+ data,
9068
+ opt
9069
+ ]);
9070
+ return this.getRequestCache().fetchSWR(key, () => {
9071
+ const requestUrl = id ? `${url}/${id}` : url;
9072
+ logger.debug("[SDK] Cacheable API request", { url: requestUrl, key });
9073
+ return storefrontRequest(method, url, id, data, opt);
9074
+ });
8686
9075
  }
8687
9076
  switch (method) {
8688
9077
  case "delete":
@@ -8729,7 +9118,9 @@ var Swell = class _Swell {
8729
9118
  };
8730
9119
  function getCacheKey(key, args) {
8731
9120
  if (Array.isArray(args) && args.length > 0) {
8732
- return `${key}_${md5(JSON.stringify(args))}`;
9121
+ const fullKey = `${key}_${md5(JSON.stringify(args))}`;
9122
+ logger.debug(`[SDK] make cache key: ${fullKey}`);
9123
+ return fullKey;
8733
9124
  }
8734
9125
  return key;
8735
9126
  }
@@ -22504,6 +22895,7 @@ function getResourceQuery(slug, query) {
22504
22895
  ThemeFont,
22505
22896
  ThemeForm,
22506
22897
  ThemeFormErrors,
22898
+ WorkerHtmlCache,
22507
22899
  adaptShopifyFontData,
22508
22900
  adaptShopifyFormData,
22509
22901
  adaptShopifyMenuData,