vinext 0.1.8 → 0.2.1

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 (285) hide show
  1. package/README.md +51 -30
  2. package/dist/build/css-url-assets.d.ts +3 -1
  3. package/dist/build/css-url-assets.js +18 -1
  4. package/dist/build/inject-pregenerated-paths.d.ts +7 -0
  5. package/dist/build/inject-pregenerated-paths.js +21 -0
  6. package/dist/build/layout-classification.js +1 -1
  7. package/dist/build/nitro-route-rules.js +1 -1
  8. package/dist/build/pages-client-assets-module.d.ts +11 -0
  9. package/dist/build/pages-client-assets-module.js +27 -0
  10. package/dist/build/prerender-server-entry.d.ts +1 -0
  11. package/dist/build/prerender-server-entry.js +49 -0
  12. package/dist/build/prerender-server-pool.d.ts +44 -0
  13. package/dist/build/prerender-server-pool.js +194 -0
  14. package/dist/build/prerender.d.ts +2 -1
  15. package/dist/build/prerender.js +98 -27
  16. package/dist/build/report.d.ts +13 -2
  17. package/dist/build/report.js +99 -2
  18. package/dist/build/run-prerender.d.ts +7 -0
  19. package/dist/build/run-prerender.js +12 -2
  20. package/dist/build/standalone.js +2 -0
  21. package/dist/cache/cache-adapters-virtual.js +3 -3
  22. package/dist/check.d.ts +4 -6
  23. package/dist/check.js +48 -11
  24. package/dist/cli-args.d.ts +1 -2
  25. package/dist/cli-args.js +1 -1
  26. package/dist/cli-dev-config.d.ts +12 -0
  27. package/dist/cli-dev-config.js +23 -0
  28. package/dist/cli.js +112 -96
  29. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  30. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  31. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  32. package/dist/{server → client}/dev-error-overlay.js +2 -2
  33. package/dist/client/navigation-runtime.d.ts +2 -0
  34. package/dist/client/navigation-runtime.js +3 -1
  35. package/dist/client/vinext-next-data.d.ts +4 -1
  36. package/dist/client/window-next.d.ts +2 -1
  37. package/dist/cloudflare/index.d.ts +2 -2
  38. package/dist/cloudflare/index.js +2 -2
  39. package/dist/config/config-matchers.js +45 -19
  40. package/dist/config/next-config.d.ts +41 -9
  41. package/dist/config/next-config.js +60 -3
  42. package/dist/config/prerender.d.ts +34 -0
  43. package/dist/config/prerender.js +55 -0
  44. package/dist/entries/app-browser-entry.js +5 -1
  45. package/dist/entries/app-rsc-entry.d.ts +5 -3
  46. package/dist/entries/app-rsc-entry.js +44 -10
  47. package/dist/entries/app-rsc-manifest.js +2 -0
  48. package/dist/entries/pages-client-entry.d.ts +3 -0
  49. package/dist/entries/pages-client-entry.js +28 -3
  50. package/dist/entries/pages-server-entry.js +23 -6
  51. package/dist/image/image-adapters-virtual.d.ts +59 -0
  52. package/dist/image/image-adapters-virtual.js +59 -0
  53. package/dist/index.d.ts +33 -0
  54. package/dist/index.js +482 -120
  55. package/dist/init-cloudflare.d.ts +43 -0
  56. package/dist/init-cloudflare.js +839 -0
  57. package/dist/init-platform.d.ts +40 -0
  58. package/dist/init-platform.js +195 -0
  59. package/dist/init.d.ts +16 -38
  60. package/dist/init.js +209 -99
  61. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  62. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  63. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  64. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  65. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +9 -2
  66. package/dist/packages/cloudflare/src/deploy-config.js +150 -0
  67. package/dist/packages/cloudflare/src/deploy-help.js +55 -0
  68. package/dist/packages/cloudflare/src/deploy.js +272 -0
  69. package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
  70. package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +44 -20
  71. package/dist/plugins/ast-scope.d.ts +16 -0
  72. package/dist/plugins/ast-scope.js +62 -0
  73. package/dist/plugins/ast-utils.d.ts +27 -1
  74. package/dist/plugins/ast-utils.js +32 -1
  75. package/dist/plugins/css-module-imports.d.ts +14 -0
  76. package/dist/plugins/css-module-imports.js +59 -0
  77. package/dist/plugins/extensionless-dynamic-import.js +2 -2
  78. package/dist/plugins/fonts.js +1 -1
  79. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  80. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  81. package/dist/plugins/og-assets.js +2 -1
  82. package/dist/plugins/optimize-imports.js +1 -1
  83. package/dist/plugins/rsc-reference-validation-normalizer.d.ts +12 -0
  84. package/dist/plugins/rsc-reference-validation-normalizer.js +48 -0
  85. package/dist/plugins/sass.d.ts +17 -1
  86. package/dist/plugins/sass.js +74 -1
  87. package/dist/plugins/styled-jsx.d.ts +16 -0
  88. package/dist/plugins/styled-jsx.js +149 -0
  89. package/dist/plugins/typeof-window.d.ts +1 -1
  90. package/dist/plugins/typeof-window.js +28 -56
  91. package/dist/routing/app-route-graph.d.ts +23 -2
  92. package/dist/routing/app-route-graph.js +138 -38
  93. package/dist/routing/file-matcher.d.ts +11 -1
  94. package/dist/routing/file-matcher.js +18 -3
  95. package/dist/routing/pages-router.js +2 -2
  96. package/dist/server/api-handler.js +9 -14
  97. package/dist/server/app-browser-action-result.d.ts +4 -1
  98. package/dist/server/app-browser-action-result.js +8 -1
  99. package/dist/server/app-browser-entry.js +198 -57
  100. package/dist/server/app-browser-interception-context.d.ts +1 -0
  101. package/dist/server/app-browser-interception-context.js +4 -2
  102. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  103. package/dist/server/app-browser-navigation-controller.js +60 -31
  104. package/dist/server/app-browser-server-action-client.d.ts +1 -1
  105. package/dist/server/app-browser-server-action-client.js +8 -7
  106. package/dist/server/app-browser-state.d.ts +12 -1
  107. package/dist/server/app-browser-state.js +25 -8
  108. package/dist/server/app-browser-visible-commit.d.ts +6 -1
  109. package/dist/server/app-browser-visible-commit.js +42 -24
  110. package/dist/server/app-elements-wire.d.ts +9 -2
  111. package/dist/server/app-elements-wire.js +8 -1
  112. package/dist/server/app-elements.d.ts +2 -2
  113. package/dist/server/app-elements.js +4 -3
  114. package/dist/server/app-fallback-renderer.d.ts +2 -1
  115. package/dist/server/app-fallback-renderer.js +10 -6
  116. package/dist/server/app-hydration-cache-publication.d.ts +11 -0
  117. package/dist/server/app-hydration-cache-publication.js +43 -0
  118. package/dist/server/app-middleware.d.ts +4 -3
  119. package/dist/server/app-middleware.js +8 -3
  120. package/dist/server/app-optimistic-routing.js +11 -4
  121. package/dist/server/app-page-boundary.js +2 -1
  122. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  123. package/dist/server/app-page-cache-finalizer.js +5 -4
  124. package/dist/server/app-page-cache-render.d.ts +1 -0
  125. package/dist/server/app-page-cache-render.js +8 -4
  126. package/dist/server/app-page-cache.d.ts +1 -0
  127. package/dist/server/app-page-cache.js +27 -7
  128. package/dist/server/app-page-dispatch.d.ts +1 -0
  129. package/dist/server/app-page-dispatch.js +26 -8
  130. package/dist/server/app-page-element-builder.d.ts +2 -1
  131. package/dist/server/app-page-element-builder.js +59 -4
  132. package/dist/server/app-page-execution.js +2 -1
  133. package/dist/server/app-page-probe.js +5 -0
  134. package/dist/server/app-page-render-identity.d.ts +2 -0
  135. package/dist/server/app-page-render-identity.js +3 -2
  136. package/dist/server/app-page-render.d.ts +2 -0
  137. package/dist/server/app-page-render.js +85 -16
  138. package/dist/server/app-page-request.d.ts +14 -0
  139. package/dist/server/app-page-request.js +69 -4
  140. package/dist/server/app-page-response.d.ts +7 -0
  141. package/dist/server/app-page-response.js +16 -4
  142. package/dist/server/app-page-route-wiring.d.ts +8 -1
  143. package/dist/server/app-page-route-wiring.js +32 -18
  144. package/dist/server/app-page-segment-state.d.ts +2 -1
  145. package/dist/server/app-page-segment-state.js +3 -1
  146. package/dist/server/app-page-stream.d.ts +7 -1
  147. package/dist/server/app-page-stream.js +3 -1
  148. package/dist/server/app-route-handler-execution.js +5 -1
  149. package/dist/server/app-route-handler-response.js +1 -0
  150. package/dist/server/app-route-handler-runtime.js +1 -1
  151. package/dist/server/app-route-tree-prefetch.d.ts +43 -0
  152. package/dist/server/app-route-tree-prefetch.js +187 -0
  153. package/dist/server/app-router-entry.js +9 -2
  154. package/dist/server/app-rsc-cache-busting.d.ts +2 -1
  155. package/dist/server/app-rsc-cache-busting.js +9 -4
  156. package/dist/server/app-rsc-handler.d.ts +7 -0
  157. package/dist/server/app-rsc-handler.js +148 -39
  158. package/dist/server/app-rsc-render-mode.d.ts +3 -2
  159. package/dist/server/app-rsc-render-mode.js +4 -1
  160. package/dist/server/app-rsc-request-normalization.d.ts +6 -6
  161. package/dist/server/app-rsc-request-normalization.js +10 -8
  162. package/dist/server/app-segment-config.d.ts +11 -0
  163. package/dist/server/app-segment-config.js +62 -6
  164. package/dist/server/app-server-action-execution.d.ts +1 -0
  165. package/dist/server/app-server-action-execution.js +61 -30
  166. package/dist/server/app-ssr-entry.d.ts +3 -0
  167. package/dist/server/app-ssr-entry.js +13 -5
  168. package/dist/server/app-ssr-stream.d.ts +7 -3
  169. package/dist/server/app-ssr-stream.js +10 -6
  170. package/dist/server/app-visited-response-cache.d.ts +6 -0
  171. package/dist/server/app-visited-response-cache.js +3 -1
  172. package/dist/server/cache-control.d.ts +3 -1
  173. package/dist/server/cache-control.js +13 -1
  174. package/dist/server/client-trace-metadata.js +26 -0
  175. package/dist/server/default-global-not-found-module.d.ts +14 -0
  176. package/dist/server/default-global-not-found-module.js +14 -0
  177. package/dist/server/dev-route-files.js +4 -0
  178. package/dist/server/dev-server.d.ts +11 -1
  179. package/dist/server/dev-server.js +94 -35
  180. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  181. package/dist/server/dev-stack-sourcemap.js +1 -1
  182. package/dist/server/fetch-handler.d.ts +2 -0
  183. package/dist/server/fetch-handler.js +18 -0
  184. package/dist/server/headers.d.ts +7 -15
  185. package/dist/server/headers.js +11 -18
  186. package/dist/server/image-optimization.d.ts +51 -1
  187. package/dist/server/image-optimization.js +52 -2
  188. package/dist/server/implicit-tags.js +1 -1
  189. package/dist/server/isr-cache.d.ts +3 -2
  190. package/dist/server/isr-cache.js +9 -5
  191. package/dist/server/metadata-routes.d.ts +3 -1
  192. package/dist/server/metadata-routes.js +12 -2
  193. package/dist/server/middleware-runtime.js +6 -1
  194. package/dist/server/navigation-planner.d.ts +1 -0
  195. package/dist/server/navigation-planner.js +14 -3
  196. package/dist/server/pages-api-route.js +2 -2
  197. package/dist/server/pages-asset-tags.d.ts +4 -6
  198. package/dist/server/pages-asset-tags.js +12 -12
  199. package/dist/server/pages-client-assets.d.ts +12 -0
  200. package/dist/server/pages-client-assets.js +10 -0
  201. package/dist/server/pages-data-route.d.ts +4 -2
  202. package/dist/server/pages-data-route.js +18 -4
  203. package/dist/server/pages-dev-module-url.d.ts +2 -1
  204. package/dist/server/pages-dev-module-url.js +6 -3
  205. package/dist/server/pages-node-compat.d.ts +19 -1
  206. package/dist/server/pages-node-compat.js +81 -4
  207. package/dist/server/pages-page-data.d.ts +33 -1
  208. package/dist/server/pages-page-data.js +62 -33
  209. package/dist/server/pages-page-handler.d.ts +2 -1
  210. package/dist/server/pages-page-handler.js +38 -19
  211. package/dist/server/pages-page-response.d.ts +8 -0
  212. package/dist/server/pages-page-response.js +7 -3
  213. package/dist/server/pages-request-pipeline.d.ts +9 -5
  214. package/dist/server/pages-request-pipeline.js +55 -7
  215. package/dist/server/pages-router-entry.d.ts +30 -0
  216. package/dist/server/pages-router-entry.js +108 -0
  217. package/dist/server/prerender-manifest.d.ts +3 -1
  218. package/dist/server/prerender-route-params.js +1 -1
  219. package/dist/server/prod-server.d.ts +5 -3
  220. package/dist/server/prod-server.js +68 -39
  221. package/dist/server/request-pipeline.js +2 -1
  222. package/dist/server/seed-cache.js +4 -4
  223. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  224. package/dist/shims/app-router-scroll-state.js +1 -0
  225. package/dist/shims/app-router-scroll.js +2 -1
  226. package/dist/shims/cache-handler.js +8 -1
  227. package/dist/shims/cache.js +22 -15
  228. package/dist/shims/cdn-cache.js +1 -1
  229. package/dist/shims/dynamic-preload-chunks.js +2 -1
  230. package/dist/shims/fetch-cache.d.ts +3 -1
  231. package/dist/shims/fetch-cache.js +77 -52
  232. package/dist/shims/form.d.ts +4 -2
  233. package/dist/shims/form.js +37 -43
  234. package/dist/shims/headers.d.ts +7 -1
  235. package/dist/shims/headers.js +17 -3
  236. package/dist/shims/image.js +75 -14
  237. package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +10 -0
  238. package/dist/shims/internal/app-prefetch-fetch-queue.js +61 -0
  239. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  240. package/dist/shims/internal/app-route-detection.js +4 -17
  241. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  242. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  243. package/dist/shims/internal/hybrid-client-route-owner.d.ts +3 -15
  244. package/dist/shims/internal/hybrid-client-route-owner.js +40 -58
  245. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +10 -5
  246. package/dist/shims/internal/pages-data-fetch-dedup.js +84 -14
  247. package/dist/shims/internal/pages-data-target.d.ts +18 -12
  248. package/dist/shims/internal/pages-data-target.js +97 -13
  249. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  250. package/dist/shims/internal/pages-router-components.js +13 -0
  251. package/dist/shims/layout-segment-context.d.ts +4 -1
  252. package/dist/shims/layout-segment-context.js +18 -4
  253. package/dist/shims/link.d.ts +1 -1
  254. package/dist/shims/link.js +224 -58
  255. package/dist/shims/navigation.d.ts +19 -3
  256. package/dist/shims/navigation.js +245 -47
  257. package/dist/shims/request-context.js +18 -0
  258. package/dist/shims/root-params.d.ts +15 -1
  259. package/dist/shims/root-params.js +21 -1
  260. package/dist/shims/router.d.ts +5 -7
  261. package/dist/shims/router.js +387 -102
  262. package/dist/shims/server.js +3 -2
  263. package/dist/shims/slot.js +3 -6
  264. package/dist/shims/unified-request-context.js +1 -0
  265. package/dist/typegen.js +1 -1
  266. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  267. package/dist/utils/client-runtime-metadata.js +31 -22
  268. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  269. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  270. package/dist/utils/domain-locale.d.ts +6 -3
  271. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  272. package/dist/{server → utils}/middleware-request-headers.js +3 -3
  273. package/dist/utils/project.d.ts +48 -2
  274. package/dist/utils/project.js +225 -4
  275. package/dist/utils/protocol-headers.d.ts +23 -0
  276. package/dist/utils/protocol-headers.js +23 -0
  277. package/dist/utils/react-version.d.ts +4 -0
  278. package/dist/utils/react-version.js +44 -0
  279. package/dist/utils/vite-version.d.ts +2 -0
  280. package/dist/utils/vite-version.js +11 -1
  281. package/package.json +47 -2
  282. package/dist/deploy.d.ts +0 -197
  283. package/dist/deploy.js +0 -1040
  284. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  285. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+
