vinext 0.0.47 → 0.0.48

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 (263) hide show
  1. package/README.md +1 -1
  2. package/dist/build/layout-classification.js +3 -1
  3. package/dist/build/layout-classification.js.map +1 -1
  4. package/dist/build/prerender.js +10 -10
  5. package/dist/build/prerender.js.map +1 -1
  6. package/dist/build/report.d.ts +8 -4
  7. package/dist/build/report.js +17 -7
  8. package/dist/build/report.js.map +1 -1
  9. package/dist/build/run-prerender.d.ts +5 -0
  10. package/dist/build/run-prerender.js +4 -1
  11. package/dist/build/run-prerender.js.map +1 -1
  12. package/dist/build/server-manifest.js +2 -7
  13. package/dist/build/server-manifest.js.map +1 -1
  14. package/dist/build/standalone.js +3 -5
  15. package/dist/build/standalone.js.map +1 -1
  16. package/dist/check.js +45 -29
  17. package/dist/check.js.map +1 -1
  18. package/dist/cli-args.d.ts +3 -1
  19. package/dist/cli-args.js +18 -1
  20. package/dist/cli-args.js.map +1 -1
  21. package/dist/cli.js +9 -1
  22. package/dist/cli.js.map +1 -1
  23. package/dist/config/config-matchers.js +46 -37
  24. package/dist/config/config-matchers.js.map +1 -1
  25. package/dist/deploy.d.ts +18 -2
  26. package/dist/deploy.js +47 -4
  27. package/dist/deploy.js.map +1 -1
  28. package/dist/entries/app-rsc-entry.js +11 -9
  29. package/dist/entries/app-rsc-entry.js.map +1 -1
  30. package/dist/entries/app-rsc-manifest.js +4 -1
  31. package/dist/entries/app-rsc-manifest.js.map +1 -1
  32. package/dist/entries/pages-client-entry.js +3 -2
  33. package/dist/entries/pages-client-entry.js.map +1 -1
  34. package/dist/entries/pages-server-entry.js +14 -59
  35. package/dist/entries/pages-server-entry.js.map +1 -1
  36. package/dist/entries/runtime-entry-module.d.ts +12 -3
  37. package/dist/entries/runtime-entry-module.js +15 -4
  38. package/dist/entries/runtime-entry-module.js.map +1 -1
  39. package/dist/index.js +12 -7
  40. package/dist/index.js.map +1 -1
  41. package/dist/plugins/og-assets.js +15 -16
  42. package/dist/plugins/og-assets.js.map +1 -1
  43. package/dist/plugins/rsc-client-shim-excludes.d.ts +2 -1
  44. package/dist/plugins/rsc-client-shim-excludes.js +10 -1
  45. package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
  46. package/dist/routing/app-route-graph.d.ts +90 -4
  47. package/dist/routing/app-route-graph.js +210 -7
  48. package/dist/routing/app-route-graph.js.map +1 -1
  49. package/dist/routing/app-router.d.ts +15 -3
  50. package/dist/routing/app-router.js +20 -23
  51. package/dist/routing/app-router.js.map +1 -1
  52. package/dist/routing/file-matcher.d.ts +3 -1
  53. package/dist/routing/file-matcher.js +6 -1
  54. package/dist/routing/file-matcher.js.map +1 -1
  55. package/dist/routing/pages-router.js +10 -19
  56. package/dist/routing/pages-router.js.map +1 -1
  57. package/dist/routing/route-matching.d.ts +28 -0
  58. package/dist/routing/route-matching.js +44 -0
  59. package/dist/routing/route-matching.js.map +1 -0
  60. package/dist/routing/route-pattern.js +4 -1
  61. package/dist/routing/route-pattern.js.map +1 -1
  62. package/dist/routing/route-trie.d.ts +8 -0
  63. package/dist/routing/route-trie.js +12 -1
  64. package/dist/routing/route-trie.js.map +1 -1
  65. package/dist/routing/route-validation.js +3 -4
  66. package/dist/routing/route-validation.js.map +1 -1
  67. package/dist/routing/utils.d.ts +8 -1
  68. package/dist/routing/utils.js +25 -2
  69. package/dist/routing/utils.js.map +1 -1
  70. package/dist/server/app-browser-entry.js +66 -49
  71. package/dist/server/app-browser-entry.js.map +1 -1
  72. package/dist/server/app-browser-navigation-controller.d.ts +7 -5
  73. package/dist/server/app-browser-navigation-controller.js +43 -35
  74. package/dist/server/app-browser-navigation-controller.js.map +1 -1
  75. package/dist/server/app-browser-state.d.ts +33 -15
  76. package/dist/server/app-browser-state.js +52 -59
  77. package/dist/server/app-browser-state.js.map +1 -1
  78. package/dist/server/app-browser-visible-commit.d.ts +68 -0
  79. package/dist/server/app-browser-visible-commit.js +182 -0
  80. package/dist/server/app-browser-visible-commit.js.map +1 -0
  81. package/dist/server/app-client-reference-preloader.d.ts +15 -0
  82. package/dist/server/app-client-reference-preloader.js +46 -0
  83. package/dist/server/app-client-reference-preloader.js.map +1 -0
  84. package/dist/server/app-elements-wire.d.ts +130 -0
  85. package/dist/server/app-elements-wire.js +205 -0
  86. package/dist/server/app-elements-wire.js.map +1 -0
  87. package/dist/server/app-elements.d.ts +2 -84
  88. package/dist/server/app-elements.js +3 -102
  89. package/dist/server/app-elements.js.map +1 -1
  90. package/dist/server/app-fallback-renderer.d.ts +1 -1
  91. package/dist/server/app-middleware.d.ts +2 -1
  92. package/dist/server/app-middleware.js +34 -11
  93. package/dist/server/app-middleware.js.map +1 -1
  94. package/dist/server/app-page-boundary-render.d.ts +1 -1
  95. package/dist/server/app-page-boundary-render.js +8 -5
  96. package/dist/server/app-page-boundary-render.js.map +1 -1
  97. package/dist/server/app-page-boundary.js +2 -1
  98. package/dist/server/app-page-boundary.js.map +1 -1
  99. package/dist/server/app-page-cache.d.ts +1 -0
  100. package/dist/server/app-page-cache.js +8 -13
  101. package/dist/server/app-page-cache.js.map +1 -1
  102. package/dist/server/app-page-dispatch.d.ts +2 -1
  103. package/dist/server/app-page-dispatch.js +18 -10
  104. package/dist/server/app-page-dispatch.js.map +1 -1
  105. package/dist/server/app-page-element-builder.d.ts +1 -1
  106. package/dist/server/app-page-element-builder.js +8 -5
  107. package/dist/server/app-page-element-builder.js.map +1 -1
  108. package/dist/server/app-page-execution.d.ts +23 -5
  109. package/dist/server/app-page-execution.js +39 -24
  110. package/dist/server/app-page-execution.js.map +1 -1
  111. package/dist/server/app-page-head.js +2 -1
  112. package/dist/server/app-page-head.js.map +1 -1
  113. package/dist/server/app-page-method.js +2 -5
  114. package/dist/server/app-page-method.js.map +1 -1
  115. package/dist/server/app-page-probe.d.ts +1 -1
  116. package/dist/server/app-page-probe.js +5 -1
  117. package/dist/server/app-page-probe.js.map +1 -1
  118. package/dist/server/app-page-render.d.ts +1 -1
  119. package/dist/server/app-page-render.js +38 -3
  120. package/dist/server/app-page-render.js.map +1 -1
  121. package/dist/server/app-page-request.d.ts +0 -1
  122. package/dist/server/app-page-request.js +7 -10
  123. package/dist/server/app-page-request.js.map +1 -1
  124. package/dist/server/app-page-response.js +3 -2
  125. package/dist/server/app-page-response.js.map +1 -1
  126. package/dist/server/app-page-route-wiring.d.ts +5 -2
  127. package/dist/server/app-page-route-wiring.js +15 -12
  128. package/dist/server/app-page-route-wiring.js.map +1 -1
  129. package/dist/server/app-page-stream.d.ts +7 -0
  130. package/dist/server/app-page-stream.js +9 -2
  131. package/dist/server/app-page-stream.js.map +1 -1
  132. package/dist/server/app-prerender-endpoints.js +3 -2
  133. package/dist/server/app-prerender-endpoints.js.map +1 -1
  134. package/dist/server/app-route-handler-cache.js +2 -1
  135. package/dist/server/app-route-handler-cache.js.map +1 -1
  136. package/dist/server/app-route-handler-dispatch.js +6 -5
  137. package/dist/server/app-route-handler-dispatch.js.map +1 -1
  138. package/dist/server/app-route-handler-policy.js +13 -13
  139. package/dist/server/app-route-handler-policy.js.map +1 -1
  140. package/dist/server/app-route-handler-response.js +2 -1
  141. package/dist/server/app-route-handler-response.js.map +1 -1
  142. package/dist/server/app-route-handler-runtime.d.ts +9 -1
  143. package/dist/server/app-route-handler-runtime.js +11 -1
  144. package/dist/server/app-route-handler-runtime.js.map +1 -1
  145. package/dist/server/app-router-entry.js +9 -4
  146. package/dist/server/app-router-entry.js.map +1 -1
  147. package/dist/server/app-rsc-cache-busting.d.ts +34 -0
  148. package/dist/server/app-rsc-cache-busting.js +137 -0
  149. package/dist/server/app-rsc-cache-busting.js.map +1 -0
  150. package/dist/server/app-rsc-handler.js +22 -11
  151. package/dist/server/app-rsc-handler.js.map +1 -1
  152. package/dist/server/app-rsc-request-normalization.d.ts +4 -2
  153. package/dist/server/app-rsc-request-normalization.js +10 -6
  154. package/dist/server/app-rsc-request-normalization.js.map +1 -1
  155. package/dist/server/app-rsc-response-finalizer.js +1 -1
  156. package/dist/server/app-rsc-route-matching.js +8 -4
  157. package/dist/server/app-rsc-route-matching.js.map +1 -1
  158. package/dist/server/app-segment-config.js +4 -0
  159. package/dist/server/app-segment-config.js.map +1 -1
  160. package/dist/server/app-server-action-execution.js +43 -51
  161. package/dist/server/app-server-action-execution.js.map +1 -1
  162. package/dist/server/app-ssr-entry.js +21 -20
  163. package/dist/server/app-ssr-entry.js.map +1 -1
  164. package/dist/server/artifact-compatibility.d.ts +44 -0
  165. package/dist/server/artifact-compatibility.js +82 -0
  166. package/dist/server/artifact-compatibility.js.map +1 -0
  167. package/dist/server/cache-proof.d.ts +200 -0
  168. package/dist/server/cache-proof.js +342 -0
  169. package/dist/server/cache-proof.js.map +1 -0
  170. package/dist/server/dev-origin-check.js +8 -4
  171. package/dist/server/dev-origin-check.js.map +1 -1
  172. package/dist/server/dev-server.js +1 -6
  173. package/dist/server/dev-server.js.map +1 -1
  174. package/dist/server/http-error-responses.d.ts +67 -0
  175. package/dist/server/http-error-responses.js +77 -0
  176. package/dist/server/http-error-responses.js.map +1 -0
  177. package/dist/server/image-optimization.js +2 -1
  178. package/dist/server/image-optimization.js.map +1 -1
  179. package/dist/server/metadata-route-response.js +6 -5
  180. package/dist/server/metadata-route-response.js.map +1 -1
  181. package/dist/server/metadata-routes.d.ts +1 -0
  182. package/dist/server/metadata-routes.js +6 -0
  183. package/dist/server/metadata-routes.js.map +1 -1
  184. package/dist/server/middleware-matcher.js +2 -2
  185. package/dist/server/middleware-matcher.js.map +1 -1
  186. package/dist/server/middleware-response-headers.js +21 -0
  187. package/dist/server/middleware-response-headers.js.map +1 -1
  188. package/dist/server/middleware-runtime.js +3 -3
  189. package/dist/server/middleware-runtime.js.map +1 -1
  190. package/dist/server/navigation-trace.d.ts +33 -0
  191. package/dist/server/navigation-trace.js +35 -0
  192. package/dist/server/navigation-trace.js.map +1 -0
  193. package/dist/server/next-error-digest.d.ts +44 -0
  194. package/dist/server/next-error-digest.js +40 -0
  195. package/dist/server/next-error-digest.js.map +1 -0
  196. package/dist/server/pages-api-route.js +2 -1
  197. package/dist/server/pages-api-route.js.map +1 -1
  198. package/dist/server/pages-node-compat.js +4 -16
  199. package/dist/server/pages-node-compat.js.map +1 -1
  200. package/dist/server/pages-page-response.d.ts +2 -8
  201. package/dist/server/pages-page-response.js +44 -14
  202. package/dist/server/pages-page-response.js.map +1 -1
  203. package/dist/server/prod-server.d.ts +6 -0
  204. package/dist/server/prod-server.js +28 -21
  205. package/dist/server/prod-server.js.map +1 -1
  206. package/dist/server/request-pipeline.d.ts +42 -1
  207. package/dist/server/request-pipeline.js +97 -17
  208. package/dist/server/request-pipeline.js.map +1 -1
  209. package/dist/shims/cache-runtime.d.ts +2 -2
  210. package/dist/shims/cache-runtime.js +3 -6
  211. package/dist/shims/cache-runtime.js.map +1 -1
  212. package/dist/shims/cache.js +3 -5
  213. package/dist/shims/cache.js.map +1 -1
  214. package/dist/shims/fetch-cache.js +2 -3
  215. package/dist/shims/fetch-cache.js.map +1 -1
  216. package/dist/shims/head-state.js +2 -3
  217. package/dist/shims/head-state.js.map +1 -1
  218. package/dist/shims/headers.js +4 -44
  219. package/dist/shims/headers.js.map +1 -1
  220. package/dist/shims/i18n-state.js +2 -3
  221. package/dist/shims/i18n-state.js.map +1 -1
  222. package/dist/shims/internal/als-registry.d.ts +15 -0
  223. package/dist/shims/internal/als-registry.js +55 -0
  224. package/dist/shims/internal/als-registry.js.map +1 -0
  225. package/dist/shims/internal/cookie-serialize.d.ts +46 -0
  226. package/dist/shims/internal/cookie-serialize.js +51 -0
  227. package/dist/shims/internal/cookie-serialize.js.map +1 -0
  228. package/dist/shims/link.js +31 -26
  229. package/dist/shims/link.js.map +1 -1
  230. package/dist/shims/metadata.d.ts +26 -1
  231. package/dist/shims/metadata.js +94 -4
  232. package/dist/shims/metadata.js.map +1 -1
  233. package/dist/shims/navigation-state.js +2 -3
  234. package/dist/shims/navigation-state.js.map +1 -1
  235. package/dist/shims/navigation.d.ts +2 -7
  236. package/dist/shims/navigation.js +44 -36
  237. package/dist/shims/navigation.js.map +1 -1
  238. package/dist/shims/request-context.js +2 -4
  239. package/dist/shims/request-context.js.map +1 -1
  240. package/dist/shims/router-state.js +2 -3
  241. package/dist/shims/router-state.js.map +1 -1
  242. package/dist/shims/router.js +2 -2
  243. package/dist/shims/router.js.map +1 -1
  244. package/dist/shims/server.js +5 -30
  245. package/dist/shims/server.js.map +1 -1
  246. package/dist/shims/slot.d.ts +1 -1
  247. package/dist/shims/slot.js +5 -4
  248. package/dist/shims/slot.js.map +1 -1
  249. package/dist/shims/thenable-params.d.ts +5 -2
  250. package/dist/shims/thenable-params.js +26 -6
  251. package/dist/shims/thenable-params.js.map +1 -1
  252. package/dist/shims/unified-request-context.js +2 -14
  253. package/dist/shims/unified-request-context.js.map +1 -1
  254. package/dist/utils/base-path.d.ts +7 -1
  255. package/dist/utils/base-path.js +12 -1
  256. package/dist/utils/base-path.js.map +1 -1
  257. package/dist/utils/safe-json-file.d.ts +18 -0
  258. package/dist/utils/safe-json-file.js +25 -0
  259. package/dist/utils/safe-json-file.js.map +1 -0
  260. package/dist/utils/text-stream.d.ts +29 -0
  261. package/dist/utils/text-stream.js +66 -0
  262. package/dist/utils/text-stream.js.map +1 -0
  263. package/package.json +5 -5
