vinext 0.0.8 → 0.0.10

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.
Files changed (99) hide show
  1. package/README.md +30 -1
  2. package/dist/cli.js +13 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/client/entry.js +1 -15
  5. package/dist/client/entry.js.map +1 -1
  6. package/dist/client/validate-module-path.d.ts +15 -0
  7. package/dist/client/validate-module-path.d.ts.map +1 -0
  8. package/dist/client/validate-module-path.js +31 -0
  9. package/dist/client/validate-module-path.js.map +1 -0
  10. package/dist/config/config-matchers.d.ts +12 -0
  11. package/dist/config/config-matchers.d.ts.map +1 -1
  12. package/dist/config/config-matchers.js +28 -0
  13. package/dist/config/config-matchers.js.map +1 -1
  14. package/dist/config/dotenv.d.ts +40 -0
  15. package/dist/config/dotenv.d.ts.map +1 -0
  16. package/dist/config/dotenv.js +100 -0
  17. package/dist/config/dotenv.js.map +1 -0
  18. package/dist/config/next-config.d.ts +4 -0
  19. package/dist/config/next-config.d.ts.map +1 -1
  20. package/dist/config/next-config.js.map +1 -1
  21. package/dist/deploy.d.ts.map +1 -1
  22. package/dist/deploy.js +16 -8
  23. package/dist/deploy.js.map +1 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +99 -111
  26. package/dist/index.js.map +1 -1
  27. package/dist/server/api-handler.d.ts.map +1 -1
  28. package/dist/server/api-handler.js +2 -1
  29. package/dist/server/api-handler.js.map +1 -1
  30. package/dist/server/app-dev-server.d.ts +2 -0
  31. package/dist/server/app-dev-server.d.ts.map +1 -1
  32. package/dist/server/app-dev-server.js +292 -155
  33. package/dist/server/app-dev-server.js.map +1 -1
  34. package/dist/server/app-router-entry.d.ts.map +1 -1
  35. package/dist/server/app-router-entry.js +16 -3
  36. package/dist/server/app-router-entry.js.map +1 -1
  37. package/dist/server/dev-origin-check.d.ts +61 -0
  38. package/dist/server/dev-origin-check.d.ts.map +1 -0
  39. package/dist/server/dev-origin-check.js +164 -0
  40. package/dist/server/dev-origin-check.js.map +1 -0
  41. package/dist/server/dev-server.d.ts +0 -2
  42. package/dist/server/dev-server.d.ts.map +1 -1
  43. package/dist/server/dev-server.js +379 -372
  44. package/dist/server/dev-server.js.map +1 -1
  45. package/dist/server/image-optimization.d.ts +32 -2
  46. package/dist/server/image-optimization.d.ts.map +1 -1
  47. package/dist/server/image-optimization.js +110 -9
  48. package/dist/server/image-optimization.js.map +1 -1
  49. package/dist/server/middleware-codegen.d.ts +41 -0
  50. package/dist/server/middleware-codegen.d.ts.map +1 -0
  51. package/dist/server/middleware-codegen.js +181 -0
  52. package/dist/server/middleware-codegen.js.map +1 -0
  53. package/dist/server/middleware.d.ts.map +1 -1
  54. package/dist/server/middleware.js +12 -7
  55. package/dist/server/middleware.js.map +1 -1
  56. package/dist/server/normalize-path.d.ts +22 -0
  57. package/dist/server/normalize-path.d.ts.map +1 -0
  58. package/dist/server/normalize-path.js +50 -0
  59. package/dist/server/normalize-path.js.map +1 -0
  60. package/dist/server/prod-server.d.ts.map +1 -1
  61. package/dist/server/prod-server.js +89 -25
  62. package/dist/server/prod-server.js.map +1 -1
  63. package/dist/shims/cache-runtime.d.ts +7 -0
  64. package/dist/shims/cache-runtime.d.ts.map +1 -1
  65. package/dist/shims/cache-runtime.js +19 -15
  66. package/dist/shims/cache-runtime.js.map +1 -1
  67. package/dist/shims/cache.d.ts +8 -0
  68. package/dist/shims/cache.d.ts.map +1 -1
  69. package/dist/shims/cache.js +20 -15
  70. package/dist/shims/cache.js.map +1 -1
  71. package/dist/shims/fetch-cache.d.ts +2 -3
  72. package/dist/shims/fetch-cache.d.ts.map +1 -1
  73. package/dist/shims/fetch-cache.js +74 -9
  74. package/dist/shims/fetch-cache.js.map +1 -1
  75. package/dist/shims/head-state.d.ts +6 -1
  76. package/dist/shims/head-state.d.ts.map +1 -1
  77. package/dist/shims/head-state.js +18 -15
  78. package/dist/shims/head-state.js.map +1 -1
  79. package/dist/shims/headers.d.ts +9 -13
  80. package/dist/shims/headers.d.ts.map +1 -1
  81. package/dist/shims/headers.js +26 -47
  82. package/dist/shims/headers.js.map +1 -1
  83. package/dist/shims/image.d.ts.map +1 -1
  84. package/dist/shims/image.js +11 -2
  85. package/dist/shims/image.js.map +1 -1
  86. package/dist/shims/navigation-state.d.ts +6 -1
  87. package/dist/shims/navigation-state.d.ts.map +1 -1
  88. package/dist/shims/navigation-state.js +20 -29
  89. package/dist/shims/navigation-state.js.map +1 -1
  90. package/dist/shims/navigation.js +2 -2
  91. package/dist/shims/navigation.js.map +1 -1
  92. package/dist/shims/router-state.d.ts +6 -1
  93. package/dist/shims/router-state.d.ts.map +1 -1
  94. package/dist/shims/router-state.js +16 -21
  95. package/dist/shims/router-state.js.map +1 -1
  96. package/dist/shims/router.d.ts.map +1 -1
  97. package/dist/shims/router.js +19 -6
  98. package/dist/shims/router.js.map +1 -1
  99. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-cache.js","sourceRoot":"","sources":["../../src/shims/fetch-cache.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Extended fetch() with Next.js caching semantics.\n *\n * Patches `globalThis.fetch` during server rendering to support:\n *\n * fetch(url, { next: { revalidate: 60, tags: ['posts'] } })\n * fetch(url, { cache: 'force-cache' })\n * fetch(url, { cache: 'no-store' })\n *\n * Cached responses are stored via the pluggable CacheHandler, so\n * revalidateTag() and revalidatePath() invalidate fetch-level caches.\n *\n * Usage (in server entry):\n * import { withFetchCache, cleanupFetchCache } from './fetch-cache';\n * const cleanup = withFetchCache();\n * try { ... render ... } finally { cleanup(); }\n *\n * Or use the async helper:\n * await runWithFetchCache(async () => { ... render ... });\n */\n\nimport {\n getCacheHandler,\n type CachedFetchValue,\n} from \"./cache.js\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n// ---------------------------------------------------------------------------\n// Cache key generation\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a deterministic cache key from a fetch request.\n *\n * Key = \"fetch:\" + URL + \"|\" + sorted relevant options.\n * We exclude headers that are request-specific (cookie, authorization)\n * unless the user explicitly opts in via `next.tags`.\n */\nfunction buildFetchCacheKey(input: string | URL | Request, init?: RequestInit & { next?: NextFetchOptions }): string {\n let url: string;\n let method = \"GET\";\n let body: string | undefined;\n\n if (typeof input === \"string\") {\n url = input;\n } else if (input instanceof URL) {\n url = input.toString();\n } else {\n // Request object\n url = input.url;\n method = input.method || \"GET\";\n }\n\n if (init?.method) method = init.method;\n if (init?.body && typeof init.body === \"string\") body = init.body;\n\n // Build a stable key from URL + method + body\n const parts = [`fetch:${method}:${url}`];\n if (body) parts.push(body);\n\n return parts.join(\"|\");\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface NextFetchOptions {\n revalidate?: number | false;\n tags?: string[];\n}\n\n// Extend the standard RequestInit to include `next`\ndeclare global {\n interface RequestInit {\n next?: NextFetchOptions;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Patching\n// ---------------------------------------------------------------------------\n\n// Capture the real (unpatched) fetch once, shared across Vite's\n// multi-environment module instances via Symbol.for().\nconst _ORIG_FETCH_KEY = Symbol.for(\"vinext.fetchCache.originalFetch\");\nconst _gFetch = globalThis as unknown as Record<PropertyKey, unknown>;\nconst originalFetch: typeof globalThis.fetch = (_gFetch[_ORIG_FETCH_KEY] ??= globalThis.fetch) as typeof globalThis.fetch;\n\n// ---------------------------------------------------------------------------\n// AsyncLocalStorage for request-scoped fetch cache state.\n// Uses Symbol.for() on globalThis so the storage is shared across Vite's\n// multi-environment module instances.\n// ---------------------------------------------------------------------------\ninterface FetchCacheState {\n currentRequestTags: string[];\n}\n\nconst _ALS_KEY = Symbol.for(\"vinext.fetchCache.als\");\nconst _FALLBACK_KEY = Symbol.for(\"vinext.fetchCache.fallback\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = (_g[_ALS_KEY] ??= new AsyncLocalStorage<FetchCacheState>()) as AsyncLocalStorage<FetchCacheState>;\n\nconst _fallbackState = (_g[_FALLBACK_KEY] ??= {\n currentRequestTags: [],\n} satisfies FetchCacheState) as FetchCacheState;\n\nfunction _getState(): FetchCacheState {\n return _als.getStore() ?? _fallbackState;\n}\n\n/**\n * Reset the fallback state for a new request. Used by `withFetchCache()`\n * in single-threaded contexts where ALS.run() isn't used.\n */\nfunction _resetFallbackState(): void {\n _fallbackState.currentRequestTags = [];\n}\n\n/**\n * Get tags collected during the current render pass.\n * Useful for associating page-level cache entries with all the\n * fetch tags used during rendering.\n */\nexport function getCollectedFetchTags(): string[] {\n return [..._getState().currentRequestTags];\n}\n\n/**\n * Create a patched fetch function with Next.js caching semantics.\n *\n * The patched fetch:\n * 1. Checks `cache` and `next` options to determine caching behavior\n * 2. On cache hit, returns the cached response without hitting the network\n * 3. On cache miss, fetches from network, stores in cache, returns response\n * 4. Respects `next.revalidate` for TTL-based revalidation\n * 5. Respects `next.tags` for tag-based invalidation via revalidateTag()\n */\nfunction createPatchedFetch(): typeof globalThis.fetch {\n return async function patchedFetch(\n input: string | URL | Request,\n init?: RequestInit,\n ): Promise<Response> {\n const nextOpts = init?.next as NextFetchOptions | undefined;\n const cacheDirective = init?.cache;\n\n // Determine caching behavior:\n // - cache: 'no-store' → skip cache entirely\n // - cache: 'force-cache' → cache indefinitely (revalidate = Infinity)\n // - next.revalidate: false → same as 'no-store'\n // - next.revalidate: 0 → same as 'no-store'\n // - next.revalidate: N → cache for N seconds\n // - No cache/next options → default behavior (no caching, pass-through)\n\n // If no caching options at all, just pass through to original fetch\n if (!nextOpts && !cacheDirective) {\n return originalFetch(input, init);\n }\n\n // Explicit no-store\n if (cacheDirective === \"no-store\" || nextOpts?.revalidate === false || nextOpts?.revalidate === 0) {\n // Strip the `next` property before passing to real fetch\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n\n // Determine revalidation period\n let revalidateSeconds: number;\n if (cacheDirective === \"force-cache\") {\n // force-cache means cache indefinitely (we use a very large number)\n revalidateSeconds = nextOpts?.revalidate && typeof nextOpts.revalidate === \"number\"\n ? nextOpts.revalidate\n : 31536000; // 1 year\n } else if (typeof nextOpts?.revalidate === \"number\" && nextOpts.revalidate > 0) {\n revalidateSeconds = nextOpts.revalidate;\n } else {\n // Has `next` options but no explicit revalidate — Next.js defaults to\n // caching when `next` is present (force-cache behavior).\n // If only tags are specified, cache indefinitely.\n if (nextOpts?.tags && nextOpts.tags.length > 0) {\n revalidateSeconds = 31536000;\n } else {\n // next: {} with no revalidate or tags — pass through\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n }\n\n const tags = nextOpts?.tags ?? [];\n const cacheKey = buildFetchCacheKey(input, init);\n const handler = getCacheHandler();\n\n // Collect tags for this render pass\n const reqTags = _getState().currentRequestTags;\n if (tags.length > 0) {\n for (const tag of tags) {\n if (!reqTags.includes(tag)) {\n reqTags.push(tag);\n }\n }\n }\n\n // Try cache first\n try {\n const cached = await handler.get(cacheKey, { kind: \"FETCH\", tags });\n if (cached?.value && cached.value.kind === \"FETCH\" && cached.cacheState !== \"stale\") {\n const cachedData = cached.value.data;\n // Reconstruct a Response from the cached data\n return new Response(cachedData.body, {\n status: cachedData.status ?? 200,\n headers: cachedData.headers,\n });\n }\n\n // Stale entry — we could do stale-while-revalidate here, but for fetch()\n // the simpler approach is to just re-fetch (the page-level ISR handles SWR).\n // However, if we have a stale entry, return it and trigger background refetch.\n if (cached?.value && cached.value.kind === \"FETCH\" && cached.cacheState === \"stale\") {\n const staleData = cached.value.data;\n\n // Background refetch\n const cleanInit = stripNextFromInit(init);\n originalFetch(input, cleanInit).then(async (freshResp) => {\n const freshBody = await freshResp.text();\n const freshHeaders: Record<string, string> = {};\n freshResp.headers.forEach((v, k) => { freshHeaders[k] = v; });\n\n const freshValue: CachedFetchValue = {\n kind: \"FETCH\",\n data: {\n headers: freshHeaders,\n body: freshBody,\n url: typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url,\n status: freshResp.status,\n },\n tags,\n revalidate: revalidateSeconds,\n };\n await handler.set(cacheKey, freshValue, {\n fetchCache: true,\n tags,\n revalidate: revalidateSeconds,\n });\n }).catch((err) => {\n console.error(\"[vinext] fetch cache background revalidation failed:\", err);\n });\n\n // Return stale data immediately\n return new Response(staleData.body, {\n status: staleData.status ?? 200,\n headers: staleData.headers,\n });\n }\n } catch (cacheErr) {\n // Cache read failed — fall through to network\n console.error(\"[vinext] fetch cache read error:\", cacheErr);\n }\n\n // Cache miss — fetch from network\n const cleanInit = stripNextFromInit(init);\n const response = await originalFetch(input, cleanInit);\n\n // Only cache successful responses (2xx)\n if (response.ok) {\n // Clone before reading body\n const cloned = response.clone();\n const body = await cloned.text();\n const headers: Record<string, string> = {};\n cloned.headers.forEach((v, k) => { headers[k] = v; });\n\n const cacheValue: CachedFetchValue = {\n kind: \"FETCH\",\n data: {\n headers,\n body,\n url: typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url,\n status: cloned.status,\n },\n tags,\n revalidate: revalidateSeconds,\n };\n\n // Store in cache (fire-and-forget)\n handler.set(cacheKey, cacheValue, {\n fetchCache: true,\n tags,\n revalidate: revalidateSeconds,\n }).catch((err) => {\n console.error(\"[vinext] fetch cache write error:\", err);\n });\n }\n\n return response;\n } as typeof globalThis.fetch;\n}\n\n/**\n * Strip the `next` property from RequestInit before passing to real fetch.\n * The `next` property is not a standard fetch option and would cause warnings\n * in some environments.\n */\nfunction stripNextFromInit(init?: RequestInit): RequestInit | undefined {\n if (!init) return init;\n if (!(\"next\" in init)) return init;\n const { next: _next, ...rest } = init as RequestInit & { next?: unknown };\n return Object.keys(rest).length > 0 ? rest : undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Fetch patching — install once, not per-request.\n// The patched fetch uses _getState() internally, which reads from ALS\n// (concurrent) or _fallbackState (single-threaded), so per-request\n// isolation is handled at the state level, not by swapping globalThis.fetch.\n// ---------------------------------------------------------------------------\n\nconst _PATCH_KEY = Symbol.for(\"vinext.fetchCache.patchInstalled\");\n\nfunction _ensurePatchInstalled(): void {\n if (_g[_PATCH_KEY]) return;\n _g[_PATCH_KEY] = true;\n globalThis.fetch = createPatchedFetch();\n}\n\n/**\n * Install the patched fetch and reset per-request tag state.\n * Returns a cleanup function that clears tags.\n *\n * In single-threaded contexts (dev server, tests) this is safe because\n * requests are sequential. For concurrent environments, prefer\n * `runWithFetchCache()` which uses `AsyncLocalStorage.run()`.\n *\n * Usage:\n * const cleanup = withFetchCache();\n * try { await render(); } finally { cleanup(); }\n */\nexport function withFetchCache(): () => void {\n _ensurePatchInstalled();\n _resetFallbackState();\n\n return () => {\n _resetFallbackState();\n };\n}\n\n/**\n * Run an async function with patched fetch caching enabled.\n * Uses `AsyncLocalStorage.run()` for proper per-request isolation\n * of collected fetch tags in concurrent server environments.\n */\nexport async function runWithFetchCache<T>(fn: () => Promise<T>): Promise<T> {\n _ensurePatchInstalled();\n return _als.run({ currentRequestTags: [] }, fn);\n}\n\n/**\n * Get the original (unpatched) fetch function.\n * Useful for internal code that should bypass caching.\n */\nexport function getOriginalFetch(): typeof globalThis.fetch {\n return originalFetch;\n}\n"]}