3
+ //#region src/server/default-global-not-found-module.d.ts
4
+ declare function DefaultGlobalNotFound(): React.ReactElement;
5
+ /**
6
+ * Module-shaped wrapper around Next.js's built-in global not-found document.
7
+ * Unlike the regular default not-found boundary, this component owns the
8
+ * document shell because global not-found responses skip the root layout.
9
+ */
10
+ declare const DEFAULT_GLOBAL_NOT_FOUND_MODULE: {
11
+ readonly default: typeof DefaultGlobalNotFound;
12
+ };
13
+ //#endregion
14
+ export { DEFAULT_GLOBAL_NOT_FOUND_MODULE };
@@ -0,0 +1,14 @@
1
+ import DefaultNotFound from "../shims/default-not-found.js";
2
+ import React from "react";
3
+ //#region src/server/default-global-not-found-module.ts
4
+ function DefaultGlobalNotFound() {
5
+ return React.createElement("html", null, React.createElement("body", null, React.createElement(DefaultNotFound)));
6
+ }
7
+ /**
8
+ * Module-shaped wrapper around Next.js's built-in global not-found document.
9
+ * Unlike the regular default not-found boundary, this component owns the
10
+ * document shell because global not-found responses skip the root layout.
11
+ */
12
+ const DEFAULT_GLOBAL_NOT_FOUND_MODULE = { default: DefaultGlobalNotFound };
13
+ //#endregion
14
+ export { DEFAULT_GLOBAL_NOT_FOUND_MODULE };
@@ -48,6 +48,10 @@ function isRootGlobalError(parts, matcher) {
48
48
  function isMetadataRouteFile(parts) {
49
49
  const fileName = parts[parts.length - 1];
50
50
  if (!fileName) return false;
51
+ if (fileName.endsWith(".alt.txt")) {
52
+ const imageBaseName = fileName.slice(0, -8);
53
+ return matchMetadataFileBaseName("opengraph-image", imageBaseName) !== null || matchMetadataFileBaseName("twitter-image", imageBaseName) !== null;
54
+ }
51
55
  const { baseName, extension } = stripLastExtension(fileName);
52
56
  if (!extension) return false;
53
57
  const routePrefix = visibleRoutePrefix(parts);
@@ -43,7 +43,17 @@ declare function createSSRHandler(server: ViteDevServer, runner: ModuleImporter,
43
43
  * `next.config`. When undefined or empty, no meta tags are emitted.
44
44
  */
45
45
 
46
- clientTraceMetadata?: readonly string[], htmlLimitedBots?: string): (req: IncomingMessage, res: ServerResponse, url: string, /** Status code override — propagated from middleware rewrite status. */
46
+ clientTraceMetadata?: readonly string[], htmlLimitedBots?: string,
47
+ /**
48
+ * Whether `reactStrictMode: true` is set in next.config. When true, the dev
49
+ * hydration script sets `window.__VINEXT_REACT_STRICT_MODE__` so
50
+ * `wrapWithRouterContext` wraps the tree in `<React.StrictMode>` on the
51
+ * initial hydration and every navigation. Pages Router default is OFF
52
+ * (Next.js: `reactStrictMode === null ? false`), so callers pass
53
+ * `nextConfig?.reactStrictMode === true`.
54
+ */
55
+
56
+ reactStrictMode?: boolean): (req: IncomingMessage, res: ServerResponse, url: string, /** Status code override — propagated from middleware rewrite status. */
47
57
 
48
58
  statusCode?: number,
49
59
  /**
@@ -1,9 +1,8 @@
1
1
  import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
2
- import { createValidFileMatcher, findFileWithExtensions } from "../routing/file-matcher.js";
2
+ import { createValidFileMatcher, findFileWithExtensions, findFileWithExts } from "../routing/file-matcher.js";
3
3
  import { patternToNextFormat } from "../routing/route-validation.js";
4
4
  import { matchRoute } from "../routing/pages-router.js";
5
5
  import { NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
6
- import { normalizeStaticPathname } from "../routing/route-pattern.js";
7
6
  import { importModule, reportRequestError } from "./instrumentation.js";
8
7
  import { buildCacheStateHeaders } from "./cache-headers.js";
9
8
  import { isUnknownRecord } from "../utils/record.js";
@@ -18,7 +17,7 @@ import "../shims/router-state.js";
18
17
  import { runWithHeadState } from "../shims/head-state.js";
19
18
  import { runWithServerInsertedHTMLState } from "../shims/navigation-state.js";
20
19
  import { withScriptNonce } from "../shims/script-nonce-context.js";
21
- import { createInlineScriptTag, createNonceAttribute, safeJsonStringify } from "./html.js";
20
+ import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr, safeJsonStringify } from "./html.js";
22
21
  import { getClientTraceMetadataHTML } from "./client-trace-metadata.js";
23
22
  import { getScriptNonceFromNodeHeaderSources } from "./csp.js";
24
23
  import { logRequest, now } from "./request-log.js";
@@ -26,12 +25,15 @@ import { detectLocaleFromAcceptLanguage, extractLocaleFromUrl as extractLocaleFr
26
25
  import { buildDefaultPagesNotFoundResponse } from "./pages-default-404.js";
27
26
  import { buildPagesReadinessNextData } from "./pages-readiness.js";
28
27
  import { resolvePagesPageMethodResponse } from "./pages-page-method.js";
29
- import { createPagesDevModuleUrl } from "./pages-dev-module-url.js";
30
- import { isSerializableProps } from "./pages-serializable-props.js";
31
28
  import { loadUserDocumentInitialProps, runDocumentRenderPage } from "./pages-document-initial-props.js";
32
29
  import { callDocumentGetInitialProps } from "./document-initial-head.js";
33
30
  import { hasPagesGetInitialProps, loadDevAppInitialProps, loadPagesGetInitialProps } from "./pages-get-initial-props.js";
31
+ import { isSerializableProps } from "./pages-serializable-props.js";
34
32
  import { isBotUserAgent } from "../utils/html-limited-bots.js";
33
+ import { getPagesRouteParams, matchesPagesStaticPath } from "./pages-page-data.js";
34
+ import { createPagesDevAssetUrl, createPagesDevModuleUrl } from "./pages-dev-module-url.js";
35
+ import { getManifestFilesForModule } from "./pages-asset-tags.js";
36
+ import { attachPagesRequestCookies, getPagesPreviewDataFromCookieHeader } from "./pages-node-compat.js";
35
37
  import path from "node:path";
36
38
  import React from "react";
37
39
  import { renderToReadableStream } from "react-dom/server.edge";
@@ -51,6 +53,35 @@ async function renderToStringAsync(element) {
51
53
  async function renderIsrPassToStringAsync(element) {
52
54
  return await runWithServerInsertedHTMLState(() => runWithHeadState(() => _runWithCacheState(() => runWithPrivateCache(() => runWithFetchCache(async () => renderToStringAsync(element))))));
53
55
  }
56
+ const DEV_STYLESHEET_ASSET_RE = /\.(?:css|scss|sass)$/i;
57
+ function createDevInitialStylesheetHeadHTML(options) {
58
+ const { ssrManifest, moduleIds, nonceAttr } = options;
59
+ if (!ssrManifest || moduleIds.length === 0) return "";
60
+ const seen = /* @__PURE__ */ new Set();
61
+ let html = "";
62
+ for (const moduleId of moduleIds) {
63
+ const files = getManifestFilesForModule(ssrManifest, moduleId);
64
+ if (!files) continue;
65
+ for (const file of files) {
66
+ if (!DEV_STYLESHEET_ASSET_RE.test(file) || seen.has(file)) continue;
67
+ seen.add(file);
68
+ const href = createPagesDevAssetUrl(file);
69
+ html += `<link rel="stylesheet"${nonceAttr} href="${escapeHtmlAttr(href)}" />\n `;
70
+ }
71
+ }
72
+ return html;
73
+ }
74
+ async function collectDevInitialStylesheetHeadHTML(runner, moduleIds, nonceAttr) {
75
+ try {
76
+ return createDevInitialStylesheetHeadHTML({
77
+ ssrManifest: (await runner.import("virtual:vinext-pages-client-assets")).default?.ssrManifest,
78
+ moduleIds,
79
+ nonceAttr
80
+ });
81
+ } catch {
82
+ return "";
83
+ }
84
+ }
54
85
  /**
55
86
  * Emit a `getServerSideProps` / `getStaticProps` `{ redirect }` result.
56
87
  *
@@ -101,7 +132,7 @@ const STREAM_BODY_MARKER = "<!--VINEXT_STREAM_BODY-->";
101
132
  * shell sooner).
102
133
  */
103
134
  async function streamPageToResponse(res, element, options) {
104
- const { url, server, fontHeadHTML, scripts, DocumentComponent, statusCode = 200, extraHeaders, getHeadHTML, enhancePageElement, scriptNonce, documentContext, setDocumentInitialHead, bufferBodyBeforeHeaders = false } = options;
135
+ const { url, server, fontHeadHTML, assetHeadHTML = "", scripts, DocumentComponent, statusCode, extraHeaders, getHeadHTML, enhancePageElement, scriptNonce, documentContext, setDocumentInitialHead, bufferBodyBeforeHeaders = false } = options;
105
136
  const documentRenderPage = await runDocumentRenderPage({
106
137
  DocumentComponent,
107
138
  enhancePageElement,
@@ -110,6 +141,7 @@ async function streamPageToResponse(res, element, options) {
110
141
  scriptNonce,
111
142
  context: documentContext
112
143
  });
144
+ if (res.headersSent || res.writableEnded) return;
113
145
  let bodyStream;
114
146
  if (documentRenderPage.status === "rendered") {
115
147
  const synthesised = documentRenderPage.bodyHtml;
@@ -127,7 +159,7 @@ async function streamPageToResponse(res, element, options) {
127
159
  const docProps = documentRenderPage.status === "skipped" ? await loadUserDocumentInitialProps(DocumentComponent) : documentRenderPage.docProps;
128
160
  let docHtml = await renderToStringAsync(docProps ? React.createElement(DocumentComponent, docProps) : React.createElement(DocumentComponent));
129
161
  docHtml = docHtml.replace("__NEXT_MAIN__", STREAM_BODY_MARKER);
130
- if (headHTML || fontHeadHTML) docHtml = docHtml.replace("</head>", ` ${fontHeadHTML}${headHTML}\n</head>`);
162
+ if (headHTML || fontHeadHTML || assetHeadHTML) docHtml = docHtml.replace("</head>", ` ${fontHeadHTML}${headHTML}\n ${assetHeadHTML}\n</head>`);
131
163
  docHtml = docHtml.replace("<!-- __NEXT_SCRIPTS__ -->", scripts);
132
164
  if (!docHtml.includes("__NEXT_DATA__")) docHtml = docHtml.replace("</body>", ` ${scripts}\n</body>`);
133
165
  shellTemplate = docHtml;
@@ -135,6 +167,7 @@ async function streamPageToResponse(res, element, options) {
135
167
  <html>
136
168
  <head>
137
169
  ${fontHeadHTML}${headHTML}
170
+ ${assetHeadHTML}
138
171
  </head>
139
172
  <body>
140
173
  <div id="__next">${STREAM_BODY_MARKER}</div>
@@ -152,7 +185,7 @@ async function streamPageToResponse(res, element, options) {
152
185
  };
153
186
  if (extraHeaders) for (const [key, val] of Object.entries(extraHeaders)) if (Array.isArray(val)) res.setHeader(key, val);
154
187
  else headers[key] = val;
155
- res.writeHead(statusCode, headers);
188
+ res.writeHead(statusCode ?? res.statusCode, headers);
156
189
  res.write(prefix);
157
190
  if (bufferedBody !== null) {
158
191
  res.end(bufferedBody + suffix);
@@ -202,7 +235,7 @@ function parseCookieLocale(req, i18nConfig) {
202
235
  * 4. Render the component to HTML
203
236
  * 5. Wrap in _document shell and send response
204
237
  */
205
- function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatcher, basePath = "", trailingSlash = false, hasMiddleware = false, hasRewrites = false, clientTraceMetadata, htmlLimitedBots) {
238
+ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatcher, basePath = "", trailingSlash = false, hasMiddleware = false, hasRewrites = false, clientTraceMetadata, htmlLimitedBots, reactStrictMode = false) {
206
239
  const matcher = fileMatcher ?? createValidFileMatcher();
207
240
  const pagePatterns = routes.map((r) => patternToNextFormat(r.pattern));
208
241
  const _alsRegistration = Promise.all([runner.import("vinext/head-state"), runner.import("vinext/router-state")]);
@@ -211,6 +244,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
211
244
  const _reqStart = now();
212
245
  let _compileEnd;
213
246
  let _renderEnd;
247
+ attachPagesRequestCookies(req);
214
248
  res.on("finish", () => {
215
249
  const totalMs = now() - _reqStart;
216
250
  const compileMs = _compileEnd !== void 0 ? Math.round(_compileEnd - _reqStart) : void 0;
@@ -248,8 +282,9 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
248
282
  if (isDataReq) {
249
283
  const deploymentId = process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID;
250
284
  const notFoundHeaders = { "Content-Type": "application/json" };
285
+ if (hasMiddleware) notFoundHeaders["x-nextjs-matched-path"] = `${locale ? `/${locale}` : ""}${localeStrippedUrl}`;
251
286
  if (deploymentId) notFoundHeaders[NEXTJS_DEPLOYMENT_ID_HEADER] = deploymentId;
252
- res.writeHead(404, notFoundHeaders);
287
+ res.writeHead(hasMiddleware ? 200 : 404, notFoundHeaders);
253
288
  res.end("{}");
254
289
  return;
255
290
  }
@@ -333,6 +368,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
333
368
  let isrRevalidateSeconds = null;
334
369
  let isFallbackRender = false;
335
370
  let shouldPersistFallbackData = false;
371
+ let staticPropsPreviewData = false;
336
372
  if (typeof pageModule.getStaticPaths === "function" && route.isDynamic) {
337
373
  const pathsResult = await pageModule.getStaticPaths({
338
374
  locales: i18nConfig?.locales ?? [],
@@ -340,17 +376,8 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
340
376
  });
341
377
  const fallback = pathsResult?.fallback ?? false;
342
378
  const paths = pathsResult?.paths ?? [];
343
- const currentPathname = normalizeStaticPathname(url);
344
- const isValidPath = paths.some((p) => {
345
- if (typeof p === "string") return normalizeStaticPathname(p) === currentPathname;
346
- const entryParams = p.params;
347
- if (entryParams === void 0 || entryParams === null) return false;
348
- return Object.entries(entryParams).every(([key, val]) => {
349
- const actual = params[key];
350
- if (Array.isArray(val)) return Array.isArray(actual) && val.join("/") === actual.join("/");
351
- return String(val) === String(actual);
352
- });
353
- });
379
+ const routeParams = getPagesRouteParams(patternToNextFormat(route.pattern));
380
+ const isValidPath = paths.some((pathEntry) => matchesPagesStaticPath(pathEntry, params, routeParams, url));
354
381
  if (fallback === false && !isValidPath) {
355
382
  if (isDataReq) {
356
383
  const deploymentId = process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID;
@@ -421,6 +448,12 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
421
448
  __N_SSP: true
422
449
  };
423
450
  const headersBeforeGSSP = new Set(Object.keys(res.getHeaders()));
451
+ const previewData = getPagesPreviewDataFromCookieHeader(req.headers.cookie);
452
+ const previewContext = previewData === false ? {} : {
453
+ draftMode: true,
454
+ preview: true,
455
+ previewData
456
+ };
424
457
  const context = {
425
458
  params: userFacingParams,
426
459
  req,
@@ -429,7 +462,8 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
429
462
  resolvedUrl: gsspResolvedUrl,
430
463
  locale: locale ?? currentDefaultLocale,
431
464
  locales: i18nConfig?.locales,
432
- defaultLocale: currentDefaultLocale
465
+ defaultLocale: currentDefaultLocale,
466
+ ...previewContext
433
467
  };
434
468
  const result = await pageModule.getServerSideProps(context);
435
469
  if (res.writableEnded) return;
@@ -485,7 +519,14 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
485
519
  const cacheKey = pagesIsrCacheKey(url.split("?")[0]);
486
520
  const cached = await isrGet(cacheKey);
487
521
  const isOnDemandRevalidate = isOnDemandRevalidateRequest(req.headers[PRERENDER_REVALIDATE_HEADER]);
488
- if (!isOnDemandRevalidate && cached && !cached.isStale && cached.value.value?.kind === "PAGES" && !cached.value.value.generatedFromDataRequest && !scriptNonce && !isDataReq) {
522
+ const previewData = getPagesPreviewDataFromCookieHeader(req.headers.cookie, { isOnDemandRevalidate });
523
+ staticPropsPreviewData = previewData;
524
+ const previewContext = previewData === false ? {} : {
525
+ draftMode: true,
526
+ preview: true,
527
+ previewData
528
+ };
529
+ if (!isOnDemandRevalidate && cached && !cached.isStale && cached.value.value?.kind === "PAGES" && !cached.value.value.generatedFromDataRequest && !scriptNonce && !isDataReq && previewData === false) {
489
530
  const cachedHtml = cached.value.value.html;
490
531
  const transformedHtml = await server.transformIndexHtml(url, cachedHtml);
491
532
  const { cacheControl: hitCacheControl } = decideIsr({
@@ -503,7 +544,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
503
544
  res.end(transformedHtml);
504
545
  return;
505
546
  }
506
- if (!isOnDemandRevalidate && cached && cached.isStale && cached.value.value?.kind === "PAGES" && !cached.value.value.generatedFromDataRequest && !scriptNonce && !isDataReq) {
547
+ if (!isOnDemandRevalidate && cached && cached.isStale && cached.value.value?.kind === "PAGES" && !cached.value.value.generatedFromDataRequest && !scriptNonce && !isDataReq && previewData === false) {
507
548
  const cachedHtml = cached.value.value.html;
508
549
  const transformedHtml = await server.transformIndexHtml(url, cachedHtml);
509
550
  triggerBackgroundRegeneration(cacheKey, async () => {
@@ -682,9 +723,10 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
682
723
  locale: locale ?? currentDefaultLocale,
683
724
  locales: i18nConfig?.locales,
684
725
  defaultLocale: currentDefaultLocale,
685
- revalidateReason: isOnDemandRevalidate ? "on-demand" : "stale"
726
+ revalidateReason: isOnDemandRevalidate ? "on-demand" : "stale",
727
+ ...previewContext
686
728
  };
687
- const generatedPageData = !isOnDemandRevalidate && cached?.isStale === false && cached?.value.value?.kind === "PAGES" && cached.value.value.generatedFromDataRequest && isUnknownRecord(cached.value.value.pageData) ? cached.value.value.pageData : null;
729
+ const generatedPageData = !isOnDemandRevalidate && previewData === false && cached?.isStale === false && cached?.value.value?.kind === "PAGES" && cached.value.value.generatedFromDataRequest && isUnknownRecord(cached.value.value.pageData) ? cached.value.value.pageData : null;
688
730
  if (!generatedPageData && await loadAppInitialProps()) return;
689
731
  const result = generatedPageData ? null : await pageModule.getStaticProps(context);
690
732
  if (generatedPageData) {
@@ -718,8 +760,8 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
718
760
  return;
719
761
  }
720
762
  if (result && "props" in result) isSerializableProps(patternToNextFormat(route.pattern), "getStaticProps", pageProps);
721
- if (typeof result?.revalidate === "number" && result.revalidate > 0) isrRevalidateSeconds = result.revalidate;
722
- else if (cached?.value.value?.kind === "PAGES" && cached.value.value.generatedFromDataRequest) isrRevalidateSeconds = cached.value.cacheControl?.revalidate ?? 31536e3;
763
+ if (previewData === false && typeof result?.revalidate === "number" && result.revalidate > 0) isrRevalidateSeconds = result.revalidate;
764
+ else if (previewData === false && cached?.value.value?.kind === "PAGES" && cached.value.value.generatedFromDataRequest) isrRevalidateSeconds = cached.value.cacheControl?.revalidate ?? 31536e3;
723
765
  }
724
766
  if (typeof pageModule.getServerSideProps !== "function" && typeof pageModule.getStaticProps !== "function" && hasAppGetInitialProps) {
725
767
  if (await loadAppInitialProps()) return;
@@ -748,7 +790,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
748
790
  }
749
791
  }
750
792
  if (isDataReq) {
751
- if (shouldPersistFallbackData) {
793
+ if (shouldPersistFallbackData && staticPropsPreviewData === false) {
752
794
  const cacheKey = pagesIsrCacheKey(url.split("?")[0]);
753
795
  const revalidateSeconds = isrRevalidateSeconds ?? 31536e3;
754
796
  await isrSet(cacheKey, {
@@ -762,6 +804,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
762
804
  setRevalidateDuration(cacheKey, revalidateSeconds);
763
805
  }
764
806
  const dataHeaders = { "Content-Type": "application/json" };
807
+ if ((statusCode ?? 200) === 200) dataHeaders["x-nextjs-matched-path"] = `${locale ? `/${locale}` : ""}${patternToNextFormat(route.pattern)}`;
765
808
  if (gsspExtraHeaders) for (const [k, v] of Object.entries(gsspExtraHeaders)) dataHeaders[k] = v;
766
809
  const dataRoutePattern = patternToNextFormat(route.pattern);
767
810
  if (dataRoutePattern !== "/_error" && dataRoutePattern !== "/500") {
@@ -790,6 +833,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
790
833
  if (typeof dynamicShim.flushPreloads === "function") await dynamicShim.flushPreloads();
791
834
  const nonceAttr = createNonceAttribute(scriptNonce);
792
835
  let fontHeadHTML = "";
836
+ const assetHeadHTML = await collectDevInitialStylesheetHeadHTML(runner, [AppComponent ? findFileWithExts(pagesDir, "_app", matcher) : null, route.filePath], nonceAttr);
793
837
  const allFontStyles = [];
794
838
  const allFontPreloads = [];
795
839
  try {
@@ -851,6 +895,9 @@ const rawPageProps = props.pageProps;
851
895
  const pageProps = rawPageProps && typeof rawPageProps === "object" ? rawPageProps : {};
852
896
  window.__VINEXT_PAGE_LOADERS__ = { [nextData.page]: () => import("${pageModuleSource}") };
853
897
  window.__VINEXT_APP_LOADER__ = ${appModuleSource ? `() => import("${appModuleSource}")` : "undefined"};
898
+ // reactStrictMode flag — read by wrapWithRouterContext so the <React.StrictMode>
899
+ // wrap is applied on initial hydration and every navigation (matches Next.js).
900
+ window.__VINEXT_REACT_STRICT_MODE__ = ${JSON.stringify(reactStrictMode === true)};
854
901
 
855
902
  async function hydrate() {
856
903
  let hydrateRootOptions;
@@ -927,6 +974,7 @@ hydrate();
927
974
  url,
928
975
  server,
929
976
  fontHeadHTML,
977
+ assetHeadHTML,
930
978
  scripts: allScripts,
931
979
  DocumentComponent,
932
980
  statusCode,
@@ -935,7 +983,11 @@ hydrate();
935
983
  documentContext: {
936
984
  pathname: patternToNextFormat(route.pattern),
937
985
  query,
938
- asPath: requestAsPath
986
+ asPath: requestAsPath,
987
+ ...pagesNextData.autoExport === true ? {} : {
988
+ req,
989
+ res
990
+ }
939
991
  },
940
992
  enhancePageElement: (renderPageOpts) => {
941
993
  let FinalApp = AppComponent;
@@ -969,7 +1021,7 @@ hydrate();
969
1021
  pageProps
970
1022
  }) : createElement(pageModule.default, pageProps);
971
1023
  if (wrapWithRouterContext) isrElement = wrapWithRouterContext(isrElement);
972
- const isrHtml = `<!DOCTYPE html><html><head></head><body><div id="__next">${await renderIsrPassToStringAsync(withScriptNonce(isrElement, scriptNonce))}</div>${allScripts}</body></html>`;
1024
+ const isrHtml = `<!DOCTYPE html><html><head>${assetHeadHTML}</head><body><div id="__next">${await renderIsrPassToStringAsync(withScriptNonce(isrElement, scriptNonce))}</div>${allScripts}</body></html>`;
973
1025
  const cacheKey = pagesIsrCacheKey(url.split("?")[0]);
974
1026
  await isrSet(cacheKey, buildPagesCacheValue(isrHtml, pageProps), isrRevalidateSeconds);
975
1027
  setRevalidateDuration(cacheKey, isrRevalidateSeconds);
@@ -1004,17 +1056,19 @@ hydrate();
1004
1056
  * - other: pages/_error.tsx -> default
1005
1057
  */
1006
1058
  async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCode, wrapWithRouterContext, fileMatcher, err) {
1059
+ attachPagesRequestCookies(req);
1007
1060
  const matcher = fileMatcher ?? createValidFileMatcher();
1008
1061
  const candidates = statusCode === 404 ? ["404", "_error"] : statusCode === 500 ? ["500", "_error"] : ["_error"];
1009
1062
  for (const candidate of candidates) try {
1010
- const candidatePath = path.join(pagesDir, candidate);
1011
- if (!findFileWithExtensions(candidatePath, matcher)) continue;
1012
- const ErrorComponent = (await importModule(runner, candidatePath)).default;
1063
+ const errorAssetPath = findFileWithExts(pagesDir, candidate, matcher);
1064
+ if (!errorAssetPath) continue;
1065
+ const ErrorComponent = (await importModule(runner, errorAssetPath)).default;
1013
1066
  if (!ErrorComponent) continue;
1014
1067
  let AppComponent = null;
1015
1068
  const appPathErr = path.join(pagesDir, "_app");
1069
+ const appAssetPath = findFileWithExts(pagesDir, "_app", matcher);
1016
1070
  if (findFileWithExtensions(appPathErr, matcher)) try {
1017
- AppComponent = (await importModule(runner, appPathErr)).default ?? null;
1071
+ AppComponent = (await importModule(runner, appAssetPath ?? appPathErr)).default ?? null;
1018
1072
  } catch {}
1019
1073
  const createElement = React.createElement;
1020
1074
  const initialErrorProps = await loadPagesGetInitialProps(ErrorComponent, {
@@ -1050,12 +1104,16 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
1050
1104
  const element = createErrorElement(AppComponent, ErrorComponent);
1051
1105
  const headShim = await importModule(runner, "next/head");
1052
1106
  if (typeof headShim.resetSSRHead === "function") headShim.resetSSRHead();
1107
+ const responseHeaders = typeof res.getHeaders === "function" ? res.getHeaders() : void 0;
1108
+ const nonceAttr = createNonceAttribute(getScriptNonceFromNodeHeaderSources(req.headers, responseHeaders));
1109
+ const assetHeadHTML = await collectDevInitialStylesheetHeadHTML(runner, [appAssetPath, errorAssetPath], nonceAttr);
1053
1110
  if (DocumentComponent) {
1054
1111
  const errorPathname = candidate === "_error" ? "/_error" : `/${candidate}`;
1055
1112
  await streamPageToResponse(res, element, {
1056
1113
  url,
1057
1114
  server,
1058
1115
  fontHeadHTML: "",
1116
+ assetHeadHTML,
1059
1117
  scripts: "",
1060
1118
  DocumentComponent,
1061
1119
  statusCode,
@@ -1083,6 +1141,7 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
1083
1141
  <head>
1084
1142
  <meta charset="utf-8" />
1085
1143
  <meta name="viewport" content="width=device-width, initial-scale=1" />
1144
+ ${assetHeadHTML}
1086
1145
  </head>
1087
1146
  <body>
1088
1147
  <div id="__next">${await renderToStringAsync(element)}</div>
@@ -1,4 +1,4 @@
1
- import { VINEXT_ORIGINAL_STACK_TRACE_ENDPOINT } from "./dev-stack-sourcemap-endpoint.js";
1
+ import { VINEXT_ORIGINAL_STACK_TRACE_ENDPOINT } from "../utils/dev-stack-sourcemap-endpoint.js";
2
2
  import { ViteDevServer } from "vite";
3
3
 
4
4
  //#region src/server/dev-stack-sourcemap.d.ts
@@ -1,4 +1,4 @@
1
- import { VINEXT_ORIGINAL_STACK_TRACE_ENDPOINT } from "./dev-stack-sourcemap-endpoint.js";
1
+ import { VINEXT_ORIGINAL_STACK_TRACE_ENDPOINT } from "../utils/dev-stack-sourcemap-endpoint.js";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
4
  //#region src/server/dev-stack-sourcemap.ts
@@ -0,0 +1,2 @@
1
+ import handler from "virtual:vinext-worker-entry";
2
+ export { handler as default };
@@ -0,0 +1,18 @@
1
+ import handler from "virtual:vinext-worker-entry";
2
+ //#region src/server/fetch-handler.ts
3
+ /**
4
+ * Default Cloudflare fetch handler for vinext.
5
+ *
6
+ * Use this directly in wrangler.jsonc:
7
+ * "main": "vinext/server/fetch-handler"
8
+ *
9
+ * Or import and delegate to it from a custom worker:
10
+ * import handler from "vinext/server/fetch-handler";
11
+ * return handler.fetch(request, env, ctx);
12
+ *
13
+ * The vinext plugin resolves this to the App Router or Pages Router handler
14
+ * for the current project at build time.
15
+ */
16
+ var fetch_handler_default = handler;
17
+ //#endregion
18
+ export { fetch_handler_default as default };
@@ -1,3 +1,5 @@
1
+ import { MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
2
+
1
3
  //#region src/server/headers.d.ts
2
4
  /**
3
5
  * Internal HTTP header name constants used throughout vinext.
@@ -15,14 +17,8 @@ declare const VINEXT_CACHE_HEADER = "X-Vinext-Cache";
15
17
  declare const NEXTJS_CACHE_HEADER = "x-nextjs-cache";
16
18
  /** Static file signal — value is URL-encoded pathname. */
17
19
  declare const VINEXT_STATIC_FILE_HEADER = "x-vinext-static-file";
18
- /** Serialized middleware context (JSON) forwarded from dev server to RSC entry. */
19
- declare const VINEXT_MW_CTX_HEADER = "x-vinext-mw-ctx";
20
20
  /** Timing metrics: `handlerStart,compileMs,renderMs`. */
21
21
  declare const VINEXT_TIMING_HEADER = "x-vinext-timing";
22
- /** Build-time prerender authentication secret. */
23
- declare const VINEXT_PRERENDER_SECRET_HEADER = "x-vinext-prerender-secret";
24
- /** URL-encoded JSON route params for build-time prerender renders. */
25
- declare const VINEXT_PRERENDER_ROUTE_PARAMS_HEADER = "x-vinext-prerender-route-params";
26
22
  /** Internal endpoint used to evaluate App Router generateStaticParams exports. */
27
23
  declare const VINEXT_PRERENDER_STATIC_PARAMS_PATH = "/__vinext/prerender/static-params";
28
24
  /** Internal endpoint used to evaluate Pages Router getStaticPaths exports. */
@@ -37,6 +33,10 @@ declare const VINEXT_PARAMS_HEADER = "X-Vinext-Params";
37
33
  declare const VINEXT_MOUNTED_SLOTS_HEADER = "X-Vinext-Mounted-Slots";
38
34
  /** Per-page dynamic stale time in seconds for App Router RSC responses. */
39
35
  declare const VINEXT_DYNAMIC_STALE_TIME_HEADER = "X-Vinext-Dynamic-Stale-Time";
36
+ /** URL-encoded rendered path and search after middleware/config rewrites. */
37
+ declare const VINEXT_RENDERED_PATH_AND_SEARCH_HEADER = "X-Vinext-Rendered-Path-And-Search";
38
+ /** Prerender-only JSON side channel carrying request cacheLife metadata. */
39
+ declare const VINEXT_PRERENDER_CACHE_LIFE_HEADER = "x-vinext-prerender-cache-life";
40
40
  /** Route interception context for parallel/intercepting routes. */
41
41
  declare const VINEXT_INTERCEPTION_CONTEXT_HEADER = "X-Vinext-Interception-Context";
42
42
  /** RSC render mode (e.g. "navigation", "prefetch"). */
@@ -81,18 +81,10 @@ declare const ACTION_REDIRECT_HEADER = "x-action-redirect";
81
81
  declare const ACTION_REDIRECT_TYPE_HEADER = "x-action-redirect-type";
82
82
  /** HTTP status for a Server Action redirect (e.g. "308"). */
83
83
  declare const ACTION_REDIRECT_STATUS_HEADER = "x-action-redirect-status";
84
- /** Prefix for forwarded request headers (e.g. `x-middleware-request-cookie`). */
85
- declare const MIDDLEWARE_REQUEST_HEADER_PREFIX = "x-middleware-request-";
86
- /** Comma-separated list of header names that middleware wants to override. */
87
- declare const MIDDLEWARE_OVERRIDE_HEADERS = "x-middleware-override-headers";
88
- /** Carries cookies set by middleware for same-render reads. */
89
- declare const MIDDLEWARE_SET_COOKIE_HEADER = "x-middleware-set-cookie";
90
84
  /** Signal from `NextResponse.next()` — value "1" means "continue to next handler". */
91
85
  declare const MIDDLEWARE_NEXT_HEADER = "x-middleware-next";
92
86
  /** Rewrite destination URL set by `NextResponse.rewrite()`. */
93
87
  declare const MIDDLEWARE_REWRITE_HEADER = "x-middleware-rewrite";
94
- /** Generic prefix for all middleware internal headers. */
95
- declare const MIDDLEWARE_HEADER_PREFIX = "x-middleware-";
96
88
  declare const NEXT_ROUTER_STATE_TREE_HEADER = "Next-Router-State-Tree";
97
89
  declare const NEXT_ROUTER_PREFETCH_HEADER = "Next-Router-Prefetch";
98
90
  declare const NEXT_ROUTER_SEGMENT_PREFETCH_HEADER = "Next-Router-Segment-Prefetch";
@@ -113,4 +105,4 @@ declare const INTERNAL_HEADERS: string[];
113
105
  /** Vinext-only internal headers stripped alongside Next.js protocol internals. */
114
106
  declare const VINEXT_INTERNAL_HEADERS: string[];
115
107
  //#endregion
116
- export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
108
+ export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
@@ -1,3 +1,4 @@
1
+ import { MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
1
2
  //#region src/server/headers.ts
2
3
  /**
3
4
  * Internal HTTP header name constants used throughout vinext.
@@ -15,14 +16,8 @@ const VINEXT_CACHE_HEADER = "X-Vinext-Cache";
15
16
  const NEXTJS_CACHE_HEADER = "x-nextjs-cache";
16
17
  /** Static file signal — value is URL-encoded pathname. */
17
18
  const VINEXT_STATIC_FILE_HEADER = "x-vinext-static-file";
18
- /** Serialized middleware context (JSON) forwarded from dev server to RSC entry. */
19
- const VINEXT_MW_CTX_HEADER = "x-vinext-mw-ctx";
20
19
  /** Timing metrics: `handlerStart,compileMs,renderMs`. */
21
20
  const VINEXT_TIMING_HEADER = "x-vinext-timing";
22
- /** Build-time prerender authentication secret. */
23
- const VINEXT_PRERENDER_SECRET_HEADER = "x-vinext-prerender-secret";
24
- /** URL-encoded JSON route params for build-time prerender renders. */
25
- const VINEXT_PRERENDER_ROUTE_PARAMS_HEADER = "x-vinext-prerender-route-params";
26
21
  /** Internal endpoint used to evaluate App Router generateStaticParams exports. */
27
22
  const VINEXT_PRERENDER_STATIC_PARAMS_PATH = "/__vinext/prerender/static-params";
28
23
  /** Internal endpoint used to evaluate Pages Router getStaticPaths exports. */
@@ -37,6 +32,10 @@ const VINEXT_PARAMS_HEADER = "X-Vinext-Params";
37
32
  const VINEXT_MOUNTED_SLOTS_HEADER = "X-Vinext-Mounted-Slots";
38
33
  /** Per-page dynamic stale time in seconds for App Router RSC responses. */
39
34
  const VINEXT_DYNAMIC_STALE_TIME_HEADER = "X-Vinext-Dynamic-Stale-Time";
35
+ /** URL-encoded rendered path and search after middleware/config rewrites. */
36
+ const VINEXT_RENDERED_PATH_AND_SEARCH_HEADER = "X-Vinext-Rendered-Path-And-Search";
37
+ /** Prerender-only JSON side channel carrying request cacheLife metadata. */
38
+ const VINEXT_PRERENDER_CACHE_LIFE_HEADER = "x-vinext-prerender-cache-life";
40
39
  /** Route interception context for parallel/intercepting routes. */
41
40
  const VINEXT_INTERCEPTION_CONTEXT_HEADER = "X-Vinext-Interception-Context";
42
41
  /** RSC render mode (e.g. "navigation", "prefetch"). */
@@ -81,22 +80,12 @@ const ACTION_REDIRECT_HEADER = "x-action-redirect";
81
80
  const ACTION_REDIRECT_TYPE_HEADER = "x-action-redirect-type";
82
81
  /** HTTP status for a Server Action redirect (e.g. "308"). */
83
82
  const ACTION_REDIRECT_STATUS_HEADER = "x-action-redirect-status";
84
- /** Prefix for forwarded request headers (e.g. `x-middleware-request-cookie`). */
85
- const MIDDLEWARE_REQUEST_HEADER_PREFIX = "x-middleware-request-";
86
- /** Comma-separated list of header names that middleware wants to override. */
87
- const MIDDLEWARE_OVERRIDE_HEADERS = "x-middleware-override-headers";
88
- /** Carries cookies set by middleware for same-render reads. */
89
- const MIDDLEWARE_SET_COOKIE_HEADER = "x-middleware-set-cookie";
90
83
  /** Signal from `NextResponse.next()` — value "1" means "continue to next handler". */
91
84
  const MIDDLEWARE_NEXT_HEADER = "x-middleware-next";
92
85
  /** Rewrite destination URL set by `NextResponse.rewrite()`. */
93
86
  const MIDDLEWARE_REWRITE_HEADER = "x-middleware-rewrite";
94
87
  /** Redirect URL set by middleware. */
95
88
  const MIDDLEWARE_REDIRECT_HEADER = "x-middleware-redirect";
96
- /** Skip-middleware signal. */
97
- const MIDDLEWARE_SKIP_HEADER = "x-middleware-skip";
98
- /** Generic prefix for all middleware internal headers. */
99
- const MIDDLEWARE_HEADER_PREFIX = "x-middleware-";
100
89
  const NEXT_ROUTER_STATE_TREE_HEADER = "Next-Router-State-Tree";
101
90
  const NEXT_ROUTER_PREFETCH_HEADER = "Next-Router-Prefetch";
102
91
  const NEXT_ROUTER_SEGMENT_PREFETCH_HEADER = "Next-Router-Segment-Prefetch";
@@ -133,6 +122,10 @@ const INTERNAL_HEADERS = [
133
122
  ACTION_FORWARDED_HEADER
134
123
  ];
135
124
  /** Vinext-only internal headers stripped alongside Next.js protocol internals. */
136
- const VINEXT_INTERNAL_HEADERS = [VINEXT_PRERENDER_ROUTE_PARAMS_HEADER];
125
+ const VINEXT_INTERNAL_HEADERS = [
126
+ VINEXT_PRERENDER_ROUTE_PARAMS_HEADER,
127
+ VINEXT_PRERENDER_SPECULATIVE_HEADER,
128
+ VINEXT_PRERENDER_CACHE_LIFE_HEADER
129
+ ];
137
130
  //#endregion
138
- export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
131
+ export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
@@ -121,5 +121,55 @@ type ImageHandlers = {
121
121
  * cache headers.
122
122
  */
123
123
  declare function handleImageOptimization(request: Request, handlers: ImageHandlers, allowedWidths?: number[], imageConfig?: ImageConfig): Promise<Response>;
124
+ /**
125
+ * A server-side image optimizer: the transform backend that resizes/transcodes
126
+ * a source image. Produced by an adapter factory (e.g. `imagesOptimizer()` from
127
+ * `@vinext/cloudflare/images/images-optimizer`) and registered via
128
+ * {@link setImageOptimizer}.
129
+ */
130
+ type ImageOptimizer = {
131
+ /** Transform the source image (resize, format, quality). */transformImage: (body: ReadableStream, options: {
132
+ width: number;
133
+ format: string;
134
+ quality: number;
135
+ }) => Promise<Response>;
136
+ };
137
+ /**
138
+ * Register the active image optimizer (transform backend). An explicit
139
+ * registration always wins; passing `null` clears it (falling back to
140
+ * unoptimized passthrough).
141
+ *
142
+ * Configure this declaratively via the `images.optimizer` option on the
143
+ * `vinext()` plugin in your `vite.config.ts` rather than calling it directly.
144
+ * On Cloudflare Workers:
145
+ *
146
+ * ```ts
147
+ * import { vinext } from "vinext";
148
+ * import { imagesOptimizer } from "@vinext/cloudflare/images/images-optimizer";
149
+ *
150
+ * export default defineConfig({
151
+ * plugins: [vinext({ images: { optimizer: imagesOptimizer() } })],
152
+ * });
153
+ * ```
154
+ *
155
+ * The plugin registers the optimizer across every runtime/router entry, so you
156
+ * don't have to wire `env.IMAGES` into a custom worker entry. This setter
157
+ * remains the internal registration target.
158
+ */
159
+ declare function setImageOptimizer(optimizer: ImageOptimizer | null): void;
160
+ /** Get the active image optimizer, or `null` when none is configured. */
161
+ declare function getImageOptimizer(): ImageOptimizer | null;
162
+ /**
163
+ * Handle an image optimization request using the configured optimizer (if any).
164
+ *
165
+ * This is the single entry point every runtime/router seam (App Router worker,
166
+ * Pages worker, Node prod server) should call: it reads the registered
167
+ * {@link ImageOptimizer} and wires its `transformImage` into
168
+ * {@link handleImageOptimization}, with the caller supplying the runtime's
169
+ * `fetchAsset` (e.g. the Cloudflare `ASSETS` binding, or filesystem reads on
170
+ * Node). When no optimizer is registered, the request is served unoptimized
171
+ * (passthrough) with the same security/cache headers.
172
+ */
173
+ declare function handleConfiguredImageOptimization(request: Request, fetchAsset: (path: string, request: Request) => Promise<Response>, allowedWidths?: number[], imageConfig?: ImageConfig): Promise<Response>;
124
174
  //#endregion
125
- export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, ImageConfig, ImageHandlers, ParseImageParamsOptions, VINEXT_IMAGE_OPTIMIZATION_PATH, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams, resolveDevImageRedirect };
175
+ export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, ImageConfig, ImageHandlers, ImageOptimizer, ParseImageParamsOptions, VINEXT_IMAGE_OPTIMIZATION_PATH, getImageOptimizer, handleConfiguredImageOptimization, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams, resolveDevImageRedirect, setImageOptimizer };