@decocms/start 0.22.2 → 0.23.0

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": "0.22.2",
3
+ "version": "0.23.0",
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",
@@ -16,6 +16,7 @@
16
16
  "./sdk/clx": "./src/sdk/clx.ts",
17
17
  "./sdk/useId": "./src/sdk/useId.ts",
18
18
  "./sdk/cookie": "./src/sdk/cookie.ts",
19
+ "./sdk/cookiePassthrough": "./src/sdk/cookiePassthrough.ts",
19
20
  "./sdk/analytics": "./src/sdk/analytics.ts",
20
21
  "./sdk/cachedLoader": "./src/sdk/cachedLoader.ts",
21
22
  "./sdk/serverTimings": "./src/sdk/serverTimings.ts",
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Request / Response cookie passthrough helpers for TanStack Start.
3
+ *
4
+ * Provides two framework-bound functions that commerce apps
5
+ * (VTEX, Shopify, etc.) can plug into their cookie provider hooks
6
+ * to transparently forward browser cookies to API calls and
7
+ * Set-Cookie headers back to the browser.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * // setup.ts
12
+ * import { getRequestCookieHeader, forwardResponseCookies } from "@decocms/start/sdk/cookiePassthrough";
13
+ * import { setRequestCookieProvider, setResponseCookieForwarder } from "@decocms/apps/vtex";
14
+ *
15
+ * setRequestCookieProvider(getRequestCookieHeader);
16
+ * setResponseCookieForwarder(forwardResponseCookies);
17
+ * ```
18
+ */
19
+
20
+ import {
21
+ getRequestHeader,
22
+ getResponseHeaders,
23
+ setResponseHeader,
24
+ } from "@tanstack/react-start/server";
25
+
26
+ /**
27
+ * Returns the Cookie header from the current TanStack Start request context.
28
+ * Safe to call outside a request scope (returns undefined).
29
+ */
30
+ export function getRequestCookieHeader(): string | undefined {
31
+ try {
32
+ return getRequestHeader("cookie") ?? undefined;
33
+ } catch {
34
+ return undefined;
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Appends Set-Cookie headers to the current TanStack Start response.
40
+ * Preserves any Set-Cookie headers already set by other middleware or
41
+ * earlier calls, so multiple API calls in one request don't clobber
42
+ * each other's cookies.
43
+ *
44
+ * Safe to call outside a request scope (no-op).
45
+ */
46
+ export function forwardResponseCookies(cookies: string[]): void {
47
+ if (!cookies.length) return;
48
+ try {
49
+ const headers = getResponseHeaders();
50
+ const existing: string[] =
51
+ typeof headers.getSetCookie === "function"
52
+ ? headers.getSetCookie()
53
+ : [];
54
+ setResponseHeader("set-cookie", [...existing, ...cookies]);
55
+ } catch {
56
+ // Outside request context (build time, etc.) — ignore.
57
+ }
58
+ }
package/src/sdk/index.ts CHANGED
@@ -60,6 +60,7 @@ export {
60
60
  export { useId } from "./useId";
61
61
  export { usePartialSection, useScript, useScriptAsDataURI, useSection } from "./useScript";
62
62
  export { createDecoWorkerEntry, type DecoWorkerEntryOptions } from "./workerEntry";
63
+ export { forwardResponseCookies, getRequestCookieHeader } from "./cookiePassthrough";
63
64
  export {
64
65
  isWrappedError,
65
66
  unwrapError,
@@ -726,6 +726,20 @@ export function createDecoWorkerEntry(
726
726
  return origin;
727
727
  }
728
728
 
729
+ // Responses with Set-Cookie must never be cached — they carry
730
+ // per-user session/auth tokens that would leak to other users.
731
+ const hasSetCookie = origin.headers.has("set-cookie");
732
+ if (hasSetCookie) {
733
+ const resp = new Response(origin.body, origin);
734
+ resp.headers.set("Cache-Control", "private, no-cache, no-store, must-revalidate");
735
+ // CDN-Cache-Control takes precedence over Cache-Control on Cloudflare.
736
+ // If the origin set it, Cloudflare would ignore our private directive.
737
+ resp.headers.delete("CDN-Cache-Control");
738
+ resp.headers.set("X-Cache", "BYPASS");
739
+ resp.headers.set("X-Cache-Reason", "set-cookie");
740
+ return resp;
741
+ }
742
+
729
743
  // Determine the right cache profile for this URL
730
744
  const profile = getProfile(url);
731
745
  const profileConfig = getCacheProfileConfig(profile);