1
+ {"version":3,"file":"fetch-cache.js","sourceRoot":"","sources":["../../src/shims/fetch-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EACL,eAAe,GAEhB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,YAAY,GAAG,CAAC,eAAe,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AAE9D;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,KAA6B,EAAE,IAAkB;IAC3E,MAAM,SAAS,GAAuB,EAAE,CAAC;IAEzC,sCAAsC;IACtC,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,YAAY,OAAO;YAC7C,CAAC,CAAC,IAAI,CAAC,OAAO;YACd,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,OAAsB,CAAC,CAAC;QAC7C,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,KAAK;gBAAE,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,IAAI,KAAK,YAAY,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAC9C,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,2CAA2C;YAC3C,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;gBAAE,SAAS;YAClD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,KAAK;gBAAE,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAExC,sCAAsC;IACtC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,KAA6B,EAAE,IAAkB;IACvE,OAAO,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC;AAClD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,kBAAkB,CAAC,KAA6B,EAAE,IAAgD;IACzG,IAAI,GAAW,CAAC;IAChB,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,IAAwB,CAAC;IAE7B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,GAAG,GAAG,KAAK,CAAC;IACd,CAAC;SAAM,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;QAChC,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,iBAAiB;QACjB,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QAChB,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC;IACjC,CAAC;IAED,IAAI,IAAI,EAAE,MAAM;QAAE,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACvC,IAAI,IAAI,EAAE,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IAElE,6DAA6D;IAC7D,MAAM,KAAK,GAAG,CAAC,SAAS,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC;IACzC,IAAI,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE3B,yEAAyE;IACzE,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjD,IAAI,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,QAAQ,EAAE,CAAC,CAAC;IAE7C,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAkBD,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E,gEAAgE;AAChE,uDAAuD;AACvD,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;AACtE,MAAM,OAAO,GAAG,UAAqD,CAAC;AACtE,MAAM,aAAa,GAA4B,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,UAAU,CAAC,KAAK,CAA4B,CAAC;AAW1H,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AACrD,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AAC/D,MAAM,EAAE,GAAG,UAAqD,CAAC;AACjE,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,IAAI,iBAAiB,EAAmB,CAAuC,CAAC;AAE/G,MAAM,cAAc,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK;IAC5C,kBAAkB,EAAE,EAAE;CACG,CAAoB,CAAC;AAEhD,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,QAAQ,EAAE,IAAI,cAAc,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,SAAS,mBAAmB;IAC1B,cAAc,CAAC,kBAAkB,GAAG,EAAE,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,GAAG,SAAS,EAAE,CAAC,kBAAkB,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,kBAAkB;IACzB,OAAO,KAAK,UAAU,YAAY,CAChC,KAA6B,EAC7B,IAAkB;QAElB,MAAM,QAAQ,GAAG,IAAI,EAAE,IAAoC,CAAC;QAC5D,MAAM,cAAc,GAAG,IAAI,EAAE,KAAK,CAAC;QAEnC,8BAA8B;QAC9B,4CAA4C;QAC5C,sEAAsE;QACtE,gDAAgD;QAChD,4CAA4C;QAC5C,6CAA6C;QAC7C,wEAAwE;QAExE,oEAAoE;QACpE,IAAI,CAAC,QAAQ,IAAI,CAAC,cAAc,EAAE,CAAC;YACjC,OAAO,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,wDAAwD;QACxD,IAAI,cAAc,KAAK,UAAU,IAAI,cAAc,KAAK,UAAU,IAAI,QAAQ,EAAE,UAAU,KAAK,KAAK,IAAI,QAAQ,EAAE,UAAU,KAAK,CAAC,EAAE,CAAC;YACnI,yDAAyD;YACzD,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC1C,OAAO,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACzC,CAAC;QAED,0EAA0E;QAC1E,2EAA2E;QAC3E,wEAAwE;QACxE,sEAAsE;QACtE,wEAAwE;QACxE,MAAM,mBAAmB,GACvB,cAAc,KAAK,aAAa;YAChC,CAAC,OAAO,QAAQ,EAAE,UAAU,KAAK,QAAQ,IAAI,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,mBAAmB,IAAI,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;YACxD,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC1C,OAAO,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACzC,CAAC;QAED,gCAAgC;QAChC,IAAI,iBAAyB,CAAC;QAC9B,IAAI,cAAc,KAAK,aAAa,EAAE,CAAC;YACrC,oEAAoE;YACpE,iBAAiB,GAAG,QAAQ,EAAE,UAAU,IAAI,OAAO,QAAQ,CAAC,UAAU,KAAK,QAAQ;gBACjF,CAAC,CAAC,QAAQ,CAAC,UAAU;gBACrB,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAS;QACzB,CAAC;aAAM,IAAI,OAAO,QAAQ,EAAE,UAAU,KAAK,QAAQ,IAAI,QAAQ,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YAC/E,iBAAiB,GAAG,QAAQ,CAAC,UAAU,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,sEAAsE;YACtE,yDAAyD;YACzD,kDAAkD;YAClD,IAAI,QAAQ,EAAE,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/C,iBAAiB,GAAG,QAAQ,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,qDAAqD;gBACrD,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAC1C,OAAO,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;QAElC,oCAAoC;QACpC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC,kBAAkB,CAAC;QAC/C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC3B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;QAED,kBAAkB;QAClB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACpE,IAAI,MAAM,EAAE,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;gBACpF,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;gBACrC,8CAA8C;gBAC9C,OAAO,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE;oBACnC,MAAM,EAAE,UAAU,CAAC,MAAM,IAAI,GAAG;oBAChC,OAAO,EAAE,UAAU,CAAC,OAAO;iBAC5B,CAAC,CAAC;YACL,CAAC;YAED,yEAAyE;YACzE,6EAA6E;YAC7E,+EAA+E;YAC/E,IAAI,MAAM,EAAE,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;gBACpF,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;gBAEpC,qBAAqB;gBACrB,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAC1C,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE;oBACvD,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;oBACzC,MAAM,YAAY,GAA2B,EAAE,CAAC;oBAChD,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAE9D,MAAM,UAAU,GAAqB;wBACnC,IAAI,EAAE,OAAO;wBACb,IAAI,EAAE;4BACJ,OAAO,EAAE,YAAY;4BACrB,IAAI,EAAE,SAAS;4BACf,GAAG,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;4BAC5F,MAAM,EAAE,SAAS,CAAC,MAAM;yBACzB;wBACD,IAAI;wBACJ,UAAU,EAAE,iBAAiB;qBAC9B,CAAC;oBACF,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE;wBACtC,UAAU,EAAE,IAAI;wBAChB,IAAI;wBACJ,UAAU,EAAE,iBAAiB;qBAC9B,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;oBACf,OAAO,CAAC,KAAK,CAAC,sDAAsD,EAAE,GAAG,CAAC,CAAC;gBAC7E,CAAC,CAAC,CAAC;gBAEH,gCAAgC;gBAChC,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE;oBAClC,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,GAAG;oBAC/B,OAAO,EAAE,SAAS,CAAC,OAAO;iBAC3B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,OAAO,QAAQ,EAAE,CAAC;YAClB,8CAA8C;YAC9C,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,QAAQ,CAAC,CAAC;QAC9D,CAAC;QAED,kCAAkC;QAClC,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAEvD,wCAAwC;QACxC,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;YAChB,4BAA4B;YAC5B,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,OAAO,GAA2B,EAAE,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAEtD,MAAM,UAAU,GAAqB;gBACnC,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE;oBACJ,OAAO;oBACP,IAAI;oBACJ,GAAG,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;oBAC5F,MAAM,EAAE,MAAM,CAAC,MAAM;iBACtB;gBACD,IAAI;gBACJ,UAAU,EAAE,iBAAiB;aAC9B,CAAC;YAEF,mCAAmC;YACnC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE;gBAChC,UAAU,EAAE,IAAI;gBAChB,IAAI;gBACJ,UAAU,EAAE,iBAAiB;aAC9B,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;YAC1D,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAA4B,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,IAAkB;IAC3C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,IAAI,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,IAAwC,CAAC;IAC1E,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACzD,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,8EAA8E;AAC9E,kDAAkD;AAClD,sEAAsE;AACtE,mEAAmE;AACnE,6EAA6E;AAC7E,8EAA8E;AAE9E,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AAElE,SAAS,qBAAqB;IAC5B,IAAI,EAAE,CAAC,UAAU,CAAC;QAAE,OAAO;IAC3B,EAAE,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,KAAK,GAAG,kBAAkB,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc;IAC5B,qBAAqB,EAAE,CAAC;IACxB,mBAAmB,EAAE,CAAC;IAEtB,OAAO,GAAG,EAAE;QACV,mBAAmB,EAAE,CAAC;IACxB,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAI,EAAoB;IAC7D,qBAAqB,EAAE,CAAC;IACxB,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,kBAAkB,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["/**\n * Extended fetch() with Next.js caching semantics.\n *\n * Patches `globalThis.fetch` during server rendering to support:\n *\n * fetch(url, { next: { revalidate: 60, tags: ['posts'] } })\n * fetch(url, { cache: 'force-cache' })\n * fetch(url, { cache: 'no-store' })\n *\n * Cached responses are stored via the pluggable CacheHandler, so\n * revalidateTag() and revalidatePath() invalidate fetch-level caches.\n *\n * Usage (in server entry):\n * import { withFetchCache, cleanupFetchCache } from './fetch-cache';\n * const cleanup = withFetchCache();\n * try { ... render ... } finally { cleanup(); }\n *\n * Or use the async helper:\n * await runWithFetchCache(async () => { ... render ... });\n */\n\nimport {\n getCacheHandler,\n type CachedFetchValue,\n} from \"./cache.js\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n// ---------------------------------------------------------------------------\n// Cache key generation\n// ---------------------------------------------------------------------------\n\n/**\n * Headers that carry per-user identity. When any of these are present in a\n * fetch request, they MUST be included in the cache key to prevent one user's\n * authenticated response from being served to another user.\n *\n * Checked case-insensitively to match HTTP header semantics.\n */\nconst AUTH_HEADERS = [\"authorization\", \"cookie\", \"x-api-key\"];\n\n/**\n * Check whether a fetch request includes any per-user authentication headers.\n * Returns the normalized header values (sorted by name) for cache key inclusion,\n * or null if no auth headers are present.\n */\nfunction extractAuthHeaders(input: string | URL | Request, init?: RequestInit): string | null {\n const collected: [string, string][] = [];\n\n // Gather headers from the init object\n if (init?.headers) {\n const headers = init.headers instanceof Headers\n ? init.headers\n : new Headers(init.headers as HeadersInit);\n for (const name of AUTH_HEADERS) {\n const value = headers.get(name);\n if (value) collected.push([name, value]);\n }\n }\n\n // Also check headers from the Request object (if input is a Request)\n if (input instanceof Request && input.headers) {\n for (const name of AUTH_HEADERS) {\n // Don't duplicate if already found in init\n if (collected.some(([n]) => n === name)) continue;\n const value = input.headers.get(name);\n if (value) collected.push([name, value]);\n }\n }\n\n if (collected.length === 0) return null;\n\n // Sort for deterministic key ordering\n collected.sort((a, b) => a[0].localeCompare(b[0]));\n return collected.map(([k, v]) => `${k}=${v}`).join(\"&\");\n}\n\n/**\n * Check whether a fetch request carries any per-user auth headers.\n */\nfunction hasAuthHeaders(input: string | URL | Request, init?: RequestInit): boolean {\n return extractAuthHeaders(input, init) !== null;\n}\n\n/**\n * Generate a deterministic cache key from a fetch request.\n *\n * Key = \"fetch:\" + method + \":\" + URL [+ \"|\" + body] [+ \"|auth:\" + auth_headers].\n *\n * When per-user headers (Authorization, Cookie, X-API-Key) are present,\n * they are included in the cache key so different users get separate cache\n * entries. This prevents authenticated responses from leaking across users.\n */\nfunction buildFetchCacheKey(input: string | URL | Request, init?: RequestInit & { next?: NextFetchOptions }): string {\n let url: string;\n let method = \"GET\";\n let body: string | undefined;\n\n if (typeof input === \"string\") {\n url = input;\n } else if (input instanceof URL) {\n url = input.toString();\n } else {\n // Request object\n url = input.url;\n method = input.method || \"GET\";\n }\n\n if (init?.method) method = init.method;\n if (init?.body && typeof init.body === \"string\") body = init.body;\n\n // Build a stable key from URL + method + body + auth headers\n const parts = [`fetch:${method}:${url}`];\n if (body) parts.push(body);\n\n // Include per-user auth headers in the key to prevent cross-user leakage\n const authPart = extractAuthHeaders(input, init);\n if (authPart) parts.push(`auth:${authPart}`);\n\n return parts.join(\"|\");\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface NextFetchOptions {\n revalidate?: number | false;\n tags?: string[];\n}\n\n// Extend the standard RequestInit to include `next`\ndeclare global {\n interface RequestInit {\n next?: NextFetchOptions;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Patching\n// ---------------------------------------------------------------------------\n\n// Capture the real (unpatched) fetch once, shared across Vite's\n// multi-environment module instances via Symbol.for().\nconst _ORIG_FETCH_KEY = Symbol.for(\"vinext.fetchCache.originalFetch\");\nconst _gFetch = globalThis as unknown as Record<PropertyKey, unknown>;\nconst originalFetch: typeof globalThis.fetch = (_gFetch[_ORIG_FETCH_KEY] ??= globalThis.fetch) as typeof globalThis.fetch;\n\n// ---------------------------------------------------------------------------\n// AsyncLocalStorage for request-scoped fetch cache state.\n// Uses Symbol.for() on globalThis so the storage is shared across Vite's\n// multi-environment module instances.\n// ---------------------------------------------------------------------------\ninterface FetchCacheState {\n currentRequestTags: string[];\n}\n\nconst _ALS_KEY = Symbol.for(\"vinext.fetchCache.als\");\nconst _FALLBACK_KEY = Symbol.for(\"vinext.fetchCache.fallback\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = (_g[_ALS_KEY] ??= new AsyncLocalStorage<FetchCacheState>()) as AsyncLocalStorage<FetchCacheState>;\n\nconst _fallbackState = (_g[_FALLBACK_KEY] ??= {\n currentRequestTags: [],\n} satisfies FetchCacheState) as FetchCacheState;\n\nfunction _getState(): FetchCacheState {\n return _als.getStore() ?? _fallbackState;\n}\n\n/**\n * Reset the fallback state for a new request. Used by `withFetchCache()`\n * in single-threaded contexts where ALS.run() isn't used.\n */\nfunction _resetFallbackState(): void {\n _fallbackState.currentRequestTags = [];\n}\n\n/**\n * Get tags collected during the current render pass.\n * Useful for associating page-level cache entries with all the\n * fetch tags used during rendering.\n */\nexport function getCollectedFetchTags(): string[] {\n return [..._getState().currentRequestTags];\n}\n\n/**\n * Create a patched fetch function with Next.js caching semantics.\n *\n * The patched fetch:\n * 1. Checks `cache` and `next` options to determine caching behavior\n * 2. On cache hit, returns the cached response without hitting the network\n * 3. On cache miss, fetches from network, stores in cache, returns response\n * 4. Respects `next.revalidate` for TTL-based revalidation\n * 5. Respects `next.tags` for tag-based invalidation via revalidateTag()\n */\nfunction createPatchedFetch(): typeof globalThis.fetch {\n return async function patchedFetch(\n input: string | URL | Request,\n init?: RequestInit,\n ): Promise<Response> {\n const nextOpts = init?.next as NextFetchOptions | undefined;\n const cacheDirective = init?.cache;\n\n // Determine caching behavior:\n // - cache: 'no-store' → skip cache entirely\n // - cache: 'force-cache' → cache indefinitely (revalidate = Infinity)\n // - next.revalidate: false → same as 'no-store'\n // - next.revalidate: 0 → same as 'no-store'\n // - next.revalidate: N → cache for N seconds\n // - No cache/next options → default behavior (no caching, pass-through)\n\n // If no caching options at all, just pass through to original fetch\n if (!nextOpts && !cacheDirective) {\n return originalFetch(input, init);\n }\n\n // Explicit no-store or no-cache — bypass cache entirely\n if (cacheDirective === \"no-store\" || cacheDirective === \"no-cache\" || nextOpts?.revalidate === false || nextOpts?.revalidate === 0) {\n // Strip the `next` property before passing to real fetch\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n\n // Safety: when per-user auth headers are present and the developer hasn't\n // explicitly opted into caching with `cache: 'force-cache'` or an explicit\n // `next.revalidate`, skip caching to prevent accidental cross-user data\n // leakage. Developers who understand the implications can still force\n // caching by using `cache: 'force-cache'` or `next: { revalidate: N }`.\n const hasExplicitCacheOpt =\n cacheDirective === \"force-cache\" ||\n (typeof nextOpts?.revalidate === \"number\" && nextOpts.revalidate > 0);\n if (!hasExplicitCacheOpt && hasAuthHeaders(input, init)) {\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n\n // Determine revalidation period\n let revalidateSeconds: number;\n if (cacheDirective === \"force-cache\") {\n // force-cache means cache indefinitely (we use a very large number)\n revalidateSeconds = nextOpts?.revalidate && typeof nextOpts.revalidate === \"number\"\n ? nextOpts.revalidate\n : 31536000; // 1 year\n } else if (typeof nextOpts?.revalidate === \"number\" && nextOpts.revalidate > 0) {\n revalidateSeconds = nextOpts.revalidate;\n } else {\n // Has `next` options but no explicit revalidate — Next.js defaults to\n // caching when `next` is present (force-cache behavior).\n // If only tags are specified, cache indefinitely.\n if (nextOpts?.tags && nextOpts.tags.length > 0) {\n revalidateSeconds = 31536000;\n } else {\n // next: {} with no revalidate or tags — pass through\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n }\n\n const tags = nextOpts?.tags ?? [];\n const cacheKey = buildFetchCacheKey(input, init);\n const handler = getCacheHandler();\n\n // Collect tags for this render pass\n const reqTags = _getState().currentRequestTags;\n if (tags.length > 0) {\n for (const tag of tags) {\n if (!reqTags.includes(tag)) {\n reqTags.push(tag);\n }\n }\n }\n\n // Try cache first\n try {\n const cached = await handler.get(cacheKey, { kind: \"FETCH\", tags });\n if (cached?.value && cached.value.kind === \"FETCH\" && cached.cacheState !== \"stale\") {\n const cachedData = cached.value.data;\n // Reconstruct a Response from the cached data\n return new Response(cachedData.body, {\n status: cachedData.status ?? 200,\n headers: cachedData.headers,\n });\n }\n\n // Stale entry — we could do stale-while-revalidate here, but for fetch()\n // the simpler approach is to just re-fetch (the page-level ISR handles SWR).\n // However, if we have a stale entry, return it and trigger background refetch.\n if (cached?.value && cached.value.kind === \"FETCH\" && cached.cacheState === \"stale\") {\n const staleData = cached.value.data;\n\n // Background refetch\n const cleanInit = stripNextFromInit(init);\n originalFetch(input, cleanInit).then(async (freshResp) => {\n const freshBody = await freshResp.text();\n const freshHeaders: Record<string, string> = {};\n freshResp.headers.forEach((v, k) => { freshHeaders[k] = v; });\n\n const freshValue: CachedFetchValue = {\n kind: \"FETCH\",\n data: {\n headers: freshHeaders,\n body: freshBody,\n url: typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url,\n status: freshResp.status,\n },\n tags,\n revalidate: revalidateSeconds,\n };\n await handler.set(cacheKey, freshValue, {\n fetchCache: true,\n tags,\n revalidate: revalidateSeconds,\n });\n }).catch((err) => {\n console.error(\"[vinext] fetch cache background revalidation failed:\", err);\n });\n\n // Return stale data immediately\n return new Response(staleData.body, {\n status: staleData.status ?? 200,\n headers: staleData.headers,\n });\n }\n } catch (cacheErr) {\n // Cache read failed — fall through to network\n console.error(\"[vinext] fetch cache read error:\", cacheErr);\n }\n\n // Cache miss — fetch from network\n const cleanInit = stripNextFromInit(init);\n const response = await originalFetch(input, cleanInit);\n\n // Only cache successful responses (2xx)\n if (response.ok) {\n // Clone before reading body\n const cloned = response.clone();\n const body = await cloned.text();\n const headers: Record<string, string> = {};\n cloned.headers.forEach((v, k) => { headers[k] = v; });\n\n const cacheValue: CachedFetchValue = {\n kind: \"FETCH\",\n data: {\n headers,\n body,\n url: typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url,\n status: cloned.status,\n },\n tags,\n revalidate: revalidateSeconds,\n };\n\n // Store in cache (fire-and-forget)\n handler.set(cacheKey, cacheValue, {\n fetchCache: true,\n tags,\n revalidate: revalidateSeconds,\n }).catch((err) => {\n console.error(\"[vinext] fetch cache write error:\", err);\n });\n }\n\n return response;\n } as typeof globalThis.fetch;\n}\n\n/**\n * Strip the `next` property from RequestInit before passing to real fetch.\n * The `next` property is not a standard fetch option and would cause warnings\n * in some environments.\n */\nfunction stripNextFromInit(init?: RequestInit): RequestInit | undefined {\n if (!init) return init;\n if (!(\"next\" in init)) return init;\n const { next: _next, ...rest } = init as RequestInit & { next?: unknown };\n return Object.keys(rest).length > 0 ? rest : undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Fetch patching — install once, not per-request.\n// The patched fetch uses _getState() internally, which reads from ALS\n// (concurrent) or _fallbackState (single-threaded), so per-request\n// isolation is handled at the state level, not by swapping globalThis.fetch.\n// ---------------------------------------------------------------------------\n\nconst _PATCH_KEY = Symbol.for(\"vinext.fetchCache.patchInstalled\");\n\nfunction _ensurePatchInstalled(): void {\n if (_g[_PATCH_KEY]) return;\n _g[_PATCH_KEY] = true;\n globalThis.fetch = createPatchedFetch();\n}\n\n/**\n * Install the patched fetch and reset per-request tag state.\n * Returns a cleanup function that clears tags.\n *\n * @deprecated Prefer `runWithFetchCache()` which uses `AsyncLocalStorage.run()`\n * for proper per-request isolation in concurrent environments.\n *\n * Usage:\n * const cleanup = withFetchCache();\n * try { await render(); } finally { cleanup(); }\n */\nexport function withFetchCache(): () => void {\n _ensurePatchInstalled();\n _resetFallbackState();\n\n return () => {\n _resetFallbackState();\n };\n}\n\n/**\n * Run an async function with patched fetch caching enabled.\n * Uses `AsyncLocalStorage.run()` for proper per-request isolation\n * of collected fetch tags in concurrent server environments.\n */\nexport async function runWithFetchCache<T>(fn: () => Promise<T>): Promise<T> {\n _ensurePatchInstalled();\n return _als.run({ currentRequestTags: [] }, fn);\n}\n\n/**\n * Get the original (unpatched) fetch function.\n * Useful for internal code that should bypass caching.\n */\nexport function getOriginalFetch(): typeof globalThis.fetch {\n return originalFetch;\n}\n"]}
@@ -7,5 +7,10 @@
7
7
  * This module is server-only — it imports node:async_hooks and must NOT
