@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 +81 -164
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +81 -164
- package/dist/index.js.map +4 -4
- package/dist/index.mjs +81 -164
- package/dist/index.mjs.map +4 -4
- package/dist/src/theme/theme-loader.d.ts +9 -0
- package/dist/types/shopify.d.ts +1 -1
- package/package.json +1 -1
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
|
|
7753
|
-
var
|
|
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:
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
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:
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
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(
|
|
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(
|
|
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(`${
|
|
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
|
-
|
|
15297
|
-
|
|
15298
|
-
|
|
15299
|
-
|
|
15300
|
-
|
|
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
|
-
|
|
20611
|
-
|
|
20612
|
-
|
|
20613
|
-
|
|
20614
|
-
|
|
20615
|
-
|
|
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
|
-
|
|
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
|