vinext 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/README.md +5 -2
  2. package/THIRD_PARTY_LICENSES.md +47 -0
  3. package/dist/_virtual/_rolldown/runtime.js +3 -2
  4. package/dist/build/prerender.js +1 -1
  5. package/dist/build/report.d.ts +0 -14
  6. package/dist/build/report.js +1 -51
  7. package/dist/check.js +1 -1
  8. package/dist/cli.js +3 -0
  9. package/dist/client/dev-error-overlay.js +1 -1
  10. package/dist/client/navigation-runtime.d.ts +13 -1
  11. package/dist/client/navigation-runtime.js +1 -1
  12. package/dist/config/next-config.d.ts +19 -0
  13. package/dist/config/next-config.js +64 -1
  14. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
  15. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
  16. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
  17. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
  18. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
  19. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
  20. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
  21. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
  22. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
  23. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
  24. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
  25. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
  26. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
  27. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
  28. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
  29. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
  30. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
  31. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
  32. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
  33. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
  34. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
  35. package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
  36. package/dist/entries/app-rsc-entry.js +17 -48
  37. package/dist/entries/app-rsc-manifest.js +3 -4
  38. package/dist/entries/app-ssr-entry.js +1 -0
  39. package/dist/entries/pages-server-entry.js +33 -8
  40. package/dist/index.js +83 -70
  41. package/dist/init-cloudflare.d.ts +1 -3
  42. package/dist/init-cloudflare.js +10 -48
  43. package/dist/init-platform.d.ts +2 -0
  44. package/dist/init-platform.js +4 -0
  45. package/dist/plugins/extensionless-dynamic-import.js +6 -2
  46. package/dist/plugins/next-intl-catalog.d.ts +12 -0
  47. package/dist/plugins/next-intl-catalog.js +85 -0
  48. package/dist/plugins/pages-node-externals.d.ts +1 -0
  49. package/dist/plugins/pages-node-externals.js +1 -1
  50. package/dist/plugins/use-cache-callable.d.ts +1 -1
  51. package/dist/plugins/use-cache-callable.js +136 -94
  52. package/dist/routing/app-route-graph.d.ts +6 -0
  53. package/dist/routing/app-route-graph.js +9 -1
  54. package/dist/server/api-handler.js +19 -4
  55. package/dist/server/app-bfcache-identity.js +1 -1
  56. package/dist/server/app-browser-entry.js +79 -63
  57. package/dist/server/app-browser-history-controller.d.ts +5 -4
  58. package/dist/server/app-browser-history-controller.js +93 -15
  59. package/dist/server/app-browser-navigation-controller.d.ts +2 -2
  60. package/dist/server/app-browser-navigation-controller.js +1 -2
  61. package/dist/server/app-browser-rsc-redirect.js +4 -4
  62. package/dist/server/app-browser-server-action-client.d.ts +2 -0
  63. package/dist/server/app-browser-server-action-client.js +4 -3
  64. package/dist/server/app-browser-state.d.ts +2 -4
  65. package/dist/server/app-browser-state.js +9 -4
  66. package/dist/server/app-browser-supplemental-refresh.js +16 -1
  67. package/dist/server/app-browser-visible-commit.d.ts +1 -1
  68. package/dist/server/app-browser-visible-commit.js +2 -12
  69. package/dist/server/app-elements-wire.d.ts +6 -38
  70. package/dist/server/app-elements-wire.js +4 -41
  71. package/dist/server/app-elements.d.ts +2 -2
  72. package/dist/server/app-elements.js +2 -2
  73. package/dist/server/app-history-state.d.ts +2 -2
  74. package/dist/server/app-history-state.js +5 -2
  75. package/dist/server/app-mounted-layouts.d.ts +21 -0
  76. package/dist/server/app-mounted-layouts.js +67 -0
  77. package/dist/server/app-optimistic-routing.d.ts +19 -1
  78. package/dist/server/app-optimistic-routing.js +42 -2
  79. package/dist/server/app-page-boundary-render.js +7 -6
  80. package/dist/server/app-page-boundary.js +2 -2
  81. package/dist/server/app-page-cache-finalizer.d.ts +12 -1
  82. package/dist/server/app-page-cache-finalizer.js +70 -29
  83. package/dist/server/app-page-cache.d.ts +13 -1
  84. package/dist/server/app-page-cache.js +31 -9
  85. package/dist/server/app-page-dispatch.d.ts +5 -10
  86. package/dist/server/app-page-dispatch.js +84 -154
  87. package/dist/server/app-page-element-builder.d.ts +2 -2
  88. package/dist/server/app-page-element-builder.js +10 -9
  89. package/dist/server/app-page-execution.d.ts +17 -52
  90. package/dist/server/app-page-execution.js +99 -95
  91. package/dist/server/app-page-head.d.ts +13 -0
  92. package/dist/server/app-page-head.js +44 -16
  93. package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
  94. package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
  95. package/dist/server/app-page-layout-gate.d.ts +35 -0
  96. package/dist/server/app-page-layout-gate.js +50 -0
  97. package/dist/server/app-page-params.d.ts +0 -1
  98. package/dist/server/app-page-params.js +1 -14
  99. package/dist/server/app-page-probe.d.ts +3 -21
  100. package/dist/server/app-page-probe.js +4 -37
  101. package/dist/server/app-page-render.d.ts +2 -12
  102. package/dist/server/app-page-render.js +89 -220
  103. package/dist/server/app-page-request.d.ts +1 -3
  104. package/dist/server/app-page-request.js +1 -1
  105. package/dist/server/app-page-response.js +3 -3
  106. package/dist/server/app-page-route-wiring.d.ts +13 -6
  107. package/dist/server/app-page-route-wiring.js +67 -61
  108. package/dist/server/app-page-rsc-render-status.d.ts +27 -1
  109. package/dist/server/app-page-rsc-render-status.js +121 -13
  110. package/dist/server/app-page-stream.d.ts +2 -0
  111. package/dist/server/app-page-stream.js +2 -2
  112. package/dist/server/app-pages-bridge.d.ts +4 -0
  113. package/dist/server/app-pages-bridge.js +7 -3
  114. package/dist/server/app-render-dependency.d.ts +11 -4
  115. package/dist/server/app-render-dependency.js +86 -38
  116. package/dist/server/app-request-stage-dispatch.js +1 -1
  117. package/dist/server/app-route-handler-cache.js +2 -2
  118. package/dist/server/app-route-handler-dispatch.js +14 -9
  119. package/dist/server/app-route-handler-execution.js +8 -3
  120. package/dist/server/app-route-handler-policy.d.ts +1 -1
  121. package/dist/server/app-route-handler-policy.js +3 -3
  122. package/dist/server/app-route-handler-response.js +1 -1
  123. package/dist/server/app-route-handler-runtime.js +17 -4
  124. package/dist/server/app-rsc-cache-busting.d.ts +2 -2
  125. package/dist/server/app-rsc-cache-busting.js +4 -4
  126. package/dist/server/app-rsc-error-handler.d.ts +2 -1
  127. package/dist/server/app-rsc-error-handler.js +9 -1
  128. package/dist/server/app-rsc-errors.d.ts +8 -0
  129. package/dist/server/app-rsc-errors.js +8 -1
  130. package/dist/server/app-rsc-handler.d.ts +5 -5
  131. package/dist/server/app-rsc-handler.js +30 -24
  132. package/dist/server/app-rsc-request-normalization.d.ts +0 -4
  133. package/dist/server/app-rsc-request-normalization.js +1 -4
  134. package/dist/server/app-rsc-response-finalizer.js +2 -2
  135. package/dist/server/app-rsc-response-stage.js +5 -3
  136. package/dist/server/app-server-action-execution.d.ts +3 -1
  137. package/dist/server/app-server-action-execution.js +7 -4
  138. package/dist/server/app-ssr-entry.d.ts +2 -0
  139. package/dist/server/app-ssr-entry.js +9 -8
  140. package/dist/server/app-ssr-stream.js +1 -1
  141. package/dist/server/app-visited-response-cache.d.ts +36 -1
  142. package/dist/server/app-visited-response-cache.js +46 -5
  143. package/dist/server/app-worker-stages.d.ts +25 -3
  144. package/dist/server/app-worker-stages.js +45 -6
  145. package/dist/server/artifact-compatibility.d.ts +0 -1
  146. package/dist/server/artifact-compatibility.js +1 -10
  147. package/dist/server/cache-proof.d.ts +1 -115
  148. package/dist/server/cache-proof.js +1 -544
  149. package/dist/server/cacheability-request.js +13 -8
  150. package/dist/server/dev-server.js +4 -3
  151. package/dist/server/headers.d.ts +6 -3
  152. package/dist/server/headers.js +9 -5
  153. package/dist/server/isr-cache.d.ts +8 -2
  154. package/dist/server/isr-cache.js +26 -1
  155. package/dist/server/metadata-route-response.js +32 -15
  156. package/dist/server/multi-stage.d.ts +52 -11
  157. package/dist/server/multi-stage.js +13 -1
  158. package/dist/server/navigation-planner.js +1 -1
  159. package/dist/server/pages-api-route.js +28 -19
  160. package/dist/server/pages-media-type.d.ts +21 -1
  161. package/dist/server/pages-media-type.js +69 -5
  162. package/dist/server/pages-node-compat.js +52 -27
  163. package/dist/server/pages-page-handler.js +11 -20
  164. package/dist/server/pages-request-pipeline.d.ts +8 -0
  165. package/dist/server/pages-request-pipeline.js +2 -2
  166. package/dist/server/pages-request-stage-entry.js +14 -12
  167. package/dist/server/pages-response-stage-entry.js +9 -3
  168. package/dist/server/prod-server.js +5 -1
  169. package/dist/server/request-pipeline.d.ts +6 -0
  170. package/dist/server/request-pipeline.js +21 -1
  171. package/dist/server/shared-cache-identity.d.ts +23 -0
  172. package/dist/server/shared-cache-identity.js +36 -0
  173. package/dist/server/worker-stages.d.ts +16 -3
  174. package/dist/server/worker-stages.js +23 -4
  175. package/dist/shims/cache-handler.js +2 -2
  176. package/dist/shims/cache-request-state.d.ts +17 -20
  177. package/dist/shims/cache-request-state.js +16 -21
  178. package/dist/shims/cache-runtime.js +27 -11
  179. package/dist/shims/cache.d.ts +8 -7
  180. package/dist/shims/cache.js +17 -19
  181. package/dist/shims/cacheability-classification.d.ts +2 -0
  182. package/dist/shims/cdn-cache.d.ts +22 -5
  183. package/dist/shims/client-page-root.js +2 -2
  184. package/dist/shims/dynamic.js +9 -6
  185. package/dist/shims/error-boundary.js +2 -2
  186. package/dist/shims/fetch-cache-state.d.ts +5 -1
  187. package/dist/shims/fetch-cache-state.js +1 -3
  188. package/dist/shims/fetch-cache.d.ts +2 -1
  189. package/dist/shims/fetch-cache.js +34 -24
  190. package/dist/shims/form.js +2 -2
  191. package/dist/shims/headers.d.ts +8 -23
  192. package/dist/shims/headers.js +17 -67
  193. package/dist/shims/internal/navigation-untracked.js +1 -1
  194. package/dist/shims/link.js +3 -1
  195. package/dist/shims/metadata.d.ts +23 -21
  196. package/dist/shims/metadata.js +62 -24
  197. package/dist/shims/navigation-server.js +1 -1
  198. package/dist/shims/navigation.d.ts +74 -7
  199. package/dist/shims/navigation.js +183 -29
  200. package/dist/shims/navigation.react-server.js +2 -2
  201. package/dist/shims/request-state-types.d.ts +2 -2
  202. package/dist/shims/slot.d.ts +12 -0
  203. package/dist/shims/slot.js +37 -9
  204. package/dist/shims/unified-request-context.d.ts +1 -1
  205. package/dist/shims/unified-request-context.js +2 -3
  206. package/dist/utils/cache-control-metadata.d.ts +5 -0
  207. package/dist/utils/cache-control-metadata.js +9 -1
  208. package/dist/utils/project.d.ts +2 -2
  209. package/dist/utils/project.js +3 -16
  210. package/dist/utils/regex.d.ts +5 -0
  211. package/dist/utils/regex.js +11 -1
  212. package/dist/utils/text-stream.d.ts +10 -5
  213. package/dist/utils/text-stream.js +6 -6
  214. package/package.json +2 -1
  215. package/dist/build/layout-classification-types.d.ts +0 -60
  216. package/dist/build/layout-classification-types.js +0 -1
  217. package/dist/build/layout-classification.d.ts +0 -62
  218. package/dist/build/layout-classification.js +0 -98
  219. package/dist/build/route-classification-injector.d.ts +0 -33
  220. package/dist/build/route-classification-injector.js +0 -59
  221. package/dist/build/route-classification-manifest.d.ts +0 -54
  222. package/dist/build/route-classification-manifest.js +0 -143
  223. package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
  224. package/dist/server/app-browser-client-reuse-manifest.js +0 -101
  225. package/dist/server/app-layout-param-observation.d.ts +0 -42
  226. package/dist/server/app-layout-param-observation.js +0 -168
  227. package/dist/server/client-reuse-manifest.d.ts +0 -103
  228. package/dist/server/client-reuse-manifest.js +0 -209
  229. package/dist/server/skip-cache-proof.d.ts +0 -60
  230. package/dist/server/skip-cache-proof.js +0 -168
  231. package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
  232. package/dist/server/static-layout-client-reuse-proof.js +0 -33
  233. package/dist/utils/sorted-array.d.ts +0 -8
  234. package/dist/utils/sorted-array.js +0 -20
