@decocms/start 1.3.2 → 1.3.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decocms/start",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "type": "module",
5
5
  "description": "Deco framework for TanStack Start - CMS bridge, admin protocol, hooks, schema generation",
6
6
  "main": "./src/index.ts",
@@ -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
 
@@ -1106,12 +1106,18 @@ export function createDecoWorkerEntry(
1106
1106
  try {
1107
1107
  const bgReq = new Request(request, { body, method: "POST" });
1108
1108
  const bgOrigin = await serverEntry.fetch(bgReq, env, ctx);
1109
- if (bgOrigin.status === 200 && !bgOrigin.headers.has("set-cookie") && serverFnCache) {
1109
+ if (
1110
+ bgOrigin.status === 200 &&
1111
+ bgOrigin.headers.get("X-Deco-Cacheable") === "true" &&
1112
+ !bgOrigin.headers.has("set-cookie") &&
1113
+ serverFnCache
1114
+ ) {
1110
1115
  const ttl = sfnEdge.fresh + Math.max(sfnEdge.swr, sfnEdge.sie);
1111
1116
  const toStore = bgOrigin.clone();
1112
1117
  toStore.headers.set("Cache-Control", `public, max-age=${ttl}`);
1113
1118
  toStore.headers.set("X-Deco-Stored-At", String(Date.now()));
1114
1119
  toStore.headers.delete("CDN-Cache-Control");
1120
+ toStore.headers.delete("X-Deco-Cacheable");
1115
1121
  await serverFnCache.put(sfnCacheKey, toStore);
1116
1122
  }
1117
1123
  } catch { /* background revalidation failed */ }
@@ -1131,29 +1137,39 @@ export function createDecoWorkerEntry(
1131
1137
  const originReq = new Request(request, { body, method: "POST" });
1132
1138
  const origin = await serverEntry.fetch(originReq, env, ctx);
1133
1139
 
1134
- // Never cache responses with Set-Cookie (cart/auth)
1135
- if (origin.headers.has("set-cookie")) {
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.set("Cache-Control", "private, no-cache, no-store, must-revalidate");
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 (origin.status === 200 && serverFnCache) {
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");