@swell/apps-sdk 1.0.152 → 1.0.153
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 +130 -72
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +130 -72
- package/dist/index.js.map +2 -2
- package/dist/index.mjs +130 -72
- package/dist/index.mjs.map +2 -2
- package/dist/src/cache/worker-html-cache.d.ts +7 -20
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7858,20 +7858,38 @@ var WorkerCacheProxy = class {
|
|
|
7858
7858
|
var CACHE_NAME2 = "swell-html-v1";
|
|
7859
7859
|
var CACHE_KEY_ORIGIN2 = "https://cache.swell.store";
|
|
7860
7860
|
var TTL_CONFIG = {
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
|
|
7861
|
+
LIVE: {
|
|
7862
|
+
DEFAULT: 300,
|
|
7863
|
+
// 5 minutes
|
|
7864
|
+
HOME: 300,
|
|
7865
|
+
// 5 minutes
|
|
7866
|
+
PRODUCT: 600,
|
|
7867
|
+
// 10 minutes
|
|
7868
|
+
COLLECTION: 900,
|
|
7869
|
+
// 15 minutes
|
|
7870
|
+
PAGE: 3600,
|
|
7871
|
+
// 1 hour
|
|
7872
|
+
BLOG: 1800,
|
|
7873
|
+
// 30 minutes
|
|
7874
|
+
SWR: 3600
|
|
7875
|
+
// 1 hour stale-while-revalidate
|
|
7876
|
+
},
|
|
7877
|
+
PREVIEW: {
|
|
7878
|
+
DEFAULT: 5,
|
|
7879
|
+
// 1 minute - faster updates in preview
|
|
7880
|
+
HOME: 5,
|
|
7881
|
+
// 1 minute
|
|
7882
|
+
PRODUCT: 5,
|
|
7883
|
+
// 2 minutes
|
|
7884
|
+
COLLECTION: 5,
|
|
7885
|
+
// 3 minutes
|
|
7886
|
+
PAGE: 5,
|
|
7887
|
+
// 5 minutes
|
|
7888
|
+
BLOG: 5,
|
|
7889
|
+
// 5 minutes
|
|
7890
|
+
SWR: 600
|
|
7891
|
+
// 10 minutes stale-while-revalidate
|
|
7892
|
+
}
|
|
7875
7893
|
};
|
|
7876
7894
|
var WorkerHtmlCache = class {
|
|
7877
7895
|
epoch;
|
|
@@ -7898,7 +7916,7 @@ var WorkerHtmlCache = class {
|
|
|
7898
7916
|
}
|
|
7899
7917
|
const age = this.getResponseAge(cached);
|
|
7900
7918
|
const ttl = parseInt(cached.headers.get("X-Original-TTL") || "") || this.getTTLForRequest(request);
|
|
7901
|
-
const swr = parseInt(cached.headers.get("X-Original-SWR") || "") ||
|
|
7919
|
+
const swr = parseInt(cached.headers.get("X-Original-SWR") || "") || this.getSWRForRequest(request);
|
|
7902
7920
|
const isStale = age >= ttl;
|
|
7903
7921
|
const isExpired = age >= ttl + swr;
|
|
7904
7922
|
if (!isExpired) {
|
|
@@ -7929,6 +7947,56 @@ var WorkerHtmlCache = class {
|
|
|
7929
7947
|
return null;
|
|
7930
7948
|
}
|
|
7931
7949
|
}
|
|
7950
|
+
// 304 support
|
|
7951
|
+
async getWithConditionals(request) {
|
|
7952
|
+
const result = await this.get(request);
|
|
7953
|
+
if (!result?.found || result.stale) {
|
|
7954
|
+
return result;
|
|
7955
|
+
}
|
|
7956
|
+
const ifModifiedSince = request.headers.get("If-Modified-Since");
|
|
7957
|
+
const ifNoneMatch = request.headers.get("If-None-Match");
|
|
7958
|
+
if ((ifModifiedSince || ifNoneMatch) && result.response) {
|
|
7959
|
+
const lastModified = result.response.headers.get("Last-Modified");
|
|
7960
|
+
const etag = result.response.headers.get("ETag");
|
|
7961
|
+
if (this.checkNotModified(ifModifiedSince, ifNoneMatch, lastModified, etag)) {
|
|
7962
|
+
result.notModified = true;
|
|
7963
|
+
result.conditional304 = new Response(null, {
|
|
7964
|
+
status: 304,
|
|
7965
|
+
headers: {
|
|
7966
|
+
"Last-Modified": lastModified || "",
|
|
7967
|
+
ETag: etag || "",
|
|
7968
|
+
"Cache-Control": result.response.headers.get("Cache-Control") || "",
|
|
7969
|
+
"Cloudflare-CDN-Cache-Control": result.response.headers.get("Cloudflare-CDN-Cache-Control") || "",
|
|
7970
|
+
"X-Cache-Status": "HIT-304"
|
|
7971
|
+
}
|
|
7972
|
+
});
|
|
7973
|
+
}
|
|
7974
|
+
}
|
|
7975
|
+
return result;
|
|
7976
|
+
}
|
|
7977
|
+
checkNotModified(ifModifiedSince, ifNoneMatch, lastModified, etag) {
|
|
7978
|
+
if (ifNoneMatch && etag) {
|
|
7979
|
+
return ifNoneMatch === etag;
|
|
7980
|
+
}
|
|
7981
|
+
if (ifModifiedSince && lastModified) {
|
|
7982
|
+
const ifModDate = new Date(ifModifiedSince);
|
|
7983
|
+
const lastModDate = new Date(lastModified);
|
|
7984
|
+
return !isNaN(ifModDate.getTime()) && !isNaN(lastModDate.getTime()) && ifModDate >= lastModDate;
|
|
7985
|
+
}
|
|
7986
|
+
return false;
|
|
7987
|
+
}
|
|
7988
|
+
createRevalidationRequest(request) {
|
|
7989
|
+
const headers = new Headers(request.headers);
|
|
7990
|
+
headers.set("X-Cache-Bypass", "revalidation");
|
|
7991
|
+
headers.delete("If-None-Match");
|
|
7992
|
+
headers.delete("If-Modified-Since");
|
|
7993
|
+
headers.delete("Cache-Control");
|
|
7994
|
+
headers.delete("Pragma");
|
|
7995
|
+
return new Request(request.url, {
|
|
7996
|
+
method: "GET",
|
|
7997
|
+
headers
|
|
7998
|
+
});
|
|
7999
|
+
}
|
|
7932
8000
|
async put(request, response) {
|
|
7933
8001
|
const trace = createTraceId();
|
|
7934
8002
|
if (request.method !== "GET" || !response.ok) {
|
|
@@ -7944,17 +8012,22 @@ var WorkerHtmlCache = class {
|
|
|
7944
8012
|
try {
|
|
7945
8013
|
const cache = await caches.open(CACHE_NAME2 + this.epoch);
|
|
7946
8014
|
const cacheKey = this.buildCacheKey(request);
|
|
8015
|
+
await cache.delete(cacheKey);
|
|
7947
8016
|
const ttl = this.getTTLForRequest(request);
|
|
7948
|
-
const swr =
|
|
8017
|
+
const swr = this.getSWRForRequest(request);
|
|
7949
8018
|
const headers = new Headers(response.headers);
|
|
7950
8019
|
const existingCacheControl = response.headers.get("Cache-Control");
|
|
7951
8020
|
if (!existingCacheControl || existingCacheControl === "public") {
|
|
7952
8021
|
const internalMaxAge = ttl + swr;
|
|
7953
8022
|
headers.set("Cache-Control", `public, max-age=${internalMaxAge}`);
|
|
7954
8023
|
}
|
|
7955
|
-
|
|
8024
|
+
const cacheTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
8025
|
+
headers.set("X-Cache-Time", cacheTime);
|
|
7956
8026
|
headers.set("X-Original-TTL", ttl.toString());
|
|
7957
8027
|
headers.set("X-Original-SWR", swr.toString());
|
|
8028
|
+
if (!headers.get("Last-Modified")) {
|
|
8029
|
+
headers.set("Last-Modified", new Date(cacheTime).toUTCString());
|
|
8030
|
+
}
|
|
7958
8031
|
const cacheableResponse = new Response(response.body, {
|
|
7959
8032
|
status: response.status,
|
|
7960
8033
|
statusText: response.statusText,
|
|
@@ -7966,28 +8039,32 @@ var WorkerHtmlCache = class {
|
|
|
7966
8039
|
logger.warn("[SDK Html-cache] no put support", { trace });
|
|
7967
8040
|
}
|
|
7968
8041
|
}
|
|
7969
|
-
/**
|
|
7970
|
-
* Build client response with correct headers
|
|
7971
|
-
*/
|
|
7972
8042
|
buildClientResponse(cachedResponse, ttl, swr, isStale, age) {
|
|
7973
8043
|
const headers = new Headers(cachedResponse.headers);
|
|
7974
8044
|
headers.set(
|
|
7975
8045
|
"Cache-Control",
|
|
7976
8046
|
`public, max-age=${ttl}, stale-while-revalidate=${swr}`
|
|
7977
8047
|
);
|
|
8048
|
+
headers.set(
|
|
8049
|
+
"Cloudflare-CDN-Cache-Control",
|
|
8050
|
+
`public, s-maxage=${ttl}, stale-while-revalidate=${swr}, stale-if-error=60`
|
|
8051
|
+
);
|
|
8052
|
+
const cacheTime = headers.get("X-Cache-Time");
|
|
8053
|
+
if (cacheTime) {
|
|
8054
|
+
const lastModified = new Date(cacheTime).toUTCString();
|
|
8055
|
+
headers.set("Last-Modified", lastModified);
|
|
8056
|
+
}
|
|
7978
8057
|
headers.set("X-Cache-Status", isStale ? "STALE" : "HIT");
|
|
7979
8058
|
headers.set("X-Cache-Age", Math.floor(age).toString());
|
|
7980
8059
|
headers.delete("X-Original-TTL");
|
|
7981
8060
|
headers.delete("X-Original-SWR");
|
|
8061
|
+
headers.delete("X-Cache-Time");
|
|
7982
8062
|
return new Response(cachedResponse.body, {
|
|
7983
8063
|
status: cachedResponse.status,
|
|
7984
8064
|
statusText: cachedResponse.statusText,
|
|
7985
8065
|
headers
|
|
7986
8066
|
});
|
|
7987
8067
|
}
|
|
7988
|
-
/**
|
|
7989
|
-
* Build cache key from request using two-level structure
|
|
7990
|
-
*/
|
|
7991
8068
|
buildCacheKey(request) {
|
|
7992
8069
|
const url = new URL(request.url);
|
|
7993
8070
|
const versionHash = this.generateVersionHash(request.headers);
|
|
@@ -8003,22 +8080,11 @@ var WorkerHtmlCache = class {
|
|
|
8003
8080
|
headers: sanitizedHeaders
|
|
8004
8081
|
});
|
|
8005
8082
|
}
|
|
8006
|
-
/**
|
|
8007
|
-
* Sanitize headers for cache operations - minimal whitelist approach
|
|
8008
|
-
*/
|
|
8009
8083
|
sanitizeHeaders(originalHeaders) {
|
|
8010
8084
|
const CACHE_RELEVANT_HEADERS = [
|
|
8011
8085
|
// Content negotiation (affects response format)
|
|
8012
8086
|
"accept",
|
|
8013
|
-
"accept-
|
|
8014
|
-
"accept-language",
|
|
8015
|
-
// Cache control directives from client/proxy
|
|
8016
|
-
"cache-control",
|
|
8017
|
-
"pragma",
|
|
8018
|
-
// Legacy cache control
|
|
8019
|
-
// Conditional request headers (for 304 responses)
|
|
8020
|
-
"if-none-match",
|
|
8021
|
-
"if-modified-since"
|
|
8087
|
+
"accept-language"
|
|
8022
8088
|
];
|
|
8023
8089
|
const sanitized = new Headers();
|
|
8024
8090
|
CACHE_RELEVANT_HEADERS.forEach((header) => {
|
|
@@ -8029,15 +8095,13 @@ var WorkerHtmlCache = class {
|
|
|
8029
8095
|
});
|
|
8030
8096
|
return sanitized;
|
|
8031
8097
|
}
|
|
8032
|
-
/**
|
|
8033
|
-
* Generate version hash from headers and cookies
|
|
8034
|
-
*/
|
|
8035
8098
|
generateVersionHash(headers) {
|
|
8036
8099
|
const swellData = this.extractSwellData(headers);
|
|
8037
8100
|
const versionFactors = {
|
|
8038
8101
|
store: headers.get("swell-storefront-id") || "",
|
|
8039
8102
|
auth: headers.get("swell-access-token") || "",
|
|
8040
8103
|
theme: headers.get("swell-theme-version-hash") || "",
|
|
8104
|
+
modified: headers.get("swell-cache-modified") || "",
|
|
8041
8105
|
currency: swellData["swell-currency"] || "USD",
|
|
8042
8106
|
locale: headers.get("x-locale") || headers.get("accept-language")?.split(",")[0] || "default",
|
|
8043
8107
|
context: headers.get("swell-storefront-context"),
|
|
@@ -8045,9 +8109,6 @@ var WorkerHtmlCache = class {
|
|
|
8045
8109
|
};
|
|
8046
8110
|
return md5(JSON.stringify(versionFactors));
|
|
8047
8111
|
}
|
|
8048
|
-
/**
|
|
8049
|
-
* Extract swell-data from cookies
|
|
8050
|
-
*/
|
|
8051
8112
|
extractSwellData(headers) {
|
|
8052
8113
|
const cookie = headers.get("cookie");
|
|
8053
8114
|
if (!cookie) return {};
|
|
@@ -8083,31 +8144,53 @@ var WorkerHtmlCache = class {
|
|
|
8083
8144
|
if (!contentType?.includes("text/html")) {
|
|
8084
8145
|
return false;
|
|
8085
8146
|
}
|
|
8147
|
+
if (response.headers.get("set-cookie")) {
|
|
8148
|
+
return false;
|
|
8149
|
+
}
|
|
8086
8150
|
const cacheControl = response.headers.get("cache-control");
|
|
8087
8151
|
if (cacheControl?.includes("no-store") || cacheControl?.includes("private")) {
|
|
8088
8152
|
return false;
|
|
8089
8153
|
}
|
|
8090
8154
|
return true;
|
|
8091
8155
|
}
|
|
8156
|
+
getDeploymentMode(headers) {
|
|
8157
|
+
const mode = headers.get("swell-deployment-mode");
|
|
8158
|
+
if (mode === "preview" || mode === "editor") {
|
|
8159
|
+
return mode;
|
|
8160
|
+
}
|
|
8161
|
+
return "live";
|
|
8162
|
+
}
|
|
8092
8163
|
getTTLForRequest(request) {
|
|
8093
8164
|
const url = new URL(request.url);
|
|
8094
8165
|
const path = url.pathname;
|
|
8166
|
+
const mode = this.getDeploymentMode(request.headers);
|
|
8167
|
+
if (mode === "editor") {
|
|
8168
|
+
return 0;
|
|
8169
|
+
}
|
|
8170
|
+
const config = mode === "preview" ? TTL_CONFIG.PREVIEW : TTL_CONFIG.LIVE;
|
|
8095
8171
|
if (path === "/") {
|
|
8096
|
-
return
|
|
8172
|
+
return config.HOME;
|
|
8097
8173
|
}
|
|
8098
8174
|
if (path.startsWith("/products/")) {
|
|
8099
|
-
return
|
|
8175
|
+
return config.PRODUCT;
|
|
8100
8176
|
}
|
|
8101
8177
|
if (path.startsWith("/categories/")) {
|
|
8102
|
-
return
|
|
8178
|
+
return config.COLLECTION;
|
|
8103
8179
|
}
|
|
8104
8180
|
if (path.startsWith("/pages/")) {
|
|
8105
|
-
return
|
|
8181
|
+
return config.PAGE;
|
|
8106
8182
|
}
|
|
8107
8183
|
if (path.startsWith("/blogs/")) {
|
|
8108
|
-
return
|
|
8184
|
+
return config.BLOG;
|
|
8185
|
+
}
|
|
8186
|
+
return config.DEFAULT;
|
|
8187
|
+
}
|
|
8188
|
+
getSWRForRequest(request) {
|
|
8189
|
+
const mode = this.getDeploymentMode(request.headers);
|
|
8190
|
+
if (mode === "editor") {
|
|
8191
|
+
return 0;
|
|
8109
8192
|
}
|
|
8110
|
-
return TTL_CONFIG.
|
|
8193
|
+
return mode === "preview" ? TTL_CONFIG.PREVIEW.SWR : TTL_CONFIG.LIVE.SWR;
|
|
8111
8194
|
}
|
|
8112
8195
|
getResponseAge(response) {
|
|
8113
8196
|
const cacheTime = response.headers.get("X-Cache-Time");
|
|
@@ -8121,31 +8204,6 @@ var WorkerHtmlCache = class {
|
|
|
8121
8204
|
const age = (Date.now() - cacheDate.getTime()) / 1e3;
|
|
8122
8205
|
return Math.max(0, age);
|
|
8123
8206
|
}
|
|
8124
|
-
getMaxAge(response) {
|
|
8125
|
-
const cacheControl = response.headers.get("Cache-Control");
|
|
8126
|
-
if (!cacheControl) {
|
|
8127
|
-
return TTL_CONFIG.DEFAULT;
|
|
8128
|
-
}
|
|
8129
|
-
const maxAgeMatch = cacheControl.match(/max-age=(\d+)/);
|
|
8130
|
-
if (maxAgeMatch) {
|
|
8131
|
-
return parseInt(maxAgeMatch[1], 10);
|
|
8132
|
-
}
|
|
8133
|
-
return TTL_CONFIG.DEFAULT;
|
|
8134
|
-
}
|
|
8135
|
-
getStaleWindow(response) {
|
|
8136
|
-
const cacheControl = response.headers.get("Cache-Control");
|
|
8137
|
-
if (!cacheControl) {
|
|
8138
|
-
return TTL_CONFIG.DEFAULT_SWR;
|
|
8139
|
-
}
|
|
8140
|
-
const swrMatch = cacheControl.match(/stale-while-revalidate=(\d+)/);
|
|
8141
|
-
if (swrMatch) {
|
|
8142
|
-
return parseInt(swrMatch[1], 10);
|
|
8143
|
-
}
|
|
8144
|
-
return TTL_CONFIG.DEFAULT_SWR;
|
|
8145
|
-
}
|
|
8146
|
-
/**
|
|
8147
|
-
* Normalize search params for cache key
|
|
8148
|
-
*/
|
|
8149
8207
|
normalizeSearchParams(searchParams) {
|
|
8150
8208
|
const ignoredParams = [
|
|
8151
8209
|
"utm_source",
|