@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.mjs CHANGED
@@ -139,7 +139,7 @@ var CFWorkerKVKeyvAdapter = class {
139
139
  if (typeof ttl === "number") {
140
140
  ttl = Math.max(60, ttl / 1e3);
141
141
  }
142
- logger.debug("[SDK] kv.set", { key });
142
+ logger.debug("[SDK] kv.set", { key, ttl });
143
143
  return this.store.put(key, value, { expirationTtl: ttl });
144
144
  }
145
145
  async delete(key) {
@@ -718,7 +718,6 @@ var RESOURCE_CLONE_PROPS = Object.freeze([
718
718
  "_getResourceObject",
719
719
  "_collection",
720
720
  "_swell",
721
- "_query",
722
721
  "_params",
723
722
  "_id",
724
723
  "_resourceName"
@@ -7282,6 +7281,14 @@ function buildStores2() {
7282
7281
 
7283
7282
  // src/cache/theme-cache.ts
7284
7283
  var TTL = 90 * 24 * 60 * 60 * 1e3;
7284
+ var ThemeCache = class extends Cache {
7285
+ constructor(options) {
7286
+ super({
7287
+ ttl: TTL,
7288
+ ...options
7289
+ });
7290
+ }
7291
+ };
7285
7292
 
7286
7293
  // src/cache/theme-file-storage.ts
7287
7294
  import bluebird2 from "bluebird";
@@ -7623,139 +7630,29 @@ var MINUTE = 60 * SECOND;
7623
7630
  var HOUR = 60 * MINUTE;
7624
7631
  var DAY = 24 * HOUR;
7625
7632
  var YEAR = 365 * DAY;
7626
- var MAX_TTL = YEAR;
7627
7633
  var SHORT_TTL = 5 * SECOND;
7628
7634
 
7629
- // src/cache/worker-cache-proxy.ts
7630
- var CACHE_NAME = "swell-cache-v011";
7631
- var CACHE_KEY_ORIGIN = "https://cache.swell.store";
7632
- var WorkerCacheProxy = class {
7633
- swell;
7634
- constructor(swell) {
7635
- this.swell = swell;
7636
- }
7637
- /**
7638
- * Reads a JSON value from Worker Cache using a key built from path+query.
7639
- * Returns null on miss or if running outside of a Worker environment.
7640
- */
7641
- async get(path, query, opts) {
7642
- if (typeof caches === "undefined") {
7643
- return null;
7644
- }
7645
- const { keyUrl } = await this.buildKeyUrl(path, query, opts?.version);
7646
- try {
7647
- const cache = await caches.open(CACHE_NAME);
7648
- const match = await cache.match(keyUrl);
7649
- if (!match) return null;
7650
- const data = await match.json();
7651
- return data;
7652
- } catch {
7653
- return null;
7654
- }
7655
- }
7656
- /**
7657
- * Stores a JSON value in Worker Cache under key built from path+query.
7658
- * No-ops outside of a Worker environment.
7659
- */
7660
- async put(path, query, value, opts) {
7661
- if (typeof caches === "undefined") {
7662
- return;
7663
- }
7664
- const { keyUrl, hasVersion } = await this.buildKeyUrl(
7665
- path,
7666
- query,
7667
- opts?.version
7668
- );
7669
- const ttlMs = hasVersion ? MAX_TTL : SHORT_TTL;
7670
- try {
7671
- const cache = await caches.open(CACHE_NAME);
7672
- const response = new Response(JSON.stringify(value), {
7673
- headers: {
7674
- "Content-Type": "application/json",
7675
- "Cache-Control": `public, max-age=${Math.floor(ttlMs / 1e3)}`
7676
- }
7677
- });
7678
- await cache.put(keyUrl, response);
7679
- logger.debug("[SDK] cache put done", { keyUrl });
7680
- } catch {
7681
- }
7682
- }
7683
- /**
7684
- * Builds a deterministic key URL for Worker Cache from the backend API URL
7685
- * composed using path and query. Includes tenant and auth isolation and an
7686
- * optional version segment.
7687
- */
7688
- async buildKeyUrl(path, query, explicitVersion) {
7689
- const apiHost = this.swell.backend?.apiHost;
7690
- const endpointPath = String(path).startsWith("/") ? String(path).substring(1) : String(path);
7691
- let queryString = "";
7692
- if (query && this.swell.backend) {
7693
- queryString = this.swell.backend.stringifyQuery(query);
7694
- }
7695
- const fullUrl = `${apiHost}/${endpointPath}${queryString ? `?${queryString}` : ""}`;
7696
- const instanceId = this.swell.instanceId || "";
7697
- const authKey = String(this.swell.swellHeaders?.["swell-auth-key"] || "");
7698
- const tenantHash = await this.sha256Hex(`${instanceId}|${authKey}`);
7699
- const version = explicitVersion !== void 0 ? explicitVersion : this.swell.swellHeaders?.["theme-version-hash"] || null;
7700
- const hasVersion = Boolean(version);
7701
- const versionHash = hasVersion ? await this.sha256Hex(String(version)) : null;
7702
- const urlHash = await this.sha256Hex(fullUrl);
7703
- const keyUrl = versionHash ? `${CACHE_KEY_ORIGIN}/v1/${tenantHash}/${versionHash}/${urlHash}` : `${CACHE_KEY_ORIGIN}/v1/${tenantHash}/${urlHash}`;
7704
- return { keyUrl, hasVersion };
7705
- }
7706
- /**
7707
- * SHA-256 digest with hex encoding. Requires Worker crypto; callers
7708
- * should avoid invoking this outside of Worker code paths.
7709
- */
7710
- async sha256Hex(input) {
7711
- if (typeof crypto !== "undefined" && crypto.subtle && crypto.subtle.digest) {
7712
- const encoder = new TextEncoder();
7713
- const digest = await crypto.subtle.digest(
7714
- "SHA-256",
7715
- encoder.encode(input)
7716
- );
7717
- const bytes = new Uint8Array(digest);
7718
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
7719
- }
7720
- return md5(input);
7721
- }
7722
- };
7723
-
7724
7635
  // src/cache/worker-html-cache.ts
7725
- var CACHE_NAME2 = "swell-html-v1";
7726
- var CACHE_KEY_ORIGIN2 = "https://cache.swell.store";
7636
+ var CACHE_NAME = "swell-html-v0";
7637
+ var CACHE_KEY_ORIGIN = "https://cache.swell.store";
7727
7638
  var TTL_CONFIG = {
7728
7639
  LIVE: {
7729
- DEFAULT: 300,
7730
- // 5 minutes
7731
- HOME: 300,
7732
- // 5 minutes
7733
- PRODUCT: 600,
7734
- // 10 minutes
7735
- COLLECTION: 900,
7736
- // 15 minutes
7737
- PAGE: 3600,
7738
- // 1 hour
7739
- BLOG: 1800,
7740
- // 30 minutes
7741
- SWR: 3600
7742
- // 1 hour stale-while-revalidate
7640
+ DEFAULT: 20,
7641
+ HOME: 20,
7642
+ PRODUCT: 20,
7643
+ COLLECTION: 20,
7644
+ PAGE: 20,
7645
+ BLOG: 20,
7646
+ SWR: 180
7743
7647
  },
7744
7648
  PREVIEW: {
7745
- DEFAULT: 5,
7746
- // 1 minute - faster updates in preview
7747
- HOME: 5,
7748
- // 1 minute
7749
- PRODUCT: 5,
7750
- // 2 minutes
7751
- COLLECTION: 5,
7752
- // 3 minutes
7753
- PAGE: 5,
7754
- // 5 minutes
7755
- BLOG: 5,
7756
- // 5 minutes
7757
- SWR: 600
7758
- // 10 minutes stale-while-revalidate
7649
+ DEFAULT: 20,
7650
+ HOME: 20,
7651
+ PRODUCT: 20,
7652
+ COLLECTION: 20,
7653
+ PAGE: 20,
7654
+ BLOG: 20,
7655
+ SWR: 180
7759
7656
  }
7760
7657
  };
7761
7658
  var WorkerHtmlCache = class {
@@ -7774,7 +7671,7 @@ var WorkerHtmlCache = class {
7774
7671
  return { found: false, cacheable: false };
7775
7672
  }
7776
7673
  try {
7777
- const cache = await caches.open(CACHE_NAME2 + this.epoch);
7674
+ const cache = await caches.open(CACHE_NAME + this.epoch);
7778
7675
  const cacheKey = this.buildCacheKey(request);
7779
7676
  const cached = await cache.match(cacheKey);
7780
7677
  if (!cached) {
@@ -7877,7 +7774,7 @@ var WorkerHtmlCache = class {
7877
7774
  return;
7878
7775
  }
7879
7776
  try {
7880
- const cache = await caches.open(CACHE_NAME2 + this.epoch);
7777
+ const cache = await caches.open(CACHE_NAME + this.epoch);
7881
7778
  const cacheKey = this.buildCacheKey(request);
7882
7779
  await cache.delete(cacheKey);
7883
7780
  const ttl = this.getTTLForRequest(request);
@@ -7937,7 +7834,7 @@ var WorkerHtmlCache = class {
7937
7834
  const versionHash = this.generateVersionHash(request.headers);
7938
7835
  const normalizedQuery = this.normalizeSearchParams(url.searchParams);
7939
7836
  const cacheKeyPath = `${versionHash}${url.pathname}`;
7940
- const keyUrl = new URL(`${CACHE_KEY_ORIGIN2}${cacheKeyPath}`);
7837
+ const keyUrl = new URL(`${CACHE_KEY_ORIGIN}${cacheKeyPath}`);
7941
7838
  if (normalizedQuery) {
7942
7839
  keyUrl.search = `?${normalizedQuery}`;
7943
7840
  }
@@ -15266,15 +15163,32 @@ function ShopifyBlog(instance, blogCategory) {
15266
15163
  return new ShopifyResource({
15267
15164
  all_tags: allTags,
15268
15165
  articles: deferWith(blogCategory, (blogCategory2) => {
15269
- return blogCategory2.blogs?._cloneWithCompatibilityResult(
15270
- (blogs) => {
15271
- return {
15272
- results: blogs?.results?.map(
15273
- (blog) => ShopifyArticle(instance, blog, blogCategory2)
15274
- )
15275
- };
15166
+ const { page, limit: limit2 } = instance.swell.queryParams;
15167
+ const categoryBlogs = new SwellStorefrontCollection(
15168
+ instance.swell,
15169
+ "content/blogs",
15170
+ {
15171
+ page,
15172
+ limit: limit2,
15173
+ category_id: blogCategory2.id,
15174
+ expand: "author"
15175
+ },
15176
+ async function() {
15177
+ return this._defaultGetter().call(this);
15276
15178
  }
15277
- ) || [];
15179
+ );
15180
+ return categoryBlogs._cloneWithCompatibilityResult((blogs) => {
15181
+ return {
15182
+ ...blogs,
15183
+ results: blogs?.results?.map(
15184
+ (blog) => ShopifyArticle(
15185
+ instance,
15186
+ blog,
15187
+ blogCategory2
15188
+ )
15189
+ )
15190
+ };
15191
+ }) || [];
15278
15192
  }),
15279
15193
  articles_count: deferWith(blogCategory.blogs, (blogs) => blogs?.count || 0),
15280
15194
  handle: defer(() => blogCategory.slug),
@@ -20443,7 +20357,8 @@ function getLiquidFS(getThemeConfig, extName) {
20443
20357
 
20444
20358
  // src/theme/theme-loader.ts
20445
20359
  var MAX_INDIVIDUAL_CONFIGS_TO_FETCH = 50;
20446
- var ThemeLoader = class {
20360
+ var ThemeLoader = class _ThemeLoader {
20361
+ static cache = null;
20447
20362
  swell;
20448
20363
  configs;
20449
20364
  constructor(swell) {
@@ -20584,24 +20499,14 @@ var ThemeLoader = class {
20584
20499
  limit: 1e3,
20585
20500
  type: "theme",
20586
20501
  fields: "id, name, type, file, file_path, hash"
20587
- // NO file_data
20588
20502
  };
20589
- const cache = new WorkerCacheProxy(this.swell);
20590
20503
  const versionHash = this.swell.swellHeaders["theme-version-hash"];
20591
- try {
20592
- const cached = await cache.get(
20593
- "/:themes:configs",
20594
- query,
20595
- {
20596
- version: versionHash || null
20597
- }
20598
- );
20599
- if (cached) {
20600
- logger.debug("[ThemeLoader] Config metadata cache hit");
20601
- return cached;
20602
- }
20603
- } catch (err) {
20604
- logger.warn("[ThemeLoader] Cache read failed, fetching from API", err);
20504
+ const cacheKey = this.buildMetadataCacheKey(versionHash, query);
20505
+ const cache = this.getCache();
20506
+ const cached = await cache.get(cacheKey);
20507
+ if (cached) {
20508
+ logger.debug("[ThemeLoader] Config metadata cache hit");
20509
+ return cached;
20605
20510
  }
20606
20511
  logger.debug("[ThemeLoader] Fetching config metadata from API");
20607
20512
  const response = await this.swell.get(
@@ -20609,14 +20514,7 @@ var ThemeLoader = class {
20609
20514
  query
20610
20515
  );
20611
20516
  const configs = response?.results || [];
20612
- const ctx = this.swell.workerCtx || globalThis.executionContext;
20613
- if (ctx && typeof ctx.waitUntil === "function") {
20614
- ctx.waitUntil(
20615
- cache.put("/:themes:configs", query, configs, {
20616
- version: versionHash || null
20617
- })
20618
- );
20619
- }
20517
+ await cache.set(cacheKey, configs);
20620
20518
  return configs;
20621
20519
  }
20622
20520
  /**
@@ -20721,6 +20619,25 @@ var ThemeLoader = class {
20721
20619
  preview: swellHeaders["deployment-mode"] === "editor" || swellHeaders["deployment-mode"] === "preview" ? true : { $ne: true }
20722
20620
  };
20723
20621
  }
20622
+ /**
20623
+ * Build cache key with tenant isolation for metadata
20624
+ */
20625
+ buildMetadataCacheKey(version, query) {
20626
+ const args = [this.swell.instanceId, version || "default", query];
20627
+ return `theme_configs:${md5(JSON.stringify(args))}`;
20628
+ }
20629
+ /**
20630
+ * Get or create the theme cache instance
20631
+ */
20632
+ getCache() {
20633
+ if (!_ThemeLoader.cache) {
20634
+ _ThemeLoader.cache = new ThemeCache({
20635
+ kvStore: this.swell.workerEnv?.THEME,
20636
+ workerCtx: this.swell.workerCtx
20637
+ });
20638
+ }
20639
+ return _ThemeLoader.cache;
20640
+ }
20724
20641
  };
20725
20642
 
20726
20643
  // src/globals.ts