@@ -0,0 +1,33 @@
1
+ //#region src/server/navigation-trace.d.ts
2
+ declare const NAVIGATION_TRACE_SCHEMA_VERSION = 0;
3
+ type NavigationTraceSchemaVersion = 0;
4
+ declare const NavigationTraceReasonCodes: {
5
+ commitCurrent: "NC_COMMIT";
6
+ rootBoundaryChanged: "NC_ROOT";
7
+ rootBoundaryUnknown: "NC_ROOT_UNKNOWN";
8
+ staleOperation: "NC_STALE";
9
+ };
10
+ declare const NavigationTraceTransactionCodes: {
11
+ hardNavigate: "NT_HARD_NAVIGATE";
12
+ noCommit: "NT_NO_COMMIT";
13
+ visibleCommit: "NT_VISIBLE_COMMIT";
14
+ };
15
+ type NavigationTraceReasonCode = (typeof NavigationTraceReasonCodes)[keyof typeof NavigationTraceReasonCodes];
16
+ type NavigationTraceTransactionCode = (typeof NavigationTraceTransactionCodes)[keyof typeof NavigationTraceTransactionCodes];
17
+ type NavigationTraceCode = NavigationTraceReasonCode | NavigationTraceTransactionCode;
18
+ type NavigationTraceFieldName = "activeNavigationId" | "currentRootLayoutTreePath" | "nextRootLayoutTreePath" | "operationLane" | "pendingOperationId" | "startedVisibleCommitVersion" | "startedNavigationId";
19
+ type NavigationTraceFieldValue = string | number | boolean | null;
20
+ type NavigationTraceFields = Readonly<Partial<Record<NavigationTraceFieldName, NavigationTraceFieldValue>>>;
21
+ type NavigationTraceEntry = Readonly<{
22
+ code: NavigationTraceCode;
23
+ fields: NavigationTraceFields;
24
+ }>;
25
+ type NavigationTrace = Readonly<{
26
+ schemaVersion: NavigationTraceSchemaVersion;
27
+ entries: readonly NavigationTraceEntry[];
28
+ }>;
29
+ declare function createNavigationTrace(code: NavigationTraceCode, fields?: NavigationTraceFields): NavigationTrace;
30
+ declare function prependNavigationTraceEntry(trace: NavigationTrace, code: NavigationTraceCode, fields?: NavigationTraceFields): NavigationTrace;
31
+ //#endregion
32
+ export { NAVIGATION_TRACE_SCHEMA_VERSION, NavigationTrace, NavigationTraceCode, NavigationTraceEntry, NavigationTraceFieldName, NavigationTraceFieldValue, NavigationTraceFields, NavigationTraceReasonCode, NavigationTraceReasonCodes, NavigationTraceSchemaVersion, NavigationTraceTransactionCode, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry };
33
+ //# sourceMappingURL=navigation-trace.d.ts.map
@@ -0,0 +1,35 @@
1
+ //#region src/server/navigation-trace.ts
2
+ const NAVIGATION_TRACE_SCHEMA_VERSION = 0;
3
+ const NavigationTraceReasonCodes = {
4
+ commitCurrent: "NC_COMMIT",
5
+ rootBoundaryChanged: "NC_ROOT",
6
+ rootBoundaryUnknown: "NC_ROOT_UNKNOWN",
7
+ staleOperation: "NC_STALE"
8
+ };
9
+ const NavigationTraceTransactionCodes = {
10
+ hardNavigate: "NT_HARD_NAVIGATE",
11
+ noCommit: "NT_NO_COMMIT",
12
+ visibleCommit: "NT_VISIBLE_COMMIT"
13
+ };
14
+ function createNavigationTraceEntry(code, fields = {}) {
15
+ return {
16
+ code,
17
+ fields: { ...fields }
18
+ };
19
+ }
20
+ function createNavigationTrace(code, fields = {}) {
21
+ return {
22
+ schemaVersion: 0,
23
+ entries: [createNavigationTraceEntry(code, fields)]
24
+ };
25
+ }
26
+ function prependNavigationTraceEntry(trace, code, fields = {}) {
27
+ return {
28
+ schemaVersion: trace.schemaVersion,
29
+ entries: [createNavigationTraceEntry(code, fields), ...trace.entries]
30
+ };
31
+ }
32
+ //#endregion
33
+ export { NAVIGATION_TRACE_SCHEMA_VERSION, NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry };
34
+
35
+ //# sourceMappingURL=navigation-trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-trace.js","names":[],"sources":["../../src/server/navigation-trace.ts"],"sourcesContent":["export const NAVIGATION_TRACE_SCHEMA_VERSION = 0;\n\nexport type NavigationTraceSchemaVersion = 0;\n\nexport const NavigationTraceReasonCodes = {\n commitCurrent: \"NC_COMMIT\",\n rootBoundaryChanged: \"NC_ROOT\",\n rootBoundaryUnknown: \"NC_ROOT_UNKNOWN\",\n staleOperation: \"NC_STALE\",\n} satisfies Readonly<{\n commitCurrent: \"NC_COMMIT\";\n rootBoundaryChanged: \"NC_ROOT\";\n rootBoundaryUnknown: \"NC_ROOT_UNKNOWN\";\n staleOperation: \"NC_STALE\";\n}>;\n\nexport const NavigationTraceTransactionCodes = {\n hardNavigate: \"NT_HARD_NAVIGATE\",\n noCommit: \"NT_NO_COMMIT\",\n visibleCommit: \"NT_VISIBLE_COMMIT\",\n} satisfies Readonly<{\n hardNavigate: \"NT_HARD_NAVIGATE\";\n noCommit: \"NT_NO_COMMIT\";\n visibleCommit: \"NT_VISIBLE_COMMIT\";\n}>;\n\nexport type NavigationTraceReasonCode =\n (typeof NavigationTraceReasonCodes)[keyof typeof NavigationTraceReasonCodes];\n\nexport type NavigationTraceTransactionCode =\n (typeof NavigationTraceTransactionCodes)[keyof typeof NavigationTraceTransactionCodes];\n\nexport type NavigationTraceCode = NavigationTraceReasonCode | NavigationTraceTransactionCode;\n\nexport type NavigationTraceFieldName =\n | \"activeNavigationId\"\n | \"currentRootLayoutTreePath\"\n | \"nextRootLayoutTreePath\"\n | \"operationLane\"\n | \"pendingOperationId\"\n | \"startedVisibleCommitVersion\"\n | \"startedNavigationId\";\n\nexport type NavigationTraceFieldValue = string | number | boolean | null;\n\nexport type NavigationTraceFields = Readonly<\n Partial<Record<NavigationTraceFieldName, NavigationTraceFieldValue>>\n>;\n\nexport type NavigationTraceEntry = Readonly<{\n code: NavigationTraceCode;\n fields: NavigationTraceFields;\n}>;\n\nexport type NavigationTrace = Readonly<{\n schemaVersion: NavigationTraceSchemaVersion;\n entries: readonly NavigationTraceEntry[];\n}>;\n\nfunction createNavigationTraceEntry(\n code: NavigationTraceCode,\n fields: NavigationTraceFields = {},\n): NavigationTraceEntry {\n return {\n code,\n fields: { ...fields },\n };\n}\n\nexport function createNavigationTrace(\n code: NavigationTraceCode,\n fields: NavigationTraceFields = {},\n): NavigationTrace {\n return {\n schemaVersion: NAVIGATION_TRACE_SCHEMA_VERSION,\n entries: [createNavigationTraceEntry(code, fields)],\n };\n}\n\nexport function prependNavigationTraceEntry(\n trace: NavigationTrace,\n code: NavigationTraceCode,\n fields: NavigationTraceFields = {},\n): NavigationTrace {\n return {\n schemaVersion: trace.schemaVersion,\n entries: [createNavigationTraceEntry(code, fields), ...trace.entries],\n };\n}\n"],"mappings":";AAAA,MAAa,kCAAkC;AAI/C,MAAa,6BAA6B;CACxC,eAAe;CACf,qBAAqB;CACrB,qBAAqB;CACrB,gBAAgB;CACjB;AAOD,MAAa,kCAAkC;CAC7C,cAAc;CACd,UAAU;CACV,eAAe;CAChB;AAuCD,SAAS,2BACP,MACA,SAAgC,EAAE,EACZ;AACtB,QAAO;EACL;EACA,QAAQ,EAAE,GAAG,QAAQ;EACtB;;AAGH,SAAgB,sBACd,MACA,SAAgC,EAAE,EACjB;AACjB,QAAO;EACL,eAAA;EACA,SAAS,CAAC,2BAA2B,MAAM,OAAO,CAAC;EACpD;;AAGH,SAAgB,4BACd,OACA,MACA,SAAgC,EAAE,EACjB;AACjB,QAAO;EACL,eAAe,MAAM;EACrB,SAAS,CAAC,2BAA2B,MAAM,OAAO,EAAE,GAAG,MAAM,QAAQ;EACtE"}
@@ -0,0 +1,44 @@
1
+ //#region src/server/next-error-digest.d.ts
2
+ /**
3
+ * Helpers for parsing Next.js error `digest` strings shared across the App
4
+ * Router execution paths (server actions, page renders, route handlers).
5
+ *
6
+ * Next.js encodes special control flow as thrown errors carrying a `digest`
7
+ * field with one of these formats:
8
+ * - `NEXT_REDIRECT;<type>;<encodedUrl>;<status>` — `redirect()` / `permanentRedirect()`
9
+ * - `NEXT_NOT_FOUND` — `notFound()`
10
+ * - `NEXT_HTTP_ERROR_FALLBACK;<status>` — `forbidden()` / `unauthorized()` / etc.
11
+ *
12
+ * Each call site needs slightly different post-processing (URL resolution
13
+ * against the request, 303-vs-307 status overrides for actions, etc.), so
14
+ * these helpers only handle the parsing — callers shape the result.
15
+ */
16
+ type NextRedirectDigest = {
17
+ status: number;
18
+ type: string;
19
+ url: string;
20
+ };
21
+ type NextHttpErrorDigest = {
22
+ status: number;
23
+ };
24
+ /**
25
+ * Pulls a stringified `digest` off an unknown thrown value, or returns null
26
+ * when the value is not a digest-bearing error.
27
+ */
28
+ declare function getNextErrorDigest(error: unknown): string | null;
29
+ /**
30
+ * Parses a `NEXT_REDIRECT;<type>;<encodedUrl>;<status>` digest. Returns null
31
+ * when the digest is not a redirect digest or the encoded URL segment is
32
+ * missing. The `url` is decoded with `decodeURIComponent`; the `status`
33
+ * defaults to 307 when omitted; the `type` defaults to "push".
34
+ */
35
+ declare function parseNextRedirectDigest(digest: string): NextRedirectDigest | null;
36
+ /**
37
+ * Parses a `NEXT_NOT_FOUND` or `NEXT_HTTP_ERROR_FALLBACK;<status>` digest.
38
+ * Returns `{ status: 404 }` for `NEXT_NOT_FOUND` and the parsed status code
39
+ * for the fallback form. Returns null otherwise.
40
+ */
41
+ declare function parseNextHttpErrorDigest(digest: string): NextHttpErrorDigest | null;
42
+ //#endregion
43
+ export { getNextErrorDigest, parseNextHttpErrorDigest, parseNextRedirectDigest };
44
+ //# sourceMappingURL=next-error-digest.d.ts.map
@@ -0,0 +1,40 @@
1
+ //#region src/server/next-error-digest.ts
2
+ /**
3
+ * Pulls a stringified `digest` off an unknown thrown value, or returns null
4
+ * when the value is not a digest-bearing error.
5
+ */
6
+ function getNextErrorDigest(error) {
7
+ if (!error || typeof error !== "object" || !("digest" in error)) return null;
8
+ return String(error.digest);
9
+ }
10
+ /**
11
+ * Parses a `NEXT_REDIRECT;<type>;<encodedUrl>;<status>` digest. Returns null
12
+ * when the digest is not a redirect digest or the encoded URL segment is
13
+ * missing. The `url` is decoded with `decodeURIComponent`; the `status`
14
+ * defaults to 307 when omitted; the `type` defaults to "push".
15
+ */
16
+ function parseNextRedirectDigest(digest) {
17
+ if (!digest.startsWith("NEXT_REDIRECT;")) return null;
18
+ const parts = digest.split(";");
19
+ const encodedUrl = parts[2];
20
+ if (!encodedUrl) return null;
21
+ return {
22
+ status: parts[3] ? parseInt(parts[3], 10) : 307,
23
+ type: parts[1] || "push",
24
+ url: decodeURIComponent(encodedUrl)
25
+ };
26
+ }
27
+ /**
28
+ * Parses a `NEXT_NOT_FOUND` or `NEXT_HTTP_ERROR_FALLBACK;<status>` digest.
29
+ * Returns `{ status: 404 }` for `NEXT_NOT_FOUND` and the parsed status code
30
+ * for the fallback form. Returns null otherwise.
31
+ */
32
+ function parseNextHttpErrorDigest(digest) {
33
+ if (digest === "NEXT_NOT_FOUND") return { status: 404 };
34
+ if (digest.startsWith("NEXT_HTTP_ERROR_FALLBACK;")) return { status: parseInt(digest.split(";")[1], 10) };
35
+ return null;
36
+ }
37
+ //#endregion
38
+ export { getNextErrorDigest, parseNextHttpErrorDigest, parseNextRedirectDigest };
39
+
40
+ //# sourceMappingURL=next-error-digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-error-digest.js","names":[],"sources":["../../src/server/next-error-digest.ts"],"sourcesContent":["/**\n * Helpers for parsing Next.js error `digest` strings shared across the App\n * Router execution paths (server actions, page renders, route handlers).\n *\n * Next.js encodes special control flow as thrown errors carrying a `digest`\n * field with one of these formats:\n * - `NEXT_REDIRECT;<type>;<encodedUrl>;<status>` — `redirect()` / `permanentRedirect()`\n * - `NEXT_NOT_FOUND` — `notFound()`\n * - `NEXT_HTTP_ERROR_FALLBACK;<status>` — `forbidden()` / `unauthorized()` / etc.\n *\n * Each call site needs slightly different post-processing (URL resolution\n * against the request, 303-vs-307 status overrides for actions, etc.), so\n * these helpers only handle the parsing — callers shape the result.\n */\n\ntype NextRedirectDigest = {\n status: number;\n type: string;\n url: string;\n};\n\ntype NextHttpErrorDigest = {\n status: number;\n};\n\n/**\n * Pulls a stringified `digest` off an unknown thrown value, or returns null\n * when the value is not a digest-bearing error.\n */\nexport function getNextErrorDigest(error: unknown): string | null {\n if (!error || typeof error !== \"object\" || !(\"digest\" in error)) {\n return null;\n }\n\n return String(error.digest);\n}\n\n/**\n * Parses a `NEXT_REDIRECT;<type>;<encodedUrl>;<status>` digest. Returns null\n * when the digest is not a redirect digest or the encoded URL segment is\n * missing. The `url` is decoded with `decodeURIComponent`; the `status`\n * defaults to 307 when omitted; the `type` defaults to \"push\".\n */\nexport function parseNextRedirectDigest(digest: string): NextRedirectDigest | null {\n if (!digest.startsWith(\"NEXT_REDIRECT;\")) {\n return null;\n }\n\n const parts = digest.split(\";\");\n const encodedUrl = parts[2];\n if (!encodedUrl) {\n return null;\n }\n\n return {\n status: parts[3] ? parseInt(parts[3], 10) : 307,\n type: parts[1] || \"push\",\n url: decodeURIComponent(encodedUrl),\n };\n}\n\n/**\n * Parses a `NEXT_NOT_FOUND` or `NEXT_HTTP_ERROR_FALLBACK;<status>` digest.\n * Returns `{ status: 404 }` for `NEXT_NOT_FOUND` and the parsed status code\n * for the fallback form. Returns null otherwise.\n */\nexport function parseNextHttpErrorDigest(digest: string): NextHttpErrorDigest | null {\n if (digest === \"NEXT_NOT_FOUND\") {\n return { status: 404 };\n }\n if (digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n return { status: parseInt(digest.split(\";\")[1], 10) };\n }\n return null;\n}\n"],"mappings":";;;;;AA6BA,SAAgB,mBAAmB,OAA+B;AAChE,KAAI,CAAC,SAAS,OAAO,UAAU,YAAY,EAAE,YAAY,OACvD,QAAO;AAGT,QAAO,OAAO,MAAM,OAAO;;;;;;;;AAS7B,SAAgB,wBAAwB,QAA2C;AACjF,KAAI,CAAC,OAAO,WAAW,iBAAiB,CACtC,QAAO;CAGT,MAAM,QAAQ,OAAO,MAAM,IAAI;CAC/B,MAAM,aAAa,MAAM;AACzB,KAAI,CAAC,WACH,QAAO;AAGT,QAAO;EACL,QAAQ,MAAM,KAAK,SAAS,MAAM,IAAI,GAAG,GAAG;EAC5C,MAAM,MAAM,MAAM;EAClB,KAAK,mBAAmB,WAAW;EACpC;;;;;;;AAQH,SAAgB,yBAAyB,QAA4C;AACnF,KAAI,WAAW,iBACb,QAAO,EAAE,QAAQ,KAAK;AAExB,KAAI,OAAO,WAAW,4BAA4B,CAChD,QAAO,EAAE,QAAQ,SAAS,OAAO,MAAM,IAAI,CAAC,IAAI,GAAG,EAAE;AAEvD,QAAO"}
@@ -1,3 +1,4 @@
1
+ import { internalServerErrorResponse } from "./http-error-responses.js";
1
2
  import { addQueryParam } from "../utils/query.js";