@@ -15,13 +15,18 @@
15
15
  */
16
16
  export declare function readStreamAsText(stream: ReadableStream<Uint8Array>): Promise<string>;
17
17
  /**
18
- * Drain a UTF-8 byte stream up to `maxBytes` of *raw* input, returning the
19
- * decoded text. If the raw size limit is exceeded, cancellation is signalled
20
- * and `onLimitExceeded` is invoked; it MUST throw — its return type is
21
- * `never` to enforce that. Each caller passes its own error type.
18
+ * Drain a byte stream up to `maxBytes` of *raw* input, returning the decoded
19
+ * text (UTF-8 unless the caller passes its own `decoder`). If the raw size
20
+ * limit is exceeded, cancellation is signalled and `onLimitExceeded` is
21
+ * invoked; it MUST throw — its return type is `never` to enforce that. Each
22
+ * caller passes its own error type.
22
23
  *
23
24
  * The size check is on raw bytes (pre-decode) to bound memory before
24
25
  * paying the decoder cost.
25
26
  */
26
- export declare function readStreamAsTextWithLimit(stream: ReadableStream<Uint8Array>, maxBytes: number, onLimitExceeded: () => never): Promise<string>;
27
+ export declare function readStreamAsTextWithLimit(stream: ReadableStream<Uint8Array>, maxBytes: number, onLimitExceeded: () => never, decoder?: {
28
+ decode(input?: Uint8Array, options?: {
29
+ stream?: boolean;
30
+ }): string;
31
+ }): Promise<string>;
27
32
  //#endregion
