vinext 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/README.md +21 -9
  2. package/dist/build/client-build-config.d.ts +10 -0
  3. package/dist/build/client-build-config.js +18 -2
  4. package/dist/build/pages-client-assets-module.d.ts +8 -0
  5. package/dist/build/pages-client-assets-module.js +21 -1
  6. package/dist/build/prerender-paths.js +5 -3
  7. package/dist/build/run-prerender.js +1 -1
  8. package/dist/build/ssr-manifest.d.ts +2 -0
  9. package/dist/build/ssr-manifest.js +6 -2
  10. package/dist/check.js +7 -6
  11. package/dist/cli.js +2 -1
  12. package/dist/client/client-redirect-matcher.d.ts +14 -0
  13. package/dist/client/client-redirect-matcher.js +37 -0
  14. package/dist/client/client-redirects.d.ts +27 -0
  15. package/dist/client/client-redirects.js +28 -0
  16. package/dist/client/client-rewrites.d.ts +2 -1
  17. package/dist/client/client-rewrites.js +1 -1
  18. package/dist/config/config-matchers.d.ts +26 -11
  19. package/dist/config/config-matchers.js +78 -81
  20. package/dist/config/destination-params.d.ts +47 -0
  21. package/dist/config/destination-params.js +116 -0
  22. package/dist/config/next-config.d.ts +7 -0
  23. package/dist/config/next-config.js +3 -0
  24. package/dist/entries/app-rsc-entry.d.ts +4 -0
  25. package/dist/entries/app-rsc-entry.js +20 -6
  26. package/dist/entries/pages-client-entry.js +3 -1
  27. package/dist/entries/pages-server-entry.js +13 -37
  28. package/dist/index.d.ts +3 -1
  29. package/dist/index.js +134 -43
  30. package/dist/init-cloudflare.d.ts +9 -0
  31. package/dist/init-cloudflare.js +107 -31
  32. package/dist/init-platform.d.ts +4 -0
  33. package/dist/init-platform.js +27 -2
  34. package/dist/init.d.ts +1 -0
  35. package/dist/init.js +67 -3
  36. package/dist/plugins/ast-scope.d.ts +7 -0
  37. package/dist/plugins/ast-scope.js +59 -3
  38. package/dist/plugins/cache-flight-codec.d.ts +1 -1
  39. package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
  40. package/dist/plugins/dynamic-preload-metadata.js +9 -8
  41. package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
  42. package/dist/plugins/ignore-dynamic-requests.js +3 -4
  43. package/dist/plugins/middleware-server-only.d.ts +5 -4
  44. package/dist/plugins/middleware-server-only.js +8 -5
  45. package/dist/plugins/pages-node-externals.js +1 -1
  46. package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
  47. package/dist/plugins/rsc-scan-glob-imports.js +50 -0
  48. package/dist/plugins/strip-server-exports.js +262 -98
  49. package/dist/plugins/transform-result.d.ts +9 -5
  50. package/dist/plugins/transitive-externals.js +1 -1
  51. package/dist/plugins/typeof-window.d.ts +2 -2
  52. package/dist/plugins/use-cache-callable.js +8 -2
  53. package/dist/plugins/worker-server-only-imports.d.ts +20 -0
  54. package/dist/plugins/worker-server-only-imports.js +31 -0
  55. package/dist/plugins/worker-use-server.d.ts +25 -0
  56. package/dist/plugins/worker-use-server.js +129 -0
  57. package/dist/server/api-handler.d.ts +1 -0
  58. package/dist/server/api-handler.js +2 -1
  59. package/dist/server/app-browser-action-result.d.ts +1 -1
  60. package/dist/server/app-browser-action-result.js +9 -2
  61. package/dist/server/app-browser-navigation-controller.js +1 -1
  62. package/dist/server/app-browser-server-action-client.js +1 -1
  63. package/dist/server/app-middleware.d.ts +11 -0
  64. package/dist/server/app-middleware.js +17 -2
  65. package/dist/server/app-page-cache.d.ts +1 -1
  66. package/dist/server/app-page-cache.js +1 -1
  67. package/dist/server/app-page-dispatch.d.ts +3 -1
  68. package/dist/server/app-page-dispatch.js +4 -3
  69. package/dist/server/app-page-ppr-runtime.js +1 -1
  70. package/dist/server/app-page-render-observation.js +1 -1
  71. package/dist/server/app-page-request.js +53 -15
  72. package/dist/server/app-page-route-wiring.js +2 -2
  73. package/dist/server/app-pages-bridge.d.ts +1 -1
  74. package/dist/server/app-pages-bridge.js +2 -3
  75. package/dist/server/app-prerender-endpoints.js +9 -6
  76. package/dist/server/app-request-stage-dispatch.js +6 -2
  77. package/dist/server/app-request-stage-independent-entry.js +25 -5
  78. package/dist/server/app-response-stage-entry.js +10 -2
  79. package/dist/server/app-route-handler-cache.d.ts +1 -0
  80. package/dist/server/app-route-handler-cache.js +1 -0
  81. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  82. package/dist/server/app-route-handler-dispatch.js +5 -2
  83. package/dist/server/app-route-handler-execution.d.ts +1 -0
  84. package/dist/server/app-route-handler-execution.js +1 -0
  85. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  86. package/dist/server/app-route-handler-runtime.js +45 -24
  87. package/dist/server/app-router-entry.js +24 -5
  88. package/dist/server/app-rsc-cache-busting.js +1 -1
  89. package/dist/server/app-rsc-errors.js +20 -16
  90. package/dist/server/app-rsc-handler.d.ts +7 -0
  91. package/dist/server/app-rsc-handler.js +85 -35
  92. package/dist/server/app-rsc-response-stage.js +4 -2
  93. package/dist/server/app-segment-config.d.ts +2 -1
  94. package/dist/server/app-server-action-execution.d.ts +2 -1
  95. package/dist/server/app-server-action-execution.js +61 -22
  96. package/dist/server/app-ssr-entry.js +2 -1
  97. package/dist/server/app-worker-stages.d.ts +5 -0
  98. package/dist/server/app-worker-stages.js +1 -1
  99. package/dist/server/cacheability-request.js +2 -2
  100. package/dist/server/client-build-files.d.ts +16 -0
  101. package/dist/server/client-build-files.js +36 -0
  102. package/dist/server/client-reuse-manifest.js +1 -1
  103. package/dist/server/dev-server.js +38 -27
  104. package/dist/server/dev-stack-sourcemap.js +18 -23
  105. package/dist/server/document-initial-head.d.ts +0 -11
  106. package/dist/server/document-initial-head.js +1 -1
  107. package/dist/server/forwarded-middleware-context.d.ts +5 -0
  108. package/dist/server/forwarded-middleware-context.js +22 -0
  109. package/dist/server/headers.d.ts +4 -1
  110. package/dist/server/headers.js +4 -1
  111. package/dist/server/http-conditional.d.ts +11 -0
  112. package/dist/server/http-conditional.js +10 -1
  113. package/dist/server/http-error-responses.d.ts +1 -1
  114. package/dist/server/image-optimization.d.ts +38 -0
  115. package/dist/server/image-optimization.js +93 -4
  116. package/dist/server/isr-cache.d.ts +10 -0
  117. package/dist/server/isr-cache.js +41 -6
  118. package/dist/server/metadata-route-response.js +9 -8
  119. package/dist/server/middleware-matcher.d.ts +2 -0
  120. package/dist/server/middleware-matcher.js +23 -2
  121. package/dist/server/middleware-runtime.d.ts +13 -0
  122. package/dist/server/middleware-runtime.js +33 -20
  123. package/dist/server/middleware.d.ts +1 -1
  124. package/dist/server/middleware.js +3 -1
  125. package/dist/server/multi-stage.d.ts +11 -0
  126. package/dist/server/normalize-path.d.ts +0 -13
  127. package/dist/server/normalize-path.js +1 -34
  128. package/dist/server/pages-api-route.d.ts +3 -2
  129. package/dist/server/pages-api-route.js +4 -3
  130. package/dist/server/pages-cache-tag.d.ts +12 -0
  131. package/dist/server/pages-cache-tag.js +19 -0
  132. package/dist/server/pages-client-assets.d.ts +2 -0
  133. package/dist/server/pages-data-route.d.ts +10 -0
  134. package/dist/server/pages-data-route.js +19 -2
  135. package/dist/server/pages-document-asset-props.d.ts +5 -1
  136. package/dist/server/pages-document-asset-props.js +13 -5
  137. package/dist/server/pages-document-splice.d.ts +19 -0
  138. package/dist/server/pages-document-splice.js +55 -0
  139. package/dist/server/pages-i18n.d.ts +12 -1
  140. package/dist/server/pages-i18n.js +18 -4
  141. package/dist/server/pages-node-compat.d.ts +16 -5
  142. package/dist/server/pages-node-compat.js +20 -12
  143. package/dist/server/pages-page-data.d.ts +32 -24
  144. package/dist/server/pages-page-data.js +50 -120
  145. package/dist/server/pages-page-handler.d.ts +0 -6
  146. package/dist/server/pages-page-handler.js +188 -126
  147. package/dist/server/pages-page-response.d.ts +12 -6
  148. package/dist/server/pages-page-response.js +41 -34
  149. package/dist/server/pages-request-pipeline.d.ts +10 -2
  150. package/dist/server/pages-request-pipeline.js +37 -18
  151. package/dist/server/pages-request-stage-entry.d.ts +6 -0
  152. package/dist/server/pages-request-stage-entry.js +71 -12
  153. package/dist/server/pages-response-stage-entry.js +4 -0
  154. package/dist/server/pages-revalidate.js +1 -1
  155. package/dist/server/pages-router-entry.js +4 -3
  156. package/dist/server/prerender-manifest.d.ts +3 -3
  157. package/dist/server/prerender-manifest.js +4 -3
  158. package/dist/server/prerender-work-unit-setup.js +4 -0
  159. package/dist/server/prod-server.d.ts +12 -0
  160. package/dist/server/prod-server.js +199 -69
  161. package/dist/server/proper-error.d.ts +4 -0
  162. package/dist/server/proper-error.js +31 -0
  163. package/dist/server/request-pipeline.d.ts +4 -1
  164. package/dist/server/request-pipeline.js +3 -2
  165. package/dist/server/revalidation-request.d.ts +1 -0
  166. package/dist/server/revalidation-request.js +1 -1
  167. package/dist/server/rsc-stream-hints.js +31 -2
  168. package/dist/server/seed-cache.d.ts +1 -0
  169. package/dist/server/seed-cache.js +5 -4
  170. package/dist/server/server-reference-loader.d.ts +4 -0
  171. package/dist/server/server-reference-loader.js +29 -0
  172. package/dist/server/socket-error-backstop.d.ts +9 -1
  173. package/dist/server/socket-error-backstop.js +46 -17
  174. package/dist/server/static-file-signal.d.ts +15 -4
  175. package/dist/server/static-file-signal.js +46 -12
  176. package/dist/server/worker-image-optimization.d.ts +34 -0
  177. package/dist/server/worker-image-optimization.js +86 -0
  178. package/dist/server/worker-stages.d.ts +1 -1
  179. package/dist/server/worker-stages.js +2 -2
  180. package/dist/server/worker-utils.d.ts +8 -3
  181. package/dist/server/worker-utils.js +12 -7
  182. package/dist/shims/app-router-scroll.js +4 -1
  183. package/dist/shims/app-router-tree-context.d.ts +5 -0
  184. package/dist/shims/app-router-tree-context.js +27 -0
  185. package/dist/shims/cache-callable-runtime.d.ts +4 -2
  186. package/dist/shims/cache-callable-runtime.js +21 -12
  187. package/dist/shims/cache-handler.js +1 -9
  188. package/dist/shims/cache-runtime.d.ts +6 -1
  189. package/dist/shims/cache-runtime.js +2 -1
  190. package/dist/shims/cache.d.ts +2 -2
  191. package/dist/shims/cache.js +40 -13
  192. package/dist/shims/cdn-cache.d.ts +8 -0
  193. package/dist/shims/cdn-cache.js +17 -1
  194. package/dist/shims/disable-smooth-scroll.d.ts +3 -0
  195. package/dist/shims/disable-smooth-scroll.js +36 -0
  196. package/dist/shims/document-placeholders.d.ts +19 -0
  197. package/dist/shims/document-placeholders.js +45 -0
  198. package/dist/shims/document.js +21 -5
  199. package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
  200. package/dist/shims/dynamic-preload-chunks.js +13 -9
  201. package/dist/shims/dynamic.d.ts +1 -1
  202. package/dist/shims/dynamic.js +60 -8
  203. package/dist/shims/fetch-cache-state.d.ts +66 -0
  204. package/dist/shims/fetch-cache-state.js +92 -0
  205. package/dist/shims/fetch-cache.d.ts +3 -67
  206. package/dist/shims/fetch-cache.js +160 -125
  207. package/dist/shims/head.d.ts +10 -6
  208. package/dist/shims/head.js +15 -13
  209. package/dist/shims/image.js +2 -1
  210. package/dist/shims/internal/work-store-scope.d.ts +5 -0
  211. package/dist/shims/internal/work-store-scope.js +24 -0
  212. package/dist/shims/navigation.js +31 -5
  213. package/dist/shims/request-context.d.ts +2 -0
  214. package/dist/shims/request-state-types.d.ts +2 -1
  215. package/dist/shims/router.js +12 -20
  216. package/dist/shims/server.d.ts +16 -0
  217. package/dist/shims/server.js +24 -4
  218. package/dist/shims/unified-request-context.d.ts +1 -1
  219. package/dist/shims/url-utils.d.ts +2 -0
  220. package/dist/shims/url-utils.js +3 -1
  221. package/dist/utils/client-runtime-metadata.js +1 -1
  222. package/dist/utils/hash.d.ts +7 -0
  223. package/dist/utils/hash.js +11 -1
  224. package/dist/utils/package-name.d.ts +6 -0
  225. package/dist/utils/package-name.js +12 -1
  226. package/dist/utils/plugin-rsc-version.d.ts +4 -0
  227. package/dist/utils/plugin-rsc-version.js +15 -0
  228. package/dist/utils/prerender-output-paths.js +15 -4
  229. package/dist/utils/public-file-path.d.ts +10 -2
  230. package/dist/utils/public-file-path.js +13 -9
  231. package/dist/utils/public-routes.js +2 -2
  232. package/dist/utils/react-version.d.ts +3 -0
  233. package/dist/utils/react-version.js +1 -1
  234. package/package.json +7 -3