2
3
  import { PagesBodyParseError } from "./pages-media-type.js";
3
4
  import { createPagesReqRes, parsePagesApiBody } from "./pages-node-compat.js";
@@ -31,7 +32,7 @@ async function handlePagesApiRoute(options) {
31
32
  statusText: error.message
32
33
  });
33
34
  options.reportRequestError?.(error instanceof Error ? error : new Error(String(error)), route.pattern);
34
- return new Response("Internal Server Error", { status: 500 });
35
+ return internalServerErrorResponse();
35
36
  }
36
37
  }
37
38
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"pages-api-route.js","names":["PagesApiBodyParseError"],"sources":["../../src/server/pages-api-route.ts"],"sourcesContent":["import type { Route } from \"../routing/pages-router.js\";\nimport { addQueryParam } from \"../utils/query.js\";\nimport {\n createPagesReqRes,\n parsePagesApiBody,\n type PagesRequestQuery,\n type PagesReqResRequest,\n type PagesReqResResponse,\n PagesApiBodyParseError,\n} from \"./pages-node-compat.js\";\n\ntype PagesApiRouteModule = {\n default?: (req: PagesReqResRequest, res: PagesReqResResponse) => void | Promise<void>;\n};\n\nexport type PagesApiRouteMatch = {\n params: PagesRequestQuery;\n route: Pick<Route, \"pattern\"> & {\n module: PagesApiRouteModule;\n };\n};\n\ntype HandlePagesApiRouteOptions = {\n match: PagesApiRouteMatch | null;\n reportRequestError?: (error: Error, routePattern: string) => void | Promise<void>;\n request: Request;\n url: string;\n};\n\nfunction buildPagesApiQuery(url: string, params: PagesRequestQuery): PagesRequestQuery {\n const query: PagesRequestQuery = { ...params };\n const search = url.split(\"?\")[1];\n if (!search) {\n return query;\n }\n\n for (const [key, value] of new URLSearchParams(search)) {\n addQueryParam(query, key, value);\n }\n\n return query;\n}\n\nexport async function handlePagesApiRoute(options: HandlePagesApiRouteOptions): Promise<Response> {\n if (!options.match) {\n return new Response(\"404 - API route not found\", { status: 404 });\n }\n\n const { route, params } = options.match;\n const handler = route.module.default;\n if (typeof handler !== \"function\") {\n return new Response(\"API route does not export a default function\", { status: 500 });\n }\n\n try {\n const query = buildPagesApiQuery(options.url, params);\n const body = await parsePagesApiBody(options.request);\n const { req, res, responsePromise } = createPagesReqRes({\n body,\n query,\n request: options.request,\n url: options.url,\n });\n\n await handler(req, res);\n res.end();\n return await responsePromise;\n } catch (error) {\n if (error instanceof PagesApiBodyParseError) {\n return new Response(error.message, {\n status: error.statusCode,\n statusText: error.message,\n });\n }\n\n void options.reportRequestError?.(\n error instanceof Error ? error : new Error(String(error)),\n route.pattern,\n );\n return new Response(\"Internal Server Error\", { status: 500 });\n }\n}\n"],"mappings":";;;;AA6BA,SAAS,mBAAmB,KAAa,QAA8C;CACrF,MAAM,QAA2B,EAAE,GAAG,QAAQ;CAC9C,MAAM,SAAS,IAAI,MAAM,IAAI,CAAC;AAC9B,KAAI,CAAC,OACH,QAAO;AAGT,MAAK,MAAM,CAAC,KAAK,UAAU,IAAI,gBAAgB,OAAO,CACpD,eAAc,OAAO,KAAK,MAAM;AAGlC,QAAO;;AAGT,eAAsB,oBAAoB,SAAwD;AAChG,KAAI,CAAC,QAAQ,MACX,QAAO,IAAI,SAAS,6BAA6B,EAAE,QAAQ,KAAK,CAAC;CAGnE,MAAM,EAAE,OAAO,WAAW,QAAQ;CAClC,MAAM,UAAU,MAAM,OAAO;AAC7B,KAAI,OAAO,YAAY,WACrB,QAAO,IAAI,SAAS,gDAAgD,EAAE,QAAQ,KAAK,CAAC;AAGtF,KAAI;EACF,MAAM,QAAQ,mBAAmB,QAAQ,KAAK,OAAO;EAErD,MAAM,EAAE,KAAK,KAAK,oBAAoB,kBAAkB;GACtD,MAFW,MAAM,kBAAkB,QAAQ,QAAQ;GAGnD;GACA,SAAS,QAAQ;GACjB,KAAK,QAAQ;GACd,CAAC;AAEF,QAAM,QAAQ,KAAK,IAAI;AACvB,MAAI,KAAK;AACT,SAAO,MAAM;UACN,OAAO;AACd,MAAI,iBAAiBA,oBACnB,QAAO,IAAI,SAAS,MAAM,SAAS;GACjC,QAAQ,MAAM;GACd,YAAY,MAAM;GACnB,CAAC;AAGC,UAAQ,qBACX,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,EACzD,MAAM,QACP;AACD,SAAO,IAAI,SAAS,yBAAyB,EAAE,QAAQ,KAAK,CAAC"}
1
+ {"version":3,"file":"pages-api-route.js","names":["PagesApiBodyParseError"],"sources":["../../src/server/pages-api-route.ts"],"sourcesContent":["import type { Route } from \"../routing/pages-router.js\";\nimport { addQueryParam } from \"../utils/query.js\";\nimport {\n createPagesReqRes,\n parsePagesApiBody,\n type PagesRequestQuery,\n type PagesReqResRequest,\n type PagesReqResResponse,\n PagesApiBodyParseError,\n} from \"./pages-node-compat.js\";\nimport { internalServerErrorResponse } from \"./http-error-responses.js\";\n\ntype PagesApiRouteModule = {\n default?: (req: PagesReqResRequest, res: PagesReqResResponse) => void | Promise<void>;\n};\n\nexport type PagesApiRouteMatch = {\n params: PagesRequestQuery;\n route: Pick<Route, \"pattern\"> & {\n module: PagesApiRouteModule;\n };\n};\n\ntype HandlePagesApiRouteOptions = {\n match: PagesApiRouteMatch | null;\n reportRequestError?: (error: Error, routePattern: string) => void | Promise<void>;\n request: Request;\n url: string;\n};\n\nfunction buildPagesApiQuery(url: string, params: PagesRequestQuery): PagesRequestQuery {\n const query: PagesRequestQuery = { ...params };\n const search = url.split(\"?\")[1];\n if (!search) {\n return query;\n }\n\n for (const [key, value] of new URLSearchParams(search)) {\n addQueryParam(query, key, value);\n }\n\n return query;\n}\n\nexport async function handlePagesApiRoute(options: HandlePagesApiRouteOptions): Promise<Response> {\n if (!options.match) {\n return new Response(\"404 - API route not found\", { status: 404 });\n }\n\n const { route, params } = options.match;\n const handler = route.module.default;\n if (typeof handler !== \"function\") {\n return new Response(\"API route does not export a default function\", { status: 500 });\n }\n\n try {\n const query = buildPagesApiQuery(options.url, params);\n const body = await parsePagesApiBody(options.request);\n const { req, res, responsePromise } = createPagesReqRes({\n body,\n query,\n request: options.request,\n url: options.url,\n });\n\n await handler(req, res);\n res.end();\n return await responsePromise;\n } catch (error) {\n if (error instanceof PagesApiBodyParseError) {\n return new Response(error.message, {\n status: error.statusCode,\n statusText: error.message,\n });\n }\n\n void options.reportRequestError?.(\n error instanceof Error ? error : new Error(String(error)),\n route.pattern,\n );\n return internalServerErrorResponse();\n }\n}\n"],"mappings":";;;;;AA8BA,SAAS,mBAAmB,KAAa,QAA8C;CACrF,MAAM,QAA2B,EAAE,GAAG,QAAQ;CAC9C,MAAM,SAAS,IAAI,MAAM,IAAI,CAAC;AAC9B,KAAI,CAAC,OACH,QAAO;AAGT,MAAK,MAAM,CAAC,KAAK,UAAU,IAAI,gBAAgB,OAAO,CACpD,eAAc,OAAO,KAAK,MAAM;AAGlC,QAAO;;AAGT,eAAsB,oBAAoB,SAAwD;AAChG,KAAI,CAAC,QAAQ,MACX,QAAO,IAAI,SAAS,6BAA6B,EAAE,QAAQ,KAAK,CAAC;CAGnE,MAAM,EAAE,OAAO,WAAW,QAAQ;CAClC,MAAM,UAAU,MAAM,OAAO;AAC7B,KAAI,OAAO,YAAY,WACrB,QAAO,IAAI,SAAS,gDAAgD,EAAE,QAAQ,KAAK,CAAC;AAGtF,KAAI;EACF,MAAM,QAAQ,mBAAmB,QAAQ,KAAK,OAAO;EAErD,MAAM,EAAE,KAAK,KAAK,oBAAoB,kBAAkB;GACtD,MAFW,MAAM,kBAAkB,QAAQ,QAAQ;GAGnD;GACA,SAAS,QAAQ;GACjB,KAAK,QAAQ;GACd,CAAC;AAEF,QAAM,QAAQ,KAAK,IAAI;AACvB,MAAI,KAAK;AACT,SAAO,MAAM;UACN,OAAO;AACd,MAAI,iBAAiBA,oBACnB,QAAO,IAAI,SAAS,MAAM,SAAS;GACjC,QAAQ,MAAM;GACd,YAAY,MAAM;GACnB,CAAC;AAGC,UAAQ,qBACX,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,EACzD,MAAM,QACP;AACD,SAAO,6BAA6B"}
@@ -1,26 +1,14 @@
1
1
  import { parseCookies } from "../config/config-matchers.js";
