@swell/apps-sdk 1.0.150 → 1.0.152

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.
Files changed (43) hide show
  1. package/dist/index.cjs +767 -185
  2. package/dist/index.cjs.map +4 -4
  3. package/dist/index.js +747 -185
  4. package/dist/index.js.map +4 -4
  5. package/dist/index.mjs +757 -185
  6. package/dist/index.mjs.map +4 -4
  7. package/dist/src/cache/cache-api-stub.d.ts +25 -0
  8. package/dist/src/cache/index.d.ts +2 -0
  9. package/dist/src/cache/worker-html-cache.d.ts +43 -0
  10. package/dist/src/compatibility/drops/all_products.d.ts +1 -1
  11. package/dist/src/compatibility/drops/articles.d.ts +1 -1
  12. package/dist/src/compatibility/drops/blogs.d.ts +1 -1
  13. package/dist/src/compatibility/drops/collections.d.ts +2 -3
  14. package/dist/src/compatibility/drops/images.d.ts +1 -1
  15. package/dist/src/compatibility/drops/pages.d.ts +2 -3
  16. package/dist/src/compatibility/shopify-objects/collections.d.ts +2 -2
  17. package/dist/src/content.d.ts +3 -3
  18. package/dist/src/index.d.ts +3 -0
  19. package/dist/src/liquid/filters/shopify/default_pagination.d.ts +1 -1
  20. package/dist/src/resources/account.d.ts +4 -4
  21. package/dist/src/resources/addresses.d.ts +7 -0
  22. package/dist/src/resources/blog.d.ts +5 -4
  23. package/dist/src/resources/blog_category.d.ts +5 -4
  24. package/dist/src/resources/cart.d.ts +4 -4
  25. package/dist/src/resources/categories.d.ts +7 -0
  26. package/dist/src/resources/category.d.ts +5 -4
  27. package/dist/src/resources/index.d.ts +18 -9
  28. package/dist/src/resources/order.d.ts +5 -4
  29. package/dist/src/resources/orders.d.ts +7 -0
  30. package/dist/src/resources/page.d.ts +5 -4
  31. package/dist/src/resources/predictive_search.d.ts +6 -0
  32. package/dist/src/resources/product.d.ts +5 -19
  33. package/dist/src/resources/product_helpers.d.ts +12 -2
  34. package/dist/src/resources/product_recommendations.d.ts +6 -0
  35. package/dist/src/resources/search.d.ts +6 -0
  36. package/dist/src/resources/subscription.d.ts +7 -0
  37. package/dist/src/resources/subscriptions.d.ts +7 -0
  38. package/dist/src/resources/swell_types.d.ts +66 -9
  39. package/dist/src/resources/variant.d.ts +8 -8
  40. package/dist/src/resources.d.ts +11 -12
  41. package/dist/types/shopify.d.ts +2 -2
  42. package/dist/types/swell.d.ts +3 -1
  43. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -66,25 +66,35 @@ __export(index_exports, {
66
66
  StorefrontResource: () => StorefrontResource,
67
67
  Swell: () => Swell,
68
68
  SwellAccount: () => SwellAccount,
69
+ SwellAddresses: () => SwellAddresses,
69
70
  SwellBackendAPI: () => SwellBackendAPI,
70
71
  SwellBlog: () => SwellBlog,
71
72
  SwellBlogCategory: () => SwellBlogCategory,
72
73
  SwellCart: () => SwellCart,
74
+ SwellCategories: () => SwellCategories,
73
75
  SwellCategory: () => SwellCategory,
74
76
  SwellError: () => SwellError,
75
77
  SwellOrder: () => SwellOrder,
78
+ SwellOrders: () => SwellOrders,
76
79
  SwellPage: () => SwellPage,
80
+ SwellPredictiveSearch: () => SwellPredictiveSearch,
77
81
  SwellProduct: () => SwellProduct,
82
+ SwellProductRecommendations: () => SwellProductRecommendations,
83
+ SwellSearch: () => SwellSearch,
78
84
  SwellStorefrontCollection: () => SwellStorefrontCollection,
79
85
  SwellStorefrontPagination: () => SwellStorefrontPagination,
80
86
  SwellStorefrontRecord: () => SwellStorefrontRecord,
81
87
  SwellStorefrontResource: () => SwellStorefrontResource,
82
88
  SwellStorefrontSingleton: () => SwellStorefrontSingleton,
89
+ SwellSubscription: () => SwellSubscription,
90
+ SwellSubscriptions: () => SwellSubscriptions,
83
91
  SwellTheme: () => SwellTheme3,
92
+ SwellVariant: () => SwellVariant,
84
93
  ThemeColor: () => ThemeColor,
85
94
  ThemeFont: () => ThemeFont,
86
95
  ThemeForm: () => ThemeForm,
87
96
  ThemeFormErrors: () => ThemeFormErrors,
97
+ WorkerHtmlCache: () => WorkerHtmlCache,
88
98
  adaptShopifyFontData: () => adaptShopifyFontData,
89
99
  adaptShopifyFormData: () => adaptShopifyFormData,
90
100
  adaptShopifyMenuData: () => adaptShopifyMenuData,
@@ -151,72 +161,6 @@ var import_qs2 = __toESM(require("qs"), 1);
151
161
  var import_keyv = require("keyv");
152
162
  var import_cache_manager = require("cache-manager");
153
163
 
154
- // src/cache/cf-worker-kv-keyv-adapter.ts
155
- var CFWorkerKVKeyvAdapter = class {
156
- store;
157
- namespace;
158
- // magically passed in from Keyv
159
- opts;
160
- constructor(store) {
161
- this.store = store;
162
- this.opts = null;
163
- this.namespace = "dummy";
164
- }
165
- async has(key) {
166
- const stream = await this.store.get(key, "stream");
167
- if (stream !== null) {
168
- await stream.cancel();
169
- return true;
170
- }
171
- return false;
172
- }
173
- async get(key) {
174
- const value = await this.store.get(key);
175
- return value !== null ? value : void 0;
176
- }
177
- set(key, value, ttl) {
178
- if (typeof ttl === "number") {
179
- ttl = Math.max(60, ttl / 1e3);
180
- }
181
- return this.store.put(key, value, { expirationTtl: ttl });
182
- }
183
- async delete(key) {
184
- await this.store.delete(key);
185
- return true;
186
- }
187
- async clear() {
188
- let cursor = "";
189
- let complete = false;
190
- const prefix = `${this.namespace}:`;
191
- do {
192
- const response = await this.store.list({
193
- prefix,
194
- cursor: cursor || void 0
195
- });
196
- cursor = response.cursor ?? "";
197
- complete = response.list_complete;
198
- if (response.keys.length > 0) {
199
- await Promise.all(
200
- response.keys.map((key) => {
201
- return this.store.delete(key.name);
202
- })
203
- );
204
- }
205
- } while (!complete);
206
- }
207
- on(_event, _listener) {
208
- return this;
209
- }
210
- };
211
-
212
- // src/utils/index.ts
213
- var import_qs = __toESM(require("qs"), 1);
214
- var import_lodash_es3 = require("lodash-es");
215
- var import_json52 = __toESM(require("json5"), 1);
216
-
217
- // src/resources.ts
218
- var import_lodash_es2 = require("lodash-es");
219
-
220
164
  // src/utils/logger.ts
221
165
  var logLevels = {
222
166
  error: 0,
@@ -308,6 +252,80 @@ function createTraceId(data) {
308
252
  return (hash >>> 0).toString(16);
309
253
  }
310
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
+
311
329
  // src/liquid/utils.ts
312
330
  var import_liquidjs = require("liquidjs");
313
331
 
@@ -763,18 +781,12 @@ var StorefrontResource = class {
763
781
  }
764
782
  return instance[prop];
765
783
  }
766
- // add additional properties to the loaded result
767
- _transformResult(result) {
768
- return result;
769
- }
770
784
  async _get(..._args) {
771
785
  if (this._getter) {
772
786
  const getter = this._getter.bind(
773
787
  this
774
788
  );
775
789
  return Promise.resolve().then(getter).then((result) => {
776
- return this._transformResult(result);
777
- }).then((result) => {
778
790
  this._result = result ?? null;
779
791
  if (result) {
780
792
  Object.assign(this, result);
@@ -857,7 +869,6 @@ function cloneStorefrontResource(input) {
857
869
  });
858
870
  const clone = new ClonedClass(input._getter);
859
871
  clone._params = input._params;
860
- clone._transformResult = input._transformResult.bind(clone);
861
872
  Object.defineProperty(clone, "_resourceName", {
862
873
  value: resourceName
863
874
  });
@@ -911,7 +922,11 @@ var SwellStorefrontCollection = class _SwellStorefrontCollection extends SwellSt
911
922
  limit = DEFAULT_QUERY_PAGE_LIMIT;
912
923
  name;
913
924
  constructor(swell, collection, query = {}, getter) {
914
- super(swell, collection, getter);
925
+ super(
926
+ swell,
927
+ collection,
928
+ getter
929
+ );
915
930
  this._query = this._initQuery(query);
916
931
  if (!getter) {
917
932
  this._setGetter(this._defaultGetter());
@@ -954,6 +969,7 @@ var SwellStorefrontCollection = class _SwellStorefrontCollection extends SwellSt
954
969
  this._collection,
955
970
  this._query,
956
971
  this._swell.queryParams,
972
+ // TODO: consider to exlcude
957
973
  this._getterHash
958
974
  ],
959
975
  getter,
@@ -1082,13 +1098,12 @@ var SwellStorefrontRecord = class extends SwellStorefrontResource {
1082
1098
  this._id,
1083
1099
  this._query,
1084
1100
  this._swell.queryParams,
1101
+ // TODO: consider to exlcude
1085
1102
  this._getterHash
1086
1103
  ],
1087
1104
  getter,
1088
1105
  isResourceCacheble(this._collection)
1089
1106
  ).then((result) => {
1090
- return this._transformResult(result);
1091
- }).then((result) => {
1092
1107
  this._result = result;
1093
1108
  if (result) {
1094
1109
  Object.assign(this, result);
@@ -7312,8 +7327,6 @@ var Cache = class {
7312
7327
  * This will always return the cached value immediately if exists
7313
7328
  */
7314
7329
  async fetchSWR(key, fetchFn, ttl = DEFAULT_SWR_TTL, isCacheble = true) {
7315
- const trace = createTraceId();
7316
- logger.debug("[SDK] Cache fetch start", { key, trace });
7317
7330
  const cacheValue = isCacheble ? await this.client.get(key) : void 0;
7318
7331
  let promise = SWR_PROMISE_MAP.get(key);
7319
7332
  if (promise === void 0) {
@@ -7321,7 +7334,6 @@ var Cache = class {
7321
7334
  const isNull = value === null || value === void 0;
7322
7335
  if (isCacheble) {
7323
7336
  await this.client.set(key, isNull ? NULL_VALUE : value, ttl);
7324
- logger.debug("[SDK] Cache update done", { key, trace });
7325
7337
  }
7326
7338
  return value;
7327
7339
  }).finally(() => {
@@ -7333,12 +7345,9 @@ var Cache = class {
7333
7345
  this.workerCtx.waitUntil(promise);
7334
7346
  }
7335
7347
  if (cacheValue !== void 0) {
7336
- logger.debug("[SDK] Cache check done", { status: "HIT", key, trace });
7337
7348
  return cacheValue === NULL_VALUE ? null : cacheValue;
7338
7349
  }
7339
- logger.debug("[SDK] Cache check done", { status: "MISS", key, trace });
7340
7350
  const result = await promise;
7341
- logger.debug("[SDK] Cache fetch end", { key, trace });
7342
7351
  return result;
7343
7352
  }
7344
7353
  async get(key) {
@@ -7845,59 +7854,466 @@ var WorkerCacheProxy = class {
7845
7854
  }
7846
7855
  };
7847
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
+ DEFAULT: 300,
7862
+ // 5 minutes
7863
+ DEFAULT_SWR: 3600,
7864
+ // 1 hour stale-while-revalidate
7865
+ HOME: 300,
7866
+ // 5 minutes
7867
+ PRODUCT: 600,
7868
+ // 10 minutes
7869
+ COLLECTION: 900,
7870
+ // 15 minutes
7871
+ PAGE: 3600,
7872
+ // 1 hour
7873
+ BLOG: 1800
7874
+ // 30 minutes
7875
+ };
7876
+ var WorkerHtmlCache = class {
7877
+ epoch;
7878
+ constructor(epoch) {
7879
+ this.epoch = epoch;
7880
+ }
7881
+ async get(request) {
7882
+ const trace = createTraceId();
7883
+ if (request.method !== "GET") {
7884
+ logger.debug("[SDK Html-cache] non-cacheable", { trace });
7885
+ return { found: false, cacheable: false };
7886
+ }
7887
+ if (!this.isCacheable(request)) {
7888
+ logger.debug("[SDK Html-cache] non-cacheable", { trace });
7889
+ return { found: false, cacheable: false };
7890
+ }
7891
+ try {
7892
+ const cache = await caches.open(CACHE_NAME2 + this.epoch);
7893
+ const cacheKey = this.buildCacheKey(request);
7894
+ const cached = await cache.match(cacheKey);
7895
+ if (!cached) {
7896
+ logger.debug("[SDK Html-cache] cacheable, MISS", { trace });
7897
+ return { found: false, cacheable: true };
7898
+ }
7899
+ const age = this.getResponseAge(cached);
7900
+ const ttl = parseInt(cached.headers.get("X-Original-TTL") || "") || this.getTTLForRequest(request);
7901
+ const swr = parseInt(cached.headers.get("X-Original-SWR") || "") || TTL_CONFIG.DEFAULT_SWR;
7902
+ const isStale = age >= ttl;
7903
+ const isExpired = age >= ttl + swr;
7904
+ if (!isExpired) {
7905
+ logger.debug("[SDK Html-cache] cacheable, HIT", {
7906
+ stale: isStale,
7907
+ age,
7908
+ trace
7909
+ });
7910
+ const clientResponse = this.buildClientResponse(
7911
+ cached,
7912
+ ttl,
7913
+ swr,
7914
+ isStale,
7915
+ age
7916
+ );
7917
+ return {
7918
+ found: true,
7919
+ stale: isStale,
7920
+ response: clientResponse,
7921
+ cacheable: true,
7922
+ age: Math.floor(age)
7923
+ };
7924
+ }
7925
+ logger.debug("[SDK Html-cache] cacheable, hit, expired", { trace });
7926
+ return { found: false, cacheable: true };
7927
+ } catch (_) {
7928
+ logger.warn("[SDK Html-cache] no get support", { trace });
7929
+ return null;
7930
+ }
7931
+ }
7932
+ async put(request, response) {
7933
+ const trace = createTraceId();
7934
+ if (request.method !== "GET" || !response.ok) {
7935
+ logger.debug("[SDK Html-cache] put skipped", { trace });
7936
+ return;
7937
+ }
7938
+ if (!this.isCacheable(request) || !this.isResponseCacheable(response)) {
7939
+ logger.debug("[SDK Html-cache] put skipped, non-cacheable", {
7940
+ trace
7941
+ });
7942
+ return;
7943
+ }
7944
+ try {
7945
+ const cache = await caches.open(CACHE_NAME2 + this.epoch);
7946
+ const cacheKey = this.buildCacheKey(request);
7947
+ const ttl = this.getTTLForRequest(request);
7948
+ const swr = TTL_CONFIG.DEFAULT_SWR;
7949
+ const headers = new Headers(response.headers);
7950
+ const existingCacheControl = response.headers.get("Cache-Control");
7951
+ if (!existingCacheControl || existingCacheControl === "public") {
7952
+ const internalMaxAge = ttl + swr;
7953
+ headers.set("Cache-Control", `public, max-age=${internalMaxAge}`);
7954
+ }
7955
+ headers.set("X-Cache-Time", (/* @__PURE__ */ new Date()).toISOString());
7956
+ headers.set("X-Original-TTL", ttl.toString());
7957
+ headers.set("X-Original-SWR", swr.toString());
7958
+ const cacheableResponse = new Response(response.body, {
7959
+ status: response.status,
7960
+ statusText: response.statusText,
7961
+ headers
7962
+ });
7963
+ await cache.put(cacheKey, cacheableResponse);
7964
+ logger.debug("[SDK Html-cache] put done", { trace });
7965
+ } catch (_) {
7966
+ logger.warn("[SDK Html-cache] no put support", { trace });
7967
+ }
7968
+ }
7969
+ /**
7970
+ * Build client response with correct headers
7971
+ */
7972
+ buildClientResponse(cachedResponse, ttl, swr, isStale, age) {
7973
+ const headers = new Headers(cachedResponse.headers);
7974
+ headers.set(
7975
+ "Cache-Control",
7976
+ `public, max-age=${ttl}, stale-while-revalidate=${swr}`
7977
+ );
7978
+ headers.set("X-Cache-Status", isStale ? "STALE" : "HIT");
7979
+ headers.set("X-Cache-Age", Math.floor(age).toString());
7980
+ headers.delete("X-Original-TTL");
7981
+ headers.delete("X-Original-SWR");
7982
+ return new Response(cachedResponse.body, {
7983
+ status: cachedResponse.status,
7984
+ statusText: cachedResponse.statusText,
7985
+ headers
7986
+ });
7987
+ }
7988
+ /**
7989
+ * Build cache key from request using two-level structure
7990
+ */
7991
+ buildCacheKey(request) {
7992
+ const url = new URL(request.url);
7993
+ const versionHash = this.generateVersionHash(request.headers);
7994
+ const normalizedQuery = this.normalizeSearchParams(url.searchParams);
7995
+ const cacheKeyPath = `${versionHash}${url.pathname}`;
7996
+ const keyUrl = new URL(`${CACHE_KEY_ORIGIN2}${cacheKeyPath}`);
7997
+ if (normalizedQuery) {
7998
+ keyUrl.search = `?${normalizedQuery}`;
7999
+ }
8000
+ const sanitizedHeaders = this.sanitizeHeaders(request.headers);
8001
+ return new Request(keyUrl.toString(), {
8002
+ method: "GET",
8003
+ headers: sanitizedHeaders
8004
+ });
8005
+ }
8006
+ /**
8007
+ * Sanitize headers for cache operations - minimal whitelist approach
8008
+ */
8009
+ sanitizeHeaders(originalHeaders) {
8010
+ const CACHE_RELEVANT_HEADERS = [
8011
+ // Content negotiation (affects response format)
8012
+ "accept",
8013
+ "accept-encoding",
8014
+ "accept-language",
8015
+ // Cache control directives from client/proxy
8016
+ "cache-control",
8017
+ "pragma",
8018
+ // Legacy cache control
8019
+ // Conditional request headers (for 304 responses)
8020
+ "if-none-match",
8021
+ "if-modified-since"
8022
+ ];
8023
+ const sanitized = new Headers();
8024
+ CACHE_RELEVANT_HEADERS.forEach((header) => {
8025
+ const value = originalHeaders.get(header);
8026
+ if (value) {
8027
+ sanitized.set(header, value);
8028
+ }
8029
+ });
8030
+ return sanitized;
8031
+ }
8032
+ /**
8033
+ * Generate version hash from headers and cookies
8034
+ */
8035
+ generateVersionHash(headers) {
8036
+ const swellData = this.extractSwellData(headers);
8037
+ const versionFactors = {
8038
+ store: headers.get("swell-storefront-id") || "",
8039
+ auth: headers.get("swell-access-token") || "",
8040
+ theme: headers.get("swell-theme-version-hash") || "",
8041
+ currency: swellData["swell-currency"] || "USD",
8042
+ locale: headers.get("x-locale") || headers.get("accept-language")?.split(",")[0] || "default",
8043
+ context: headers.get("swell-storefront-context"),
8044
+ epoch: this.epoch
8045
+ };
8046
+ return md5(JSON.stringify(versionFactors));
8047
+ }
8048
+ /**
8049
+ * Extract swell-data from cookies
8050
+ */
8051
+ extractSwellData(headers) {
8052
+ const cookie = headers.get("cookie");
8053
+ if (!cookie) return {};
8054
+ const swellDataMatch = cookie.match(/swell-data=([^;]+)/);
8055
+ if (!swellDataMatch) return {};
8056
+ try {
8057
+ const parsed = JSON.parse(decodeURIComponent(swellDataMatch[1]));
8058
+ if (typeof parsed === "object" && parsed !== null) {
8059
+ return parsed;
8060
+ }
8061
+ return {};
8062
+ } catch {
8063
+ return {};
8064
+ }
8065
+ }
8066
+ isCacheable(request) {
8067
+ const url = new URL(request.url);
8068
+ const headers = request.headers;
8069
+ if (headers.get("swell-deployment-mode") === "editor") {
8070
+ return false;
8071
+ }
8072
+ const skipPaths = ["/checkout"];
8073
+ if (skipPaths.some((path) => url.pathname.startsWith(path))) {
8074
+ return false;
8075
+ }
8076
+ if (headers.get("cache-control")?.includes("no-cache")) {
8077
+ return false;
8078
+ }
8079
+ return true;
8080
+ }
8081
+ isResponseCacheable(response) {
8082
+ const contentType = response.headers.get("content-type");
8083
+ if (!contentType?.includes("text/html")) {
8084
+ return false;
8085
+ }
8086
+ const cacheControl = response.headers.get("cache-control");
8087
+ if (cacheControl?.includes("no-store") || cacheControl?.includes("private")) {
8088
+ return false;
8089
+ }
8090
+ return true;
8091
+ }
8092
+ getTTLForRequest(request) {
8093
+ const url = new URL(request.url);
8094
+ const path = url.pathname;
8095
+ if (path === "/") {
8096
+ return TTL_CONFIG.HOME;
8097
+ }
8098
+ if (path.startsWith("/products/")) {
8099
+ return TTL_CONFIG.PRODUCT;
8100
+ }
8101
+ if (path.startsWith("/categories/")) {
8102
+ return TTL_CONFIG.COLLECTION;
8103
+ }
8104
+ if (path.startsWith("/pages/")) {
8105
+ return TTL_CONFIG.PAGE;
8106
+ }
8107
+ if (path.startsWith("/blogs/")) {
8108
+ return TTL_CONFIG.BLOG;
8109
+ }
8110
+ return TTL_CONFIG.DEFAULT;
8111
+ }
8112
+ getResponseAge(response) {
8113
+ const cacheTime = response.headers.get("X-Cache-Time");
8114
+ if (!cacheTime) {
8115
+ return Infinity;
8116
+ }
8117
+ const cacheDate = new Date(cacheTime);
8118
+ if (isNaN(cacheDate.getTime())) {
8119
+ return Infinity;
8120
+ }
8121
+ const age = (Date.now() - cacheDate.getTime()) / 1e3;
8122
+ return Math.max(0, age);
8123
+ }
8124
+ getMaxAge(response) {
8125
+ const cacheControl = response.headers.get("Cache-Control");
8126
+ if (!cacheControl) {
8127
+ return TTL_CONFIG.DEFAULT;
8128
+ }
8129
+ const maxAgeMatch = cacheControl.match(/max-age=(\d+)/);
8130
+ if (maxAgeMatch) {
8131
+ return parseInt(maxAgeMatch[1], 10);
8132
+ }
8133
+ return TTL_CONFIG.DEFAULT;
8134
+ }
8135
+ getStaleWindow(response) {
8136
+ const cacheControl = response.headers.get("Cache-Control");
8137
+ if (!cacheControl) {
8138
+ return TTL_CONFIG.DEFAULT_SWR;
8139
+ }
8140
+ const swrMatch = cacheControl.match(/stale-while-revalidate=(\d+)/);
8141
+ if (swrMatch) {
8142
+ return parseInt(swrMatch[1], 10);
8143
+ }
8144
+ return TTL_CONFIG.DEFAULT_SWR;
8145
+ }
8146
+ /**
8147
+ * Normalize search params for cache key
8148
+ */
8149
+ normalizeSearchParams(searchParams) {
8150
+ const ignoredParams = [
8151
+ "utm_source",
8152
+ "utm_medium",
8153
+ "utm_campaign",
8154
+ "utm_content",
8155
+ "utm_term",
8156
+ "fbclid",
8157
+ "gclid",
8158
+ "gbraid",
8159
+ "wbraid",
8160
+ "ref",
8161
+ "source",
8162
+ "mc_cid",
8163
+ "mc_eid"
8164
+ ];
8165
+ const relevantParams = [];
8166
+ searchParams.forEach((value, key) => {
8167
+ if (!ignoredParams.includes(key)) {
8168
+ relevantParams.push(
8169
+ `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
8170
+ );
8171
+ }
8172
+ });
8173
+ return relevantParams.sort().join("&");
8174
+ }
8175
+ };
8176
+
8177
+ // src/resources/addresses.ts
8178
+ var SwellAddresses = class extends SwellStorefrontCollection {
8179
+ constructor(swell, query) {
8180
+ const { page, limit: limit2 } = swell.queryParams;
8181
+ super(swell, "accounts:addresses", { page, limit: limit2, ...query }, function() {
8182
+ return this._swell.storefront.account.listAddresses(
8183
+ this._query
8184
+ );
8185
+ });
8186
+ }
8187
+ };
8188
+
8189
+ // src/resources/orders.ts
8190
+ var SwellOrders = class extends SwellStorefrontCollection {
8191
+ constructor(swell, query) {
8192
+ const { page, limit: limit2 } = swell.queryParams;
8193
+ super(swell, "accounts:orders", { page, limit: limit2, ...query }, function() {
8194
+ return this._swell.storefront.account.listOrders(this._query);
8195
+ });
8196
+ }
8197
+ };
8198
+
8199
+ // src/resources/subscriptions.ts
8200
+ var SwellSubscriptions = class extends SwellStorefrontCollection {
8201
+ constructor(swell, query) {
8202
+ const { page, limit: limit2 } = swell.queryParams;
8203
+ super(
8204
+ swell,
8205
+ "accounts:subscriptions",
8206
+ { page, limit: limit2, ...query },
8207
+ function() {
8208
+ return this._swell.storefront.subscriptions.list(
8209
+ this._query
8210
+ );
8211
+ }
8212
+ );
8213
+ }
8214
+ };
8215
+
7848
8216
  // src/resources/account.ts
7849
8217
  var SwellAccount = class extends SwellStorefrontSingleton {
7850
- constructor(swell, getter) {
7851
- super(swell, "account", getter);
8218
+ constructor(swell) {
8219
+ super(swell, "account", async function() {
8220
+ const account = await this._defaultGetter().call(this);
8221
+ if (!account) {
8222
+ return null;
8223
+ }
8224
+ account.addresses = new SwellAddresses(
8225
+ this._swell
8226
+ );
8227
+ account.orders = new SwellOrders(
8228
+ this._swell
8229
+ );
8230
+ account.subscriptions = new SwellSubscriptions(
8231
+ this._swell
8232
+ );
8233
+ return account;
8234
+ });
7852
8235
  return this._getProxy();
7853
8236
  }
7854
8237
  };
7855
8238
 
7856
8239
  // src/resources/blog_category.ts
7857
8240
  var SwellBlogCategory = class extends SwellStorefrontRecord {
7858
- constructor(swell, id, query = {}, getter) {
7859
- super(swell, "content/blog-categories", id, query, getter);
8241
+ constructor(swell, id, query) {
8242
+ super(swell, "content/blog-categories", id, query, async function() {
8243
+ const category = await this._defaultGetter().call(this);
8244
+ if (!category) {
8245
+ return null;
8246
+ }
8247
+ category.blogs = new SwellStorefrontCollection(
8248
+ this._swell,
8249
+ "content/blogs",
8250
+ {
8251
+ category_id: category.id,
8252
+ expand: "author"
8253
+ }
8254
+ );
8255
+ return category;
8256
+ });
7860
8257
  return this._getProxy();
7861
8258
  }
7862
8259
  };
7863
8260
 
7864
8261
  // src/resources/blog.ts
7865
8262
  var SwellBlog = class extends SwellStorefrontRecord {
7866
- constructor(swell, id, query = {}, getter) {
7867
- super(swell, "content/blogs", id, query, getter);
8263
+ constructor(swell, blogId, categoryId, query) {
8264
+ super(swell, "content/blogs", blogId, query, async function() {
8265
+ this._query = { ...this._query, expand: "author" };
8266
+ const blog = await this._defaultGetter().call(this);
8267
+ if (!blog) {
8268
+ return null;
8269
+ }
8270
+ if (categoryId) {
8271
+ blog.category = new SwellStorefrontRecord(
8272
+ this._swell,
8273
+ "content/blog-categories",
8274
+ categoryId
8275
+ );
8276
+ }
8277
+ return blog;
8278
+ });
7868
8279
  return this._getProxy();
7869
8280
  }
7870
8281
  };
7871
8282
 
7872
8283
  // src/resources/cart.ts
7873
8284
  var SwellCart = class extends SwellStorefrontSingleton {
7874
- constructor(swell, getter) {
7875
- super(swell, "cart", getter);
7876
- return this._getProxy();
7877
- }
7878
- };
7879
-
7880
- // src/resources/category.ts
7881
- var SwellCategory = class extends SwellStorefrontRecord {
7882
- constructor(swell, id, query = {}, getter) {
7883
- super(swell, "categories", id, query, getter);
7884
- return this._getProxy();
7885
- }
7886
- };
7887
-
7888
- // src/resources/order.ts
7889
- var SwellOrder = class extends SwellStorefrontRecord {
7890
- constructor(swell, id, query = {}, getter) {
7891
- super(swell, "orders", id, query, getter);
8285
+ constructor(swell) {
8286
+ super(swell, "cart");
7892
8287
  return this._getProxy();
7893
8288
  }
7894
8289
  };
7895
8290
 
7896
- // src/resources/page.ts
7897
- var SwellPage = class extends SwellStorefrontRecord {
7898
- constructor(swell, id, query = {}, getter) {
7899
- super(swell, "content/pages", id, query, getter);
7900
- return this._getProxy();
8291
+ // src/resources/categories.ts
8292
+ var SwellCategories = class extends SwellStorefrontCollection {
8293
+ constructor(swell, query) {
8294
+ super(
8295
+ swell,
8296
+ "categories",
8297
+ {
8298
+ limit: 100,
8299
+ top_id: null,
8300
+ ...query
8301
+ },
8302
+ async function() {
8303
+ const categories = await this._defaultGetter().call(this);
8304
+ if (!categories) {
8305
+ return null;
8306
+ }
8307
+ for (const category of categories.results) {
8308
+ category.products = new SwellStorefrontCollection(
8309
+ this._swell,
8310
+ "products",
8311
+ { category: category.id }
8312
+ );
8313
+ }
8314
+ return categories;
8315
+ }
8316
+ );
7901
8317
  }
7902
8318
  };
7903
8319
 
@@ -8057,6 +8473,143 @@ function getSelectedSubscriptionPurchaseOptionPlan(selectedPurchaseOptionType, s
8057
8473
  }
8058
8474
  return selectedPlan || subscriptionPurchaseOption.plans[0];
8059
8475
  }
8476
+ var SORT_OPTIONS = Object.freeze([
8477
+ { value: "", name: "Featured" },
8478
+ { value: "popularity", name: "Popularity", query: "popularity desc" },
8479
+ { value: "price_asc", name: "Price, low to high", query: "price asc" },
8480
+ { value: "price_desc", name: "Price, high to low", query: "price desc" },
8481
+ { value: "date_asc", name: "Date, old to new", query: "date asc" },
8482
+ { value: "date_desc", name: "Date, new to old", query: "date desc" },
8483
+ { value: "name_asc", name: "Product name, A-Z", query: "name asc" },
8484
+ { value: "name_desc", name: "Product name, Z-A", query: "name desc" }
8485
+ ]);
8486
+ async function getProductFilters(swell, productQuery) {
8487
+ const sortBy = swell.queryParams.sort || "";
8488
+ const filterQuery = productQueryWithFilters(swell, productQuery);
8489
+ return {
8490
+ filter_options: await getProductFiltersByQuery(swell, filterQuery),
8491
+ sort: SORT_OPTIONS.find((option) => option.value === sortBy)?.value,
8492
+ sort_options: [...SORT_OPTIONS]
8493
+ };
8494
+ }
8495
+ async function getProductFiltersByQuery(swell, query = {}) {
8496
+ const filters2 = await swell.get("/products/:filters", {
8497
+ ...query,
8498
+ sort: void 0
8499
+ }) || [];
8500
+ if (!Array.isArray(filters2)) {
8501
+ throw new Error("Product filters must be an array");
8502
+ }
8503
+ for (const filter of filters2) {
8504
+ filter.param_name = `filter_${filter.id}`;
8505
+ if (Array.isArray(filter.options)) {
8506
+ filter.active_options = [];
8507
+ filter.inactive_options = [];
8508
+ for (const option of filter.options) {
8509
+ const queryValue = swell.queryParams[filter.param_name];
8510
+ option.active = Array.isArray(queryValue) ? queryValue.includes(option.value) : queryValue === option.value;
8511
+ const list = option.active ? filter.active_options : filter.inactive_options;
8512
+ list.push(option);
8513
+ }
8514
+ }
8515
+ }
8516
+ return filters2;
8517
+ }
8518
+ function productQueryWithFilters(swell, query) {
8519
+ const filters2 = Object.keys(swell.queryParams).reduce(
8520
+ (acc, key) => {
8521
+ if (key.startsWith("filter_")) {
8522
+ const qkey = key.replace("filter_", "");
8523
+ const value = swell.queryParams[key];
8524
+ if (typeof value === "object" && value !== null && !Array.isArray(value) && (value.gte !== void 0 || value.lte !== void 0)) {
8525
+ acc[qkey] = [value.gte || 0, value.lte || void 0];
8526
+ } else {
8527
+ acc[qkey] = value;
8528
+ }
8529
+ }
8530
+ return acc;
8531
+ },
8532
+ {}
8533
+ );
8534
+ const sortBy = swell.queryParams.sort || "";
8535
+ return {
8536
+ sort: SORT_OPTIONS.find((option) => option.value === sortBy)?.query || void 0,
8537
+ $filters: filters2,
8538
+ ...query
8539
+ };
8540
+ }
8541
+
8542
+ // src/resources/category.ts
8543
+ var SwellCategory = class extends SwellStorefrontRecord {
8544
+ constructor(swell, id, query) {
8545
+ super(swell, "categories", id, query, async function() {
8546
+ let category = await this._defaultGetter().call(this);
8547
+ if (!category && this._id === "all") {
8548
+ category = {
8549
+ name: "Products",
8550
+ id: "all",
8551
+ slug: "all",
8552
+ filter_options: [],
8553
+ sort_options: []
8554
+ };
8555
+ }
8556
+ if (!category) {
8557
+ return null;
8558
+ }
8559
+ const productFilters = await getProductFilters(
8560
+ this._swell,
8561
+ category.id !== "all" ? { category: category.id, $variants: true } : { $variants: true }
8562
+ );
8563
+ Object.assign(category, productFilters);
8564
+ return category;
8565
+ });
8566
+ return this._getProxy();
8567
+ }
8568
+ };
8569
+
8570
+ // src/resources/order.ts
8571
+ var SwellOrder = class extends SwellStorefrontRecord {
8572
+ constructor(swell, id, query) {
8573
+ super(swell, "accounts:orders", id, query, function() {
8574
+ return this._swell.storefront.account.getOrder(this._id);
8575
+ });
8576
+ return this._getProxy();
8577
+ }
8578
+ };
8579
+
8580
+ // src/resources/page.ts
8581
+ var SwellPage = class extends SwellStorefrontRecord {
8582
+ constructor(swell, id, query) {
8583
+ super(swell, "content/pages", id, query);
8584
+ return this._getProxy();
8585
+ }
8586
+ };
8587
+
8588
+ // src/resources/predictive_search.ts
8589
+ var SwellPredictiveSearch = class extends StorefrontResource {
8590
+ constructor(swell, query) {
8591
+ super(async function() {
8592
+ const performed = String(query || "").length > 0;
8593
+ let products;
8594
+ if (performed) {
8595
+ products = new SwellStorefrontCollection(
8596
+ swell,
8597
+ "products",
8598
+ {
8599
+ search: query,
8600
+ limit: 10
8601
+ }
8602
+ );
8603
+ await products.resolve();
8604
+ }
8605
+ return {
8606
+ query,
8607
+ performed,
8608
+ products
8609
+ };
8610
+ });
8611
+ }
8612
+ };
8060
8613
 
8061
8614
  // src/resources/variant.ts
8062
8615
  function transformSwellVariant(params, product, variant) {
@@ -8076,27 +8629,30 @@ function transformSwellVariant(params, product, variant) {
8076
8629
  )
8077
8630
  };
8078
8631
  }
8632
+ var SwellVariant = class extends SwellStorefrontRecord {
8633
+ product;
8634
+ constructor(swell, product, id, query) {
8635
+ super(swell, "products:variants", id, query, async function() {
8636
+ const variant = await this._swell.get(
8637
+ "/products:variants/{id}",
8638
+ { id: this._id }
8639
+ );
8640
+ return variant ?? null;
8641
+ });
8642
+ this.product = product;
8643
+ }
8644
+ };
8079
8645
 
8080
8646
  // src/resources/product.ts
8081
- var SORT_OPTIONS = [
8082
- { value: "", name: "Featured" },
8083
- { value: "popularity", name: "Popularity", query: "popularity desc" },
8084
- { value: "price_asc", name: "Price, low to high", query: "price asc" },
8085
- { value: "price_desc", name: "Price, high to low", query: "price desc" },
8086
- { value: "date_asc", name: "Date, old to new", query: "date asc" },
8087
- { value: "date_desc", name: "Date, new to old", query: "date desc" },
8088
- { value: "name_asc", name: "Product name, A-Z", query: "name asc" },
8089
- { value: "name_desc", name: "Product name, Z-A", query: "name desc" }
8090
- ];
8091
8647
  function transformSwellProduct(params, product) {
8092
8648
  if (!product) {
8093
- return product;
8649
+ return null;
8094
8650
  }
8095
8651
  const newProduct = {
8096
8652
  ...product,
8097
8653
  // add swell properties there
8098
8654
  selected_option_values: getSelectedVariantOptionValues(product, params),
8099
- purchase_options: getPurchaseOptions(product, params)
8655
+ purchase_options: getPurchaseOptions(product, params) ?? void 0
8100
8656
  };
8101
8657
  if (Array.isArray(newProduct.variants?.results)) {
8102
8658
  newProduct.variants = {
@@ -8109,43 +8665,49 @@ function transformSwellProduct(params, product) {
8109
8665
  return newProduct;
8110
8666
  }
8111
8667
  var SwellProduct = class extends SwellStorefrontRecord {
8112
- _params;
8113
- constructor(swell, id, query = {}, getter) {
8114
- super(swell, "products", id, query, getter);
8115
- this._params = swell.queryParams;
8668
+ constructor(swell, id, query) {
8669
+ const params = swell.queryParams;
8670
+ super(swell, "products", id, query, async function() {
8671
+ const result = await this._defaultGetter().call(this);
8672
+ return transformSwellProduct(params, result);
8673
+ });
8116
8674
  return this._getProxy();
8117
8675
  }
8118
- // add swell properties to the resolved object
8119
- _transformResult(result) {
8120
- const res = transformSwellProduct(
8121
- this._params,
8122
- result
8123
- );
8124
- return res;
8676
+ };
8677
+
8678
+ // src/resources/product_recommendations.ts
8679
+ var SwellProductRecommendations = class extends SwellProduct {
8680
+ constructor(swell, id, query) {
8681
+ super(swell, id, { ...query, $recommendations: true });
8682
+ }
8683
+ };
8684
+
8685
+ // src/resources/search.ts
8686
+ var SwellSearch = class extends StorefrontResource {
8687
+ constructor(swell, query) {
8688
+ super(async () => {
8689
+ const performed = String(query || "").length > 0;
8690
+ const productFilters = await getProductFilters(
8691
+ swell,
8692
+ performed ? { search: query } : void 0
8693
+ );
8694
+ return {
8695
+ query,
8696
+ performed,
8697
+ ...productFilters
8698
+ };
8699
+ });
8700
+ }
8701
+ };
8702
+
8703
+ // src/resources/subscription.ts
8704
+ var SwellSubscription = class extends SwellStorefrontRecord {
8705
+ constructor(swell, id, query) {
8706
+ super(swell, "accounts:subscriptions", id, query, function() {
8707
+ return this._swell.storefront.subscriptions.get(this._id, this._query);
8708
+ });
8125
8709
  }
8126
8710
  };
8127
- function productQueryWithFilters(swell, query = {}) {
8128
- const sortBy = swell.queryParams.sort || "";
8129
- const filters2 = Object.entries(swell.queryParams).reduce(
8130
- (acc, [key, value]) => {
8131
- if (key.startsWith("filter_")) {
8132
- const qkey = key.replace("filter_", "");
8133
- if (value?.gte !== void 0 || value?.lte !== void 0) {
8134
- acc[qkey] = [value.gte || 0, value.lte || void 0];
8135
- } else {
8136
- acc[qkey] = value;
8137
- }
8138
- }
8139
- return acc;
8140
- },
8141
- {}
8142
- );
8143
- return {
8144
- sort: SORT_OPTIONS.find((option) => option.value === sortBy)?.query || void 0,
8145
- $filters: filters2,
8146
- ...query
8147
- };
8148
- }
8149
8711
 
8150
8712
  // src/api.ts
8151
8713
  var DEFAULT_API_HOST = "https://api.schema.io";
@@ -8439,13 +9001,19 @@ var Swell = class _Swell {
8439
9001
  const storefrontRequest = storefront.request;
8440
9002
  return (method, url, id, data, opt) => {
8441
9003
  if (this.isStorefrontRequestCacheable(method, url, opt)) {
8442
- return this.getRequestCache().fetchSWR(
8443
- getCacheKey("request", [this.instanceId, method, url, id, data, opt]),
8444
- () => {
8445
- logger.info("[SDK] Storefront request", { method, url, id, data });
8446
- return storefrontRequest(method, url, id, data, opt);
8447
- }
8448
- );
9004
+ const key = getCacheKey("request", [
9005
+ this.instanceId,
9006
+ method,
9007
+ url,
9008
+ id,
9009
+ data,
9010
+ opt
9011
+ ]);
9012
+ return this.getRequestCache().fetchSWR(key, () => {
9013
+ const requestUrl = id ? `${url}/${id}` : url;
9014
+ logger.debug("[SDK] Cacheable API request", { url: requestUrl, key });
9015
+ return storefrontRequest(method, url, id, data, opt);
9016
+ });
8449
9017
  }
8450
9018
  switch (method) {
8451
9019
  case "delete":
@@ -8492,7 +9060,9 @@ var Swell = class _Swell {
8492
9060
  };
8493
9061
  function getCacheKey(key, args) {
8494
9062
  if (Array.isArray(args) && args.length > 0) {
8495
- return `${key}_${md5(JSON.stringify(args))}`;
9063
+ const fullKey = `${key}_${md5(JSON.stringify(args))}`;
9064
+ logger.debug(`[SDK] make cache key: ${fullKey}`);
9065
+ return fullKey;
8496
9066
  }
8497
9067
  return key;
8498
9068
  }
@@ -15716,11 +16286,9 @@ function getProducts(instance, object, mapper) {
15716
16286
  return this._defaultGetter().call(this);
15717
16287
  }
15718
16288
  );
15719
- return products._cloneWithCompatibilityResult(
15720
- (products2) => {
15721
- return { ...products2, results: products2.results.map(mapper) };
15722
- }
15723
- );
16289
+ return products._cloneWithCompatibilityResult((products2) => {
16290
+ return { ...products2, results: products2.results.map(mapper) };
16291
+ });
15724
16292
  });
15725
16293
  }
15726
16294
  function makeProductsCollectionResolve(instance, object, mapper) {
@@ -15737,19 +16305,24 @@ function makeProductsCollectionResolve(instance, object, mapper) {
15737
16305
 
15738
16306
  // src/compatibility/shopify-objects/collections.ts
15739
16307
  function ShopifyCollections(instance, categories) {
15740
- return new SwellStorefrontCollection(instance.swell, categories._collection, categories._query, async () => {
15741
- const results = (await categories.results)?.map((category) => {
15742
- return ShopifyCollection(instance, category);
15743
- });
15744
- return {
15745
- page: categories.page ?? 1,
15746
- count: categories.count ?? 0,
15747
- results: results ?? [],
15748
- page_count: categories.page_count ?? 0,
15749
- limit: categories.limit,
15750
- pages: categories.pages ?? {}
15751
- };
15752
- });
16308
+ return new SwellStorefrontCollection(
16309
+ instance.swell,
16310
+ categories._collection,
16311
+ categories._query,
16312
+ async () => {
16313
+ const results = (await categories.results)?.map((category) => {
16314
+ return ShopifyCollection(instance, category);
16315
+ });
16316
+ return {
16317
+ page: categories.page ?? 1,
16318
+ count: categories.count ?? 0,
16319
+ results: results ?? [],
16320
+ page_count: categories.page_count ?? 0,
16321
+ limit: categories.limit,
16322
+ pages: categories.pages ?? {}
16323
+ };
16324
+ }
16325
+ );
15753
16326
  }
15754
16327
 
15755
16328
  // src/compatibility/shopify-objects/address.ts
@@ -16936,13 +17509,12 @@ var ImagesDrop = class extends import_liquidjs7.Drop {
16936
17509
  var SwellImage = class extends StorefrontResource {
16937
17510
  constructor(swell, name) {
16938
17511
  super(async () => {
16939
- const files = await swell.get("/:files", {
17512
+ const file = await swell.get("/:files/:last", {
16940
17513
  private: { $ne: true },
16941
17514
  content_type: { $regex: "^image/" },
16942
17515
  filename: name
16943
17516
  });
16944
- const file = files?.results[0] ?? null;
16945
- if (file === null) {
17517
+ if (!file) {
16946
17518
  return null;
16947
17519
  }
16948
17520
  return { file };
@@ -22237,25 +22809,35 @@ function getResourceQuery(slug, query) {
22237
22809
  StorefrontResource,
22238
22810
  Swell,
22239
22811
  SwellAccount,
22812
+ SwellAddresses,
22240
22813
  SwellBackendAPI,
22241
22814
  SwellBlog,
22242
22815
  SwellBlogCategory,
22243
22816
  SwellCart,
22817
+ SwellCategories,
22244
22818
  SwellCategory,
22245
22819
  SwellError,
22246
22820
  SwellOrder,
22821
+ SwellOrders,
22247
22822
  SwellPage,
22823
+ SwellPredictiveSearch,
22248
22824
  SwellProduct,
22825
+ SwellProductRecommendations,
22826
+ SwellSearch,
22249
22827
  SwellStorefrontCollection,
22250
22828
  SwellStorefrontPagination,
22251
22829
  SwellStorefrontRecord,
22252
22830
  SwellStorefrontResource,
22253
22831
  SwellStorefrontSingleton,
22832
+ SwellSubscription,
22833
+ SwellSubscriptions,
22254
22834
  SwellTheme,
22835
+ SwellVariant,
22255
22836
  ThemeColor,
22256
22837
  ThemeFont,
22257
22838
  ThemeForm,
22258
22839
  ThemeFormErrors,
22840
+ WorkerHtmlCache,
22259
22841
  adaptShopifyFontData,
22260
22842
  adaptShopifyFormData,
22261
22843
  adaptShopifyMenuData,