@@ -0,0 +1,25 @@
1
+ import { Plugin } from "vite";
2
+ //#region src/plugins/worker-use-server.d.ts
3
+ type RscPluginModule = typeof import("@vitejs/plugin-rsc");
4
+ /**
5
+ * Replace `"use server"` modules in browser Web Worker bundles with Server
6
+ * Function reference proxies.
7
+ *
8
+ * Vite bundles every worker in a fresh plugin container built from
9
+ * `worker.plugins`, so @vitejs/plugin-rsc's `rsc:use-server` transform never
10
+ * sees worker modules in production builds and the module bodies would be
11
+ * emitted verbatim. Next.js compiles workers as part of the browser graph,
12
+ * where `"use server"` exports become `createServerReference(...)` proxies.
13
+ * This mirrors the client-environment branch of `rsc:use-server` with the
14
+ * same reference keys, without claiming references.
15
+ *
16
+ * The worker realm has no router to dispatch Server Function calls. Next.js's
17
+ * `callServer` dispatches inside `startTransition`, so the dispatch error is
18
+ * reported globally and the call's promise never settles; the worker
19
+ * references reproduce that instead of reaching the server.
20
+ */
21
+ export declare function createWorkerUseServerPlugins(options: {
22
+ rscPluginModule: Promise<RscPluginModule>;
23
+ rscPluginPath: string;
24
+ }): Promise<Plugin[]>;
25
+ //#endregion
@@ -0,0 +1,129 @@
1
+ import path, { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
+ import { escapeRegExp } from "../utils/regex.js";
3
+ import { magicStringTransformResult } from "./transform-result.js";
4
+ import { createRequire } from "node:module";
5
+ import fs from "node:fs";
6
+ import { pathToFileURL } from "node:url";
7
+ import { parseAstAsync, transformWithOxc } from "vite";
8
+ //#region src/plugins/worker-use-server.ts
9
+ const WORKER_REFERENCE_RUNTIME_ID = "\0vinext:worker-server-reference";
10
+ const WORKER_REFERENCE_RUNTIME_ID_RE = /^\0vinext:worker-server-reference$/;
11
+ function workerReferenceRuntime(browserRuntime) {
12
+ return `import { createServerReference } from ${JSON.stringify(browserRuntime)};
13
+
14
+ function callServer() {
15
+ return new Promise(() => {
16
+ reportError(new Error("Server Functions cannot be called from a browser Web Worker."));
17
+ });
18
+ }
19
+
20
+ export function createWorkerServerReference(id, name) {
21
+ return createServerReference(id, callServer, undefined, undefined, name);
22
+ }
23
+ `;
24
+ }
25
+ /** A module-local binding that cannot collide with any name in `code`. */
26
+ function uniqueBinding(code, base) {
27
+ let binding = base;
28
+ while (code.includes(binding)) binding += "_";
29
+ return binding;
30
+ }
31
+ function isPlainFilePath(id) {
32
+ return !/[\0?#]/.test(id) && fs.existsSync(id);
33
+ }
34
+ function withPositionedError(ctx, run) {
35
+ return Promise.resolve().then(run).catch((error) => {
36
+ if (error instanceof Error && "pos" in error && typeof error.pos === "number") ctx.error(error.message, error.pos);
37
+ throw error;
38
+ });
39
+ }
40
+ /**
41
+ * Replace `"use server"` modules in browser Web Worker bundles with Server
42
+ * Function reference proxies.
43
+ *
44
+ * Vite bundles every worker in a fresh plugin container built from
45
+ * `worker.plugins`, so @vitejs/plugin-rsc's `rsc:use-server` transform never
46
+ * sees worker modules in production builds and the module bodies would be
47
+ * emitted verbatim. Next.js compiles workers as part of the browser graph,
48
+ * where `"use server"` exports become `createServerReference(...)` proxies.
49
+ * This mirrors the client-environment branch of `rsc:use-server` with the
50
+ * same reference keys, without claiming references.
51
+ *
52
+ * The worker realm has no router to dispatch Server Function calls. Next.js's
53
+ * `callServer` dispatches inside `startTransition`, so the dispatch error is
54
+ * reported globally and the call's promise never settles; the worker
55
+ * references reproduce that instead of reaching the server.
56
+ */
57
+ async function createWorkerUseServerPlugins(options) {
58
+ const rscRequire = createRequire(options.rscPluginPath);
59
+ const importRscModule = (specifier) => import(pathToFileURL(rscRequire.resolve(specifier)).href);
60
+ const browserRuntime = pathToFileURL(rscRequire.resolve("@vitejs/plugin-rsc/react/browser")).href;
61
+ const [transforms, rscCore] = await Promise.all([importRscModule("@vitejs/plugin-rsc/transforms"), importRscModule("@vitejs/plugin-rsc/core/plugin")]);
62
+ let manager;
63
+ const useServerPlugin = {
64
+ name: "vinext:worker-use-server",
65
+ async configResolved(config) {
66
+ // @vitejs/plugin-rsc's plugin API (and its reference manager) lives.
67
+ const mainConfig = config.mainConfig;
68
+ manager = (await options.rscPluginModule).getPluginApi(mainConfig ?? config)?.manager;
69
+ },
70
+ resolveId: {
71
+ filter: { id: WORKER_REFERENCE_RUNTIME_ID_RE },
72
+ handler: (source) => source
73
+ },
74
+ load: {
75
+ filter: { id: WORKER_REFERENCE_RUNTIME_ID_RE },
76
+ handler: () => workerReferenceRuntime(browserRuntime)
77
+ },
78
+ transform: {
79
+ filter: { code: "use server" },
80
+ async handler(code, id) {
81
+ let ast = await parseAstAsync(code);
82
+ if (!transforms.hasDirective(ast.body, "use server")) return null;
83
+ if (!manager) throw new Error("vinext: cannot compile a \"use server\" module in a Web Worker without @vitejs/plugin-rsc.");
84
+ const expanded = await withPositionedError(this, () => transforms.transformExpandExportAll({
85
+ code,
86
+ ast,
87
+ importer: id,
88
+ resolve: async (source, importer) => (await this.resolve(source, importer))?.id,
89
+ load: async (target) => {
90
+ if (!isPlainFilePath(target)) throw new Error(`vinext: a "use server" module imported by a Web Worker cannot \`export *\` from ${JSON.stringify(target)}; re-export its names explicitly.`);
91
+ this.addWatchFile(target);
92
+ const source = await fs.promises.readFile(target, "utf-8");
93
+ return parseAstAsync((await transformWithOxc(source, target, { sourcemap: false })).code);
94
+ }
95
+ }));
96
+ if (expanded) {
97
+ code = expanded.code;
98
+ ast = await parseAstAsync(code);
99
+ }
100
+ const { referenceKey } = manager.serverReferences.resolve(id, "rsc");
101
+ const runtime = uniqueBinding(code, "$$vinextWorkerReference");
102
+ const result = await withPositionedError(this, () => transforms.transformDirectiveProxyExport(ast, {
103
+ code,
104
+ directive: "use server",
105
+ rejectNonAsyncFunction: true,
106
+ runtime: (name) => `${runtime}(${JSON.stringify(`${referenceKey}#${name}`)}, ${JSON.stringify(name)})`
107
+ }));
108
+ if (!result?.output.hasChanged()) return null;
109
+ result.output.prepend(`import { createWorkerServerReference as ${runtime} } from ${JSON.stringify(WORKER_REFERENCE_RUNTIME_ID)};\n`);
110
+ return magicStringTransformResult(result.output);
111
+ }
112
+ }
113
+ };
114
+ const patchHook = rscCore.default().find((plugin) => plugin.name === "rsc:patch-react-server-dom-webpack")?.transform;
115
+ if (!patchHook || typeof patchHook !== "object") throw new Error("vinext: @vitejs/plugin-rsc no longer exposes its Flight client patch plugin.");
116
+ const flightClientDir = path.dirname(rscRequire.resolve("@vitejs/plugin-rsc/vendor/react-server-dom/client.browser"));
117
+ return [{
118
+ name: "vinext:worker-patch-react-server-dom",
119
+ transform: {
120
+ filter: {
121
+ id: new RegExp(`^${escapeRegExp(`${toSlash(flightClientDir)}/`)}`),
122
+ code: "__webpack_require__"
123
+ },
124
+ handler: patchHook.handler
125
+ }
126
+ }, useServerPlugin];
127
+ }
128
+ //#endregion
129
+ export { createWorkerUseServerPlugins };
@@ -13,5 +13,6 @@ export declare function handleApiRoute(runner: ModuleImporter, req: IncomingMess
13
13
  trustedRevalidateOrigin?: string;
14
14
  allowedRevalidateHeaderKeys?: readonly string[];
15
15
  trailingSlash?: boolean;
16
+ skipTrailingSlashRedirect?: boolean;
16
17
  }): Promise<boolean>;
17
18
  //#endregion
@@ -237,7 +237,8 @@ async function handleApiRoute(runner, req, res, url, apiRoutes, nextConfig) {
237
237
  const nextRequest = new NextRequest(createEdgeApiRequest(req, res, url, params, nextConfig), nextConfig ? { nextConfig: {
238
238
  basePath: nextConfig.basePath,
239
239
  i18n: nextConfig.i18n ?? void 0,
240
- trailingSlash: nextConfig.trailingSlash
240
+ trailingSlash: nextConfig.trailingSlash,
241
+ skipTrailingSlashRedirect: nextConfig.skipTrailingSlashRedirect
241
242
  } } : void 0);
242
243
  const handlerResponse = await tracePagesApiHandler(route.pattern, () => apiModule.default(nextRequest));
243
244
  if (!(handlerResponse instanceof Response)) throw new Error("Edge API route did not return a Response");
@@ -25,7 +25,7 @@ export declare function isServerActionResult<TRoot>(value: unknown): value is Ap
25
25
  export declare function shouldClearClientNavigationCachesForServerActionResult<TRoot>(result: AppBrowserServerActionResult<TRoot> | TRoot, revalidation?: ServerActionRevalidationKind): boolean;
26
26
  export declare function parseServerActionRevalidationHeader(headers: Pick<Headers, "get">): ServerActionRevalidationKind;
27
27
  export declare function resolveServerActionOperationLane(revalidation: ServerActionRevalidationKind): Extract<OperationLane, "refresh" | "server-action">;
28
- export declare function normalizeServerActionThrownValue(data: unknown, responseStatus: number): unknown;
28
+ export declare function normalizeServerActionThrownValue(data: unknown, responseStatus: number): Promise<unknown>;
29
29
  export declare function shouldSyncServerActionHttpFallbackHead<TRoot>(result: AppBrowserServerActionResult<TRoot> | TRoot): boolean;
30
30
  export declare function readInvalidServerActionResponseError(response: Pick<Response, "headers" | "status" | "text">, hasRedirectLocation: boolean): Promise<Error | null>;
31
31
  export type ServerActionResultResponseFactsInput = {
@@ -41,8 +41,15 @@ function createServerActionHttpFallbackError(status) {
41
41
  const error = /* @__PURE__ */ new Error(status === 404 ? "NEXT_NOT_FOUND" : `NEXT_HTTP_ERROR_FALLBACK;${status}`);
42
42
  return Object.assign(error, { digest });
43
43
  }
44
- function normalizeServerActionThrownValue(data, responseStatus) {
45
- return createServerActionHttpFallbackError(responseStatus) ?? data;
44
+ async function normalizeServerActionThrownValue(data, responseStatus) {
45
+ const fallbackError = createServerActionHttpFallbackError(responseStatus);
46
+ if (fallbackError) return fallbackError;
47
+ try {
48
+ await data;
49
+ } catch (error) {
50
+ return error;
51
+ }
52
+ return data;
46
53
  }
47
54
  function shouldSyncServerActionHttpFallbackHead(result) {
48
55
  if (!isServerActionResult(result) || result.root !== void 0) return false;
@@ -583,7 +583,7 @@ function createAppBrowserNavigationController(deps = {}) {
583
583
  } else notifyDiscardedServerActionRevalidation(lifecycleOptions);
584
584
  } else if (decision.disposition === "no-commit") notifyDiscardedServerActionRevalidation(lifecycleOptions);
585
585
  if (returnValue) {
586
- if (!returnValue.ok) throw returnValue.data;
586
+ if (!returnValue.ok) throw await returnValue.data;
587
587
  return returnValue.data;
588
588
  }
589
589
  }
@@ -123,7 +123,7 @@ async function invokeClientServerAction(id, args, actionInitiation, deps) {
123
123
  return deps.commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result.root)), actionInitiation, returnValue, revalidation, renderedPathAndSearch);
124
124
  }