@@ -30,17 +30,17 @@ async function readStreamAsText(stream) {
30
30
  }
31
31
  }
32
32
  /**
33
- * Drain a UTF-8 byte stream up to `maxBytes` of *raw* input, returning the
34
- * decoded text. If the raw size limit is exceeded, cancellation is signalled
35
- * and `onLimitExceeded` is invoked; it MUST throw — its return type is
36
- * `never` to enforce that. Each caller passes its own error type.
33
+ * Drain a byte stream up to `maxBytes` of *raw* input, returning the decoded
34
+ * text (UTF-8 unless the caller passes its own `decoder`). If the raw size
35
+ * limit is exceeded, cancellation is signalled and `onLimitExceeded` is
36
+ * invoked; it MUST throw — its return type is `never` to enforce that. Each
37
+ * caller passes its own error type.
37
38
  *
38
39
  * The size check is on raw bytes (pre-decode) to bound memory before
39
40
  * paying the decoder cost.
40
41
  */
41
- async function readStreamAsTextWithLimit(stream, maxBytes, onLimitExceeded) {
42
+ async function readStreamAsTextWithLimit(stream, maxBytes, onLimitExceeded, decoder = new TextDecoder()) {
42
43
  const reader = stream.getReader();
43
- const decoder = new TextDecoder();
44
44
  const chunks = [];
45
45
  let totalSize = 0;
46
46
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinext",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "Run Next.js apps on Vite. Drop-in replacement for the next CLI.",
5
5
  "homepage": "https://vinext.dev/",
6
6
  "license": "MIT",
@@ -240,6 +240,7 @@
240
240
  "@vitejs/plugin-react": "^6.1.0",
241
241
  "@vitejs/plugin-rsc": "^0.5.38",
242
242
  "am-i-vibing": "^0.5.0",
243
+ "iconv-lite": "0.4.24",
243
244
  "ignore": "5.3.2",
244
245
  "image-size": "2.0.4",
245
246
  "pathslash": "^0.1.0",
@@ -1,60 +0,0 @@
1
- //#region src/build/layout-classification-types.d.ts
2
- /**
3
- * Shared types for the layout classification pipeline.
4
- *
5
- * Kept in a leaf module so both `report.ts` (which implements segment-config
6
- * classification) and `layout-classification.ts` (which composes the full
7
- * pipeline) can import them without forming a cycle.
8
- *
9
- * The wire contract between build and runtime is intentionally narrow: the
10
- * runtime only cares about the `"static" | "dynamic"` decision for a layout.
11
- * Reasons live in a sidecar structure so operators can trace how each
12
- * decision was made without bloating the hot-path payload.
13
- */
14
- /**
15
- * Structured record of which classifier layer produced a decision and what
16
- * evidence it used. Kept as a discriminated union so each layer can carry
17
- * its own diagnostic shape without the consumer having to fall back to
18
- * stringly-typed `reason` fields.
19
- */
20
- export type ClassificationReason = {
21
- layer: "segment-config";
22
- key: "dynamic" | "revalidate";
23
- value: string | number;
24
- } | {
25
- layer: "module-graph";
26
- result: "static" | "needs-probe";
27
- firstShimMatch?: string;
28
- } | {
29
- layer: "runtime-probe";
30
- outcome: "static" | "dynamic";
31
- error?: string;
32
- } | {
33
- layer: "no-classifier";
34
- };
35
- export type ModuleGraphStaticReason = {
36
- layer: "module-graph";
37
- result: "static";
38
- firstShimMatch?: string;
39
- };
40
- /**
41
- * Build-time classification outcome for a single layout. Tagged with `kind`
42
- * so callers can branch exhaustively and carry diagnostic reasons alongside
43
- * the decision.
44
- *
45
- * `absent` means no classifier layer had anything to say — the caller should
46
- * defer to the next layer (or to the runtime probe).
47
- */
48
- export type LayoutBuildClassification = {
49
- kind: "absent";
50
- } | {
51
- kind: "static";
52
- reason: ClassificationReason;
53
- } | {
54
- kind: "dynamic";
55
- reason: ClassificationReason;
56
- } | {
57
- kind: "needs-probe";
58
- reason: ClassificationReason;
59
- };
60
- //#endregion
@@ -1 +0,0 @@
1
- export {};
@@ -1,62 +0,0 @@
1
- import { ClassificationReason, LayoutBuildClassification, ModuleGraphStaticReason } from "./layout-classification-types.js";
2
- //#region src/build/layout-classification.d.ts
3
- type ModuleGraphClassification = "static" | "needs-probe";
4
- type ModuleGraphClassificationResult = {
5
- result: ModuleGraphClassification;
6
- /** First dynamic shim module ID encountered during BFS, when any. */
7
- firstShimMatch?: string;
8
- };
9
- export type ModuleInfoProvider = {
10
- getModuleInfo(id: string): {
11
- importedIds: string[];
12
- dynamicImportedIds: string[];
13
- } | null;
14
- };
15
- type LayoutEntry = {
16
- /** Rollup/Vite module ID for the layout file. */
17
- moduleId: string;
18
- /** Directory depth from the app root, used to build the stable layout ID. */
19
- treePosition: number;
20
- /** Segment config source code extracted at build time, or null when absent. */
21
- segmentConfig?: {
22
- code: string;
23
- } | null;
24
- };
25
- type RouteForClassification = {
26
- layouts: readonly LayoutEntry[];
27
- routeSegments: string[];
28
- };
29
- /**
30
- * BFS traversal of a layout's dependency tree. If any transitive import
31
- * resolves to a dynamic shim path (headers, cache, server), the layout
32
- * cannot be proven static at build time and needs a runtime probe.
33
- *
34
- * The returned object carries the classification plus the first matching
35
- * shim module ID (when any). Operators use the shim ID via the debug
36
- * channel to trace why a layout was flagged for probing.
37
- */
38
- export declare function classifyLayoutByModuleGraph(layoutModuleId: string, dynamicShimPaths: ReadonlySet<string>, moduleInfo: ModuleInfoProvider): ModuleGraphClassificationResult;
39
- export declare function moduleGraphReason(graphResult: ModuleGraphClassificationResult & {
40
- result: "static";
41
- }): ModuleGraphStaticReason;
42
- export declare function moduleGraphReason(graphResult: ModuleGraphClassificationResult): ClassificationReason;
43
- export declare function isStaticModuleGraphResult(graphResult: ModuleGraphClassificationResult): graphResult is ModuleGraphClassificationResult & {
44
- result: "static";
45
- };
46
- /**
47
- * Classifies all layouts across all routes using a two-layer strategy:
48
- *
49
- * 1. Segment config (Layer 1) — short-circuits to "static" or "dynamic"
50
- * 2. Module graph (Layer 2) — BFS for dynamic shim imports → "static" or "needs-probe"
51
- *
52
- * Shared layouts (same file appearing in multiple routes) are classified once
53
- * and deduplicated by layout ID.
54
- *
55
- * @internal Not called by production code. The `renderChunk` hook in
56
- * `index.ts` calls `classifyLayoutByModuleGraph` directly and composes
57
- * via the numeric-index manifest in `route-classification-manifest.ts`.
58
- * Used only by `tests/layout-classification.test.ts`.
59
- */
60
- export declare function classifyAllRouteLayouts(routes: readonly RouteForClassification[], dynamicShimPaths: ReadonlySet<string>, moduleInfo: ModuleInfoProvider): Map<string, LayoutBuildClassification>;
61
- //#endregion
62
- export {};
@@ -1,98 +0,0 @@
1
- import { classifyLayoutSegmentConfig } from "./report.js";
2
- import { AppElementsWire } from "../server/app-elements-wire.js";
3
- import "../server/app-elements.js";
4
- import { createAppPageTreePath } from "../server/app-page-route-wiring.js";
5
- //#region src/build/layout-classification.ts
6
- /**
7
- * Layout classification — determines whether each layout in an App Router
8
- * route tree is static or dynamic via two complementary detection layers:
9
- *
10
- * Layer 1: Segment config (`export const dynamic`, `export const revalidate`)
11
- * Layer 2: Module graph traversal (checks for transitive dynamic shim imports)
12
- *
13
- * Layer 3 (probe-based runtime detection) is handled separately in
14
- * `app-page-execution.ts` at request time.
15
- *
16
- * Every result is carried as a `LayoutBuildClassification` tagged variant so
17
- * operators can trace which layer produced a decision via the structured
18
- * `ClassificationReason` sidecar without that metadata leaking onto the wire.
19
- */
20
- /**
21
- * BFS traversal of a layout's dependency tree. If any transitive import
22
- * resolves to a dynamic shim path (headers, cache, server), the layout
23
- * cannot be proven static at build time and needs a runtime probe.
24
- *
25
- * The returned object carries the classification plus the first matching
26
- * shim module ID (when any). Operators use the shim ID via the debug
27
- * channel to trace why a layout was flagged for probing.
28
- */
29
- function classifyLayoutByModuleGraph(layoutModuleId, dynamicShimPaths, moduleInfo) {
30
- const visited = /* @__PURE__ */ new Set();
31
- const queue = [layoutModuleId];
32
- let head = 0;
33
- while (head < queue.length) {
34
- const currentId = queue[head++];
35
- if (visited.has(currentId)) continue;
36
- visited.add(currentId);
37
- if (dynamicShimPaths.has(currentId)) return {
38
- result: "needs-probe",
39
- firstShimMatch: currentId
40
- };
41
- const info = moduleInfo.getModuleInfo(currentId);
42
- if (!info) continue;
43
- for (const importedId of info.importedIds) if (!visited.has(importedId)) queue.push(importedId);
44
- for (const dynamicId of info.dynamicImportedIds) if (!visited.has(dynamicId)) queue.push(dynamicId);
45
- }
46
- return { result: "static" };
47
- }
48
- function moduleGraphReason(graphResult) {
49
- if (graphResult.firstShimMatch === void 0) return {
50
- layer: "module-graph",
51
- result: graphResult.result
52
- };
53
- return {
54
- layer: "module-graph",
55
- result: graphResult.result,
56
- firstShimMatch: graphResult.firstShimMatch
57
- };
58
- }
59
- function isStaticModuleGraphResult(graphResult) {
60
- return graphResult.result === "static";
61
- }
62
- /**
63
- * Classifies all layouts across all routes using a two-layer strategy:
64
- *
65
- * 1. Segment config (Layer 1) — short-circuits to "static" or "dynamic"
66
- * 2. Module graph (Layer 2) — BFS for dynamic shim imports → "static" or "needs-probe"
67
- *
68
- * Shared layouts (same file appearing in multiple routes) are classified once
69
- * and deduplicated by layout ID.
70
- *
71
- * @internal Not called by production code. The `renderChunk` hook in
72
- * `index.ts` calls `classifyLayoutByModuleGraph` directly and composes
73
- * via the numeric-index manifest in `route-classification-manifest.ts`.
74
- * Used only by `tests/layout-classification.test.ts`.
75
- */
76
- function classifyAllRouteLayouts(routes, dynamicShimPaths, moduleInfo) {
77
- const result = /* @__PURE__ */ new Map();
78
- for (const route of routes) for (const layout of route.layouts) {
79
- const layoutId = AppElementsWire.encodeLayoutId(createAppPageTreePath(route.routeSegments, layout.treePosition));
80
- if (result.has(layoutId)) continue;
81
- if (layout.segmentConfig) {
82
- const configResult = classifyLayoutSegmentConfig(layout.segmentConfig.code);
83
- if (configResult.kind !== "absent") {
84
- result.set(layoutId, configResult);
85
- continue;
86
- }
87
- }
88
- const graphResult = classifyLayoutByModuleGraph(layout.moduleId, dynamicShimPaths, moduleInfo);
89
- const reason = moduleGraphReason(graphResult);
90
- result.set(layoutId, {
91
- kind: graphResult.result,
92
- reason
93
- });
94
- }
95
- return result;
96
- }
97
- //#endregion
98
- export { classifyAllRouteLayouts, classifyLayoutByModuleGraph, isStaticModuleGraphResult, moduleGraphReason };
@@ -1,33 +0,0 @@
1
- import { ModuleInfoProvider } from "./layout-classification.js";
2
- import { RouteClassificationManifest } from "./route-classification-manifest.js";
3
- //#region src/build/route-classification-injector.d.ts
4
- /**
5
- * Build-time route classification injection.
6
- *
7
- * Codegen describes route shape by emitting stable `__VINEXT_CLASS` stubs and
8
- * per-route call sites. This module owns the behavioral side of replacing
9
- * those stubs with build-time decisions once the final RSC module graph exists.
10
- */
11
- type RouteClassificationChunk = {
12
- code: string;
13
- fileName: string;
14
- };
15
- type RouteClassificationInjectionPlan = {
16
- kind: "skip";
17
- } | {
18
- code: string;
19
- fileName: string;
20
- kind: "patch";
21
- map: null;
22
- };
23
- type PlanRouteClassificationInjectionOptions = {
24
- canonicalizeLayoutPath?: (path: string) => string;
25
- chunks: readonly RouteClassificationChunk[];
26
- dynamicShimPaths: ReadonlySet<string>;
27
- enableDebugReasons: boolean;
28
- manifest: RouteClassificationManifest;
29
- moduleInfo: ModuleInfoProvider;
30
- };
31
- export declare function planRouteClassificationInjection(options: PlanRouteClassificationInjectionOptions): RouteClassificationInjectionPlan;
32
- //#endregion
33
- export {};
@@ -1,59 +0,0 @@
1
- import { buildClassificationReplacement, buildReasonsReplacement } from "./route-classification-manifest.js";
2
- import { classifyLayoutByModuleGraph, isStaticModuleGraphResult, moduleGraphReason } from "./layout-classification.js";
3
- //#region src/build/route-classification-injector.ts
4
- const CLASS_STUB_RE = /function __VINEXT_CLASS\(routeIdx\)\s*\{\s*return null;?\s*\}/;
5
- const REASONS_STUB_RE = /function __VINEXT_CLASS_REASONS\(routeIdx\)\s*\{\s*return null;?\s*\}/;
6
- function identityPath(path) {
7
- return path;
8
- }
9
- function findClassificationChunk(chunks) {
10
- const chunksMentioningStub = chunks.filter((chunk) => chunk.code.includes("__VINEXT_CLASS"));
11
- const chunksWithStubBody = chunksMentioningStub.filter((chunk) => CLASS_STUB_RE.test(chunk.code));
12
- const chunkWithStubBody = chunksWithStubBody[0];
13
- if (chunksMentioningStub.length === 0) return null;
14
- if (chunkWithStubBody === void 0) throw new Error(`vinext: build-time classification — __VINEXT_CLASS is referenced in ${chunksMentioningStub.map((chunk) => chunk.fileName).join(", ")} but no chunk contains the stub body. The generator and the classification injector have drifted.`);
15
- if (chunksWithStubBody.length > 1) throw new Error(`vinext: build-time classification — expected __VINEXT_CLASS stub in exactly one RSC chunk, found ${chunksWithStubBody.length}`);
16
- return chunkWithStubBody;
17
- }
18
- function buildLayer2Classifications(options) {
19
- const canonicalizeLayoutPath = options.canonicalizeLayoutPath ?? identityPath;
20
- const layer2PerRoute = /* @__PURE__ */ new Map();
21
- const graphCache = /* @__PURE__ */ new Map();
22
- for (let routeIdx = 0; routeIdx < options.manifest.routes.length; routeIdx++) {
23
- const route = options.manifest.routes[routeIdx];
24
- const perRoute = /* @__PURE__ */ new Map();
25
- for (let layoutIdx = 0; layoutIdx < route.layoutPaths.length; layoutIdx++) {
26
- if (route.layer1.has(layoutIdx)) continue;
27
- const layoutModuleId = canonicalizeLayoutPath(route.layoutPaths[layoutIdx]);
28
- if (!options.moduleInfo.getModuleInfo(layoutModuleId)) continue;
29
- let graphResult = graphCache.get(layoutModuleId);
30
- if (graphResult === void 0) {
31
- graphResult = classifyLayoutByModuleGraph(layoutModuleId, options.dynamicShimPaths, options.moduleInfo);
32
- graphCache.set(layoutModuleId, graphResult);
33
- }
34
- if (isStaticModuleGraphResult(graphResult)) perRoute.set(layoutIdx, moduleGraphReason(graphResult));
35
- }
36
- if (perRoute.size > 0) layer2PerRoute.set(routeIdx, perRoute);
37
- }
38
- return layer2PerRoute;
39
- }
40
- function planRouteClassificationInjection(options) {
41
- const target = findClassificationChunk(options.chunks);
42
- if (!target) return { kind: "skip" };
43
- if (options.enableDebugReasons && !REASONS_STUB_RE.test(target.code)) throw new Error("vinext: build-time classification — __VINEXT_CLASS_REASONS stub is missing alongside __VINEXT_CLASS. The generator and the classification injector have drifted.");
44
- const layer2PerRoute = buildLayer2Classifications(options);
45
- const patchedBody = `function __VINEXT_CLASS(routeIdx) { return (${buildClassificationReplacement(options.manifest, layer2PerRoute)})(routeIdx); }`;
46
- let code = target.code.replace(CLASS_STUB_RE, patchedBody);
47
- if (options.enableDebugReasons) {
48
- const patchedReasonsBody = `function __VINEXT_CLASS_REASONS(routeIdx) { return (${buildReasonsReplacement(options.manifest, layer2PerRoute)})(routeIdx); }`;
49
- code = code.replace(REASONS_STUB_RE, patchedReasonsBody);
50
- }
51
- return {
52
- code,
53
- fileName: target.fileName,
54
- kind: "patch",
55
- map: null
56
- };
57
- }
58
- //#endregion
59
- export { planRouteClassificationInjection };
@@ -1,54 +0,0 @@
1
- import { AppRoute } from "../routing/app-route-graph.js";
2
- import { ClassificationReason, ModuleGraphStaticReason } from "./layout-classification-types.js";
3
- //#region src/build/route-classification-manifest.d.ts
4
- type Layer1Class = "static" | "dynamic";
5
- type RouteManifestEntry = {
6
- /** Route pattern for diagnostics (e.g. "/blog/:slug"). */
7
- pattern: string;
8
- /** Absolute file paths for each layout, ordered root → leaf. */
9
- layoutPaths: string[];
10
- /** Layer 1 (segment config) results keyed by numeric layout index. */
11
- layer1: Map<number, Layer1Class>;
12
- /**
13
- * Structured reasons for every Layer 1 decision, keyed by the same layout
14
- * index. Always populated in lockstep with `layer1` so the debug channel
15
- * can surface which segment-config field produced the decision.
16
- */
17
- layer1Reasons: Map<number, ClassificationReason>;
18
- };
19
- export type RouteClassificationManifest = {
20
- routes: RouteManifestEntry[];
21
- };
22
- /**
23
- * Reads each layout's source at build time and runs Layer 1 segment-config
24
- * classification. Fails loudly if any layout file is missing — a missing
25
- * layout means the routing scan and the filesystem have drifted, and shipping
26
- * a build in that state would silently break layout rendering.
27
- */
28
- export declare function collectRouteClassificationManifest(routes: readonly AppRoute[]): RouteClassificationManifest;
29
- /**
30
- * Builds a JavaScript arrow-function expression that dispatches route index
31
- * to a pre-computed `Map<layoutIndex, "static" | "dynamic">` of build-time
32
- * classifications. The returned string is suitable for embedding into the
33
- * generated RSC entry via the `renderChunk` hook.
34
- *
35
- * `layer2PerRoute` is typed to only carry `"static"` entries — the
36
- * module-graph classifier can only prove static, so "needs-probe" results
37
- * are omitted by the caller before this map is constructed.
38
- */
39
- export declare function buildClassificationReplacement(manifest: RouteClassificationManifest, layer2PerRoute: ReadonlyMap<number, ReadonlyMap<number, ModuleGraphStaticReason>>): string;
40
- /**
41
- * Sibling of `buildClassificationReplacement`: emits a dispatch function
42
- * that returns `Map<layoutIndex, ClassificationReason>` per route.
43
- *
44
- * The runtime consults this map only when `VINEXT_DEBUG_CLASSIFICATION` is
45
- * set, and the plugin only patches this dispatcher into the built bundle when
46
- * that env var is present at build time.
47
- *
48
- * Layer 1 priority applies the same way as in `buildClassificationReplacement`:
49
- * a segment-config reason must override a module-graph reason for the same
50
- * layout index.
51
- */
52
- export declare function buildReasonsReplacement(manifest: RouteClassificationManifest, layer2PerRoute: ReadonlyMap<number, ReadonlyMap<number, ModuleGraphStaticReason>>): string;
53
- //#endregion
54
- export {};
@@ -1,143 +0,0 @@
1
- import { classifyLayoutSegmentConfig } from "./report.js";
2
- import fs from "node:fs";
3
- //#region src/build/route-classification-manifest.ts
4
- /**
5
- * Build-time layout classification manifest.
6
- *
7
- * Bridges the classifier in `./layout-classification.ts` with the RSC entry
8
- * codegen so that the per-layout static/dynamic classifications produced at
9
- * build time are visible to the runtime probe loop in
10
- * `server/app-page-execution.ts`.
11
- *
12
- * The runtime probe looks up entries by numeric `layoutIndex`, so this module
13
- * is responsible for flattening the classifier's string-keyed layout IDs into
14
- * a per-route, index-keyed structure that can be emitted from codegen.
15
- */
16
- /**
17
- * Reads each layout's source at build time and runs Layer 1 segment-config
18
- * classification. Fails loudly if any layout file is missing — a missing
19
- * layout means the routing scan and the filesystem have drifted, and shipping
20
- * a build in that state would silently break layout rendering.
21
- */
22
- function collectRouteClassificationManifest(routes) {
23
- const manifestRoutes = [];
24
- const sourceCache = /* @__PURE__ */ new Map();
25
- for (const route of routes) {
26
- const layer1 = /* @__PURE__ */ new Map();
27
- const layer1Reasons = /* @__PURE__ */ new Map();
28
- for (let layoutIndex = 0; layoutIndex < route.layouts.length; layoutIndex++) {
29
- const layoutPath = route.layouts[layoutIndex];
30
- let source = sourceCache.get(layoutPath);
31
- if (source === void 0) try {
32
- source = fs.readFileSync(layoutPath, "utf8");
33
- sourceCache.set(layoutPath, source);
34
- } catch (cause) {
35
- throw new Error(`vinext: failed to read layout for route ${route.pattern} at ${layoutPath}`, { cause });
36
- }
37
- const result = classifyLayoutSegmentConfig(source);
38
- if (result.kind === "static" || result.kind === "dynamic") {
39
- layer1.set(layoutIndex, result.kind);
40
- layer1Reasons.set(layoutIndex, result.reason);
41
- }
42
- }
43
- manifestRoutes.push({
44
- pattern: route.pattern,
45
- layoutPaths: [...route.layouts],
46
- layer1,
47
- layer1Reasons
48
- });
49
- }
50
- return { routes: manifestRoutes };
51
- }
52
- /**
53
- * Merges Layer 1 (segment config) and Layer 2 (module graph) into a single
54
- * per-route map, applying the Layer-1-wins priority rule.
55
- *
56
- * Layer 1 always takes priority over Layer 2 for the same layout index:
57
- * segment config is a user-authored guarantee, so a layout that explicitly
58
- * says `force-dynamic` must never be demoted to "static" because its module
59
- * graph happened to be clean.
60
- */
61
- function mergeLayersForRoute(route, layer2) {
62
- const merged = /* @__PURE__ */ new Map();
63
- if (layer2) for (const [layoutIdx, reason] of layer2) merged.set(layoutIdx, {
64
- kind: "static",
65
- reason
66
- });
67
- for (const [layoutIdx, kind] of route.layer1) {
68
- const reason = route.layer1Reasons.get(layoutIdx);
69
- if (reason === void 0) throw new Error(`vinext: layout ${layoutIdx} in route ${route.pattern} has a Layer 1 decision without a reason`);
70
- merged.set(layoutIdx, {
71
- kind,
72
- reason
73
- });
74
- }
75
- return merged;
76
- }
77
- function serializeReasonExpression(reason) {
78
- switch (reason.layer) {
79
- case "segment-config": {
80
- const value = reason.value === Infinity ? "Infinity" : JSON.stringify(reason.value);
81
- return `{ layer: "segment-config", key: ${JSON.stringify(reason.key)}, value: ${value} }`;
82
- }
83
- case "module-graph": {
84
- const props = [`layer: "module-graph"`, `result: ${JSON.stringify(reason.result)}`];
85
- if (reason.firstShimMatch !== void 0) props.push(`firstShimMatch: ${JSON.stringify(reason.firstShimMatch)}`);
86
- return `{ ${props.join(", ")} }`;
87
- }
88
- case "runtime-probe": {
89
- const props = [`layer: "runtime-probe"`, `outcome: ${JSON.stringify(reason.outcome)}`];
90
- if (reason.error !== void 0) props.push(`error: ${JSON.stringify(reason.error)}`);
91
- return `{ ${props.join(", ")} }`;
92
- }
93
- case "no-classifier": return `{ layer: "no-classifier" }`;
94
- }
95
- }
96
- function buildRouteDispatchReplacement(manifest, layer2PerRoute, serializeEntry) {
97
- const cases = [];
98
- for (let routeIdx = 0; routeIdx < manifest.routes.length; routeIdx++) {
99
- const route = manifest.routes[routeIdx];
100
- const merged = mergeLayersForRoute(route, layer2PerRoute.get(routeIdx));
101
- if (merged.size === 0) continue;
102
- const entries = [...merged.entries()].sort((a, b) => a[0] - b[0]).map(([idx, value]) => `[${idx}, ${serializeEntry(value)}]`).join(", ");
103
- cases.push(` case ${routeIdx}: return new Map([${entries}]);`);
104
- }
105
- return [
106
- "(routeIdx) => {",
107
- " switch (routeIdx) {",
108
- ...cases,
109
- " default: return null;",
110
- " }",
111
- " }"
112
- ].join("\n");
113
- }
114
- /**
115
- * Builds a JavaScript arrow-function expression that dispatches route index
116
- * to a pre-computed `Map<layoutIndex, "static" | "dynamic">` of build-time
117
- * classifications. The returned string is suitable for embedding into the
118
- * generated RSC entry via the `renderChunk` hook.
119
- *
120
- * `layer2PerRoute` is typed to only carry `"static"` entries — the
121
- * module-graph classifier can only prove static, so "needs-probe" results
122
- * are omitted by the caller before this map is constructed.
123
- */
124
- function buildClassificationReplacement(manifest, layer2PerRoute) {
125
- return buildRouteDispatchReplacement(manifest, layer2PerRoute, (value) => JSON.stringify(value.kind));
126
- }
127
- /**
128
- * Sibling of `buildClassificationReplacement`: emits a dispatch function
129
- * that returns `Map<layoutIndex, ClassificationReason>` per route.
130
- *
131
- * The runtime consults this map only when `VINEXT_DEBUG_CLASSIFICATION` is
132
- * set, and the plugin only patches this dispatcher into the built bundle when
133
- * that env var is present at build time.
134
- *
135
- * Layer 1 priority applies the same way as in `buildClassificationReplacement`:
136
- * a segment-config reason must override a module-graph reason for the same
137
- * layout index.
138
- */
139
- function buildReasonsReplacement(manifest, layer2PerRoute) {
140
- return buildRouteDispatchReplacement(manifest, layer2PerRoute, (value) => serializeReasonExpression(value.reason));
141
- }
142
- //#endregion
143
- export { buildClassificationReplacement, buildReasonsReplacement, collectRouteClassificationManifest };
@@ -1,11 +0,0 @@
1
- import { DEFAULT_CLIENT_REUSE_MANIFEST_LIMITS } from "./client-reuse-manifest.js";
2
- import { AppRouterState } from "./app-browser-state.js";
3
- //#region src/server/app-browser-client-reuse-manifest.d.ts
4
- type ClientReuseManifestLimits = typeof DEFAULT_CLIENT_REUSE_MANIFEST_LIMITS;
5
- type VisibleAppState = Pick<AppRouterState, "elements" | "visibleCommitVersion">;
6
- type CreateClientReuseManifestHeaderOptions = Readonly<{
7
- limits?: ClientReuseManifestLimits;
8
- }>;
9
- export declare function createClientReuseManifestHeaderFromVisibleAppState(state: VisibleAppState, options?: CreateClientReuseManifestHeaderOptions): string | null;
10
- //#endregion
11
- export {};