@swell/apps-sdk 1.0.157 → 1.0.159

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) {
@@ -864,7 +864,6 @@ var RESOURCE_CLONE_PROPS = Object.freeze([
864
864
  "_getResourceObject",
865
865
  "_collection",
866
866
  "_swell",
867
- "_query",
868
867
  "_params",
869
868
  "_id",
870
869
  "_resourceName"
@@ -7428,6 +7427,14 @@ function buildStores2() {
7428
7427
 
7429
7428
  // src/cache/theme-cache.ts
7430
7429
  var TTL = 90 * 24 * 60 * 60 * 1e3;
7430
+ var ThemeCache = class extends Cache {
7431
+ constructor(options) {
7432
+ super({
7433
+ ttl: TTL,
7434
+ ...options
7435
+ });
7436
+ }
7437
+ };
7431
7438
 
7432
7439
  // src/cache/theme-file-storage.ts
7433
7440
  var import_bluebird2 = __toESM(require("bluebird"), 1);
@@ -7769,139 +7776,29 @@ var MINUTE = 60 * SECOND;
7769
7776
  var HOUR = 60 * MINUTE;
7770
7777
  var DAY = 24 * HOUR;
7771
7778
  var YEAR = 365 * DAY;
7772
- var MAX_TTL = YEAR;
7773
7779
  var SHORT_TTL = 5 * SECOND;
7774
7780
 
7775
- // src/cache/worker-cache-proxy.ts
7776
- var CACHE_NAME = "swell-cache-v011";
7777
- var CACHE_KEY_ORIGIN = "https://cache.swell.store";
7778
- var WorkerCacheProxy = class {
7779
- swell;
7780
- constructor(swell) {
7781
- this.swell = swell;
7782
- }
7783
- /**
7784
- * Reads a JSON value from Worker Cache using a key built from path+query.
7785
- * Returns null on miss or if running outside of a Worker environment.
7786
- */
7787
- async get(path, query, opts) {
7788
- if (typeof caches === "undefined") {
7789
- return null;
7790
- }
7791
- const { keyUrl } = await this.buildKeyUrl(path, query, opts?.version);
7792
- try {
7793
- const cache = await caches.open(CACHE_NAME);
7794
- const match = await cache.match(keyUrl);
7795
- if (!match) return null;
7796
- const data = await match.json();
7797
- return data;
7798
- } catch {
7799
- return null;
7800
- }
7801
- }
7802
- /**
7803
- * Stores a JSON value in Worker Cache under key built from path+query.
7804
- * No-ops outside of a Worker environment.
7805
- */
7806
- async put(path, query, value, opts) {
7807
- if (typeof caches === "undefined") {
7808
- return;
7809
- }
7810
- const { keyUrl, hasVersion } = await this.buildKeyUrl(
7811
- path,
7812
- query,
7813
- opts?.version
7814
- );
7815
- const ttlMs = hasVersion ? MAX_TTL : SHORT_TTL;
7816
- try {
7817
- const cache = await caches.open(CACHE_NAME);
7818
- const response = new Response(JSON.stringify(value), {
7819
- headers: {
7820
- "Content-Type": "application/json",
7821
- "Cache-Control": `public, max-age=${Math.floor(ttlMs / 1e3)}`
7822
- }
7823
- });
7824
- await cache.put(keyUrl, response);
7825
- logger.debug("[SDK] cache put done", { keyUrl });
7826
- } catch {
7827
- }
7828
- }
7829
- /**
7830
- * Builds a deterministic key URL for Worker Cache from the backend API URL
7831
- * composed using path and query. Includes tenant and auth isolation and an
7832
- * optional version segment.
7833
- */
7834
- async buildKeyUrl(path, query, explicitVersion) {
7835
- const apiHost = this.swell.backend?.apiHost;
7836
- const endpointPath = String(path).startsWith("/") ? String(path).substring(1) : String(path);
7837
- let queryString = "";
7838
- if (query && this.swell.backend) {
7839
- queryString = this.swell.backend.stringifyQuery(query);
7840
- }
7841
- const fullUrl = `${apiHost}/${endpointPath}${queryString ? `?${queryString}` : ""}`;
7842
- const instanceId = this.swell.instanceId || "";
7843
- const authKey = String(this.swell.swellHeaders?.["swell-auth-key"] || "");
7844
- const tenantHash = await this.sha256Hex(`${instanceId}|${authKey}`);
7845
- const version = explicitVersion !== void 0 ? explicitVersion : this.swell.swellHeaders?.["theme-version-hash"] || null;
7846
- const hasVersion = Boolean(version);
7847
- const versionHash = hasVersion ? await this.sha256Hex(String(version)) : null;
7848
- const urlHash = await this.sha256Hex(fullUrl);
7849
- const keyUrl = versionHash ? `${CACHE_KEY_ORIGIN}/v1/${tenantHash}/${versionHash}/${urlHash}` : `${CACHE_KEY_ORIGIN}/v1/${tenantHash}/${urlHash}`;
7850
- return { keyUrl, hasVersion };
7851
- }
7852
- /**
7853
- * SHA-256 digest with hex encoding. Requires Worker crypto; callers
7854
- * should avoid invoking this outside of Worker code paths.
7855
- */
7856
- async sha256Hex(input) {
7857
- if (typeof crypto !== "undefined" && crypto.subtle && crypto.subtle.digest) {
7858
- const encoder = new TextEncoder();
7859
- const digest = await crypto.subtle.digest(
7860
- "SHA-256",
7861
- encoder.encode(input)
7862
- );
7863
- const bytes = new Uint8Array(digest);
7864
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
7865
- }
7866
- return md5(input);
7867
- }
7868
- };
7869
-
7870
7781
  // src/cache/worker-html-cache.ts
7871
- var CACHE_NAME2 = "swell-html-v1";
7872
- var CACHE_KEY_ORIGIN2 = "https://cache.swell.store";
7782
+ var CACHE_NAME = "swell-html-v0";
7783
+ var CACHE_KEY_ORIGIN = "https://cache.swell.store";
7873
7784
  var TTL_CONFIG = {
7874
7785
  LIVE: {
7875
- DEFAULT: 300,
7876
- // 5 minutes
7877
- HOME: 300,
7878
- // 5 minutes
7879
- PRODUCT: 600,
7880
- // 10 minutes
7881
- COLLECTION: 900,
7882
- // 15 minutes
7883
- PAGE: 3600,
7884
- // 1 hour
7885
- BLOG: 1800,
7886
- // 30 minutes
7887
- SWR: 3600
7888
- // 1 hour stale-while-revalidate
7786
+ DEFAULT: 20,
7787
+ HOME: 20,
7788
+ PRODUCT: 20,
7789
+ COLLECTION: 20,
7790
+ PAGE: 20,
7791
+ BLOG: 20,
7792
+ SWR: 180
7889
7793
  },
7890
7794
  PREVIEW: {
7891
- DEFAULT: 5,
7892
- // 1 minute - faster updates in preview
7893
- HOME: 5,
7894
- // 1 minute
7895
- PRODUCT: 5,
7896
- // 2 minutes
7897
- COLLECTION: 5,
7898
- // 3 minutes
7899
- PAGE: 5,
7900
- // 5 minutes
7901
- BLOG: 5,
7902
- // 5 minutes
7903
- SWR: 600
7904
- // 10 minutes stale-while-revalidate
7795
+ DEFAULT: 20,
7796
+ HOME: 20,
7797
+ PRODUCT: 20,
7798
+ COLLECTION: 20,
7799
+ PAGE: 20,
7800
+ BLOG: 20,
7801
+ SWR: 180
7905
7802
  }
7906
7803
  };
7907
7804
  var WorkerHtmlCache = class {
@@ -7920,7 +7817,7 @@ var WorkerHtmlCache = class {
7920
7817
  return { found: false, cacheable: false };
7921
7818
  }
7922
7819
  try {
7923
- const cache = await caches.open(CACHE_NAME2 + this.epoch);
7820
+ const cache = await caches.open(CACHE_NAME + this.epoch);
7924
7821
  const cacheKey = this.buildCacheKey(request);
7925
7822
  const cached = await cache.match(cacheKey);
7926
7823
  if (!cached) {
@@ -8023,7 +7920,7 @@ var WorkerHtmlCache = class {
8023
7920
  return;
8024
7921
  }
8025
7922
  try {
8026
- const cache = await caches.open(CACHE_NAME2 + this.epoch);
7923
+ const cache = await caches.open(CACHE_NAME + this.epoch);
8027
7924
  const cacheKey = this.buildCacheKey(request);
8028
7925
  await cache.delete(cacheKey);
8029
7926
  const ttl = this.getTTLForRequest(request);
@@ -8083,7 +7980,7 @@ var WorkerHtmlCache = class {
8083
7980
  const versionHash = this.generateVersionHash(request.headers);
8084
7981
  const normalizedQuery = this.normalizeSearchParams(url.searchParams);
8085
7982
  const cacheKeyPath = `${versionHash}${url.pathname}`;
8086
- const keyUrl = new URL(`${CACHE_KEY_ORIGIN2}${cacheKeyPath}`);
7983
+ const keyUrl = new URL(`${CACHE_KEY_ORIGIN}${cacheKeyPath}`);
8087
7984
  if (normalizedQuery) {
8088
7985
  keyUrl.search = `?${normalizedQuery}`;
8089
7986
  }
@@ -15412,15 +15309,32 @@ function ShopifyBlog(instance, blogCategory) {
15412
15309
  return new ShopifyResource({
15413
15310
  all_tags: allTags,
15414
15311
  articles: deferWith(blogCategory, (blogCategory2) => {
15415
- return blogCategory2.blogs?._cloneWithCompatibilityResult(
15416
- (blogs) => {
15417
- return {
15418
- results: blogs?.results?.map(
15419
- (blog) => ShopifyArticle(instance, blog, blogCategory2)
15420
- )
15421
- };
15312
+ const { page, limit: limit2 } = instance.swell.queryParams;
15313
+ const categoryBlogs = new SwellStorefrontCollection(
15314
+ instance.swell,
15315
+ "content/blogs",
15316
+ {
15317
+ page,
15318
+ limit: limit2,
15319
+ category_id: blogCategory2.id,
15320
+ expand: "author"
15321
+ },
15322
+ async function() {
15323
+ return this._defaultGetter().call(this);
15422
15324
  }
15423
- ) || [];
15325
+ );
15326
+ return categoryBlogs._cloneWithCompatibilityResult((blogs) => {
15327
+ return {
15328
+ ...blogs,
15329
+ results: blogs?.results?.map(
15330
+ (blog) => ShopifyArticle(
15331
+ instance,
15332
+ blog,
15333
+ blogCategory2
15334
+ )
15335
+ )
15336
+ };
15337
+ }) || [];
15424
15338
  }),
15425
15339
  articles_count: deferWith(blogCategory.blogs, (blogs) => blogs?.count || 0),
15426
15340
  handle: defer(() => blogCategory.slug),
@@ -20581,7 +20495,8 @@ function getLiquidFS(getThemeConfig, extName) {
20581
20495
 
20582
20496
  // src/theme/theme-loader.ts
20583
20497
  var MAX_INDIVIDUAL_CONFIGS_TO_FETCH = 50;
20584
- var ThemeLoader = class {
20498
+ var ThemeLoader = class _ThemeLoader {
20499
+ static cache = null;
20585
20500
  swell;
20586
20501
  configs;
20587
20502
  constructor(swell) {
@@ -20722,24 +20637,14 @@ var ThemeLoader = class {
20722
20637
  limit: 1e3,
20723
20638
  type: "theme",
20724
20639
  fields: "id, name, type, file, file_path, hash"
20725
- // NO file_data
20726
20640
  };
20727
- const cache = new WorkerCacheProxy(this.swell);
20728
20641
  const versionHash = this.swell.swellHeaders["theme-version-hash"];
20729
- try {
20730
- const cached = await cache.get(
20731
- "/:themes:configs",
20732
- query,
20733
- {
20734
- version: versionHash || null
20735
- }
20736
- );
20737
- if (cached) {
20738
- logger.debug("[ThemeLoader] Config metadata cache hit");
20739
- return cached;
20740
- }
20741
- } catch (err) {
20742
- logger.warn("[ThemeLoader] Cache read failed, fetching from API", err);
20642
+ const cacheKey = this.buildMetadataCacheKey(versionHash, query);
20643
+ const cache = this.getCache();
20644
+ const cached = await cache.get(cacheKey);
20645
+ if (cached) {
20646
+ logger.debug("[ThemeLoader] Config metadata cache hit");
20647
+ return cached;
20743
20648
  }
20744
20649
  logger.debug("[ThemeLoader] Fetching config metadata from API");
20745
20650
  const response = await this.swell.get(
@@ -20747,14 +20652,7 @@ var ThemeLoader = class {
20747
20652
  query
20748
20653
  );
20749
20654
  const configs = response?.results || [];
20750
- const ctx = this.swell.workerCtx || globalThis.executionContext;
20751
- if (ctx && typeof ctx.waitUntil === "function") {
20752
- ctx.waitUntil(
20753
- cache.put("/:themes:configs", query, configs, {
20754
- version: versionHash || null
20755
- })
20756
- );
20757
- }
20655
+ await cache.set(cacheKey, configs);
20758
20656
  return configs;
20759
20657
  }
20760
20658
  /**
@@ -20859,6 +20757,25 @@ var ThemeLoader = class {
20859
20757
  preview: swellHeaders["deployment-mode"] === "editor" || swellHeaders["deployment-mode"] === "preview" ? true : { $ne: true }
20860
20758
  };
20861
20759
  }
20760
+ /**
20761
+ * Build cache key with tenant isolation for metadata
20762
+ */
20763
+ buildMetadataCacheKey(version, query) {
20764
+ const args = [this.swell.instanceId, version || "default", query];
20765
+ return `theme_configs:${md5(JSON.stringify(args))}`;
20766
+ }
20767
+ /**
20768
+ * Get or create the theme cache instance
20769
+ */
20770
+ getCache() {
20771
+ if (!_ThemeLoader.cache) {
20772
+ _ThemeLoader.cache = new ThemeCache({
20773
+ kvStore: this.swell.workerEnv?.THEME,
20774
+ workerCtx: this.swell.workerCtx
20775
+ });
20776
+ }
20777
+ return _ThemeLoader.cache;
20778
+ }
20862
20779
  };
20863
20780
 
20864
20781
  // src/globals.ts