125
125
  if (result.returnValue) {
126
- if (!result.returnValue.ok) throw normalizeServerActionThrownValue(result.returnValue.data, fetchResponse.status);
126
+ if (!result.returnValue.ok) throw await normalizeServerActionThrownValue(result.returnValue.data, fetchResponse.status);
127
127
  return result.returnValue.data;
128
128
  }
129
129
  return;
@@ -34,6 +34,8 @@ export type ApplyAppMiddlewareOptions = {
34
34
  * `trailingSlash`.
35
35
  */
36
36
  trailingSlash?: boolean;
37
+ /** next.config `skipTrailingSlashRedirect`, forwarded to `executeMiddleware`. */
38
+ skipTrailingSlashRedirect?: boolean;
37
39
  };
38
40
  export type ApplyAppMiddlewareResult = {
39
41
  kind: "continue";
@@ -43,6 +45,8 @@ export type ApplyAppMiddlewareResult = {
43
45
  /** True when this pathname can match middleware for some request context. */
44
46
  pathnameEligible?: boolean;
45
47
  rewritten: boolean;
48
+ /** False when a same-origin rewrite target was outside the basePath. */
49
+ rewriteHadBasePath?: boolean;
46
50
  search: string | null;
47
51
  } | {
48
52
  kind: "response";
@@ -53,6 +57,13 @@ export type ApplyAppMiddlewareResult = {
53
57
  response: Response;
54
58
  };
55
59
  export declare function isExternalMiddlewareRewrite(rewriteUrl: string, request: Request): boolean;
60
+ /**
61
+ * The request an external rewrite forwards after middleware ran: the complete
62
+ * middleware request-header override, so deleted credentials stay deleted.
63
+ * Flight headers come from the original request, matching Next.js, which
64
+ * treats them as non-overridable.
65
+ */
66
+ export declare function requestWithMiddlewareContextHeaders(request: Request, context: AppMiddlewareContext): Request;
56
67
  export declare function proxyExternalMiddlewareRewrite(request: Request, rewriteUrl: string, context: AppMiddlewareContext): Promise<Response>;
57
68
  export declare function applyAppMiddleware(options: ApplyAppMiddlewareOptions): Promise<ApplyAppMiddlewareResult>;
58
69
  //#endregion
@@ -75,8 +75,17 @@ function restoreFlightHeaders(request, source) {
75
75
  }
76
76
  return changed ? cloneRequestWithHeaders(request, headers) : request;
77
77
  }
78
+ /**
79
+ * The request an external rewrite forwards after middleware ran: the complete
80
+ * middleware request-header override, so deleted credentials stay deleted.
81
+ * Flight headers come from the original request, matching Next.js, which
82
+ * treats them as non-overridable.
83
+ */
84
+ function requestWithMiddlewareContextHeaders(request, context) {
85
+ return restoreFlightHeaders(requestWithMiddlewareRequestHeaders(request, context.requestHeaders ?? context.headers), request);
86
+ }
78
87
  async function proxyExternalMiddlewareRewrite(request, rewriteUrl, context) {
79
- const proxyRequest = restoreFlightHeaders(requestWithMiddlewareRequestHeaders(request, context.requestHeaders ?? context.headers), request);
88
+ const proxyRequest = requestWithMiddlewareContextHeaders(request, context);
80
89
  setHeadersContext(null);
81
90
  setNavigationContext(null);
82
91
  const { proxyExternalRequest } = await import("../config/config-matchers.js");
@@ -129,6 +138,7 @@ function applyForwardedMiddlewareContext(request, context) {
129
138
  if (typeof data.s === "number") context.status = data.s;
130
139
  if (typeof data.r === "string" && data.r.length > 0) return {
131
140
  applied: true,
141
+ rewriteHadBasePath: typeof data.b === "boolean" ? data.b : void 0,
132
142
  rewriteUrl: data.r
133
143
  };
134
144
  return { applied: true };
@@ -143,6 +153,7 @@ async function applyAppMiddleware(options) {
143
153
  let pathnameEligible = forwarded.applied;
144
154
  let cleanPathname = options.cleanPathname;
145
155
  let rewritten = false;
156
+ let rewriteHadBasePath;
146
157
  let search = null;
147
158
  if (forwarded.rewriteUrl) try {
148
159
  if (isExternalMiddlewareRewrite(forwarded.rewriteUrl, options.request)) {
@@ -168,6 +179,7 @@ async function applyAppMiddleware(options) {
168
179
  const rewriteParsed = new URL(forwarded.rewriteUrl, options.request.url);
169
180
  cleanPathname = rewriteParsed.pathname;
170
181
  rewritten = true;
182
+ rewriteHadBasePath = forwarded.rewriteHadBasePath;
171
183
  search = rewriteParsed.search;
172
184
  } catch (e) {
173
185
  console.error("[vinext] Failed to apply forwarded middleware rewrite:", e);
@@ -194,6 +206,7 @@ async function applyAppMiddleware(options) {
194
206
  },
195
207
  requestBodyAlreadyIsolated: true,
196
208
  request: middlewareRequest,
209
+ skipTrailingSlashRedirect: options.skipTrailingSlashRedirect,
197
210
  trailingSlash: options.trailingSlash
198
211
  });
199
212
  } finally {
@@ -243,6 +256,7 @@ async function applyAppMiddleware(options) {
243
256
  const rewriteParsed = new URL(result.rewriteUrl, middlewareRequest.url);
244
257
  cleanPathname = rewriteParsed.pathname;
245
258
  rewritten = true;
259
+ rewriteHadBasePath = result.rewriteHadBasePath;
246
260
  search = rewriteParsed.search;
247
261
  }
248
262
  }
@@ -258,8 +272,9 @@ async function applyAppMiddleware(options) {
258
272
  matched,
259
273
  pathnameEligible,
260
274
  rewritten,
275
+ rewriteHadBasePath,
261
276
  search
262
277
  };
263
278
  }
264
279
  //#endregion
265
- export { FLIGHT_HEADERS, applyAppMiddleware, isExternalMiddlewareRewrite, proxyExternalMiddlewareRewrite };
280
+ export { FLIGHT_HEADERS, applyAppMiddleware, isExternalMiddlewareRewrite, proxyExternalMiddlewareRewrite, requestWithMiddlewareContextHeaders };
@@ -93,7 +93,7 @@ type ReadAppPageFallbackShellCacheResponseOptions = {
93
93
  isEdgeRuntime?: boolean;
94
94
  isrDebug?: AppPageDebugLogger;
95
95
  isrGet: AppPageCacheGetter;
96
- isrHtmlKey: (pathname: string) => string;
96
+ isrFallbackShellHtmlKey: (pathname: string) => string;
97
97
  middlewareHeaders?: Headers | null;
98
98
  middlewareStatus?: number | null;
99
99
  revalidateSeconds: number;
@@ -375,7 +375,7 @@ see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error`);
375
375
  return null;
376
376
  }
377
377
  async function readAppPageFallbackShellCacheResponse(options) {
378
- const isrKey = options.isrHtmlKey(options.fallbackPathname);
378
+ const isrKey = options.isrFallbackShellHtmlKey(options.fallbackPathname);
379
379
  try {
380
380
  const cached = await options.isrGet(isrKey);
381
381
  const cachedValue = getCachedAppPageValue(cached);
@@ -13,7 +13,8 @@ import { AppPageSsrHandler } from "./app-page-stream.js";
13
13
  import { AppRenderErrorContextOverrides } from "./app-rsc-error-handler.js";
14
14
  import { AppPageCacheSetter, ISRCacheEntry } from "./isr-cache.js";
15
15
  import { PprFallbackShellState } from "../shims/ppr-fallback-shell.js";
16
- import { FetchCacheMode } from "../shims/fetch-cache.js";
16
+ import { FetchCacheMode } from "../shims/fetch-cache-state.js";
17
+ import "../shims/fetch-cache.js";
17
18
  import { AppPagePprFallbackCacheShell } from "./app-ppr-fallback-shell.js";
18
19
  import { WarmPprFallbackShellCachesOptions } from "./app-ppr-fallback-shell-render.js";
19
20
  import { ValidateAppPageDynamicParamsOptions } from "./app-page-request.js";
@@ -197,6 +198,7 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
197
198
  isRscRequest: boolean;
198
199
  isrDebug?: AppPageDebugLogger;
199
200
  isrGet: AppPageCacheGetter;
201
+ isrFallbackShellHtmlKey: (pathname: string) => string;
200
202
  isrHtmlKey: (pathname: string) => string;
201
203
  isrRscKey: (pathname: string, mountedSlotsHeader?: string | null, renderMode?: AppRscRenderMode, interceptionContext?: string | null, interceptionId?: string | null) => string;
202
204
  isrSet: AppPageCacheSetter;
@@ -3,6 +3,7 @@ import "../utils/protocol-headers.js";
3
3
  import { getRequestExecutionContext } from "../shims/request-context.js";
4
4
  import { VINEXT_INTERCEPTION_ID_HEADER, VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
5
5
  import "./headers.js";
6
+ import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
6
7
  import { beginRouteCacheability, isRouteCacheabilityIdentityProbe, isRouteCacheabilityProbe, markRouteCacheabilityPatternDynamic, readRouteCacheabilityState } from "../shims/cacheability-classification.js";
7
8
  import { APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL } from "./app-rsc-render-mode.js";
8
9
  import { consumeDynamicUsage, consumeInvalidDynamicUsageError, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersContext, isDraftModeRequest, peekDynamicUsage, peekRenderRequestApiUsage, runWithIsolatedDynamicUsage, setHeadersContext } from "../shims/headers.js";
@@ -150,7 +151,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
150
151
  executionContext: getRequestExecutionContext(),
151
152
  unstableCacheRevalidation: "foreground"
152
153
  });
153
- const revalidation = runWithRequestContext(requestContext, async () => {
154
+ const revalidation = runWithRequestContext(requestContext, () => runInWorkStoreScope(async () => {
154
155
  ensureFetchPatch();
155
156
  setRefreshStaleFetchesInForeground(process.env.VINEXT_PRERENDER === "1");
156
157
  setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], options.routeSegments));
@@ -160,7 +161,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
160
161
  params: options.params
161
162
  });
162
163
  return await runWithFetchDedupe(renderFn);
163
- });
164
+ }));
164
165
  try {
165
166
  return await revalidation;
166
167
  } finally {
@@ -313,7 +314,7 @@ async function dispatchAppPageInner(options) {
313
314
  });
314
315
  const isNeverStoredPath = options.pprRuntime === void 0 && hasNoManifestAdmissionState(route.pattern);
315
316
  const shouldReadCache = !isRouteCacheabilityProbe() && isCacheEligibleRender && !isNeverStoredPath;
316
- const isCacheCandidate = isCacheEligibleRender && isStaticEligible && options.pprRuntime === void 0 && !isNeverStoredPath;
317
+ const isCacheCandidate = isCacheEligibleRender && isStaticEligible && options.pprFallbackShell === void 0 && !isNeverStoredPath;
317
318
  if (shouldReadCache && isStaticEligible) {
318
319
  traceOperation = resolveAppPageTraceOperation({
319
320
  hasRequestSearchParams,
@@ -34,7 +34,7 @@ async function probePprFallbackShellCache(options, fallbackShells, currentRevali
34
34
  isEdgeRuntime: options.isEdgeRuntime,
35
35
  isrDebug: options.isrDebug,
36
36
  isrGet: options.isrGet,
37
- isrHtmlKey: options.isrHtmlKey,
37
+ isrFallbackShellHtmlKey: options.isrFallbackShellHtmlKey,
38
38
  middlewareHeaders: options.middlewareContext.headers,
39
39
  middlewareStatus: options.middlewareContext.status,
40
40
  revalidateSeconds: currentRevalidateSeconds ?? 0,
@@ -1,5 +1,5 @@
1
- import { fnv1a64 } from "../utils/hash.js";
2
1
  import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
2
+ import { fnv1a64 } from "../utils/hash.js";
3
3
  import { consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage } from "../shims/headers.js";
4
4
  import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js";
5
5
  import { consumeDynamicFetchObservations } from "../shims/fetch-cache.js";
@@ -183,24 +183,62 @@ async function generateIndependentStaticParams(sources, primaryParams, requestPa
183
183
  validated
184
184
  };
185
185
  }
186
- async function generateChainedStaticParams(sources) {
187
- let generatedParams = [];
186
+ function isStaticParamsRowConsistentWithRequest(row, requestParams) {
187
+ const sharedKeys = Object.keys(row).filter((key) => requestParams[key] !== void 0);
188
+ return areStaticParamsAllowed(requestParams, [row], false, sharedKeys);
189
+ }
190
+ function rewritesParentParams(parentParams, item) {
191
+ return Object.keys(item).some((key) => Object.hasOwn(parentParams, key) && JSON.stringify(item[key]) !== JSON.stringify(parentParams[key]));
192
+ }
193
+ async function generateChainedStaticParams(sources, requestParams, results = /* @__PURE__ */ new Map()) {
194
+ let generatedRows = [];
195
+ let skippedParents = false;
196
+ let needsEveryCombination = false;
188
197
  for (const source of sources) {
189
- const hasParentParams = generatedParams.length > 0;
190
- const parents = hasParentParams ? generatedParams : [{}];
191
- const nextParams = [];
192
- for (const parentParams of parents) {
193
- const result = await runWithFetchDedupe(() => source.generateStaticParams({ params: parentParams }));
194
- if (Array.isArray(result) && result.length > 0) {
195
- for (const item of result) if (item !== null && typeof item === "object" && !Array.isArray(item)) nextParams.push({
196
- ...parentParams,
197
- ...item
198
+ let sourceResults = results.get(source);
199
+ if (!sourceResults) {
200
+ sourceResults = /* @__PURE__ */ new Map();
201
+ results.set(source, sourceResults);
202
+ }
203
+ const hasParentParams = generatedRows.length > 0;
204
+ let parents = hasParentParams ? generatedRows : [{
205
+ params: {},
206
+ lineage: ""
207
+ }];
208
+ const nextRows = [];
209
+ if (requestParams) {
210
+ const consistent = parents.filter((row) => isStaticParamsRowConsistentWithRequest(row.params, requestParams));
211
+ parents = consistent.length > 0 ? consistent : parents.slice(0, 1);
212
+ }
213
+ if (hasParentParams && parents.length < generatedRows.length) skippedParents = true;
214
+ for (const parent of parents) {
215
+ let result = sourceResults.get(parent.lineage);
216
+ if (!sourceResults.has(parent.lineage)) {
217
+ result = await runWithFetchDedupe(() => source.generateStaticParams({ params: parent.params }));
218
+ sourceResults.set(parent.lineage, result);
219
+ }
220
+ if (Array.isArray(result) && result.length > 0) result.forEach((item, index) => {
221
+ if (item === null || typeof item !== "object" || Array.isArray(item)) return;
222
+ const row = item;
223
+ if (skippedParents && rewritesParentParams(parent.params, row)) needsEveryCombination = true;
224
+ nextRows.push({
225
+ params: {
226
+ ...parent.params,
227
+ ...row
228
+ },
229
+ lineage: `${parent.lineage}/${index}`
198
230
  });
199
- } else if (hasParentParams) nextParams.push(parentParams);
231
+ });
232
+ else if (hasParentParams) nextRows.push({
233
+ params: parent.params,
234
+ lineage: `${parent.lineage}/-`
235
+ });
200
236
  }
201
- generatedParams = nextParams;
237
+ if (skippedParents && nextRows.length === 0) needsEveryCombination = true;
238
+ generatedRows = nextRows;
202
239
  }
203
- return generatedParams;
240
+ if (needsEveryCombination) return generateChainedStaticParams(sources, null, results);
241
+ return generatedRows.map((row) => row.params);
204
242
  }
205
243
  function normalizeGenerateStaticParams(generateStaticParams) {
206
244
  return (Array.isArray(generateStaticParams) ? generateStaticParams : [generateStaticParams]).flatMap((source) => {
@@ -218,7 +256,7 @@ async function validateAppPageDynamicParams(options) {
218
256
  if (generateStaticParamsSources.length === 0) return notFoundResponse();
219
257
  const chainedSources = generateStaticParamsSources.filter((source) => source.chained);
220
258
  let chainedStaticParams = null;
221
- if (chainedSources.length > 0) chainedStaticParams = await generateChainedStaticParams(chainedSources);
259
+ if (chainedSources.length > 0) chainedStaticParams = await generateChainedStaticParams(chainedSources, generateStaticParamsSources.some((source) => !source.chained) ? null : options.params);
222
260
  const independentChains = /* @__PURE__ */ new Map();
223
261
  for (const source of generateStaticParamsSources.filter((source) => !source.chained)) {
224
262
  const chain = independentChains.get(source.independentChain ?? source) ?? [];
@@ -1,5 +1,5 @@
1
- import { fnv1a64 } from "../utils/hash.js";
2
1
  import { APP_RSC_RENDER_MODE_PREFETCH_EMPTY, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "./app-rsc-render-mode.js";
2
+ import { fnv1a64 } from "../utils/hash.js";
3
3
  import { createInlineScriptTag, escapeHtmlAttr } from "./html.js";
4
4
  import { createAppRenderDependency, registerAppElementRenderDependencies, renderAfterAppDependencies, renderAppComponentWithDependencyBarrier } from "./app-render-dependency.js";
5
5
  import { APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_STATIC_SIBLINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
@@ -289,7 +289,7 @@ function createAppPageRouteBodyMetadata(metadata, pathname, metadataPlacement, t
289
289
  streamedIconKey
290
290
  });
291
291
  const metadataKey = streamedIconKey ? createStreamedIconKey(pathname, renderedMetadataHtml) : "";
292
- const parserInsertedMetadataHtml = (streamedIconKey ? renderedMetadataHtml.replaceAll(`<link data-vinext-streamed-icon="${STREAMED_ICON_KEY_PLACEHOLDER}:`, `<link data-vinext-streamed-icon="${escapeHtmlAttr(metadataKey)}:`) : renderedMetadataHtml) + createInlineScriptTag(REINSERT_STREAMED_ICONS_SCRIPT, scriptNonce);
292
+ const parserInsertedMetadataHtml = (streamedIconKey ? renderedMetadataHtml.replaceAll(`<link data-vinext-streamed-icon="${STREAMED_ICON_KEY_PLACEHOLDER}:`, () => `<link data-vinext-streamed-icon="${escapeHtmlAttr(metadataKey)}:`) : renderedMetadataHtml) + createInlineScriptTag(REINSERT_STREAMED_ICONS_SCRIPT, scriptNonce);
293
293
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
294
294
  hidden: true,
295
295
  suppressHydrationWarning: true,
@@ -24,7 +24,6 @@ type AppRouteMatch = {
24
24
  type RenderPagesFallbackDependencies = {
25
25
  loadPagesEntry: () => Promise<PagesEntry> | PagesEntry;
26
26
  buildRequestHeaders: (requestHeaders: Headers, middlewareRequestHeaders: Headers) => Headers | null;
27
- decodePathParams: (pathname: string) => string;
28
27
  applyRouteHandlerMiddlewareContext: (response: Response, middlewareContext: AppMiddlewareContext) => Response;
29
28
  /**
30
29
  * Returns the `__prerender_bypass` Set-Cookie header emitted by a
@@ -51,6 +50,7 @@ type RenderPagesFallbackOptions = {
51
50
  initialResponseHeaders?: Headers;
52
51
  matchKind?: "dynamic" | "static";
53
52
  middlewareContext: AppMiddlewareContext;
53
+ /** Raw (still percent-encoded) Pages route URL; defaults to `url.pathname`. */
54
54
  pathname?: string;
55
55
  pagesDataRequest?: Request | null;
56
56
  request: Request;
@@ -19,7 +19,7 @@ function applyPagesMiddlewareContext(response, middlewareContext) {
19
19
  */
20
20
  async function renderPagesFallback(options, dependencies) {
21
21
  const { allowRscDocumentFallback = false, appRouteMatch = null, isDataRequest = false, isRscRequest, initialResponseHeaders, matchKind, middlewareContext, pathname = options.url.pathname, pagesDataRequest = null, request, url } = options;
22
- const { loadPagesEntry, buildRequestHeaders, decodePathParams, applyRouteHandlerMiddlewareContext, getDraftModeCookieHeader } = dependencies;
22
+ const { loadPagesEntry, buildRequestHeaders, applyRouteHandlerMiddlewareContext, getDraftModeCookieHeader } = dependencies;
23
23
  if (isRscRequest && !allowRscDocumentFallback) return null;
24
24
  const pagesEntry = await loadPagesEntry();
25
25
  const pagesRequestHeaders = middlewareContext.requestHeaders ? buildRequestHeaders(request.headers, middlewareContext.requestHeaders) : null;
@@ -27,8 +27,7 @@ async function renderPagesFallback(options, dependencies) {
27
27
  if (pagesRequestHeaders) pagesRequest = cloneRequestWithHeaders(request, pagesRequestHeaders);
28
28
  const queryIndex = pathname.indexOf("?");
29
29
  const pagesPathname = queryIndex === -1 ? pathname : pathname.slice(0, queryIndex);
30
- const pagesSearch = queryIndex === -1 ? url.search || "" : pathname.slice(queryIndex);
31
- const pagesUrl = decodePathParams(pagesPathname) + pagesSearch;
30
+ const pagesUrl = pagesPathname + (queryIndex === -1 ? url.search || "" : pathname.slice(queryIndex));
32
31
  if (pagesPathname.startsWith("/api/") || pagesPathname === "/api") {
33
32
  if (typeof pagesEntry.handleApiRoute !== "function") return null;
34
33
  const hasApiMatcher = typeof pagesEntry.matchApiRoute === "function";
@@ -1,4 +1,5 @@
1
1
  import "./headers.js";
2
+ import { runInWorkStoreScope, runOutsideWorkStoreScope } from "../shims/internal/work-store-scope.js";
2
3
  import { notFoundResponse } from "./http-error-responses.js";
3
4
  import { callAppPrerenderStaticParams } from "./app-prerender-static-params.js";
4
5
  //#region src/server/app-prerender-endpoints.ts
@@ -39,13 +40,13 @@ async function handleStaticParamsEndpoint(request, options) {
39
40
  if (typeof generateStaticParams !== "function") return jsonNullResponse();
40
41
  try {
41
42
  const params = parseParentParams(url.searchParams.get("parentParams"));
42
- const result = await callAppPrerenderStaticParams({
43
+ const result = await runInWorkStoreScope(() => callAppPrerenderStaticParams({
43
44
  fn: generateStaticParams,
44
45
  params,
45
46
  pattern,
46
47
  rejectEmptyResults: url.searchParams.get("rejectEmptyResults") === "1",
47
48
  rootParamNamesByPattern: options.rootParamNamesByPattern ?? {}
48
- });
49
+ }));
49
50
  if (result === null) return jsonNullResponse();
50
51
  return jsonResponse(result);
51
52
  } catch (error) {
@@ -63,10 +64,12 @@ async function handlePagesStaticPathsEndpoint(request, options) {
63
64
  try {
64
65
  const getStaticPaths = findPageRoute(await options.loadPagesRoutes?.(), pattern)?.module?.getStaticPaths;
65
66
  if (typeof getStaticPaths !== "function") return jsonNullResponse();
66
- return jsonResponse(await getStaticPaths({
67
- locales: parseLocales(url.searchParams.get("locales")),
68
- defaultLocale: url.searchParams.get("defaultLocale") ?? ""
69
- }));
67
+ const locales = parseLocales(url.searchParams.get("locales"));
68
+ const defaultLocale = url.searchParams.get("defaultLocale") ?? "";
69
+ return jsonResponse(await runOutsideWorkStoreScope(() => getStaticPaths({
70
+ locales,
71
+ defaultLocale
72
+ })));
70
73
  } catch (error) {
71
74
  return jsonResponse({ error: String(error) }, 500);
72
75
  }
@@ -1,8 +1,10 @@
1
1
  import "../utils/protocol-headers.js";
2
2
  import "./headers.js";
3
3
  import { restoreStaticFileSignalFromTransport } from "./static-file-signal.js";
4
+ import { attachRequestCfMetadata } from "./request-pipeline.js";
4
5
  import { isDraftModeRequest } from "../shims/headers.js";
5
6
  import { getScriptNonceFromHeaderSources } from "./csp.js";
7
+ import { restoreImageOptimizationSignalFromTransport } from "./image-optimization.js";
6
8
  import { isRouteTreePrefetchRequest } from "./app-route-tree-prefetch.js";
7
9
  import "./app-worker-stages.js";
8
10
  //#region src/server/app-request-stage-dispatch.ts
@@ -29,7 +31,8 @@ async function dispatchAppRequestStage(request, ctx, dispatchResponseStage, opti
29
31
  if (!dispatchResponseStage) throw new Error("App request stage requires a response-stage dispatcher");
30
32
  if (appRequestUsesFullResponseGraph(request, options)) {
31
33
  const staticFileSignalToken = crypto.randomUUID();
32
- const response = await dispatchResponseStage(request, {
34
+ const headRequest = request.method === "HEAD";
35
+ const response = await dispatchResponseStage(headRequest ? attachRequestCfMetadata(new Request(request, { method: "GET" }), request) : request, {
33
36
  kind: "app-full-request",
34
37
  buildId: options.buildId,
35
38
  cacheability: {
@@ -38,6 +41,7 @@ async function dispatchAppRequestStage(request, ctx, dispatchResponseStage, opti
38
41
  resolvedRoutePathname: new URL(request.url).pathname
39
42
  },
40
43
  draftModeCookie: null,
44
+ headRequest,
41
45
  middlewareCookieOverlay: null,
42
46
  prerenderDiscovery: options.prerenderDiscovery,
43
47
  protocolVersion: 11,
@@ -46,7 +50,7 @@ async function dispatchAppRequestStage(request, ctx, dispatchResponseStage, opti
46
50
  staticFileSignalToken,
47
51
  trustedPrerenderState: options.trustedPrerenderState ?? null
48
52
  }, { cache: "bypass" });
49
- return restoreStaticFileSignalFromTransport(response, staticFileSignalToken);
53
+ return await restoreImageOptimizationSignalFromTransport(await restoreStaticFileSignalFromTransport(response, staticFileSignalToken), staticFileSignalToken);
50
54
  }
51
55
  return options.handleRequest(request, ctx, false, dispatchResponseStage, options.probeMode);
52
56
  }