@decocms/start 1.3.2 → 1.3.4
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/package.json +1 -1
- package/src/routes/cmsRoute.ts +7 -0
- package/src/sdk/workerEntry.ts +29 -13
package/package.json
CHANGED
package/src/routes/cmsRoute.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
getRequest,
|
|
28
28
|
getRequestHeader,
|
|
29
29
|
getRequestUrl,
|
|
30
|
+
setResponseHeader,
|
|
30
31
|
} from "@tanstack/react-start/server";
|
|
31
32
|
import { createElement } from "react";
|
|
32
33
|
import { preloadSectionComponents } from "../cms/registry";
|
|
@@ -227,6 +228,12 @@ export const loadDeferredSection = createServerFn({ method: "POST" })
|
|
|
227
228
|
headers: originRequest.headers,
|
|
228
229
|
});
|
|
229
230
|
const enriched = await runSingleSectionLoader(section, request);
|
|
231
|
+
|
|
232
|
+
// Signal to the worker entry that this response is safe to edge-cache.
|
|
233
|
+
// Without this header, POST _serverFn responses are passed through
|
|
234
|
+
// without caching (checkout actions, invoke mutations, etc.).
|
|
235
|
+
setResponseHeader("X-Deco-Cacheable", "true");
|
|
236
|
+
|
|
230
237
|
return normalizeUrlsInObject(enriched);
|
|
231
238
|
});
|
|
232
239
|
|
package/src/sdk/workerEntry.ts
CHANGED
|
@@ -1034,9 +1034,7 @@ export function createDecoWorkerEntry(
|
|
|
1034
1034
|
|
|
1035
1035
|
// Logged-in users always bypass — personalized content must not leak
|
|
1036
1036
|
if (sfnSegment?.loggedIn) {
|
|
1037
|
-
const
|
|
1038
|
-
const originReq = new Request(request, { body, method: "POST" });
|
|
1039
|
-
const origin = await serverEntry.fetch(originReq, env, ctx);
|
|
1037
|
+
const origin = await serverEntry.fetch(request, env, ctx);
|
|
1040
1038
|
const resp = new Response(origin.body, origin);
|
|
1041
1039
|
resp.headers.set("Cache-Control", "private, no-cache, no-store, must-revalidate");
|
|
1042
1040
|
resp.headers.set("X-Cache", "BYPASS");
|
|
@@ -1044,7 +1042,10 @@ export function createDecoWorkerEntry(
|
|
|
1044
1042
|
return resp;
|
|
1045
1043
|
}
|
|
1046
1044
|
|
|
1047
|
-
//
|
|
1045
|
+
// Clone request before consuming body — the clone goes to origin
|
|
1046
|
+
// untouched so TanStack Start internals (cookie passthrough, etc.)
|
|
1047
|
+
// work correctly. We only read the body for the cache key hash.
|
|
1048
|
+
const originClone = request.clone();
|
|
1048
1049
|
const body = await request.text();
|
|
1049
1050
|
const bodyHash = await hashText(body);
|
|
1050
1051
|
|
|
@@ -1106,12 +1107,18 @@ export function createDecoWorkerEntry(
|
|
|
1106
1107
|
try {
|
|
1107
1108
|
const bgReq = new Request(request, { body, method: "POST" });
|
|
1108
1109
|
const bgOrigin = await serverEntry.fetch(bgReq, env, ctx);
|
|
1109
|
-
if (
|
|
1110
|
+
if (
|
|
1111
|
+
bgOrigin.status === 200 &&
|
|
1112
|
+
bgOrigin.headers.get("X-Deco-Cacheable") === "true" &&
|
|
1113
|
+
!bgOrigin.headers.has("set-cookie") &&
|
|
1114
|
+
serverFnCache
|
|
1115
|
+
) {
|
|
1110
1116
|
const ttl = sfnEdge.fresh + Math.max(sfnEdge.swr, sfnEdge.sie);
|
|
1111
1117
|
const toStore = bgOrigin.clone();
|
|
1112
1118
|
toStore.headers.set("Cache-Control", `public, max-age=${ttl}`);
|
|
1113
1119
|
toStore.headers.set("X-Deco-Stored-At", String(Date.now()));
|
|
1114
1120
|
toStore.headers.delete("CDN-Cache-Control");
|
|
1121
|
+
toStore.headers.delete("X-Deco-Cacheable");
|
|
1115
1122
|
await serverFnCache.put(sfnCacheKey, toStore);
|
|
1116
1123
|
}
|
|
1117
1124
|
} catch { /* background revalidation failed */ }
|
|
@@ -1128,32 +1135,41 @@ export function createDecoWorkerEntry(
|
|
|
1128
1135
|
}
|
|
1129
1136
|
|
|
1130
1137
|
// Cache MISS — fetch origin with the body we already read
|
|
1131
|
-
const
|
|
1132
|
-
const origin = await serverEntry.fetch(originReq, env, ctx);
|
|
1138
|
+
const origin = await serverEntry.fetch(originClone, env, ctx);
|
|
1133
1139
|
|
|
1134
|
-
//
|
|
1135
|
-
|
|
1140
|
+
// Only cache responses explicitly marked as cacheable by the handler
|
|
1141
|
+
// (loadDeferredSection sets X-Deco-Cacheable: true). Checkout actions,
|
|
1142
|
+
// invoke mutations, and other server functions are passed through.
|
|
1143
|
+
const isCacheableResponse =
|
|
1144
|
+
origin.headers.get("X-Deco-Cacheable") === "true" &&
|
|
1145
|
+
!origin.headers.has("set-cookie") &&
|
|
1146
|
+
origin.status === 200;
|
|
1147
|
+
|
|
1148
|
+
if (!isCacheableResponse) {
|
|
1136
1149
|
const resp = new Response(origin.body, origin);
|
|
1137
|
-
resp.headers.
|
|
1138
|
-
resp.headers.delete("CDN-Cache-Control");
|
|
1150
|
+
resp.headers.delete("X-Deco-Cacheable");
|
|
1139
1151
|
resp.headers.set("X-Cache", "BYPASS");
|
|
1140
|
-
resp.headers.set("X-Cache-Reason", "set-cookie")
|
|
1152
|
+
resp.headers.set("X-Cache-Reason", origin.headers.has("set-cookie")
|
|
1153
|
+
? "set-cookie"
|
|
1154
|
+
: "not-cacheable");
|
|
1141
1155
|
return resp;
|
|
1142
1156
|
}
|
|
1143
1157
|
|
|
1144
1158
|
// Store in edge cache
|
|
1145
|
-
if (
|
|
1159
|
+
if (serverFnCache) {
|
|
1146
1160
|
try {
|
|
1147
1161
|
const ttl = sfnEdge.fresh + Math.max(sfnEdge.swr, sfnEdge.sie);
|
|
1148
1162
|
const toStore = origin.clone();
|
|
1149
1163
|
toStore.headers.set("Cache-Control", `public, max-age=${ttl}`);
|
|
1150
1164
|
toStore.headers.set("X-Deco-Stored-At", String(Date.now()));
|
|
1151
1165
|
toStore.headers.delete("CDN-Cache-Control");
|
|
1166
|
+
toStore.headers.delete("X-Deco-Cacheable");
|
|
1152
1167
|
ctx.waitUntil(serverFnCache.put(sfnCacheKey, toStore));
|
|
1153
1168
|
} catch { /* Cache API unavailable */ }
|
|
1154
1169
|
}
|
|
1155
1170
|
|
|
1156
1171
|
const resp = new Response(origin.body, origin);
|
|
1172
|
+
resp.headers.delete("X-Deco-Cacheable");
|
|
1157
1173
|
const hdrs = cacheHeaders(sfnProfile);
|
|
1158
1174
|
for (const [k, v] of Object.entries(hdrs)) resp.headers.set(k, v);
|
|
1159
1175
|
resp.headers.set("X-Cache", "MISS");
|