2
2
  import { PagesBodyParseError, getMediaType, isJsonMediaType } from "./pages-media-type.js";
3
+ import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
3
4
  import { decode } from "node:querystring";
4
5
  //#region src/server/pages-node-compat.ts
5
6
  const MAX_PAGES_API_BODY_SIZE = 1 * 1024 * 1024;
6
7
  async function readPagesRequestBodyWithLimit(request, maxBytes) {
7
8
  if (!request.body) return "";
8
- const reader = request.body.getReader();
9
- const decoder = new TextDecoder();
10
- const chunks = [];
11
- let totalSize = 0;
12
- for (;;) {
13
- const result = await reader.read();
14
- if (result.done) break;
15
- totalSize += result.value.byteLength;
16
- if (totalSize > maxBytes) {
17
- await reader.cancel();
18
- throw new PagesBodyParseError("Request body too large", 413);
19
- }
20
- chunks.push(decoder.decode(result.value, { stream: true }));
21
- }
22
- chunks.push(decoder.decode());
23
- return chunks.join("");
9
+ return readStreamAsTextWithLimit(request.body, maxBytes, () => {
10
+ throw new PagesBodyParseError("Request body too large", 413);
11
+ });
24
12
  }
25
13
  async function parsePagesApiBody(request, maxBytes = MAX_PAGES_API_BODY_SIZE) {
26
14
  if (Number.parseInt(request.headers.get("content-length") || "0", 10) > maxBytes) throw new PagesBodyParseError("Request body too large", 413);
@@ -1 +1 @@
1
- {"version":3,"file":"pages-node-compat.js","names":["decodeQueryString"],"sources":["../../src/server/pages-node-compat.ts"],"sourcesContent":["import { decode as decodeQueryString } from \"node:querystring\";\nimport { parseCookies } from \"../config/config-matchers.js\";\nimport { PagesBodyParseError, getMediaType, isJsonMediaType } from \"./pages-media-type.js\";\n\nconst MAX_PAGES_API_BODY_SIZE = 1 * 1024 * 1024;\n\n/**\n * @deprecated Use PagesBodyParseError from pages-media-type.ts instead.\n * Kept for backwards compatibility.\n */\nexport { PagesBodyParseError as PagesApiBodyParseError };\n\nexport type PagesRequestQuery = Record<string, string | string[]>;\n\nexport type PagesReqResRequest = {\n method: string;\n url: string;\n headers: Record<string, string>;\n query: PagesRequestQuery;\n body: unknown;\n cookies: Record<string, string>;\n};\n\nexport type PagesReqResHeaders = {\n [key: string]: string | number | boolean | string[];\n};\n\nexport type PagesReqResResponse = {\n statusCode: number;\n readonly headersSent: boolean;\n writeHead: (code: number, headers?: PagesReqResHeaders) => PagesReqResResponse;\n setHeader: (name: string, value: string | number | boolean | string[]) => PagesReqResResponse;\n getHeader: (name: string) => string | number | boolean | string[] | undefined;\n end: (data?: BodyInit | null) => void;\n status: (code: number) => PagesReqResResponse;\n json: (data: unknown) => void;\n send: (data: unknown) => void;\n redirect: (statusOrUrl: number | string, url?: string) => void;\n getHeaders: () => PagesReqResHeaders;\n};\n\ntype CreatePagesReqResOptions = {\n body: unknown;\n query: PagesRequestQuery;\n request: Request;\n url: string;\n};\n\ntype CreatePagesReqResResult = {\n req: PagesReqResRequest;\n res: PagesReqResResponse;\n responsePromise: Promise<Response>;\n};\n\nasync function readPagesRequestBodyWithLimit(request: Request, maxBytes: number): Promise<string> {\n if (!request.body) {\n return \"\";\n }\n\n const reader = request.body.getReader();\n const decoder = new TextDecoder();\n const chunks: string[] = [];\n let totalSize = 0;\n\n for (;;) {\n const result = await reader.read();\n if (result.done) {\n break;\n }\n\n totalSize += result.value.byteLength;\n if (totalSize > maxBytes) {\n await reader.cancel();\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n chunks.push(decoder.decode(result.value, { stream: true }));\n }\n\n chunks.push(decoder.decode());\n return chunks.join(\"\");\n}\n\nexport async function parsePagesApiBody(\n request: Request,\n maxBytes = MAX_PAGES_API_BODY_SIZE,\n): Promise<unknown> {\n const contentLength = Number.parseInt(request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > maxBytes) {\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n let rawBody = \"\";\n try {\n rawBody = await readPagesRequestBodyWithLimit(request, maxBytes);\n } catch (err) {\n if (err instanceof PagesBodyParseError) {\n throw err;\n }\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n const mediaType = getMediaType(request.headers.get(\"content-type\"));\n if (!rawBody) {\n return isJsonMediaType(mediaType)\n ? {}\n : mediaType === \"application/x-www-form-urlencoded\"\n ? decodeQueryString(rawBody)\n : undefined;\n }\n\n if (isJsonMediaType(mediaType)) {\n try {\n return JSON.parse(rawBody);\n } catch {\n throw new PagesBodyParseError(\"Invalid JSON\", 400);\n }\n }\n\n if (mediaType === \"application/x-www-form-urlencoded\") {\n return decodeQueryString(rawBody);\n }\n\n return rawBody;\n}\n\nexport function createPagesReqRes(options: CreatePagesReqResOptions): CreatePagesReqResResult {\n const headersObj: Record<string, string> = {};\n for (const [key, value] of options.request.headers) {\n headersObj[key.toLowerCase()] = value;\n }\n\n const req: PagesReqResRequest = {\n method: options.request.method,\n url: options.url,\n headers: headersObj,\n query: options.query,\n body: options.body,\n cookies: parseCookies(options.request.headers.get(\"cookie\")),\n };\n\n let resStatusCode = 200;\n const resHeaders: Record<string, string | number | boolean> = {};\n const setCookieHeaders: string[] = [];\n let resBody: BodyInit | null = null;\n let ended = false;\n let resolveResponse!: (value: Response) => void;\n const responsePromise = new Promise<Response>((resolve) => {\n resolveResponse = resolve;\n });\n\n const res: PagesReqResResponse = {\n get statusCode() {\n return resStatusCode;\n },\n set statusCode(code) {\n resStatusCode = code;\n },\n get headersSent() {\n return ended;\n },\n writeHead(code, headers) {\n resStatusCode = code;\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === \"set-cookie\") {\n if (Array.isArray(value)) {\n setCookieHeaders.push(...value.map(String));\n } else {\n setCookieHeaders.push(String(value));\n }\n } else {\n resHeaders[key.toLowerCase()] = Array.isArray(value) ? value.join(\", \") : value;\n }\n }\n }\n return res;\n },\n setHeader(name, value) {\n if (name.toLowerCase() === \"set-cookie\") {\n // Node.js res.setHeader() replaces the existing value entirely.\n setCookieHeaders.length = 0;\n if (Array.isArray(value)) {\n setCookieHeaders.push(...value.map(String));\n } else {\n setCookieHeaders.push(String(value));\n }\n } else {\n resHeaders[name.toLowerCase()] = Array.isArray(value) ? value.join(\", \") : value;\n }\n return res;\n },\n getHeader(name) {\n if (name.toLowerCase() === \"set-cookie\") {\n return setCookieHeaders.length > 0 ? setCookieHeaders : undefined;\n }\n return resHeaders[name.toLowerCase()];\n },\n end(data) {\n if (ended) {\n return;\n }\n ended = true;\n if (data !== undefined && data !== null) {\n resBody = data;\n }\n const headers = new Headers();\n for (const [key, value] of Object.entries(resHeaders)) {\n headers.set(key, String(value));\n }\n for (const cookie of setCookieHeaders) {\n headers.append(\"set-cookie\", cookie);\n }\n resolveResponse(new Response(resBody, { status: resStatusCode, headers }));\n },\n status(code) {\n resStatusCode = code;\n return res;\n },\n json(data) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n },\n send(data) {\n if (Buffer.isBuffer(data)) {\n if (!resHeaders[\"content-type\"]) {\n resHeaders[\"content-type\"] = \"application/octet-stream\";\n }\n resHeaders[\"content-length\"] = String(data.length);\n res.end(new Uint8Array(data));\n return;\n }\n\n if (typeof data === \"object\" && data !== null) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n return;\n }\n\n if (!resHeaders[\"content-type\"]) {\n resHeaders[\"content-type\"] = \"text/plain\";\n }\n res.end(String(data));\n },\n redirect(statusOrUrl, url) {\n if (typeof statusOrUrl === \"string\") {\n res.writeHead(307, { Location: statusOrUrl });\n } else {\n res.writeHead(statusOrUrl, { Location: url ?? \"\" });\n }\n res.end();\n },\n getHeaders() {\n const headers: PagesReqResHeaders = { ...resHeaders };\n if (setCookieHeaders.length > 0) {\n headers[\"set-cookie\"] = setCookieHeaders;\n }\n return headers;\n },\n };\n\n return { req, res, responsePromise };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pages-node-compat.js","names":["decodeQueryString"],"sources":["../../src/server/pages-node-compat.ts"],"sourcesContent":["import { decode as decodeQueryString } from \"node:querystring\";\nimport { parseCookies } from \"../config/config-matchers.js\";\nimport { readStreamAsTextWithLimit } from \"../utils/text-stream.js\";\nimport { PagesBodyParseError, getMediaType, isJsonMediaType } from \"./pages-media-type.js\";\n\nconst MAX_PAGES_API_BODY_SIZE = 1 * 1024 * 1024;\n\n/**\n * @deprecated Use PagesBodyParseError from pages-media-type.ts instead.\n * Kept for backwards compatibility.\n */\nexport { PagesBodyParseError as PagesApiBodyParseError };\n\nexport type PagesRequestQuery = Record<string, string | string[]>;\n\nexport type PagesReqResRequest = {\n method: string;\n url: string;\n headers: Record<string, string>;\n query: PagesRequestQuery;\n body: unknown;\n cookies: Record<string, string>;\n};\n\nexport type PagesReqResHeaders = {\n [key: string]: string | number | boolean | string[];\n};\n\nexport type PagesReqResResponse = {\n statusCode: number;\n readonly headersSent: boolean;\n writeHead: (code: number, headers?: PagesReqResHeaders) => PagesReqResResponse;\n setHeader: (name: string, value: string | number | boolean | string[]) => PagesReqResResponse;\n getHeader: (name: string) => string | number | boolean | string[] | undefined;\n end: (data?: BodyInit | null) => void;\n status: (code: number) => PagesReqResResponse;\n json: (data: unknown) => void;\n send: (data: unknown) => void;\n redirect: (statusOrUrl: number | string, url?: string) => void;\n getHeaders: () => PagesReqResHeaders;\n};\n\ntype CreatePagesReqResOptions = {\n body: unknown;\n query: PagesRequestQuery;\n request: Request;\n url: string;\n};\n\ntype CreatePagesReqResResult = {\n req: PagesReqResRequest;\n res: PagesReqResResponse;\n responsePromise: Promise<Response>;\n};\n\nasync function readPagesRequestBodyWithLimit(request: Request, maxBytes: number): Promise<string> {\n if (!request.body) {\n return \"\";\n }\n\n return readStreamAsTextWithLimit(request.body, maxBytes, () => {\n throw new PagesBodyParseError(\"Request body too large\", 413);\n });\n}\n\nexport async function parsePagesApiBody(\n request: Request,\n maxBytes = MAX_PAGES_API_BODY_SIZE,\n): Promise<unknown> {\n const contentLength = Number.parseInt(request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > maxBytes) {\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n let rawBody = \"\";\n try {\n rawBody = await readPagesRequestBodyWithLimit(request, maxBytes);\n } catch (err) {\n if (err instanceof PagesBodyParseError) {\n throw err;\n }\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n const mediaType = getMediaType(request.headers.get(\"content-type\"));\n if (!rawBody) {\n return isJsonMediaType(mediaType)\n ? {}\n : mediaType === \"application/x-www-form-urlencoded\"\n ? decodeQueryString(rawBody)\n : undefined;\n }\n\n if (isJsonMediaType(mediaType)) {\n try {\n return JSON.parse(rawBody);\n } catch {\n throw new PagesBodyParseError(\"Invalid JSON\", 400);\n }\n }\n\n if (mediaType === \"application/x-www-form-urlencoded\") {\n return decodeQueryString(rawBody);\n }\n\n return rawBody;\n}\n\nexport function createPagesReqRes(options: CreatePagesReqResOptions): CreatePagesReqResResult {\n const headersObj: Record<string, string> = {};\n for (const [key, value] of options.request.headers) {\n headersObj[key.toLowerCase()] = value;\n }\n\n const req: PagesReqResRequest = {\n method: options.request.method,\n url: options.url,\n headers: headersObj,\n query: options.query,\n body: options.body,\n cookies: parseCookies(options.request.headers.get(\"cookie\")),\n };\n\n let resStatusCode = 200;\n const resHeaders: Record<string, string | number | boolean> = {};\n const setCookieHeaders: string[] = [];\n let resBody: BodyInit | null = null;\n let ended = false;\n let resolveResponse!: (value: Response) => void;\n const responsePromise = new Promise<Response>((resolve) => {\n resolveResponse = resolve;\n });\n\n const res: PagesReqResResponse = {\n get statusCode() {\n return resStatusCode;\n },\n set statusCode(code) {\n resStatusCode = code;\n },\n get headersSent() {\n return ended;\n },\n writeHead(code, headers) {\n resStatusCode = code;\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === \"set-cookie\") {\n if (Array.isArray(value)) {\n setCookieHeaders.push(...value.map(String));\n } else {\n setCookieHeaders.push(String(value));\n }\n } else {\n resHeaders[key.toLowerCase()] = Array.isArray(value) ? value.join(\", \") : value;\n }\n }\n }\n return res;\n },\n setHeader(name, value) {\n if (name.toLowerCase() === \"set-cookie\") {\n // Node.js res.setHeader() replaces the existing value entirely.\n setCookieHeaders.length = 0;\n if (Array.isArray(value)) {\n setCookieHeaders.push(...value.map(String));\n } else {\n setCookieHeaders.push(String(value));\n }\n } else {\n resHeaders[name.toLowerCase()] = Array.isArray(value) ? value.join(\", \") : value;\n }\n return res;\n },\n getHeader(name) {\n if (name.toLowerCase() === \"set-cookie\") {\n return setCookieHeaders.length > 0 ? setCookieHeaders : undefined;\n }\n return resHeaders[name.toLowerCase()];\n },\n end(data) {\n if (ended) {\n return;\n }\n ended = true;\n if (data !== undefined && data !== null) {\n resBody = data;\n }\n const headers = new Headers();\n for (const [key, value] of Object.entries(resHeaders)) {\n headers.set(key, String(value));\n }\n for (const cookie of setCookieHeaders) {\n headers.append(\"set-cookie\", cookie);\n }\n resolveResponse(new Response(resBody, { status: resStatusCode, headers }));\n },\n status(code) {\n resStatusCode = code;\n return res;\n },\n json(data) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n },\n send(data) {\n if (Buffer.isBuffer(data)) {\n if (!resHeaders[\"content-type\"]) {\n resHeaders[\"content-type\"] = \"application/octet-stream\";\n }\n resHeaders[\"content-length\"] = String(data.length);\n res.end(new Uint8Array(data));\n return;\n }\n\n if (typeof data === \"object\" && data !== null) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n return;\n }\n\n if (!resHeaders[\"content-type\"]) {\n resHeaders[\"content-type\"] = \"text/plain\";\n }\n res.end(String(data));\n },\n redirect(statusOrUrl, url) {\n if (typeof statusOrUrl === \"string\") {\n res.writeHead(307, { Location: statusOrUrl });\n } else {\n res.writeHead(statusOrUrl, { Location: url ?? \"\" });\n }\n res.end();\n },\n getHeaders() {\n const headers: PagesReqResHeaders = { ...resHeaders };\n if (setCookieHeaders.length > 0) {\n headers[\"set-cookie\"] = setCookieHeaders;\n }\n return headers;\n },\n };\n\n return { req, res, responsePromise };\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { CachedPagesValue } from "../shims/cache.js";
1
2
  import { ComponentType, ReactNode } from "react";
2
3
 
3
4
  //#region src/server/pages-page-response.d.ts
@@ -31,18 +32,11 @@ type RenderPagesPageResponseOptions = {
31
32
  isrCacheKey: (router: string, pathname: string) => string;
32
33
  expireSeconds?: number;
33
34
  isrRevalidateSeconds: number | null;
34
- isrSet: (key: string, data: {
35
- kind: "PAGES";
36
- html: string;
37
- pageData: Record<string, unknown>;
38
- headers: undefined;
39
- status: undefined;
40
- }, revalidateSeconds: number, tags?: string[], expireSeconds?: number) => Promise<void>;
35
+ isrSet: (key: string, data: CachedPagesValue, revalidateSeconds: number, tags?: string[], expireSeconds?: number) => Promise<void>;
41
36
  i18n: PagesI18nRenderContext;
42
37
  pageProps: Record<string, unknown>;
43
38
  params: Record<string, unknown>;
44
39
  renderDocumentToString: (element: ReactNode) => Promise<string>;
45
- renderIsrPassToStringAsync: (element: ReactNode) => Promise<string>;
46
40
  renderToReadableStream: (element: ReactNode) => Promise<ReadableStream<Uint8Array>>;
47
41
  resetSSRHead?: (() => void) | undefined;
48
42
  routePattern: string;
@@ -1,6 +1,9 @@
1
+ import { getRequestExecutionContext } from "../shims/request-context.js";
2
+ import { reportRequestError } from "./instrumentation.js";
1
3
  import { withScriptNonce } from "../shims/script-nonce-context.js";
2
4
  import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr } from "./html.js";
3
5
  import { buildRevalidateCacheControl } from "./cache-control.js";
6
+ import { readStreamAsText } from "../utils/text-stream.js";
4
7
  import React from "react";
5
8
  //#region src/server/pages-page-response.ts
6
9
  function buildPagesFontHeadHtml(fontLinks, fontPreloads, fontStyles, scriptNonce) {
@@ -65,6 +68,30 @@ async function buildPagesCompositeStream(bodyStream, shellPrefix, shellSuffix) {
65
68
  controller.close();
66
69
  } });
67
70
  }
71
+ async function reportPagesIsrCacheWriteError(error, cacheKey, routePattern) {
72
+ console.error(`[vinext] Pages ISR cache write failed for ${cacheKey}:`, error);
73
+ try {
74
+ await reportRequestError(error instanceof Error ? error : new Error(String(error)), {
75
+ path: cacheKey,
76
+ method: "GET",
77
+ headers: {}
78
+ }, {
79
+ routerKind: "Pages Router",
80
+ routePath: routePattern,
81
+ routeType: "render"
82
+ });
83
+ } catch {}
84
+ }
85
+ function schedulePagesIsrCacheWrite(options) {
86
+ const cacheWritePromise = readStreamAsText(options.stream).then((bodyHtml) => options.setCache(options.cacheKey, {
87
+ kind: "PAGES",
88
+ html: options.shellPrefix + bodyHtml + options.shellSuffix,
89
+ pageData: options.pageData,
90
+ headers: void 0,
91
+ status: void 0
92
+ }, options.revalidateSeconds, void 0, options.expireSeconds)).catch((error) => reportPagesIsrCacheWriteError(error, options.cacheKey, options.routePattern));
93
+ getRequestExecutionContext()?.waitUntil(cacheWritePromise);
94
+ }
68
95
  function applyGsspHeaders(headers, gsspRes) {
69
96
  if (!gsspRes) return 200;
70
97
  const gsspHeaders = gsspRes.getHeaders();
@@ -109,20 +136,25 @@ async function renderPagesPageResponse(options) {
109
136
  const markerIndex = shellHtml.indexOf(bodyMarker);
110
137
  const shellPrefix = shellHtml.slice(0, markerIndex);
111
138
  const shellSuffix = shellHtml.slice(markerIndex + 25);
112
- const compositeStream = await buildPagesCompositeStream(bodyStream, shellPrefix, shellSuffix);
139
+ let responseBodyStream = bodyStream;
113
140
  if (!options.scriptNonce && options.isrRevalidateSeconds !== null && options.isrRevalidateSeconds > 0) {
114
- const isrElement = React.createElement(React.Fragment, null, options.createPageElement(options.pageProps));
115
- const fullHtml = shellPrefix + await options.renderIsrPassToStringAsync(isrElement) + shellSuffix;
141
+ const cacheBodyStreamPair = bodyStream.tee();
142
+ responseBodyStream = cacheBodyStreamPair[0];
143
+ const cacheBodyStream = cacheBodyStreamPair[1];
116
144
  const isrPathname = options.routeUrl.split("?")[0];
117
- const cacheKey = options.isrCacheKey("pages", isrPathname);
118
- await options.isrSet(cacheKey, {
119
- kind: "PAGES",
120
- html: fullHtml,
145
+ schedulePagesIsrCacheWrite({
146
+ cacheKey: options.isrCacheKey("pages", isrPathname),
147
+ expireSeconds: options.expireSeconds,
121
148
  pageData: options.pageProps,
122
- headers: void 0,
123
- status: void 0
124
- }, options.isrRevalidateSeconds, void 0, options.expireSeconds);
149
+ revalidateSeconds: options.isrRevalidateSeconds,
150
+ routePattern: options.routePattern,
151
+ setCache: options.isrSet,
152
+ shellPrefix,
153
+ shellSuffix,
154
+ stream: cacheBodyStream
155
+ });
125
156
  }
157
+ const compositeStream = await buildPagesCompositeStream(responseBodyStream, shellPrefix, shellSuffix);
126
158
  const responseHeaders = new Headers({ "Content-Type": "text/html" });
127
159
  const finalStatus = applyGsspHeaders(responseHeaders, options.gsspRes);
128
160
  if (options.scriptNonce) responseHeaders.set("Cache-Control", "no-store, must-revalidate");
@@ -131,12 +163,10 @@ async function renderPagesPageResponse(options) {
131
163
  responseHeaders.set("X-Vinext-Cache", "MISS");
132
164
  }
133
165
  if (options.fontLinkHeader) responseHeaders.set("Link", options.fontLinkHeader);
134
- const response = new Response(compositeStream, {
166
+ return Object.assign(new Response(compositeStream, {
135
167
  status: finalStatus,
136
168
  headers: responseHeaders
137
- });
138
- response.__vinextStreamedHtmlResponse = true;
139
- return response;
169
+ }), { __vinextStreamedHtmlResponse: true });
140
170
  }
141
171
  //#endregion
142
172
  export { buildPagesNextDataScript, renderPagesPageResponse };
@@ -1 +1 @@
1
- {"version":3,"file":"pages-page-response.js","names":[],"sources":["../../src/server/pages-page-response.ts"],"sourcesContent":["import React, { type ComponentType, type ReactNode } from \"react\";\nimport { withScriptNonce } from \"vinext/shims/script-nonce-context\";\nimport { buildRevalidateCacheControl } from \"./cache-control.js\";\nimport { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr } from \"./html.js\";\n\ntype PagesFontPreload = {\n href: string;\n type: string;\n};\n\nexport type PagesI18nRenderContext = {\n locale?: string;\n locales?: string[];\n defaultLocale?: string;\n domainLocales?: unknown;\n};\n\nexport type PagesGsspResponse = {\n statusCode: number;\n getHeaders(): Record<string, string | number | boolean | string[]>;\n};\n\ntype PagesStreamedHtmlResponse = {\n __vinextStreamedHtmlResponse?: boolean;\n} & Response;\n\ntype RenderPagesPageResponseOptions = {\n assetTags: string;\n buildId: string | null;\n clearSsrContext: () => void;\n createPageElement: (pageProps: Record<string, unknown>) => ReactNode;\n DocumentComponent: ComponentType | null;\n flushPreloads?: (() => Promise<void> | void) | undefined;\n fontLinkHeader: string;\n fontPreloads: PagesFontPreload[];\n getFontLinks: () => string[];\n getFontStyles: () => string[];\n getSSRHeadHTML?: (() => string) | undefined;\n gsspRes: PagesGsspResponse | null;\n isrCacheKey: (router: string, pathname: string) => string;\n expireSeconds?: number;\n isrRevalidateSeconds: number | null;\n isrSet: (\n key: string,\n data: {\n kind: \"PAGES\";\n html: string;\n pageData: Record<string, unknown>;\n headers: undefined;\n status: undefined;\n },\n revalidateSeconds: number,\n tags?: string[],\n expireSeconds?: number,\n ) => Promise<void>;\n i18n: PagesI18nRenderContext;\n pageProps: Record<string, unknown>;\n params: Record<string, unknown>;\n renderDocumentToString: (element: ReactNode) => Promise<string>;\n renderIsrPassToStringAsync: (element: ReactNode) => Promise<string>;\n renderToReadableStream: (element: ReactNode) => Promise<ReadableStream<Uint8Array>>;\n resetSSRHead?: (() => void) | undefined;\n routePattern: string;\n routeUrl: string;\n safeJsonStringify: (value: unknown) => string;\n scriptNonce?: string;\n};\n\nfunction buildPagesFontHeadHtml(\n fontLinks: string[],\n fontPreloads: PagesFontPreload[],\n fontStyles: string[],\n scriptNonce?: string,\n): string {\n let html = \"\";\n const nonceAttr = createNonceAttribute(scriptNonce);\n\n for (const link of fontLinks) {\n html += `<link rel=\"stylesheet\"${nonceAttr} href=\"${escapeHtmlAttr(link)}\" />\\n `;\n }\n\n for (const preload of fontPreloads) {\n html += `<link rel=\"preload\"${nonceAttr} href=\"${escapeHtmlAttr(preload.href)}\" as=\"font\" type=\"${escapeHtmlAttr(preload.type)}\" crossorigin />\\n `;\n }\n\n if (fontStyles.length > 0) {\n html += `<style data-vinext-fonts${nonceAttr}>${fontStyles.join(\"\\n\")}</style>\\n `;\n }\n\n return html;\n}\n\nexport function buildPagesNextDataScript(\n options: Pick<\n RenderPagesPageResponseOptions,\n | \"buildId\"\n | \"i18n\"\n | \"pageProps\"\n | \"params\"\n | \"routePattern\"\n | \"safeJsonStringify\"\n | \"scriptNonce\"\n >,\n): string {\n const nextDataPayload: Record<string, unknown> = {\n props: { pageProps: options.pageProps },\n page: options.routePattern,\n query: options.params,\n buildId: options.buildId,\n isFallback: false,\n };\n\n if (options.i18n.locales) {\n nextDataPayload.locale = options.i18n.locale;\n nextDataPayload.locales = options.i18n.locales;\n nextDataPayload.defaultLocale = options.i18n.defaultLocale;\n nextDataPayload.domainLocales = options.i18n.domainLocales;\n }\n\n const localeGlobals = options.i18n.locales\n ? `;window.__VINEXT_LOCALE__=${options.safeJsonStringify(options.i18n.locale)}` +\n `;window.__VINEXT_LOCALES__=${options.safeJsonStringify(options.i18n.locales)}` +\n `;window.__VINEXT_DEFAULT_LOCALE__=${options.safeJsonStringify(options.i18n.defaultLocale)}`\n : \"\";\n\n return createInlineScriptTag(\n `window.__NEXT_DATA__ = ${options.safeJsonStringify(nextDataPayload)}${localeGlobals}`,\n options.scriptNonce,\n );\n}\n\nasync function buildPagesShellHtml(\n bodyMarker: string,\n fontHeadHTML: string,\n nextDataScript: string,\n options: Pick<\n RenderPagesPageResponseOptions,\n \"assetTags\" | \"DocumentComponent\" | \"renderDocumentToString\"\n > & {\n ssrHeadHTML: string;\n },\n): Promise<string> {\n if (options.DocumentComponent) {\n let html = await options.renderDocumentToString(React.createElement(options.DocumentComponent));\n html = html.replace(\"__NEXT_MAIN__\", bodyMarker);\n if (options.ssrHeadHTML || options.assetTags || fontHeadHTML) {\n html = html.replace(\n \"</head>\",\n ` ${fontHeadHTML}${options.ssrHeadHTML}\\n ${options.assetTags}\\n</head>`,\n );\n }\n html = html.replace(\"<!-- __NEXT_SCRIPTS__ -->\", nextDataScript);\n if (!html.includes(\"__NEXT_DATA__\")) {\n html = html.replace(\"</body>\", ` ${nextDataScript}\\n</body>`);\n }\n return html;\n }\n\n return (\n \"<!DOCTYPE html>\\n<html>\\n<head>\\n\" +\n ' <meta charset=\"utf-8\" />\\n' +\n ' <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\\n' +\n ` ${fontHeadHTML}${options.ssrHeadHTML}\\n` +\n ` ${options.assetTags}\\n` +\n \"</head>\\n<body>\\n\" +\n ` <div id=\"__next\">${bodyMarker}</div>\\n` +\n ` ${nextDataScript}\\n` +\n \"</body>\\n</html>\"\n );\n}\n\nasync function buildPagesCompositeStream(\n bodyStream: ReadableStream<Uint8Array>,\n shellPrefix: string,\n shellSuffix: string,\n): Promise<ReadableStream<Uint8Array>> {\n const encoder = new TextEncoder();\n\n return new ReadableStream({\n async start(controller) {\n controller.enqueue(encoder.encode(shellPrefix));\n const reader = bodyStream.getReader();\n try {\n for (;;) {\n const chunk = await reader.read();\n if (chunk.done) {\n break;\n }\n controller.enqueue(chunk.value);\n }\n } finally {\n reader.releaseLock();\n }\n controller.enqueue(encoder.encode(shellSuffix));\n controller.close();\n },\n });\n}\n\nfunction applyGsspHeaders(headers: Headers, gsspRes: PagesGsspResponse | null): number {\n if (!gsspRes) {\n return 200;\n }\n\n const gsspHeaders = gsspRes.getHeaders();\n for (const key of Object.keys(gsspHeaders)) {\n const value = gsspHeaders[key];\n const lowerKey = key.toLowerCase();\n if (lowerKey === \"set-cookie\" && Array.isArray(value)) {\n for (const cookie of value) {\n headers.append(\"set-cookie\", String(cookie));\n }\n continue;\n }\n if (Array.isArray(value)) {\n headers.set(key, value.join(\", \"));\n continue;\n }\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n headers.set(key, String(value));\n }\n }\n headers.set(\"Content-Type\", \"text/html\");\n return gsspRes.statusCode;\n}\n\nexport async function renderPagesPageResponse(\n options: RenderPagesPageResponseOptions,\n): Promise<Response> {\n const pageElement = withScriptNonce(\n React.createElement(React.Fragment, null, options.createPageElement(options.pageProps)),\n options.scriptNonce,\n );\n\n options.resetSSRHead?.();\n await options.flushPreloads?.();\n\n const fontHeadHTML = buildPagesFontHeadHtml(\n options.getFontLinks(),\n options.fontPreloads,\n options.getFontStyles(),\n options.scriptNonce,\n );\n const nextDataScript = buildPagesNextDataScript({\n buildId: options.buildId,\n i18n: options.i18n,\n pageProps: options.pageProps,\n params: options.params,\n routePattern: options.routePattern,\n safeJsonStringify: options.safeJsonStringify,\n scriptNonce: options.scriptNonce,\n });\n const bodyMarker = \"<!--VINEXT_STREAM_BODY-->\";\n // Render the page FIRST so that <Head> and other SSR state collectors\n // (e.g. styled-jsx, useServerInsertedHTML) are populated before we read\n // them. This fixes a race condition where head styles were silently dropped\n // because they were collected before the page had finished rendering.\n // Mirrors Next.js fix: vercel/next.js@9853944\n const bodyStream = await options.renderToReadableStream(pageElement);\n\n const shellHtml = await buildPagesShellHtml(bodyMarker, fontHeadHTML, nextDataScript, {\n assetTags: options.assetTags,\n DocumentComponent: options.DocumentComponent,\n renderDocumentToString: options.renderDocumentToString,\n ssrHeadHTML: options.getSSRHeadHTML?.() ?? \"\",\n });\n\n options.clearSsrContext();\n\n const markerIndex = shellHtml.indexOf(bodyMarker);\n const shellPrefix = shellHtml.slice(0, markerIndex);\n const shellSuffix = shellHtml.slice(markerIndex + bodyMarker.length);\n const compositeStream = await buildPagesCompositeStream(bodyStream, shellPrefix, shellSuffix);\n\n if (\n // Keep nonce-bearing pages out of ISR writes: rewritePagesCachedHtml()\n // later matches the cached __NEXT_DATA__ block via a bare <script> marker.\n !options.scriptNonce &&\n options.isrRevalidateSeconds !== null &&\n options.isrRevalidateSeconds > 0\n ) {\n const isrElement = React.createElement(\n React.Fragment,\n null,\n options.createPageElement(options.pageProps),\n );\n const isrHtml = await options.renderIsrPassToStringAsync(isrElement);\n const fullHtml = shellPrefix + isrHtml + shellSuffix;\n const isrPathname = options.routeUrl.split(\"?\")[0];\n const cacheKey = options.isrCacheKey(\"pages\", isrPathname);\n await options.isrSet(\n cacheKey,\n {\n kind: \"PAGES\",\n html: fullHtml,\n pageData: options.pageProps,\n headers: undefined,\n status: undefined,\n },\n options.isrRevalidateSeconds,\n undefined,\n options.expireSeconds,\n );\n }\n\n const responseHeaders = new Headers({ \"Content-Type\": \"text/html\" });\n const finalStatus = applyGsspHeaders(responseHeaders, options.gsspRes);\n\n if (options.scriptNonce) {\n responseHeaders.set(\"Cache-Control\", \"no-store, must-revalidate\");\n } else if (options.isrRevalidateSeconds) {\n responseHeaders.set(\n \"Cache-Control\",\n buildRevalidateCacheControl(options.isrRevalidateSeconds, options.expireSeconds),\n );\n responseHeaders.set(\"X-Vinext-Cache\", \"MISS\");\n }\n if (options.fontLinkHeader) {\n responseHeaders.set(\"Link\", options.fontLinkHeader);\n }\n\n const response = new Response(compositeStream, {\n status: finalStatus,\n headers: responseHeaders,\n }) as PagesStreamedHtmlResponse;\n // Mark the normal streamed HTML render so the Node prod server can strip\n // stale Content-Length only for this path, not for custom gSSP responses.\n response.__vinextStreamedHtmlResponse = true;\n return response;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pages-page-response.js","names":[],"sources":["../../src/server/pages-page-response.ts"],"sourcesContent":["import React, { type ComponentType, type ReactNode } from \"react\";\nimport type { CachedPagesValue } from \"vinext/shims/cache\";\nimport { withScriptNonce } from \"vinext/shims/script-nonce-context\";\nimport { getRequestExecutionContext } from \"vinext/shims/request-context\";\nimport { buildRevalidateCacheControl } from \"./cache-control.js\";\nimport { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr } from \"./html.js\";\nimport { reportRequestError } from \"./instrumentation.js\";\nimport { readStreamAsText } from \"../utils/text-stream.js\";\n\ntype PagesFontPreload = {\n href: string;\n type: string;\n};\n\nexport type PagesI18nRenderContext = {\n locale?: string;\n locales?: string[];\n defaultLocale?: string;\n domainLocales?: unknown;\n};\n\nexport type PagesGsspResponse = {\n statusCode: number;\n getHeaders(): Record<string, string | number | boolean | string[]>;\n};\n\ntype PagesStreamedHtmlResponse = {\n __vinextStreamedHtmlResponse?: boolean;\n} & Response;\n\ntype RenderPagesPageResponseOptions = {\n assetTags: string;\n buildId: string | null;\n clearSsrContext: () => void;\n createPageElement: (pageProps: Record<string, unknown>) => ReactNode;\n DocumentComponent: ComponentType | null;\n flushPreloads?: (() => Promise<void> | void) | undefined;\n fontLinkHeader: string;\n fontPreloads: PagesFontPreload[];\n getFontLinks: () => string[];\n getFontStyles: () => string[];\n getSSRHeadHTML?: (() => string) | undefined;\n gsspRes: PagesGsspResponse | null;\n isrCacheKey: (router: string, pathname: string) => string;\n expireSeconds?: number;\n isrRevalidateSeconds: number | null;\n isrSet: (\n key: string,\n data: CachedPagesValue,\n revalidateSeconds: number,\n tags?: string[],\n expireSeconds?: number,\n ) => Promise<void>;\n i18n: PagesI18nRenderContext;\n pageProps: Record<string, unknown>;\n params: Record<string, unknown>;\n renderDocumentToString: (element: ReactNode) => Promise<string>;\n renderToReadableStream: (element: ReactNode) => Promise<ReadableStream<Uint8Array>>;\n resetSSRHead?: (() => void) | undefined;\n routePattern: string;\n routeUrl: string;\n safeJsonStringify: (value: unknown) => string;\n scriptNonce?: string;\n};\n\nfunction buildPagesFontHeadHtml(\n fontLinks: string[],\n fontPreloads: PagesFontPreload[],\n fontStyles: string[],\n scriptNonce?: string,\n): string {\n let html = \"\";\n const nonceAttr = createNonceAttribute(scriptNonce);\n\n for (const link of fontLinks) {\n html += `<link rel=\"stylesheet\"${nonceAttr} href=\"${escapeHtmlAttr(link)}\" />\\n `;\n }\n\n for (const preload of fontPreloads) {\n html += `<link rel=\"preload\"${nonceAttr} href=\"${escapeHtmlAttr(preload.href)}\" as=\"font\" type=\"${escapeHtmlAttr(preload.type)}\" crossorigin />\\n `;\n }\n\n if (fontStyles.length > 0) {\n html += `<style data-vinext-fonts${nonceAttr}>${fontStyles.join(\"\\n\")}</style>\\n `;\n }\n\n return html;\n}\n\nexport function buildPagesNextDataScript(\n options: Pick<\n RenderPagesPageResponseOptions,\n | \"buildId\"\n | \"i18n\"\n | \"pageProps\"\n | \"params\"\n | \"routePattern\"\n | \"safeJsonStringify\"\n | \"scriptNonce\"\n >,\n): string {\n const nextDataPayload: Record<string, unknown> = {\n props: { pageProps: options.pageProps },\n page: options.routePattern,\n query: options.params,\n buildId: options.buildId,\n isFallback: false,\n };\n\n if (options.i18n.locales) {\n nextDataPayload.locale = options.i18n.locale;\n nextDataPayload.locales = options.i18n.locales;\n nextDataPayload.defaultLocale = options.i18n.defaultLocale;\n nextDataPayload.domainLocales = options.i18n.domainLocales;\n }\n\n const localeGlobals = options.i18n.locales\n ? `;window.__VINEXT_LOCALE__=${options.safeJsonStringify(options.i18n.locale)}` +\n `;window.__VINEXT_LOCALES__=${options.safeJsonStringify(options.i18n.locales)}` +\n `;window.__VINEXT_DEFAULT_LOCALE__=${options.safeJsonStringify(options.i18n.defaultLocale)}`\n : \"\";\n\n return createInlineScriptTag(\n `window.__NEXT_DATA__ = ${options.safeJsonStringify(nextDataPayload)}${localeGlobals}`,\n options.scriptNonce,\n );\n}\n\nasync function buildPagesShellHtml(\n bodyMarker: string,\n fontHeadHTML: string,\n nextDataScript: string,\n options: Pick<\n RenderPagesPageResponseOptions,\n \"assetTags\" | \"DocumentComponent\" | \"renderDocumentToString\"\n > & {\n ssrHeadHTML: string;\n },\n): Promise<string> {\n if (options.DocumentComponent) {\n let html = await options.renderDocumentToString(React.createElement(options.DocumentComponent));\n html = html.replace(\"__NEXT_MAIN__\", bodyMarker);\n if (options.ssrHeadHTML || options.assetTags || fontHeadHTML) {\n html = html.replace(\n \"</head>\",\n ` ${fontHeadHTML}${options.ssrHeadHTML}\\n ${options.assetTags}\\n</head>`,\n );\n }\n html = html.replace(\"<!-- __NEXT_SCRIPTS__ -->\", nextDataScript);\n if (!html.includes(\"__NEXT_DATA__\")) {\n html = html.replace(\"</body>\", ` ${nextDataScript}\\n</body>`);\n }\n return html;\n }\n\n return (\n \"<!DOCTYPE html>\\n<html>\\n<head>\\n\" +\n ' <meta charset=\"utf-8\" />\\n' +\n ' <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\\n' +\n ` ${fontHeadHTML}${options.ssrHeadHTML}\\n` +\n ` ${options.assetTags}\\n` +\n \"</head>\\n<body>\\n\" +\n ` <div id=\"__next\">${bodyMarker}</div>\\n` +\n ` ${nextDataScript}\\n` +\n \"</body>\\n</html>\"\n );\n}\n\nasync function buildPagesCompositeStream(\n bodyStream: ReadableStream<Uint8Array>,\n shellPrefix: string,\n shellSuffix: string,\n): Promise<ReadableStream<Uint8Array>> {\n const encoder = new TextEncoder();\n\n return new ReadableStream({\n async start(controller) {\n controller.enqueue(encoder.encode(shellPrefix));\n const reader = bodyStream.getReader();\n try {\n for (;;) {\n const chunk = await reader.read();\n if (chunk.done) {\n break;\n }\n controller.enqueue(chunk.value);\n }\n } finally {\n reader.releaseLock();\n }\n controller.enqueue(encoder.encode(shellSuffix));\n controller.close();\n },\n });\n}\n\nasync function reportPagesIsrCacheWriteError(\n error: unknown,\n cacheKey: string,\n routePattern: string,\n): Promise<void> {\n console.error(`[vinext] Pages ISR cache write failed for ${cacheKey}:`, error);\n try {\n await reportRequestError(\n error instanceof Error ? error : new Error(String(error)),\n { path: cacheKey, method: \"GET\", headers: {} },\n {\n routerKind: \"Pages Router\",\n routePath: routePattern,\n routeType: \"render\",\n },\n );\n } catch {\n // Cache-write failure reporting must never make the background task reject.\n }\n}\n\nfunction schedulePagesIsrCacheWrite(options: {\n cacheKey: string;\n expireSeconds?: number;\n pageData: Record<string, unknown>;\n revalidateSeconds: number;\n routePattern: string;\n shellPrefix: string;\n shellSuffix: string;\n stream: ReadableStream<Uint8Array>;\n setCache: RenderPagesPageResponseOptions[\"isrSet\"];\n}): void {\n const cacheWritePromise = readStreamAsText(options.stream)\n .then((bodyHtml) =>\n options.setCache(\n options.cacheKey,\n {\n kind: \"PAGES\",\n html: options.shellPrefix + bodyHtml + options.shellSuffix,\n pageData: options.pageData,\n headers: undefined,\n status: undefined,\n },\n options.revalidateSeconds,\n undefined,\n options.expireSeconds,\n ),\n )\n .catch((error: unknown) =>\n reportPagesIsrCacheWriteError(error, options.cacheKey, options.routePattern),\n );\n\n getRequestExecutionContext()?.waitUntil(cacheWritePromise);\n}\n\nfunction applyGsspHeaders(headers: Headers, gsspRes: PagesGsspResponse | null): number {\n if (!gsspRes) {\n return 200;\n }\n\n const gsspHeaders = gsspRes.getHeaders();\n for (const key of Object.keys(gsspHeaders)) {\n const value = gsspHeaders[key];\n const lowerKey = key.toLowerCase();\n if (lowerKey === \"set-cookie\" && Array.isArray(value)) {\n for (const cookie of value) {\n headers.append(\"set-cookie\", String(cookie));\n }\n continue;\n }\n if (Array.isArray(value)) {\n headers.set(key, value.join(\", \"));\n continue;\n }\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n headers.set(key, String(value));\n }\n }\n headers.set(\"Content-Type\", \"text/html\");\n return gsspRes.statusCode;\n}\n\nexport async function renderPagesPageResponse(\n options: RenderPagesPageResponseOptions,\n): Promise<Response> {\n const pageElement = withScriptNonce(\n React.createElement(React.Fragment, null, options.createPageElement(options.pageProps)),\n options.scriptNonce,\n );\n\n options.resetSSRHead?.();\n await options.flushPreloads?.();\n\n const fontHeadHTML = buildPagesFontHeadHtml(\n options.getFontLinks(),\n options.fontPreloads,\n options.getFontStyles(),\n options.scriptNonce,\n );\n const nextDataScript = buildPagesNextDataScript({\n buildId: options.buildId,\n i18n: options.i18n,\n pageProps: options.pageProps,\n params: options.params,\n routePattern: options.routePattern,\n safeJsonStringify: options.safeJsonStringify,\n scriptNonce: options.scriptNonce,\n });\n const bodyMarker = \"<!--VINEXT_STREAM_BODY-->\";\n // Render the page FIRST so that <Head> and other SSR state collectors\n // (e.g. styled-jsx, useServerInsertedHTML) are populated before we read\n // them. This fixes a race condition where head styles were silently dropped\n // because they were collected before the page had finished rendering.\n // Mirrors Next.js fix: vercel/next.js@9853944\n const bodyStream = await options.renderToReadableStream(pageElement);\n\n const shellHtml = await buildPagesShellHtml(bodyMarker, fontHeadHTML, nextDataScript, {\n assetTags: options.assetTags,\n DocumentComponent: options.DocumentComponent,\n renderDocumentToString: options.renderDocumentToString,\n ssrHeadHTML: options.getSSRHeadHTML?.() ?? \"\",\n });\n\n options.clearSsrContext();\n\n const markerIndex = shellHtml.indexOf(bodyMarker);\n const shellPrefix = shellHtml.slice(0, markerIndex);\n const shellSuffix = shellHtml.slice(markerIndex + bodyMarker.length);\n\n let responseBodyStream = bodyStream;\n if (\n // Keep nonce-bearing pages out of ISR writes: rewritePagesCachedHtml()\n // later matches the cached __NEXT_DATA__ block via a bare <script> marker.\n !options.scriptNonce &&\n options.isrRevalidateSeconds !== null &&\n options.isrRevalidateSeconds > 0\n ) {\n const cacheBodyStreamPair = bodyStream.tee();\n responseBodyStream = cacheBodyStreamPair[0];\n const cacheBodyStream = cacheBodyStreamPair[1];\n const isrPathname = options.routeUrl.split(\"?\")[0];\n const cacheKey = options.isrCacheKey(\"pages\", isrPathname);\n\n schedulePagesIsrCacheWrite({\n cacheKey,\n expireSeconds: options.expireSeconds,\n pageData: options.pageProps,\n revalidateSeconds: options.isrRevalidateSeconds,\n routePattern: options.routePattern,\n setCache: options.isrSet,\n shellPrefix,\n shellSuffix,\n stream: cacheBodyStream,\n });\n }\n\n const compositeStream = await buildPagesCompositeStream(\n responseBodyStream,\n shellPrefix,\n shellSuffix,\n );\n\n const responseHeaders = new Headers({ \"Content-Type\": \"text/html\" });\n const finalStatus = applyGsspHeaders(responseHeaders, options.gsspRes);\n\n if (options.scriptNonce) {\n responseHeaders.set(\"Cache-Control\", \"no-store, must-revalidate\");\n } else if (options.isrRevalidateSeconds) {\n responseHeaders.set(\n \"Cache-Control\",\n buildRevalidateCacheControl(options.isrRevalidateSeconds, options.expireSeconds),\n );\n responseHeaders.set(\"X-Vinext-Cache\", \"MISS\");\n }\n if (options.fontLinkHeader) {\n responseHeaders.set(\"Link\", options.fontLinkHeader);\n }\n\n const response: PagesStreamedHtmlResponse = Object.assign(\n new Response(compositeStream, {\n status: finalStatus,\n headers: responseHeaders,\n }),\n {\n __vinextStreamedHtmlResponse: true,\n },\n );\n // Mark the normal streamed HTML render so the Node prod server can strip\n // stale Content-Length only for this path, not for custom gSSP responses.\n return response;\n}\n"],"mappings":"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"}
@@ -8,6 +8,12 @@ type ProdServerOptions = {
8
8
  host?: string; /** Path to the build output directory */
9
9
  outDir?: string; /** Disable compression (default: false) */
10
10
  noCompression?: boolean;
11
+ /**
12
+ * Narrow startup context for callers that need a more precise log line.
13
+ * Omitted for normal `vinext start` so the existing production-server output
14
+ * remains stable.
15
+ */
16
+ purpose?: "prerender";
11
17
  };
12
18
  /** Content types that benefit from compression. */
13
19
  declare const COMPRESSIBLE_TYPES: Set<string>;