8
8
  * be bundled for the browser.
9
9
  */
10
- export {};
10
+ /**
11
+ * Run a function within a head state ALS scope.
12
+ * Ensures per-request isolation for Pages Router <Head> elements
13
+ * on concurrent runtimes.
14
+ */
15
+ export declare function runWithHeadState<T>(fn: () => T | Promise<T>): T | Promise<T>;
11
16
  //# sourceMappingURL=head-state.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"head-state.d.ts","sourceRoot":"","sources":["../../src/shims/head-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
1
+ {"version":3,"file":"head-state.d.ts","sourceRoot":"","sources":["../../src/shims/head-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0BH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAK5E"}
@@ -16,22 +16,20 @@ const _als = (_g[_ALS_KEY] ??= new AsyncLocalStorage());
16
16
  const _fallbackState = (_g[_FALLBACK_KEY] ??= {
17
17
  ssrHeadElements: [],
18
18
  });
19
- function _enterWith(state) {
20
- const enterWith = _als.enterWith;
21
- if (typeof enterWith === "function") {
22
- try {
23
- enterWith.call(_als, state);
24
- return;
25
- }
26
- catch {
27
- // Fall through to best-effort fallback.
28
- }
29
- }
30
- _fallbackState.ssrHeadElements = state.ssrHeadElements;
31
- }
32
19
  function _getState() {
33
20
  return _als.getStore() ?? _fallbackState;
34
21
  }
22
+ /**
23
+ * Run a function within a head state ALS scope.
24
+ * Ensures per-request isolation for Pages Router <Head> elements
25
+ * on concurrent runtimes.
26
+ */
27
+ export function runWithHeadState(fn) {
28
+ const state = {
29
+ ssrHeadElements: [],
30
+ };
31
+ return _als.run(state, fn);
32
+ }
35
33
  // ---------------------------------------------------------------------------
36
34
  // Register ALS-backed accessors into head.ts
37
35
  // ---------------------------------------------------------------------------
@@ -40,8 +38,13 @@ _registerHeadStateAccessors({
40
38
  return _getState().ssrHeadElements;
41
39
  },
42
40
  resetSSRHead() {
43
- _enterWith({ ssrHeadElements: [] });
44
- _fallbackState.ssrHeadElements = [];
41
+ const state = _als.getStore();
42
+ if (state) {
43
+ state.ssrHeadElements = [];
44
+ }
45
+ else {
46
+ _fallbackState.ssrHeadElements = [];
47
+ }
45
48
  },
46
49
  });
