@swell/apps-sdk 1.0.158 → 1.0.160

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
@@ -285,7 +285,7 @@ var CFWorkerKVKeyvAdapter = class {
285
285
  if (typeof ttl === "number") {
286
286
  ttl = Math.max(60, ttl / 1e3);
287
287
  }
288
- logger.debug("[SDK] kv.set", { key });
288
+ logger.debug("[SDK] kv.set", { key, ttl });
289
289
  return this.store.put(key, value, { expirationTtl: ttl });
290
290
  }
291
291
  async delete(key) {
@@ -866,7 +866,8 @@ var RESOURCE_CLONE_PROPS = Object.freeze([
866
866
  "_swell",
867
867
  "_params",
868
868
  "_id",
869
- "_resourceName"
869
+ "_resourceName",
870
+ "_result"
870
871
  ]);
871
872
  function cloneStorefrontResource(input) {
872
873
  const resourceName = input._resourceName || input.constructor?.name;
@@ -7427,6 +7428,14 @@ function buildStores2() {
7427
7428
 
7428
7429
  // src/cache/theme-cache.ts
7429
7430
  var TTL = 90 * 24 * 60 * 60 * 1e3;
7431
+ var ThemeCache = class extends Cache {
7432
+ constructor(options) {
7433
+ super({
7434
+ ttl: TTL,
7435
+ ...options
7436
+ });
7437
+ }
7438
+ };
7430
7439
 
7431
7440
  // src/cache/theme-file-storage.ts
7432
7441
  var import_bluebird2 = __toESM(require("bluebird"), 1);
@@ -7768,139 +7777,29 @@ var MINUTE = 60 * SECOND;
7768
7777
  var HOUR = 60 * MINUTE;
7769
7778
  var DAY = 24 * HOUR;
7770
7779
  var YEAR = 365 * DAY;
7771
- var MAX_TTL = YEAR;
7772
7780
  var SHORT_TTL = 5 * SECOND;
7773
7781
 
7774
- // src/cache/worker-cache-proxy.ts
7775
- var CACHE_NAME = "swell-cache-v011";
7776
- var CACHE_KEY_ORIGIN = "https://cache.swell.store";
7777
- var WorkerCacheProxy = class {
7778
- swell;
7779
- constructor(swell) {
7780
- this.swell = swell;
7781
- }
7782
- /**
7783
- * Reads a JSON value from Worker Cache using a key built from path+query.
7784
- * Returns null on miss or if running outside of a Worker environment.
7785
- */
7786
- async get(path, query, opts) {
7787
- if (typeof caches === "undefined") {
7788
- return null;
7789
- }
7790
- const { keyUrl } = await this.buildKeyUrl(path, query, opts?.version);
7791
- try {
7792
- const cache = await caches.open(CACHE_NAME);
7793
- const match = await cache.match(keyUrl);
7794
- if (!match) return null;
7795
- const data = await match.json();
7796
- return data;
7797
- } catch {
7798
- return null;
7799
- }
7800
- }
7801
- /**
7802
- * Stores a JSON value in Worker Cache under key built from path+query.
7803
- * No-ops outside of a Worker environment.
7804
- */
7805
- async put(path, query, value, opts) {
7806
- if (typeof caches === "undefined") {
7807
- return;
7808
- }
7809
- const { keyUrl, hasVersion } = await this.buildKeyUrl(
7810
- path,
7811
- query,
7812
- opts?.version
7813
- );
7814
- const ttlMs = hasVersion ? MAX_TTL : SHORT_TTL;
7815
- try {
7816
- const cache = await caches.open(CACHE_NAME);
7817
- const response = new Response(JSON.stringify(value), {
7818
- headers: {
7819
- "Content-Type": "application/json",
7820
- "Cache-Control": `public, max-age=${Math.floor(ttlMs / 1e3)}`
7821
- }
7822
- });
7823
- await cache.put(keyUrl, response);
7824
- logger.debug("[SDK] cache put done", { keyUrl });
7825
- } catch {
7826
- }
7827
- }
7828
- /**
7829
- * Builds a deterministic key URL for Worker Cache from the backend API URL
7830
- * composed using path and query. Includes tenant and auth isolation and an
7831
- * optional version segment.
7832
- */
7833
- async buildKeyUrl(path, query, explicitVersion) {
7834
- const apiHost = this.swell.backend?.apiHost;
7835
- const endpointPath = String(path).startsWith("/") ? String(path).substring(1) : String(path);
7836
- let queryString = "";
7837
- if (query && this.swell.backend) {
7838
- queryString = this.swell.backend.stringifyQuery(query);
7839
- }
7840
- const fullUrl = `${apiHost}/${endpointPath}${queryString ? `?${queryString}` : ""}`;
7841
- const instanceId = this.swell.instanceId || "";
7842
- const authKey = String(this.swell.swellHeaders?.["swell-auth-key"] || "");
7843
- const tenantHash = await this.sha256Hex(`${instanceId}|${authKey}`);
7844
- const version = explicitVersion !== void 0 ? explicitVersion : this.swell.swellHeaders?.["theme-version-hash"] || null;
7845
- const hasVersion = Boolean(version);
7846
- const versionHash = hasVersion ? await this.sha256Hex(String(version)) : null;
7847
- const urlHash = await this.sha256Hex(fullUrl);
7848
- const keyUrl = versionHash ? `${CACHE_KEY_ORIGIN}/v1/${tenantHash}/${versionHash}/${urlHash}` : `${CACHE_KEY_ORIGIN}/v1/${tenantHash}/${urlHash}`;
7849
- return { keyUrl, hasVersion };
7850
- }
7851
- /**
7852
- * SHA-256 digest with hex encoding. Requires Worker crypto; callers
7853
- * should avoid invoking this outside of Worker code paths.
7854
- */
7855
- async sha256Hex(input) {
7856
- if (typeof crypto !== "undefined" && crypto.subtle && crypto.subtle.digest) {
7857
- const encoder = new TextEncoder();
7858
- const digest = await crypto.subtle.digest(
7859
- "SHA-256",
7860
- encoder.encode(input)
7861
- );
7862
- const bytes = new Uint8Array(digest);
7863
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
7864
- }
7865
- return md5(input);
7866
- }
7867
- };
7868
-
7869
7782
  // src/cache/worker-html-cache.ts
7870
- var CACHE_NAME2 = "swell-html-v1";
7871
- var CACHE_KEY_ORIGIN2 = "https://cache.swell.store";
7783
+ var CACHE_NAME = "swell-html-v0";
7784
+ var CACHE_KEY_ORIGIN = "https://cache.swell.store";
7872
7785
  var TTL_CONFIG = {
7873
7786
  LIVE: {
7874
- DEFAULT: 300,
7875
- // 5 minutes
7876
- HOME: 300,
7877
- // 5 minutes
7878
- PRODUCT: 600,
7879
- // 10 minutes
7880
- COLLECTION: 900,
7881
- // 15 minutes
7882
- PAGE: 3600,
7883
- // 1 hour
7884
- BLOG: 1800,
7885
- // 30 minutes
7886
- SWR: 3600
7887
- // 1 hour stale-while-revalidate
7787
+ DEFAULT: 20,
7788
+ HOME: 20,
7789
+ PRODUCT: 20,
7790
+ COLLECTION: 20,
7791
+ PAGE: 20,
7792
+ BLOG: 20,
7793
+ SWR: 180
7888
7794
  },
7889
7795
  PREVIEW: {
7890
- DEFAULT: 5,
7891
- // 1 minute - faster updates in preview
7892
- HOME: 5,
7893
- // 1 minute
7894
- PRODUCT: 5,
7895
- // 2 minutes
7896
- COLLECTION: 5,
7897
- // 3 minutes
7898
- PAGE: 5,
7899
- // 5 minutes
7900
- BLOG: 5,
7901
- // 5 minutes
7902
- SWR: 600
7903
- // 10 minutes stale-while-revalidate
7796
+ DEFAULT: 20,
7797
+ HOME: 20,
7798
+ PRODUCT: 20,
7799
+ COLLECTION: 20,
7800
+ PAGE: 20,
7801
+ BLOG: 20,
7802
+ SWR: 180
7904
7803
  }
7905
7804
  };
7906
7805
  var WorkerHtmlCache = class {
@@ -7919,7 +7818,7 @@ var WorkerHtmlCache = class {
7919
7818
  return { found: false, cacheable: false };
7920
7819
  }
7921
7820
  try {
7922
- const cache = await caches.open(CACHE_NAME2 + this.epoch);
7821
+ const cache = await caches.open(CACHE_NAME + this.epoch);
7923
7822
  const cacheKey = this.buildCacheKey(request);
7924
7823
  const cached = await cache.match(cacheKey);
7925
7824
  if (!cached) {
@@ -8022,7 +7921,7 @@ var WorkerHtmlCache = class {
8022
7921
  return;
8023
7922
  }
8024
7923
  try {
8025
- const cache = await caches.open(CACHE_NAME2 + this.epoch);
7924
+ const cache = await caches.open(CACHE_NAME + this.epoch);
8026
7925
  const cacheKey = this.buildCacheKey(request);
8027
7926
  await cache.delete(cacheKey);
8028
7927
  const ttl = this.getTTLForRequest(request);
@@ -8082,7 +7981,7 @@ var WorkerHtmlCache = class {
8082
7981
  const versionHash = this.generateVersionHash(request.headers);
8083
7982
  const normalizedQuery = this.normalizeSearchParams(url.searchParams);
8084
7983
  const cacheKeyPath = `${versionHash}${url.pathname}`;
8085
- const keyUrl = new URL(`${CACHE_KEY_ORIGIN2}${cacheKeyPath}`);
7984
+ const keyUrl = new URL(`${CACHE_KEY_ORIGIN}${cacheKeyPath}`);
8086
7985
  if (normalizedQuery) {
8087
7986
  keyUrl.search = `?${normalizedQuery}`;
8088
7987
  }
@@ -16385,8 +16284,15 @@ function convertToShopifySorting(value) {
16385
16284
  function getProducts(instance, object, mapper) {
16386
16285
  return deferWith(object, (object2) => {
16387
16286
  const { page, limit: limit2 } = instance.swell.queryParams;
16388
- const categoryFilter = object2.id && object2.id !== "all" ? object2.id : void 0;
16389
- const productQuery = categoryFilter ? { category: categoryFilter, $variants: true } : { $variants: true };
16287
+ const productQuery = {
16288
+ $variants: true
16289
+ };
16290
+ if (typeof object2.id === "string" && object2.id !== "all") {
16291
+ productQuery.category = object2.id;
16292
+ }
16293
+ if (object2.performed && typeof object2.query === "string") {
16294
+ productQuery.search = object2.query;
16295
+ }
16390
16296
  const filterQuery = productQueryWithFilters(instance.swell, productQuery);
16391
16297
  const products = new SwellStorefrontCollection(
16392
16298
  instance.swell,
@@ -17202,11 +17108,11 @@ function ShopifySearch(instance, search) {
17202
17108
  (filter) => ShopifyFilter(instance, filter)
17203
17109
  );
17204
17110
  }),
17205
- performed: defer(() => search.performed),
17111
+ performed: deferWith(search, (search2) => search2.performed),
17206
17112
  results: defer(async () => (await resolveProducts())?.results ?? []),
17207
17113
  results_count: defer(async () => (await resolveProducts())?.count || 0),
17208
17114
  sort_by: defer(() => search.sort),
17209
- sort_options: defer(() => search.sort_options),
17115
+ sort_options: deferWith(search, (search2) => search2.sort_options),
17210
17116
  terms: defer(() => search.query),
17211
17117
  types: ["product"]
17212
17118
  });
@@ -20597,7 +20503,8 @@ function getLiquidFS(getThemeConfig, extName) {
20597
20503
 
20598
20504
  // src/theme/theme-loader.ts
20599
20505
  var MAX_INDIVIDUAL_CONFIGS_TO_FETCH = 50;
20600
- var ThemeLoader = class {
20506
+ var ThemeLoader = class _ThemeLoader {
20507
+ static cache = null;
20601
20508
  swell;
20602
20509
  configs;
20603
20510
  constructor(swell) {
@@ -20738,24 +20645,14 @@ var ThemeLoader = class {
20738
20645
  limit: 1e3,
20739
20646
  type: "theme",
20740
20647
  fields: "id, name, type, file, file_path, hash"
20741
- // NO file_data
20742
20648
  };
20743
- const cache = new WorkerCacheProxy(this.swell);
20744
20649
  const versionHash = this.swell.swellHeaders["theme-version-hash"];
20745
- try {
20746
- const cached = await cache.get(
20747
- "/:themes:configs",
20748
- query,
20749
- {
20750
- version: versionHash || null
20751
- }
20752
- );
20753
- if (cached) {
20754
- logger.debug("[ThemeLoader] Config metadata cache hit");
20755
- return cached;
20756
- }
20757
- } catch (err) {
20758
- logger.warn("[ThemeLoader] Cache read failed, fetching from API", err);
20650
+ const cacheKey = this.buildMetadataCacheKey(versionHash, query);
20651
+ const cache = this.getCache();
20652
+ const cached = await cache.get(cacheKey);
20653
+ if (cached) {
20654
+ logger.debug("[ThemeLoader] Config metadata cache hit");
20655
+ return cached;
20759
20656
  }
20760
20657
  logger.debug("[ThemeLoader] Fetching config metadata from API");
20761
20658
  const response = await this.swell.get(
@@ -20763,14 +20660,7 @@ var ThemeLoader = class {
20763
20660
  query
20764
20661
  );
20765
20662
  const configs = response?.results || [];
20766
- const ctx = this.swell.workerCtx || globalThis.executionContext;
20767
- if (ctx && typeof ctx.waitUntil === "function") {
20768
- ctx.waitUntil(
20769
- cache.put("/:themes:configs", query, configs, {
20770
- version: versionHash || null
20771
- })
20772
- );
20773
- }
20663
+ await cache.set(cacheKey, configs);
20774
20664
  return configs;
20775
20665
  }
20776
20666
  /**
@@ -20875,6 +20765,25 @@ var ThemeLoader = class {
20875
20765
  preview: swellHeaders["deployment-mode"] === "editor" || swellHeaders["deployment-mode"] === "preview" ? true : { $ne: true }
20876
20766
  };
20877
20767
  }
20768
+ /**
20769
+ * Build cache key with tenant isolation for metadata
20770
+ */
20771
+ buildMetadataCacheKey(version, query) {
20772
+ const args = [this.swell.instanceId, version || "default", query];
20773
+ return `theme_configs:${md5(JSON.stringify(args))}`;
20774
+ }
20775
+ /**
20776
+ * Get or create the theme cache instance
20777
+ */
20778
+ getCache() {
20779
+ if (!_ThemeLoader.cache) {
20780
+ _ThemeLoader.cache = new ThemeCache({
20781
+ kvStore: this.swell.workerEnv?.THEME,
20782
+ workerCtx: this.swell.workerCtx
20783
+ });
20784
+ }
20785
+ return _ThemeLoader.cache;
20786
+ }
20878
20787
  };
20879
20788
 
20880
20789
  // src/globals.ts