@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.js CHANGED
@@ -166,7 +166,7 @@
166
166
  if (typeof ttl === "number") {
167
167
  ttl = Math.max(60, ttl / 1e3);
168
168
  }
169
- logger.debug("[SDK] kv.set", { key });
169
+ logger.debug("[SDK] kv.set", { key, ttl });
170
170
  return this.store.put(key, value, { expirationTtl: ttl });
171
171
  }
172
172
  async delete(key) {
@@ -745,7 +745,6 @@
745
745
  "_getResourceObject",
746
746
  "_collection",
747
747
  "_swell",
748
- "_query",
749
748
  "_params",
750
749
  "_id",
751
750
  "_resourceName"
@@ -7309,6 +7308,14 @@
7309
7308
 
7310
7309
  // src/cache/theme-cache.ts
7311
7310
  var TTL = 90 * 24 * 60 * 60 * 1e3;
7311
+ var ThemeCache = class extends Cache {
7312
+ constructor(options) {
7313
+ super({
7314
+ ttl: TTL,
7315
+ ...options
7316
+ });
7317
+ }
7318
+ };
7312
7319
 
7313
7320
  // src/cache/theme-file-storage.ts
7314
7321
  var import_bluebird2 = __toESM(__require("bluebird"), 1);
@@ -7650,139 +7657,29 @@
7650
7657
  var HOUR = 60 * MINUTE;
7651
7658
  var DAY = 24 * HOUR;
7652
7659
  var YEAR = 365 * DAY;
7653
- var MAX_TTL = YEAR;
7654
7660
  var SHORT_TTL = 5 * SECOND;
7655
7661
 
7656
- // src/cache/worker-cache-proxy.ts
7657
- var CACHE_NAME = "swell-cache-v011";
7658
- var CACHE_KEY_ORIGIN = "https://cache.swell.store";
7659
- var WorkerCacheProxy = class {
7660
- swell;
7661
- constructor(swell) {
7662
- this.swell = swell;
7663
- }
7664
- /**
7665
- * Reads a JSON value from Worker Cache using a key built from path+query.
7666
- * Returns null on miss or if running outside of a Worker environment.
7667
- */
7668
- async get(path, query, opts) {
7669
- if (typeof caches === "undefined") {
7670
- return null;
7671
- }
7672
- const { keyUrl } = await this.buildKeyUrl(path, query, opts?.version);
7673
- try {
7674
- const cache = await caches.open(CACHE_NAME);
7675
- const match = await cache.match(keyUrl);
7676
- if (!match) return null;
7677
- const data = await match.json();
7678
- return data;
7679
- } catch {
7680
- return null;
7681
- }
7682
- }
7683
- /**
7684
- * Stores a JSON value in Worker Cache under key built from path+query.
7685
- * No-ops outside of a Worker environment.
7686
- */
7687
- async put(path, query, value, opts) {
7688
- if (typeof caches === "undefined") {
7689
- return;
7690
- }
7691
- const { keyUrl, hasVersion } = await this.buildKeyUrl(
7692
- path,
7693
- query,
7694
- opts?.version
7695
- );
7696
- const ttlMs = hasVersion ? MAX_TTL : SHORT_TTL;
7697
- try {
7698
- const cache = await caches.open(CACHE_NAME);
7699
- const response = new Response(JSON.stringify(value), {
7700
- headers: {
7701
- "Content-Type": "application/json",
7702
- "Cache-Control": `public, max-age=${Math.floor(ttlMs / 1e3)}`
7703
- }
7704
- });
7705
- await cache.put(keyUrl, response);
7706
- logger.debug("[SDK] cache put done", { keyUrl });
7707
- } catch {
7708
- }
7709
- }
7710
- /**
7711
- * Builds a deterministic key URL for Worker Cache from the backend API URL
7712
- * composed using path and query. Includes tenant and auth isolation and an
7713
- * optional version segment.
7714
- */
7715
- async buildKeyUrl(path, query, explicitVersion) {
7716
- const apiHost = this.swell.backend?.apiHost;
7717
- const endpointPath = String(path).startsWith("/") ? String(path).substring(1) : String(path);
7718
- let queryString = "";
7719
- if (query && this.swell.backend) {
7720
- queryString = this.swell.backend.stringifyQuery(query);
7721
- }
7722
- const fullUrl = `${apiHost}/${endpointPath}${queryString ? `?${queryString}` : ""}`;
7723
- const instanceId = this.swell.instanceId || "";
7724
- const authKey = String(this.swell.swellHeaders?.["swell-auth-key"] || "");
7725
- const tenantHash = await this.sha256Hex(`${instanceId}|${authKey}`);
7726
- const version = explicitVersion !== void 0 ? explicitVersion : this.swell.swellHeaders?.["theme-version-hash"] || null;
7727
- const hasVersion = Boolean(version);
7728
- const versionHash = hasVersion ? await this.sha256Hex(String(version)) : null;
7729
- const urlHash = await this.sha256Hex(fullUrl);
7730
- const keyUrl = versionHash ? `${CACHE_KEY_ORIGIN}/v1/${tenantHash}/${versionHash}/${urlHash}` : `${CACHE_KEY_ORIGIN}/v1/${tenantHash}/${urlHash}`;
7731
- return { keyUrl, hasVersion };
7732
- }
7733
- /**
7734
- * SHA-256 digest with hex encoding. Requires Worker crypto; callers
7735
- * should avoid invoking this outside of Worker code paths.
7736
- */
7737
- async sha256Hex(input) {
7738
- if (typeof crypto !== "undefined" && crypto.subtle && crypto.subtle.digest) {
7739
- const encoder = new TextEncoder();
7740
- const digest = await crypto.subtle.digest(
7741
- "SHA-256",
7742
- encoder.encode(input)
7743
- );
7744
- const bytes = new Uint8Array(digest);
7745
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
7746
- }
7747
- return md5(input);
7748
- }
7749
- };
7750
-
7751
7662
  // src/cache/worker-html-cache.ts
7752
- var CACHE_NAME2 = "swell-html-v1";
7753
- var CACHE_KEY_ORIGIN2 = "https://cache.swell.store";
7663
+ var CACHE_NAME = "swell-html-v0";
7664
+ var CACHE_KEY_ORIGIN = "https://cache.swell.store";
7754
7665
  var TTL_CONFIG = {
7755
7666
  LIVE: {
7756
- DEFAULT: 300,
7757
- // 5 minutes
7758
- HOME: 300,
7759
- // 5 minutes
7760
- PRODUCT: 600,
7761
- // 10 minutes
7762
- COLLECTION: 900,
7763
- // 15 minutes
7764
- PAGE: 3600,
7765
- // 1 hour
7766
- BLOG: 1800,
7767
- // 30 minutes
7768
- SWR: 3600
7769
- // 1 hour stale-while-revalidate
7667
+ DEFAULT: 20,
7668
+ HOME: 20,
7669
+ PRODUCT: 20,
7670
+ COLLECTION: 20,
7671
+ PAGE: 20,
7672
+ BLOG: 20,
7673
+ SWR: 180
7770
7674
  },
7771
7675
  PREVIEW: {
7772
- DEFAULT: 5,
7773
- // 1 minute - faster updates in preview
7774
- HOME: 5,
7775
- // 1 minute
7776
- PRODUCT: 5,
7777
- // 2 minutes
7778
- COLLECTION: 5,
7779
- // 3 minutes
7780
- PAGE: 5,
7781
- // 5 minutes
7782
- BLOG: 5,
7783
- // 5 minutes
7784
- SWR: 600
7785
- // 10 minutes stale-while-revalidate
7676
+ DEFAULT: 20,
7677
+ HOME: 20,
7678
+ PRODUCT: 20,
7679
+ COLLECTION: 20,
7680
+ PAGE: 20,
7681
+ BLOG: 20,
7682
+ SWR: 180
7786
7683
  }
7787
7684
  };
7788
7685
  var WorkerHtmlCache = class {
@@ -7801,7 +7698,7 @@
7801
7698
  return { found: false, cacheable: false };
7802
7699
  }
7803
7700
  try {
7804
- const cache = await caches.open(CACHE_NAME2 + this.epoch);
7701
+ const cache = await caches.open(CACHE_NAME + this.epoch);
7805
7702
  const cacheKey = this.buildCacheKey(request);
7806
7703
  const cached = await cache.match(cacheKey);
7807
7704
  if (!cached) {
@@ -7904,7 +7801,7 @@
7904
7801
  return;
7905
7802
  }
7906
7803
  try {
7907
- const cache = await caches.open(CACHE_NAME2 + this.epoch);
7804
+ const cache = await caches.open(CACHE_NAME + this.epoch);
7908
7805
  const cacheKey = this.buildCacheKey(request);
7909
7806
  await cache.delete(cacheKey);
7910
7807
  const ttl = this.getTTLForRequest(request);
@@ -7964,7 +7861,7 @@
7964
7861
  const versionHash = this.generateVersionHash(request.headers);
7965
7862
  const normalizedQuery = this.normalizeSearchParams(url.searchParams);
7966
7863
  const cacheKeyPath = `${versionHash}${url.pathname}`;
7967
- const keyUrl = new URL(`${CACHE_KEY_ORIGIN2}${cacheKeyPath}`);
7864
+ const keyUrl = new URL(`${CACHE_KEY_ORIGIN}${cacheKeyPath}`);
7968
7865
  if (normalizedQuery) {
7969
7866
  keyUrl.search = `?${normalizedQuery}`;
7970
7867
  }
@@ -15293,15 +15190,32 @@ ${formattedMessage}`;
15293
15190
  return new ShopifyResource({
15294
15191
  all_tags: allTags,
15295
15192
  articles: deferWith(blogCategory, (blogCategory2) => {
15296
- return blogCategory2.blogs?._cloneWithCompatibilityResult(
15297
- (blogs) => {
15298
- return {
15299
- results: blogs?.results?.map(
15300
- (blog) => ShopifyArticle(instance, blog, blogCategory2)
15301
- )
15302
- };
15193
+ const { page, limit: limit2 } = instance.swell.queryParams;
15194
+ const categoryBlogs = new SwellStorefrontCollection(
15195
+ instance.swell,
15196
+ "content/blogs",
15197
+ {
15198
+ page,
15199
+ limit: limit2,
15200
+ category_id: blogCategory2.id,
15201
+ expand: "author"
15202
+ },
15203
+ async function() {
15204
+ return this._defaultGetter().call(this);
15303
15205
  }
15304
- ) || [];
15206
+ );
15207
+ return categoryBlogs._cloneWithCompatibilityResult((blogs) => {
15208
+ return {
15209
+ ...blogs,
15210
+ results: blogs?.results?.map(
15211
+ (blog) => ShopifyArticle(
15212
+ instance,
15213
+ blog,
15214
+ blogCategory2
15215
+ )
15216
+ )
15217
+ };
15218
+ }) || [];
15305
15219
  }),
15306
15220
  articles_count: deferWith(blogCategory.blogs, (blogs) => blogs?.count || 0),
15307
15221
  handle: defer(() => blogCategory.slug),
@@ -20462,7 +20376,8 @@ ${injects.join("\n")}<\/script>`;
20462
20376
 
20463
20377
  // src/theme/theme-loader.ts
20464
20378
  var MAX_INDIVIDUAL_CONFIGS_TO_FETCH = 50;
20465
- var ThemeLoader = class {
20379
+ var ThemeLoader = class _ThemeLoader {
20380
+ static cache = null;
20466
20381
  swell;
20467
20382
  configs;
20468
20383
  constructor(swell) {
@@ -20603,24 +20518,14 @@ ${injects.join("\n")}<\/script>`;
20603
20518
  limit: 1e3,
20604
20519
  type: "theme",
20605
20520
  fields: "id, name, type, file, file_path, hash"
20606
- // NO file_data
20607
20521
  };
20608
- const cache = new WorkerCacheProxy(this.swell);
20609
20522
  const versionHash = this.swell.swellHeaders["theme-version-hash"];
20610
- try {
20611
- const cached = await cache.get(
20612
- "/:themes:configs",
20613
- query,
20614
- {
20615
- version: versionHash || null
20616
- }
20617
- );
20618
- if (cached) {
20619
- logger.debug("[ThemeLoader] Config metadata cache hit");
20620
- return cached;
20621
- }
20622
- } catch (err) {
20623
- logger.warn("[ThemeLoader] Cache read failed, fetching from API", err);
20523
+ const cacheKey = this.buildMetadataCacheKey(versionHash, query);
20524
+ const cache = this.getCache();
20525
+ const cached = await cache.get(cacheKey);
20526
+ if (cached) {
20527
+ logger.debug("[ThemeLoader] Config metadata cache hit");
20528
+ return cached;
20624
20529
  }
20625
20530
  logger.debug("[ThemeLoader] Fetching config metadata from API");
20626
20531
  const response = await this.swell.get(
@@ -20628,14 +20533,7 @@ ${injects.join("\n")}<\/script>`;
20628
20533
  query
20629
20534
  );
20630
20535
  const configs = response?.results || [];
20631
- const ctx = this.swell.workerCtx || globalThis.executionContext;
20632
- if (ctx && typeof ctx.waitUntil === "function") {
20633
- ctx.waitUntil(
20634
- cache.put("/:themes:configs", query, configs, {
20635
- version: versionHash || null
20636
- })
20637
- );
20638
- }
20536
+ await cache.set(cacheKey, configs);
20639
20537
  return configs;
20640
20538
  }
20641
20539
  /**
@@ -20740,6 +20638,25 @@ ${injects.join("\n")}<\/script>`;
20740
20638
  preview: swellHeaders["deployment-mode"] === "editor" || swellHeaders["deployment-mode"] === "preview" ? true : { $ne: true }
20741
20639
  };
20742
20640
  }
20641
+ /**
20642
+ * Build cache key with tenant isolation for metadata
20643
+ */
20644
+ buildMetadataCacheKey(version, query) {
20645
+ const args = [this.swell.instanceId, version || "default", query];
20646
+ return `theme_configs:${md5(JSON.stringify(args))}`;
20647
+ }
20648
+ /**
20649
+ * Get or create the theme cache instance
20650
+ */
20651
+ getCache() {
20652
+ if (!_ThemeLoader.cache) {
20653
+ _ThemeLoader.cache = new ThemeCache({
20654
+ kvStore: this.swell.workerEnv?.THEME,
20655
+ workerCtx: this.swell.workerCtx
20656
+ });
20657
+ }
20658
+ return _ThemeLoader.cache;
20659
+ }
20743
20660
  };
20744
20661
 
20745
20662
  // src/globals.ts