47
50
  //# sourceMappingURL=head-state.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"head-state.js","sourceRoot":"","sources":["../../src/shims/head-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;AAUxD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAC/C,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AACzD,MAAM,EAAE,GAAG,UAAqD,CAAC;AACjE,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,IAAI,iBAAiB,EAAa,CAAiC,CAAC;AAEnG,MAAM,cAAc,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK;IAC5C,eAAe,EAAE,EAAE;CACA,CAAc,CAAC;AAEpC,SAAS,UAAU,CAAC,KAAgB;IAClC,MAAM,SAAS,GAAI,IAAY,CAAC,SAAS,CAAC;IAC1C,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC5B,OAAO;QACT,CAAC;QAAC,MAAM,CAAC;YACP,wCAAwC;QAC1C,CAAC;IACH,CAAC;IACD,cAAc,CAAC,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;AACzD,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,QAAQ,EAAE,IAAI,cAAc,CAAC;AAC3C,CAAC;AAED,8EAA8E;AAC9E,6CAA6C;AAC7C,8EAA8E;AAE9E,2BAA2B,CAAC;IAC1B,kBAAkB;QAChB,OAAO,SAAS,EAAE,CAAC,eAAe,CAAC;IACrC,CAAC;IAED,YAAY;QACV,UAAU,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC,CAAC;QACpC,cAAc,CAAC,eAAe,GAAG,EAAE,CAAC;IACtC,CAAC;CACF,CAAC,CAAC","sourcesContent":["/**\n * Server-only head state backed by AsyncLocalStorage.\n *\n * Provides request-scoped isolation for SSR head elements so concurrent\n * requests on Workers don't leak <Head> tags between responses.\n *\n * This module is server-only — it imports node:async_hooks and must NOT\n * be bundled for the browser.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { _registerHeadStateAccessors } from \"./head.js\";\n\n// ---------------------------------------------------------------------------\n// ALS setup\n// ---------------------------------------------------------------------------\n\ninterface HeadState {\n ssrHeadElements: string[];\n}\n\nconst _ALS_KEY = Symbol.for(\"vinext.head.als\");\nconst _FALLBACK_KEY = Symbol.for(\"vinext.head.fallback\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = (_g[_ALS_KEY] ??= new AsyncLocalStorage<HeadState>()) as AsyncLocalStorage<HeadState>;\n\nconst _fallbackState = (_g[_FALLBACK_KEY] ??= {\n ssrHeadElements: [],\n} satisfies HeadState) as HeadState;\n\nfunction _enterWith(state: HeadState): void {\n const enterWith = (_als as any).enterWith;\n if (typeof enterWith === \"function\") {\n try {\n enterWith.call(_als, state);\n return;\n } catch {\n // Fall through to best-effort fallback.\n }\n }\n _fallbackState.ssrHeadElements = state.ssrHeadElements;\n}\n\nfunction _getState(): HeadState {\n return _als.getStore() ?? _fallbackState;\n}\n\n// ---------------------------------------------------------------------------\n// Register ALS-backed accessors into head.ts\n// ---------------------------------------------------------------------------\n\n_registerHeadStateAccessors({\n getSSRHeadElements(): string[] {\n return _getState().ssrHeadElements;\n },\n\n resetSSRHead(): void {\n _enterWith({ ssrHeadElements: [] });\n _fallbackState.ssrHeadElements = [];\n },\n});\n"]}
