@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 +69 -160
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +69 -160
- package/dist/index.js.map +4 -4
- package/dist/index.mjs +69 -160
- package/dist/index.mjs.map +4 -4
- package/dist/src/theme/theme-loader.d.ts +9 -0
- package/dist/types/swell.d.ts +5 -0
- package/package.json +1 -1
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
|
|
7871
|
-
var
|
|
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:
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
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:
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
|
|
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(
|
|
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(
|
|
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(`${
|
|
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
|
|
16389
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
20746
|
-
|
|
20747
|
-
|
|
20748
|
-
|
|
20749
|
-
|
|
20750
|
-
|
|
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
|
-
|
|
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
|