1
+ {"version":3,"file":"head-state.js","sourceRoot":"","sources":["../../src/shims/head-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;AAUxD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAC/C,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AACzD,MAAM,EAAE,GAAG,UAAqD,CAAC;AACjE,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,IAAI,iBAAiB,EAAa,CAAiC,CAAC;AAEnG,MAAM,cAAc,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK;IAC5C,eAAe,EAAE,EAAE;CACA,CAAc,CAAC;AAEpC,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,QAAQ,EAAE,IAAI,cAAc,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAI,EAAwB;IAC1D,MAAM,KAAK,GAAc;QACvB,eAAe,EAAE,EAAE;KACpB,CAAC;IACF,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,8EAA8E;AAC9E,6CAA6C;AAC7C,8EAA8E;AAE9E,2BAA2B,CAAC;IAC1B,kBAAkB;QAChB,OAAO,SAAS,EAAE,CAAC,eAAe,CAAC;IACrC,CAAC;IAED,YAAY;QACV,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC9B,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,eAAe,GAAG,EAAE,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,eAAe,GAAG,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;CACF,CAAC,CAAC","sourcesContent":["/**\n * Server-only head state backed by AsyncLocalStorage.\n *\n * Provides request-scoped isolation for SSR head elements so concurrent\n * requests on Workers don't leak <Head> tags between responses.\n *\n * This module is server-only — it imports node:async_hooks and must NOT\n * be bundled for the browser.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { _registerHeadStateAccessors } from \"./head.js\";\n\n// ---------------------------------------------------------------------------\n// ALS setup\n// ---------------------------------------------------------------------------\n\ninterface HeadState {\n ssrHeadElements: string[];\n}\n\nconst _ALS_KEY = Symbol.for(\"vinext.head.als\");\nconst _FALLBACK_KEY = Symbol.for(\"vinext.head.fallback\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = (_g[_ALS_KEY] ??= new AsyncLocalStorage<HeadState>()) as AsyncLocalStorage<HeadState>;\n\nconst _fallbackState = (_g[_FALLBACK_KEY] ??= {\n ssrHeadElements: [],\n} satisfies HeadState) as HeadState;\n\nfunction _getState(): HeadState {\n return _als.getStore() ?? _fallbackState;\n}\n\n/**\n * Run a function within a head state ALS scope.\n * Ensures per-request isolation for Pages Router <Head> elements\n * on concurrent runtimes.\n */\nexport function runWithHeadState<T>(fn: () => T | Promise<T>): T | Promise<T> {\n const state: HeadState = {\n ssrHeadElements: [],\n };\n return _als.run(state, fn);\n}\n\n// ---------------------------------------------------------------------------\n// Register ALS-backed accessors into head.ts\n// ---------------------------------------------------------------------------\n\n_registerHeadStateAccessors({\n getSSRHeadElements(): string[] {\n return _getState().ssrHeadElements;\n },\n\n resetSSRHead(): void {\n const state = _als.getStore();\n if (state) {\n state.ssrHeadElements = [];\n } else {\n _fallbackState.ssrHeadElements = [];\n }\n },\n});\n"]}
@@ -30,25 +30,21 @@ export declare function consumeDynamicUsage(): boolean;
30
30
  * Set the headers/cookies context for the current RSC render.
31
31
  * Called by the framework's RSC entry before rendering each request.
32
32
  *
33
- * NOTE: This uses enterWith() which only works reliably within the same
34
- * synchronous call stack. For full async context propagation (needed for
35
- * RSC streaming), use runWithHeadersContext() instead.
33
+ * @deprecated Prefer runWithHeadersContext() which uses als.run() for
34
+ * proper per-request isolation. This function mutates the ALS store
35
+ * in-place and is only safe for cleanup (ctx=null) within an existing
36
+ * als.run() scope.
36
37
  */
37
38
  export declare function setHeadersContext(ctx: HeadersContext | null): void;
38
39
  /**
39
40
  * Run a function with headers context, ensuring the context propagates
40
41
  * through all async operations (including RSC streaming).
41
42
  *
42
- * IMPORTANT: RSC rendering is streaming - renderToReadableStream() returns
43
- * immediately but component execution happens later when the stream is consumed.
44
- * AsyncLocalStorage.run() only maintains context within the callback scope,
45
- * so by the time components actually render, we'd be outside that scope.
46
- *
47
- * Solution: We use enterWith() to set persistent context AND update the
48
- * fallback state. This way, even after run() returns, getStore() still
49
- * returns the right state (via enterWith), and if that fails, we have
50
- * the fallback. For single-request-at-a-time scenarios (dev mode), this
51
- * works correctly. For concurrent requests, the ALS should work.
43
+ * Uses AsyncLocalStorage.run() to guarantee per-request isolation.
44
+ * The ALS store propagates through all async continuations including
45
+ * ReadableStream consumption, setTimeout callbacks, and Promise chains,
46
+ * so RSC streaming works correctly — components that render when the
47
+ * stream is consumed still see the correct request's context.
52
48
  */
53
49
  export declare function runWithHeadersContext<T>(ctx: HeadersContext, fn: () => T | Promise<T>): T | Promise<T>;
54
50
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/shims/headers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,UAAU,cAAc;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAmDD;;;;GAIG;AAGH;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAK7C;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI,CAoBlE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,GAAG,EAAE,cAAc,EACnB,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAmBhB;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,yBAAyB,EAAE,OAAO,GACjC,IAAI,CAyBN;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,CAa1E;AAMD;;;;GAIG;AACH,wBAAsB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAUhD;AAED;;;GAGG;AACH,wBAAsB,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC,CAUvD;AAMD,4EAA4E;AAG5E;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CAKpD;AAsBD;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,IAAI,CAKxD;AAED,UAAU,eAAe;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC,CAwB1D;AAmCD,cAAM,cAAc;IAClB,OAAO,CAAC,QAAQ,CAAsB;gBAE1B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAIxC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IAM9D,MAAM,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAQhD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;;OAGG;IACH,GAAG,CACD,aAAa,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAA;KAAE,EACpM,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAA;KAAE,GACxJ,IAAI;IAwCP;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAO1B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAchF,QAAQ,IAAI,MAAM;CAOnB;AAGD,YAAY,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/shims/headers.ts"],"names":[],"mappings":"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"}
@@ -25,24 +25,6 @@ const _fallbackState = (_g[_FALLBACK_KEY] ??= {
25
25
  pendingSetCookies: [],
26
26
  draftModeCookieHeader: null,
27
27
  });
28
- function _enterWith(state) {
29
- // Some non-Node runtimes/polyfills provide AsyncLocalStorage but not enterWith().
30
- const enterWith = _als.enterWith;
31
- if (typeof enterWith === "function") {
32
- try {
33
- enterWith.call(_als, state);
34
- return;
35
- }
36
- catch {
37
- // Fall through to best-effort fallback.
38
- }
39
- }
40
- // Best-effort fallback: global state (not concurrency-safe).
41
- _fallbackState.headersContext = state.headersContext;
42
- _fallbackState.dynamicUsageDetected = state.dynamicUsageDetected;
43
- _fallbackState.pendingSetCookies = state.pendingSetCookies;
44
- _fallbackState.draftModeCookieHeader = state.draftModeCookieHeader;
45
- }
46
28
  function _getState() {
47
29
  const state = _als.getStore();
48
30
  return state ?? _fallbackState;
@@ -74,19 +56,29 @@ export function consumeDynamicUsage() {
74
56
  * Set the headers/cookies context for the current RSC render.
75
57
  * Called by the framework's RSC entry before rendering each request.
76
58
  *
77
- * NOTE: This uses enterWith() which only works reliably within the same
78
- * synchronous call stack. For full async context propagation (needed for
79
- * RSC streaming), use runWithHeadersContext() instead.
59
+ * @deprecated Prefer runWithHeadersContext() which uses als.run() for
60
+ * proper per-request isolation. This function mutates the ALS store
61
+ * in-place and is only safe for cleanup (ctx=null) within an existing
62
+ * als.run() scope.
80
63
  */
81
64
  export function setHeadersContext(ctx) {
82
- // Start of request: enter a fresh per-request store.
83
65
  if (ctx !== null) {
84
- _enterWith({
85
- headersContext: ctx,
86
- dynamicUsageDetected: false,
87
- pendingSetCookies: [],
88
- draftModeCookieHeader: null,
89
- });
66
+ // For backward compatibility, set context on the current ALS store
67
+ // if one exists, otherwise update the fallback. Callers should
68
+ // migrate to runWithHeadersContext() for new-request setup.
69
+ const existing = _als.getStore();
70
+ if (existing) {
71
+ existing.headersContext = ctx;
72
+ existing.dynamicUsageDetected = false;
73
+ existing.pendingSetCookies = [];
74
+ existing.draftModeCookieHeader = null;
75
+ }
76
+ else {
77
+ _fallbackState.headersContext = ctx;
78
+ _fallbackState.dynamicUsageDetected = false;
79
+ _fallbackState.pendingSetCookies = [];
80
+ _fallbackState.draftModeCookieHeader = null;
81
+ }
90
82
  return;
91
83
  }
92
84
  // End of request cleanup: keep the store (so consumeDynamicUsage and
@@ -103,16 +95,11 @@ export function setHeadersContext(ctx) {
103
95
  * Run a function with headers context, ensuring the context propagates
104
96
  * through all async operations (including RSC streaming).
105
97
  *
106
- * IMPORTANT: RSC rendering is streaming - renderToReadableStream() returns
107
- * immediately but component execution happens later when the stream is consumed.
108
- * AsyncLocalStorage.run() only maintains context within the callback scope,
109
- * so by the time components actually render, we'd be outside that scope.
110
- *
111
- * Solution: We use enterWith() to set persistent context AND update the
112
- * fallback state. This way, even after run() returns, getStore() still
113
- * returns the right state (via enterWith), and if that fails, we have
114
- * the fallback. For single-request-at-a-time scenarios (dev mode), this
115
- * works correctly. For concurrent requests, the ALS should work.
98
+ * Uses AsyncLocalStorage.run() to guarantee per-request isolation.
99
+ * The ALS store propagates through all async continuations including
100
+ * ReadableStream consumption, setTimeout callbacks, and Promise chains,
101
+ * so RSC streaming works correctly — components that render when the
102
+ * stream is consumed still see the correct request's context.
116
103
  */
117
104
  export function runWithHeadersContext(ctx, fn) {
118
105
  const state = {
@@ -121,15 +108,7 @@ export function runWithHeadersContext(ctx, fn) {
121
108
  pendingSetCookies: [],
122
109
  draftModeCookieHeader: null,
123
110
  };
124
- // Use enterWith to set persistent context for this async context
125
- _enterWith(state);
126
- // Also update fallback state directly for environments where ALS doesn't
127
- // propagate correctly (this is not concurrency-safe but works for dev)
128
- _fallbackState.headersContext = ctx;
129
- _fallbackState.dynamicUsageDetected = false;
130
- _fallbackState.pendingSetCookies = [];
131
- _fallbackState.draftModeCookieHeader = null;
132
- return fn();
111
+ return _als.run(state, fn);
133
112
  }
134
113
  /**
135
114
  * Apply middleware-forwarded request headers to the current headers context.
@@ -1 +1 @@
1
- {"version":3,"file":"headers.js","sourceRoot":"","sources":["../../src/shims/headers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * next/headers shim\n *\n * Provides cookies() and headers() functions for App Router Server Components.\n * These read from a request context set by the RSC handler before rendering.\n *\n * In Next.js 15+, cookies() and headers() return Promises (async).\n * We support both the sync (legacy) and async patterns.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n// ---------------------------------------------------------------------------\n// Request context\n// ---------------------------------------------------------------------------\n\ninterface HeadersContext {\n headers: Headers;\n cookies: Map<string, string>;\n}\n\ntype VinextHeadersShimState = {\n headersContext: HeadersContext | null;\n dynamicUsageDetected: boolean;\n pendingSetCookies: string[];\n draftModeCookieHeader: string | null;\n};\n\n// NOTE:\n// - This shim can be loaded under multiple module specifiers in Vite's\n// multi-environment setup (RSC/SSR). Store the AsyncLocalStorage on\n// globalThis so `connection()` (next/server) and `consumeDynamicUsage()`\n// (next/headers) always share it.\n// - We use AsyncLocalStorage so concurrent requests don't stomp each other's\n// headers/cookies/dynamic-usage state.\nconst _ALS_KEY = Symbol.for(\"vinext.nextHeadersShim.als\");\nconst _FALLBACK_KEY = Symbol.for(\"vinext.nextHeadersShim.fallback\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = (_g[_ALS_KEY] ??= new AsyncLocalStorage<VinextHeadersShimState>()) as AsyncLocalStorage<VinextHeadersShimState>;\n\nconst _fallbackState = (_g[_FALLBACK_KEY] ??= {\n headersContext: null,\n dynamicUsageDetected: false,\n pendingSetCookies: [],\n draftModeCookieHeader: null,\n} satisfies VinextHeadersShimState) as VinextHeadersShimState;\n\nfunction _enterWith(state: VinextHeadersShimState): void {\n // Some non-Node runtimes/polyfills provide AsyncLocalStorage but not enterWith().\n const enterWith = (_als as any).enterWith;\n if (typeof enterWith === \"function\") {\n try {\n enterWith.call(_als, state);\n return;\n } catch {\n // Fall through to best-effort fallback.\n }\n }\n // Best-effort fallback: global state (not concurrency-safe).\n _fallbackState.headersContext = state.headersContext;\n _fallbackState.dynamicUsageDetected = state.dynamicUsageDetected;\n _fallbackState.pendingSetCookies = state.pendingSetCookies;\n _fallbackState.draftModeCookieHeader = state.draftModeCookieHeader;\n}\n\nfunction _getState(): VinextHeadersShimState {\n const state = _als.getStore();\n return state ?? _fallbackState;\n}\n\n/**\n * Dynamic usage flag — set when a component calls connection(), cookies(),\n * headers(), or noStore() during rendering. When true, ISR caching is\n * bypassed and the response gets Cache-Control: no-store.\n */\n// (stored on _state)\n\n/**\n * Mark the current render as requiring dynamic (uncached) rendering.\n * Called by connection(), cookies(), headers(), and noStore().\n */\nexport function markDynamicUsage(): void {\n _getState().dynamicUsageDetected = true;\n}\n\n/**\n * Check and reset the dynamic usage flag.\n * Called by the server after rendering to decide on caching.\n */\nexport function consumeDynamicUsage(): boolean {\n const state = _getState();\n const used = state.dynamicUsageDetected;\n state.dynamicUsageDetected = false;\n return used;\n}\n\n/**\n * Set the headers/cookies context for the current RSC render.\n * Called by the framework's RSC entry before rendering each request.\n *\n * NOTE: This uses enterWith() which only works reliably within the same\n * synchronous call stack. For full async context propagation (needed for\n * RSC streaming), use runWithHeadersContext() instead.\n */\nexport function setHeadersContext(ctx: HeadersContext | null): void {\n // Start of request: enter a fresh per-request store.\n if (ctx !== null) {\n _enterWith({\n headersContext: ctx,\n dynamicUsageDetected: false,\n pendingSetCookies: [],\n draftModeCookieHeader: null,\n });\n return;\n }\n\n // End of request cleanup: keep the store (so consumeDynamicUsage and\n // cookie flushing can still run), but clear the request headers/cookies.\n const state = _als.getStore();\n if (state) {\n state.headersContext = null;\n } else {\n _fallbackState.headersContext = null;\n }\n}\n\n/**\n * Run a function with headers context, ensuring the context propagates\n * through all async operations (including RSC streaming).\n *\n * IMPORTANT: RSC rendering is streaming - renderToReadableStream() returns\n * immediately but component execution happens later when the stream is consumed.\n * AsyncLocalStorage.run() only maintains context within the callback scope,\n * so by the time components actually render, we'd be outside that scope.\n *\n * Solution: We use enterWith() to set persistent context AND update the\n * fallback state. This way, even after run() returns, getStore() still\n * returns the right state (via enterWith), and if that fails, we have\n * the fallback. For single-request-at-a-time scenarios (dev mode), this\n * works correctly. For concurrent requests, the ALS should work.\n */\nexport function runWithHeadersContext<T>(\n ctx: HeadersContext,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n const state: VinextHeadersShimState = {\n headersContext: ctx,\n dynamicUsageDetected: false,\n pendingSetCookies: [],\n draftModeCookieHeader: null,\n };\n\n // Use enterWith to set persistent context for this async context\n _enterWith(state);\n\n // Also update fallback state directly for environments where ALS doesn't\n // propagate correctly (this is not concurrency-safe but works for dev)\n _fallbackState.headersContext = ctx;\n _fallbackState.dynamicUsageDetected = false;\n _fallbackState.pendingSetCookies = [];\n _fallbackState.draftModeCookieHeader = null;\n\n return fn();\n}\n\n/**\n * Apply middleware-forwarded request headers to the current headers context.\n *\n * When Next.js middleware calls `NextResponse.next({ request: { headers } })`,\n * the modified headers are encoded as `x-middleware-request-<name>` on the\n * middleware response. This function unpacks those prefixed headers and\n * replaces the corresponding entries on the live `HeadersContext` so that\n * subsequent calls to `headers()` / `cookies()` see the middleware changes.\n */\nexport function applyMiddlewareRequestHeaders(\n middlewareResponseHeaders: Headers,\n): void {\n const state = _getState();\n if (!state.headersContext) return;\n\n const ctx = state.headersContext;\n const PREFIX = \"x-middleware-request-\";\n\n for (const [key, value] of middlewareResponseHeaders) {\n if (key.startsWith(PREFIX)) {\n const realName = key.slice(PREFIX.length);\n ctx.headers.set(realName, value);\n }\n }\n\n // If middleware modified the cookie header, rebuild the cookies map.\n const newCookieHeader = ctx.headers.get(\"cookie\");\n if (newCookieHeader !== null) {\n ctx.cookies.clear();\n for (const part of newCookieHeader.split(\";\")) {\n const [k, ...rest] = part.split(\"=\");\n if (k) {\n ctx.cookies.set(k.trim(), rest.join(\"=\").trim());\n }\n }\n }\n}\n\n/**\n * Create a HeadersContext from a standard Request object.\n */\nexport function headersContextFromRequest(request: Request): HeadersContext {\n const cookies = new Map<string, string>();\n const cookieHeader = request.headers.get(\"cookie\") || \"\";\n for (const part of cookieHeader.split(\";\")) {\n const [key, ...rest] = part.split(\"=\");\n if (key) {\n cookies.set(key.trim(), rest.join(\"=\").trim());\n }\n }\n return {\n headers: request.headers,\n cookies,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Read-only Headers instance from the incoming request.\n * Returns a Promise in Next.js 15+ style (but resolves synchronously since\n * the context is already available).\n */\nexport async function headers(): Promise<Headers> {\n const state = _getState();\n if (!state.headersContext) {\n throw new Error(\n \"headers() can only be called from a Server Component, Route Handler, \" +\n \"or Server Action. Make sure you're not calling it from a Client Component.\",\n );\n }\n markDynamicUsage();\n return state.headersContext.headers;\n}\n\n/**\n * Cookie jar from the incoming request.\n * Returns a ReadonlyRequestCookies-like object.\n */\nexport async function cookies(): Promise<RequestCookies> {\n const state = _getState();\n if (!state.headersContext) {\n throw new Error(\n \"cookies() can only be called from a Server Component, Route Handler, \" +\n \"or Server Action.\",\n );\n }\n markDynamicUsage();\n return new RequestCookies(state.headersContext.cookies);\n}\n\n// ---------------------------------------------------------------------------\n// Writable cookie accumulator for Route Handlers / Server Actions\n// ---------------------------------------------------------------------------\n\n/** Accumulated Set-Cookie headers from cookies().set() / .delete() calls */\n// (stored on _state)\n\n/**\n * Get and clear all pending Set-Cookie headers generated by cookies().set()/delete().\n * Called by the framework after rendering to attach headers to the response.\n */\nexport function getAndClearPendingCookies(): string[] {\n const state = _getState();\n const cookies = state.pendingSetCookies;\n state.pendingSetCookies = [];\n return cookies;\n}\n\n// Draft mode cookie name (matches Next.js convention)\nconst DRAFT_MODE_COOKIE = \"__prerender_bypass\";\n\n// Draft mode secret — generated once at build time via Vite `define` so the\n// __prerender_bypass cookie is consistent across all server instances (e.g.\n// multiple Cloudflare Workers isolates).\nfunction getDraftSecret(): string {\n const secret = process.env.__VINEXT_DRAFT_SECRET;\n if (!secret) {\n throw new Error(\n \"[vinext] __VINEXT_DRAFT_SECRET is not defined. \" +\n \"This should be set by the Vite plugin at build time.\",\n );\n }\n return secret;\n}\n\n// Store for Set-Cookie headers generated by draftMode().enable()/disable()\n// (stored on _state)\n\n/**\n * Get any Set-Cookie header generated by draftMode().enable()/disable().\n * Called by the framework after rendering to attach the header to the response.\n */\nexport function getDraftModeCookieHeader(): string | null {\n const state = _getState();\n const header = state.draftModeCookieHeader;\n state.draftModeCookieHeader = null;\n return header;\n}\n\ninterface DraftModeResult {\n isEnabled: boolean;\n enable(): void;\n disable(): void;\n}\n\n/**\n * Draft mode — check/toggle via a `__prerender_bypass` cookie.\n *\n * - `isEnabled`: true if the bypass cookie is present in the request\n * - `enable()`: sets the bypass cookie (for Route Handlers)\n * - `disable()`: clears the bypass cookie\n */\nexport async function draftMode(): Promise<DraftModeResult> {\n const state = _getState();\n const secret = getDraftSecret();\n const isEnabled = state.headersContext\n ? state.headersContext.cookies.get(DRAFT_MODE_COOKIE) === secret\n : false;\n\n return {\n isEnabled,\n enable(): void {\n if (state.headersContext) {\n state.headersContext.cookies.set(DRAFT_MODE_COOKIE, secret);\n }\n state.draftModeCookieHeader =\n `${DRAFT_MODE_COOKIE}=${secret}; Path=/; HttpOnly; SameSite=Lax`;\n },\n disable(): void {\n if (state.headersContext) {\n state.headersContext.cookies.delete(DRAFT_MODE_COOKIE);\n }\n state.draftModeCookieHeader =\n `${DRAFT_MODE_COOKIE}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`;\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Cookie name/value validation (RFC 6265)\n// ---------------------------------------------------------------------------\n\n/**\n * RFC 6265 §4.1.1: cookie-name is a token (RFC 2616 §2.2).\n * Allowed: any visible ASCII (0x21-0x7E) except separators: ()<>@,;:\\\"/[]?={}\n */\nconst VALID_COOKIE_NAME_RE = /^[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2E\\x30-\\x39\\x41-\\x5A\\x5E-\\x7A\\x7C\\x7E]+$/;\n\nfunction validateCookieName(name: string): void {\n if (!name || !VALID_COOKIE_NAME_RE.test(name)) {\n throw new Error(`Invalid cookie name: ${JSON.stringify(name)}`);\n }\n}\n\n/**\n * Validate cookie attribute values (path, domain) to prevent injection\n * via semicolons, newlines, or other control characters.\n */\nfunction validateCookieAttributeValue(value: string, attributeName: string): void {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n if (code <= 0x1F || code === 0x7F || value[i] === \";\") {\n throw new Error(`Invalid cookie ${attributeName} value: ${JSON.stringify(value)}`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// RequestCookies implementation\n// ---------------------------------------------------------------------------\n\nclass RequestCookies {\n private _cookies: Map<string, string>;\n\n constructor(cookies: Map<string, string>) {\n this._cookies = cookies;\n }\n\n get(name: string): { name: string; value: string } | undefined {\n const value = this._cookies.get(name);\n if (value === undefined) return undefined;\n return { name, value };\n }\n\n getAll(): Array<{ name: string; value: string }> {\n const result: Array<{ name: string; value: string }> = [];\n for (const [name, value] of this._cookies) {\n result.push({ name, value });\n }\n return result;\n }\n\n has(name: string): boolean {\n return this._cookies.has(name);\n }\n\n /**\n * Set a cookie. In Route Handlers and Server Actions, this produces\n * a Set-Cookie header on the response.\n */\n set(\n nameOrOptions: string | { name: string; value: string; path?: string; domain?: string; maxAge?: number; expires?: Date; httpOnly?: boolean; secure?: boolean; sameSite?: \"Strict\" | \"Lax\" | \"None\" },\n value?: string,\n options?: { path?: string; domain?: string; maxAge?: number; expires?: Date; httpOnly?: boolean; secure?: boolean; sameSite?: \"Strict\" | \"Lax\" | \"None\" },\n ): this {\n let cookieName: string;\n let cookieValue: string;\n let opts: typeof options;\n\n if (typeof nameOrOptions === \"string\") {\n cookieName = nameOrOptions;\n cookieValue = value ?? \"\";\n opts = options;\n } else {\n cookieName = nameOrOptions.name;\n cookieValue = nameOrOptions.value;\n opts = nameOrOptions;\n }\n\n validateCookieName(cookieName);\n\n // Update the local cookie map\n this._cookies.set(cookieName, cookieValue);\n\n // Build Set-Cookie header string\n const parts = [`${cookieName}=${encodeURIComponent(cookieValue)}`];\n if (opts?.path) {\n validateCookieAttributeValue(opts.path, \"Path\");\n parts.push(`Path=${opts.path}`);\n }\n if (opts?.domain) {\n validateCookieAttributeValue(opts.domain, \"Domain\");\n parts.push(`Domain=${opts.domain}`);\n }\n if (opts?.maxAge !== undefined) parts.push(`Max-Age=${opts.maxAge}`);\n if (opts?.expires) parts.push(`Expires=${opts.expires.toUTCString()}`);\n if (opts?.httpOnly) parts.push(\"HttpOnly\");\n if (opts?.secure) parts.push(\"Secure\");\n if (opts?.sameSite) parts.push(`SameSite=${opts.sameSite}`);\n\n _getState().pendingSetCookies.push(parts.join(\"; \"));\n return this;\n }\n\n /**\n * Delete a cookie by setting it with Max-Age=0.\n */\n delete(name: string): this {\n validateCookieName(name);\n this._cookies.delete(name);\n _getState().pendingSetCookies.push(`${name}=; Path=/; Max-Age=0`);\n return this;\n }\n\n get size(): number {\n return this._cookies.size;\n }\n\n [Symbol.iterator](): IterableIterator<[string, { name: string; value: string }]> {\n const entries = this._cookies.entries();\n const iter: IterableIterator<[string, { name: string; value: string }]> = {\n [Symbol.iterator]() { return iter; },\n next() {\n const { value, done } = entries.next();\n if (done) return { value: undefined, done: true };\n const [name, val] = value;\n return { value: [name, { name, value: val }], done: false };\n },\n };\n return iter;\n }\n\n toString(): string {\n const parts: string[] = [];\n for (const [name, value] of this._cookies) {\n parts.push(`${name}=${value}`);\n }\n return parts.join(\"; \");\n }\n}\n\n// Re-export types\nexport type { RequestCookies };\n"]}
1
+ {"version":3,"file":"headers.js","sourceRoot":"","sources":["../../src/shims/headers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAkBrD,QAAQ;AACR,uEAAuE;AACvE,sEAAsE;AACtE,2EAA2E;AAC3E,oCAAoC;AACpC,6EAA6E;AAC7E,yCAAyC;AACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AAC1D,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;AACpE,MAAM,EAAE,GAAG,UAAqD,CAAC;AACjE,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,IAAI,iBAAiB,EAA0B,CAA8C,CAAC;AAE7H,MAAM,cAAc,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK;IAC5C,cAAc,EAAE,IAAI;IACpB,oBAAoB,EAAE,KAAK;IAC3B,iBAAiB,EAAE,EAAE;IACrB,qBAAqB,EAAE,IAAI;CACK,CAA2B,CAAC;AAE9D,SAAS,SAAS;IAChB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC9B,OAAO,KAAK,IAAI,cAAc,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,qBAAqB;AAErB;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,SAAS,EAAE,CAAC,oBAAoB,GAAG,IAAI,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,oBAAoB,CAAC;IACxC,KAAK,CAAC,oBAAoB,GAAG,KAAK,CAAC;IACnC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAA0B;IAC1D,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,mEAAmE;QACnE,+DAA+D;QAC/D,4DAA4D;QAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QACjC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,cAAc,GAAG,GAAG,CAAC;YAC9B,QAAQ,CAAC,oBAAoB,GAAG,KAAK,CAAC;YACtC,QAAQ,CAAC,iBAAiB,GAAG,EAAE,CAAC;YAChC,QAAQ,CAAC,qBAAqB,GAAG,IAAI,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,cAAc,GAAG,GAAG,CAAC;YACpC,cAAc,CAAC,oBAAoB,GAAG,KAAK,CAAC;YAC5C,cAAc,CAAC,iBAAiB,GAAG,EAAE,CAAC;YACtC,cAAc,CAAC,qBAAqB,GAAG,IAAI,CAAC;QAC9C,CAAC;QACD,OAAO;IACT,CAAC;IAED,qEAAqE;IACrE,yEAAyE;IACzE,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC9B,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,cAAc,CAAC,cAAc,GAAG,IAAI,CAAC;IACvC,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CACnC,GAAmB,EACnB,EAAwB;IAExB,MAAM,KAAK,GAA2B;QACpC,cAAc,EAAE,GAAG;QACnB,oBAAoB,EAAE,KAAK;QAC3B,iBAAiB,EAAE,EAAE;QACrB,qBAAqB,EAAE,IAAI;KAC5B,CAAC;IAEF,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,6BAA6B,CAC3C,yBAAkC;IAElC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,IAAI,CAAC,KAAK,CAAC,cAAc;QAAE,OAAO;IAElC,MAAM,GAAG,GAAG,KAAK,CAAC,cAAc,CAAC;IACjC,MAAM,MAAM,GAAG,uBAAuB,CAAC;IAEvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,yBAAyB,EAAE,CAAC;QACrD,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1C,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,MAAM,eAAe,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClD,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;QAC7B,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACpB,KAAK,MAAM,IAAI,IAAI,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,CAAC,EAAE,CAAC;gBACN,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAgB;IACxD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzD,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,GAAG,EAAE,CAAC;YACR,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IACD,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO;KACR,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,uEAAuE;YACrE,4EAA4E,CAC/E,CAAC;IACJ,CAAC;IACD,gBAAgB,EAAE,CAAC;IACnB,OAAO,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,uEAAuE;YACrE,mBAAmB,CACtB,CAAC;IACJ,CAAC;IACD,gBAAgB,EAAE,CAAC;IACnB,OAAO,IAAI,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED,8EAA8E;AAC9E,kEAAkE;AAClE,8EAA8E;AAE9E,4EAA4E;AAC5E,qBAAqB;AAErB;;;GAGG;AACH,MAAM,UAAU,yBAAyB;IACvC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAG,KAAK,CAAC,iBAAiB,CAAC;IACxC,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC;IAC7B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,sDAAsD;AACtD,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AAE/C,4EAA4E;AAC5E,4EAA4E;AAC5E,yCAAyC;AACzC,SAAS,cAAc;IACrB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IACjD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,iDAAiD;YAC/C,sDAAsD,CACzD,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,2EAA2E;AAC3E,qBAAqB;AAErB;;;GAGG;AACH,MAAM,UAAU,wBAAwB;IACtC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,KAAK,CAAC,qBAAqB,CAAC;IAC3C,KAAK,CAAC,qBAAqB,GAAG,IAAI,CAAC;IACnC,OAAO,MAAM,CAAC;AAChB,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc;QACpC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,KAAK,MAAM;QAChE,CAAC,CAAC,KAAK,CAAC;IAEV,OAAO;QACL,SAAS;QACT,MAAM;YACJ,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;gBACzB,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;YAC9D,CAAC;YACD,KAAK,CAAC,qBAAqB;gBACzB,GAAG,iBAAiB,IAAI,MAAM,kCAAkC,CAAC;QACrE,CAAC;QACD,OAAO;YACL,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;gBACzB,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;YACzD,CAAC;YACD,KAAK,CAAC,qBAAqB;gBACzB,GAAG,iBAAiB,8CAA8C,CAAC;QACvE,CAAC;KACF,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,0CAA0C;AAC1C,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,oBAAoB,GAAG,uEAAuE,CAAC;AAErG,SAAS,kBAAkB,CAAC,IAAY;IACtC,IAAI,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,4BAA4B,CAAC,KAAa,EAAE,aAAqB;IACxE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CAAC,kBAAkB,aAAa,WAAW,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E,MAAM,cAAc;IACV,QAAQ,CAAsB;IAEtC,YAAY,OAA4B;QACtC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,GAAG,CAAC,IAAY;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC1C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACzB,CAAC;IAED,MAAM;QACJ,MAAM,MAAM,GAA2C,EAAE,CAAC;QAC1D,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1C,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED;;;OAGG;IACH,GAAG,CACD,aAAoM,EACpM,KAAc,EACd,OAAyJ;QAEzJ,IAAI,UAAkB,CAAC;QACvB,IAAI,WAAmB,CAAC;QACxB,IAAI,IAAoB,CAAC;QAEzB,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;YACtC,UAAU,GAAG,aAAa,CAAC;YAC3B,WAAW,GAAG,KAAK,IAAI,EAAE,CAAC;YAC1B,IAAI,GAAG,OAAO,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC;YAChC,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC;YAClC,IAAI,GAAG,aAAa,CAAC;QACvB,CAAC;QAED,kBAAkB,CAAC,UAAU,CAAC,CAAC;QAE/B,8BAA8B;QAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAE3C,iCAAiC;QACjC,MAAM,KAAK,GAAG,CAAC,GAAG,UAAU,IAAI,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACnE,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC;YACf,4BAA4B,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAChD,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;YACjB,4BAA4B,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACpD,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,IAAI,EAAE,MAAM,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrE,IAAI,IAAI,EAAE,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACvE,IAAI,IAAI,EAAE,QAAQ;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3C,IAAI,IAAI,EAAE,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,IAAI,EAAE,QAAQ;YAAE,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAE5D,SAAS,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,IAAY;QACjB,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,SAAS,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,IAAI,sBAAsB,CAAC,CAAC;QAClE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED,CAAC,MAAM,CAAC,QAAQ,CAAC;QACf,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACxC,MAAM,IAAI,GAAgE;YACxE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC;YACpC,IAAI;gBACF,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;gBACvC,IAAI,IAAI;oBAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;gBAClD,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;gBAC1B,OAAO,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;YAC9D,CAAC;SACF,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,QAAQ;QACN,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1C,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF","sourcesContent":["/**\n * next/headers shim\n *\n * Provides cookies() and headers() functions for App Router Server Components.\n * These read from a request context set by the RSC handler before rendering.\n *\n * In Next.js 15+, cookies() and headers() return Promises (async).\n * We support both the sync (legacy) and async patterns.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n// ---------------------------------------------------------------------------\n// Request context\n// ---------------------------------------------------------------------------\n\ninterface HeadersContext {\n headers: Headers;\n cookies: Map<string, string>;\n}\n\ntype VinextHeadersShimState = {\n headersContext: HeadersContext | null;\n dynamicUsageDetected: boolean;\n pendingSetCookies: string[];\n draftModeCookieHeader: string | null;\n};\n\n// NOTE:\n// - This shim can be loaded under multiple module specifiers in Vite's\n// multi-environment setup (RSC/SSR). Store the AsyncLocalStorage on\n// globalThis so `connection()` (next/server) and `consumeDynamicUsage()`\n// (next/headers) always share it.\n// - We use AsyncLocalStorage so concurrent requests don't stomp each other's\n// headers/cookies/dynamic-usage state.\nconst _ALS_KEY = Symbol.for(\"vinext.nextHeadersShim.als\");\nconst _FALLBACK_KEY = Symbol.for(\"vinext.nextHeadersShim.fallback\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = (_g[_ALS_KEY] ??= new AsyncLocalStorage<VinextHeadersShimState>()) as AsyncLocalStorage<VinextHeadersShimState>;\n\nconst _fallbackState = (_g[_FALLBACK_KEY] ??= {\n headersContext: null,\n dynamicUsageDetected: false,\n pendingSetCookies: [],\n draftModeCookieHeader: null,\n} satisfies VinextHeadersShimState) as VinextHeadersShimState;\n\nfunction _getState(): VinextHeadersShimState {\n const state = _als.getStore();\n return state ?? _fallbackState;\n}\n\n/**\n * Dynamic usage flag — set when a component calls connection(), cookies(),\n * headers(), or noStore() during rendering. When true, ISR caching is\n * bypassed and the response gets Cache-Control: no-store.\n */\n// (stored on _state)\n\n/**\n * Mark the current render as requiring dynamic (uncached) rendering.\n * Called by connection(), cookies(), headers(), and noStore().\n */\nexport function markDynamicUsage(): void {\n _getState().dynamicUsageDetected = true;\n}\n\n/**\n * Check and reset the dynamic usage flag.\n * Called by the server after rendering to decide on caching.\n */\nexport function consumeDynamicUsage(): boolean {\n const state = _getState();\n const used = state.dynamicUsageDetected;\n state.dynamicUsageDetected = false;\n return used;\n}\n\n/**\n * Set the headers/cookies context for the current RSC render.\n * Called by the framework's RSC entry before rendering each request.\n *\n * @deprecated Prefer runWithHeadersContext() which uses als.run() for\n * proper per-request isolation. This function mutates the ALS store\n * in-place and is only safe for cleanup (ctx=null) within an existing\n * als.run() scope.\n */\nexport function setHeadersContext(ctx: HeadersContext | null): void {\n if (ctx !== null) {\n // For backward compatibility, set context on the current ALS store\n // if one exists, otherwise update the fallback. Callers should\n // migrate to runWithHeadersContext() for new-request setup.\n const existing = _als.getStore();\n if (existing) {\n existing.headersContext = ctx;\n existing.dynamicUsageDetected = false;\n existing.pendingSetCookies = [];\n existing.draftModeCookieHeader = null;\n } else {\n _fallbackState.headersContext = ctx;\n _fallbackState.dynamicUsageDetected = false;\n _fallbackState.pendingSetCookies = [];\n _fallbackState.draftModeCookieHeader = null;\n }\n return;\n }\n\n // End of request cleanup: keep the store (so consumeDynamicUsage and\n // cookie flushing can still run), but clear the request headers/cookies.\n const state = _als.getStore();\n if (state) {\n state.headersContext = null;\n } else {\n _fallbackState.headersContext = null;\n }\n}\n\n/**\n * Run a function with headers context, ensuring the context propagates\n * through all async operations (including RSC streaming).\n *\n * Uses AsyncLocalStorage.run() to guarantee per-request isolation.\n * The ALS store propagates through all async continuations including\n * ReadableStream consumption, setTimeout callbacks, and Promise chains,\n * so RSC streaming works correctly — components that render when the\n * stream is consumed still see the correct request's context.\n */\nexport function runWithHeadersContext<T>(\n ctx: HeadersContext,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n const state: VinextHeadersShimState = {\n headersContext: ctx,\n dynamicUsageDetected: false,\n pendingSetCookies: [],\n draftModeCookieHeader: null,\n };\n\n return _als.run(state, fn);\n}\n\n/**\n * Apply middleware-forwarded request headers to the current headers context.\n *\n * When Next.js middleware calls `NextResponse.next({ request: { headers } })`,\n * the modified headers are encoded as `x-middleware-request-<name>` on the\n * middleware response. This function unpacks those prefixed headers and\n * replaces the corresponding entries on the live `HeadersContext` so that\n * subsequent calls to `headers()` / `cookies()` see the middleware changes.\n */\nexport function applyMiddlewareRequestHeaders(\n middlewareResponseHeaders: Headers,\n): void {\n const state = _getState();\n if (!state.headersContext) return;\n\n const ctx = state.headersContext;\n const PREFIX = \"x-middleware-request-\";\n\n for (const [key, value] of middlewareResponseHeaders) {\n if (key.startsWith(PREFIX)) {\n const realName = key.slice(PREFIX.length);\n ctx.headers.set(realName, value);\n }\n }\n\n // If middleware modified the cookie header, rebuild the cookies map.\n const newCookieHeader = ctx.headers.get(\"cookie\");\n if (newCookieHeader !== null) {\n ctx.cookies.clear();\n for (const part of newCookieHeader.split(\";\")) {\n const [k, ...rest] = part.split(\"=\");\n if (k) {\n ctx.cookies.set(k.trim(), rest.join(\"=\").trim());\n }\n }\n }\n}\n\n/**\n * Create a HeadersContext from a standard Request object.\n */\nexport function headersContextFromRequest(request: Request): HeadersContext {\n const cookies = new Map<string, string>();\n const cookieHeader = request.headers.get(\"cookie\") || \"\";\n for (const part of cookieHeader.split(\";\")) {\n const [key, ...rest] = part.split(\"=\");\n if (key) {\n cookies.set(key.trim(), rest.join(\"=\").trim());\n }\n }\n return {\n headers: request.headers,\n cookies,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Read-only Headers instance from the incoming request.\n * Returns a Promise in Next.js 15+ style (but resolves synchronously since\n * the context is already available).\n */\nexport async function headers(): Promise<Headers> {\n const state = _getState();\n if (!state.headersContext) {\n throw new Error(\n \"headers() can only be called from a Server Component, Route Handler, \" +\n \"or Server Action. Make sure you're not calling it from a Client Component.\",\n );\n }\n markDynamicUsage();\n return state.headersContext.headers;\n}\n\n/**\n * Cookie jar from the incoming request.\n * Returns a ReadonlyRequestCookies-like object.\n */\nexport async function cookies(): Promise<RequestCookies> {\n const state = _getState();\n if (!state.headersContext) {\n throw new Error(\n \"cookies() can only be called from a Server Component, Route Handler, \" +\n \"or Server Action.\",\n );\n }\n markDynamicUsage();\n return new RequestCookies(state.headersContext.cookies);\n}\n\n// ---------------------------------------------------------------------------\n// Writable cookie accumulator for Route Handlers / Server Actions\n// ---------------------------------------------------------------------------\n\n/** Accumulated Set-Cookie headers from cookies().set() / .delete() calls */\n// (stored on _state)\n\n/**\n * Get and clear all pending Set-Cookie headers generated by cookies().set()/delete().\n * Called by the framework after rendering to attach headers to the response.\n */\nexport function getAndClearPendingCookies(): string[] {\n const state = _getState();\n const cookies = state.pendingSetCookies;\n state.pendingSetCookies = [];\n return cookies;\n}\n\n// Draft mode cookie name (matches Next.js convention)\nconst DRAFT_MODE_COOKIE = \"__prerender_bypass\";\n\n// Draft mode secret — generated once at build time via Vite `define` so the\n// __prerender_bypass cookie is consistent across all server instances (e.g.\n// multiple Cloudflare Workers isolates).\nfunction getDraftSecret(): string {\n const secret = process.env.__VINEXT_DRAFT_SECRET;\n if (!secret) {\n throw new Error(\n \"[vinext] __VINEXT_DRAFT_SECRET is not defined. \" +\n \"This should be set by the Vite plugin at build time.\",\n );\n }\n return secret;\n}\n\n// Store for Set-Cookie headers generated by draftMode().enable()/disable()\n// (stored on _state)\n\n/**\n * Get any Set-Cookie header generated by draftMode().enable()/disable().\n * Called by the framework after rendering to attach the header to the response.\n */\nexport function getDraftModeCookieHeader(): string | null {\n const state = _getState();\n const header = state.draftModeCookieHeader;\n state.draftModeCookieHeader = null;\n return header;\n}\n\ninterface DraftModeResult {\n isEnabled: boolean;\n enable(): void;\n disable(): void;\n}\n\n/**\n * Draft mode — check/toggle via a `__prerender_bypass` cookie.\n *\n * - `isEnabled`: true if the bypass cookie is present in the request\n * - `enable()`: sets the bypass cookie (for Route Handlers)\n * - `disable()`: clears the bypass cookie\n */\nexport async function draftMode(): Promise<DraftModeResult> {\n const state = _getState();\n const secret = getDraftSecret();\n const isEnabled = state.headersContext\n ? state.headersContext.cookies.get(DRAFT_MODE_COOKIE) === secret\n : false;\n\n return {\n isEnabled,\n enable(): void {\n if (state.headersContext) {\n state.headersContext.cookies.set(DRAFT_MODE_COOKIE, secret);\n }\n state.draftModeCookieHeader =\n `${DRAFT_MODE_COOKIE}=${secret}; Path=/; HttpOnly; SameSite=Lax`;\n },\n disable(): void {\n if (state.headersContext) {\n state.headersContext.cookies.delete(DRAFT_MODE_COOKIE);\n }\n state.draftModeCookieHeader =\n `${DRAFT_MODE_COOKIE}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`;\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Cookie name/value validation (RFC 6265)\n// ---------------------------------------------------------------------------\n\n/**\n * RFC 6265 §4.1.1: cookie-name is a token (RFC 2616 §2.2).\n * Allowed: any visible ASCII (0x21-0x7E) except separators: ()<>@,;:\\\"/[]?={}\n */\nconst VALID_COOKIE_NAME_RE = /^[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2E\\x30-\\x39\\x41-\\x5A\\x5E-\\x7A\\x7C\\x7E]+$/;\n\nfunction validateCookieName(name: string): void {\n if (!name || !VALID_COOKIE_NAME_RE.test(name)) {\n throw new Error(`Invalid cookie name: ${JSON.stringify(name)}`);\n }\n}\n\n/**\n * Validate cookie attribute values (path, domain) to prevent injection\n * via semicolons, newlines, or other control characters.\n */\nfunction validateCookieAttributeValue(value: string, attributeName: string): void {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n if (code <= 0x1F || code === 0x7F || value[i] === \";\") {\n throw new Error(`Invalid cookie ${attributeName} value: ${JSON.stringify(value)}`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// RequestCookies implementation\n// ---------------------------------------------------------------------------\n\nclass RequestCookies {\n private _cookies: Map<string, string>;\n\n constructor(cookies: Map<string, string>) {\n this._cookies = cookies;\n }\n\n get(name: string): { name: string; value: string } | undefined {\n const value = this._cookies.get(name);\n if (value === undefined) return undefined;\n return { name, value };\n }\n\n getAll(): Array<{ name: string; value: string }> {\n const result: Array<{ name: string; value: string }> = [];\n for (const [name, value] of this._cookies) {\n result.push({ name, value });\n }\n return result;\n }\n\n has(name: string): boolean {\n return this._cookies.has(name);\n }\n\n /**\n * Set a cookie. In Route Handlers and Server Actions, this produces\n * a Set-Cookie header on the response.\n */\n set(\n nameOrOptions: string | { name: string; value: string; path?: string; domain?: string; maxAge?: number; expires?: Date; httpOnly?: boolean; secure?: boolean; sameSite?: \"Strict\" | \"Lax\" | \"None\" },\n value?: string,\n options?: { path?: string; domain?: string; maxAge?: number; expires?: Date; httpOnly?: boolean; secure?: boolean; sameSite?: \"Strict\" | \"Lax\" | \"None\" },\n ): this {\n let cookieName: string;\n let cookieValue: string;\n let opts: typeof options;\n\n if (typeof nameOrOptions === \"string\") {\n cookieName = nameOrOptions;\n cookieValue = value ?? \"\";\n opts = options;\n } else {\n cookieName = nameOrOptions.name;\n cookieValue = nameOrOptions.value;\n opts = nameOrOptions;\n }\n\n validateCookieName(cookieName);\n\n // Update the local cookie map\n this._cookies.set(cookieName, cookieValue);\n\n // Build Set-Cookie header string\n const parts = [`${cookieName}=${encodeURIComponent(cookieValue)}`];\n if (opts?.path) {\n validateCookieAttributeValue(opts.path, \"Path\");\n parts.push(`Path=${opts.path}`);\n }\n if (opts?.domain) {\n validateCookieAttributeValue(opts.domain, \"Domain\");\n parts.push(`Domain=${opts.domain}`);\n }\n if (opts?.maxAge !== undefined) parts.push(`Max-Age=${opts.maxAge}`);\n if (opts?.expires) parts.push(`Expires=${opts.expires.toUTCString()}`);\n if (opts?.httpOnly) parts.push(\"HttpOnly\");\n if (opts?.secure) parts.push(\"Secure\");\n if (opts?.sameSite) parts.push(`SameSite=${opts.sameSite}`);\n\n _getState().pendingSetCookies.push(parts.join(\"; \"));\n return this;\n }\n\n /**\n * Delete a cookie by setting it with Max-Age=0.\n */\n delete(name: string): this {\n validateCookieName(name);\n this._cookies.delete(name);\n _getState().pendingSetCookies.push(`${name}=; Path=/; Max-Age=0`);\n return this;\n }\n\n get size(): number {\n return this._cookies.size;\n }\n\n [Symbol.iterator](): IterableIterator<[string, { name: string; value: string }]> {\n const entries = this._cookies.entries();\n const iter: IterableIterator<[string, { name: string; value: string }]> = {\n [Symbol.iterator]() { return iter; },\n next() {\n const { value, done } = entries.next();\n if (done) return { value: undefined, done: true };\n const [name, val] = value;\n return { value: [name, { name, value: val }], done: false };\n },\n };\n return iter;\n }\n\n toString(): string {\n const parts: string[] = [];\n for (const [name, value] of this._cookies) {\n parts.push(`${name}=${value}`);\n }\n return parts.join(\"; \");\n }\n}\n\n// Re-export types\nexport type { RequestCookies };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/shims/image.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAqB,MAAM,OAAO,CAAC;AAI1C,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAyDD,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,MAAM,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IACnD,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IACpD,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IACpD,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AA0CD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW,GAAG,MAAM,CAE7F;AAeD,QAAA,MAAM,KAAK,qFAoKT,CAAC;AAEH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG;IAChD,KAAK,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;CAClD,CA4FA;AAED,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/shims/image.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAqB,MAAM,OAAO,CAAC;AAI1C,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA+DD,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,MAAM,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IACnD,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IACpD,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IACpD,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AA2CD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW,GAAG,MAAM,CAE7F;AAeD,QAAA,MAAM,KAAK,qFAoKT,CAAC;AAEH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG;IAChD,KAAK,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;CAClD,CA4FA;AAED,eAAe,KAAK,CAAC"}
@@ -36,6 +36,14 @@ const __imageDomains = (() => {
36
36
  })();
37
37
  const __hasImageConfig = __imageRemotePatterns.length > 0 || __imageDomains.length > 0;
38
38
  const __isDev = process.env.NODE_ENV !== "production";
39
+ const __imageDeviceSizes = (() => {
40
+ try {
41
+ return JSON.parse(process.env.__VINEXT_IMAGE_DEVICE_SIZES ?? "[640,750,828,1080,1200,1920,2048,3840]");
42
+ }
43
+ catch {
44
+ return [640, 750, 828, 1080, 1200, 1920, 2048, 3840];
45
+ }
46
+ })();
39
47
  /**
40
48
  * Validate that a remote URL is allowed by the configured remote patterns.
41
49
  * Returns true if the URL is allowed, false otherwise.
@@ -102,10 +110,11 @@ function isRemoteUrl(src) {
102
110
  return src.startsWith("http://") || src.startsWith("https://") || src.startsWith("//");
103
111
  }
104
112
  /**
105
- * Common responsive image widths matching Next.js's default device sizes + image sizes.
113
+ * Responsive image widths matching Next.js's device sizes config.
106
114
  * These are the breakpoints used for srcSet generation.
115
+ * Configurable via `images.deviceSizes` in next.config.js.
107
116
  */
108
- const RESPONSIVE_WIDTHS = [640, 750, 828, 1080, 1200, 1920, 2048, 3840];
117
+ const RESPONSIVE_WIDTHS = __imageDeviceSizes;
109
118
  /**
110
119
  * Build a `/_vinext/image` optimization URL.
111
120
  *