vinext 0.1.8 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/README.md +51 -30
  2. package/dist/build/css-url-assets.d.ts +3 -1
  3. package/dist/build/css-url-assets.js +18 -1
  4. package/dist/build/inject-pregenerated-paths.d.ts +7 -0
  5. package/dist/build/inject-pregenerated-paths.js +21 -0
  6. package/dist/build/layout-classification.js +1 -1
  7. package/dist/build/nitro-route-rules.js +1 -1
  8. package/dist/build/pages-client-assets-module.d.ts +11 -0
  9. package/dist/build/pages-client-assets-module.js +27 -0
  10. package/dist/build/prerender-server-entry.d.ts +1 -0
  11. package/dist/build/prerender-server-entry.js +49 -0
  12. package/dist/build/prerender-server-pool.d.ts +44 -0
  13. package/dist/build/prerender-server-pool.js +194 -0
  14. package/dist/build/prerender.d.ts +2 -1
  15. package/dist/build/prerender.js +98 -27
  16. package/dist/build/report.d.ts +13 -2
  17. package/dist/build/report.js +99 -2
  18. package/dist/build/run-prerender.d.ts +7 -0
  19. package/dist/build/run-prerender.js +12 -2
  20. package/dist/build/standalone.js +2 -0
  21. package/dist/cache/cache-adapters-virtual.js +3 -3
  22. package/dist/check.d.ts +4 -6
  23. package/dist/check.js +48 -11
  24. package/dist/cli-args.d.ts +1 -2
  25. package/dist/cli-args.js +1 -1
  26. package/dist/cli-dev-config.d.ts +12 -0
  27. package/dist/cli-dev-config.js +23 -0
  28. package/dist/cli.js +112 -96
  29. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  30. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  31. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  32. package/dist/{server → client}/dev-error-overlay.js +2 -2
  33. package/dist/client/navigation-runtime.d.ts +2 -0
  34. package/dist/client/navigation-runtime.js +3 -1
  35. package/dist/client/vinext-next-data.d.ts +4 -1
  36. package/dist/client/window-next.d.ts +2 -1
  37. package/dist/cloudflare/index.d.ts +2 -2
  38. package/dist/cloudflare/index.js +2 -2
  39. package/dist/config/config-matchers.js +45 -19
  40. package/dist/config/next-config.d.ts +41 -9
  41. package/dist/config/next-config.js +60 -3
  42. package/dist/config/prerender.d.ts +34 -0
  43. package/dist/config/prerender.js +55 -0
  44. package/dist/entries/app-browser-entry.js +5 -1
  45. package/dist/entries/app-rsc-entry.d.ts +5 -3
  46. package/dist/entries/app-rsc-entry.js +44 -10
  47. package/dist/entries/app-rsc-manifest.js +2 -0
  48. package/dist/entries/pages-client-entry.d.ts +3 -0
  49. package/dist/entries/pages-client-entry.js +28 -3
  50. package/dist/entries/pages-server-entry.js +23 -6
  51. package/dist/image/image-adapters-virtual.d.ts +59 -0
  52. package/dist/image/image-adapters-virtual.js +59 -0
  53. package/dist/index.d.ts +33 -0
  54. package/dist/index.js +482 -120
  55. package/dist/init-cloudflare.d.ts +43 -0
  56. package/dist/init-cloudflare.js +839 -0
  57. package/dist/init-platform.d.ts +40 -0
  58. package/dist/init-platform.js +195 -0
  59. package/dist/init.d.ts +16 -38
  60. package/dist/init.js +209 -99
  61. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  62. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  63. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  64. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  65. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +9 -2
  66. package/dist/packages/cloudflare/src/deploy-config.js +150 -0
  67. package/dist/packages/cloudflare/src/deploy-help.js +55 -0
  68. package/dist/packages/cloudflare/src/deploy.js +272 -0
  69. package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
  70. package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +44 -20
  71. package/dist/plugins/ast-scope.d.ts +16 -0
  72. package/dist/plugins/ast-scope.js +62 -0
  73. package/dist/plugins/ast-utils.d.ts +27 -1
  74. package/dist/plugins/ast-utils.js +32 -1
  75. package/dist/plugins/css-module-imports.d.ts +14 -0
  76. package/dist/plugins/css-module-imports.js +59 -0
  77. package/dist/plugins/extensionless-dynamic-import.js +2 -2
  78. package/dist/plugins/fonts.js +1 -1
  79. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  80. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  81. package/dist/plugins/og-assets.js +2 -1
  82. package/dist/plugins/optimize-imports.js +1 -1
  83. package/dist/plugins/rsc-reference-validation-normalizer.d.ts +12 -0
  84. package/dist/plugins/rsc-reference-validation-normalizer.js +48 -0
  85. package/dist/plugins/sass.d.ts +17 -1
  86. package/dist/plugins/sass.js +74 -1
  87. package/dist/plugins/styled-jsx.d.ts +16 -0
  88. package/dist/plugins/styled-jsx.js +149 -0
  89. package/dist/plugins/typeof-window.d.ts +1 -1
  90. package/dist/plugins/typeof-window.js +28 -56
  91. package/dist/routing/app-route-graph.d.ts +23 -2
  92. package/dist/routing/app-route-graph.js +138 -38
  93. package/dist/routing/file-matcher.d.ts +11 -1
  94. package/dist/routing/file-matcher.js +18 -3
  95. package/dist/routing/pages-router.js +2 -2
  96. package/dist/server/api-handler.js +9 -14
  97. package/dist/server/app-browser-action-result.d.ts +4 -1
  98. package/dist/server/app-browser-action-result.js +8 -1
  99. package/dist/server/app-browser-entry.js +198 -57
  100. package/dist/server/app-browser-interception-context.d.ts +1 -0
  101. package/dist/server/app-browser-interception-context.js +4 -2
  102. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  103. package/dist/server/app-browser-navigation-controller.js +60 -31
  104. package/dist/server/app-browser-server-action-client.d.ts +1 -1
  105. package/dist/server/app-browser-server-action-client.js +8 -7
  106. package/dist/server/app-browser-state.d.ts +12 -1
  107. package/dist/server/app-browser-state.js +25 -8
  108. package/dist/server/app-browser-visible-commit.d.ts +6 -1
  109. package/dist/server/app-browser-visible-commit.js +42 -24
  110. package/dist/server/app-elements-wire.d.ts +9 -2
  111. package/dist/server/app-elements-wire.js +8 -1
  112. package/dist/server/app-elements.d.ts +2 -2
  113. package/dist/server/app-elements.js +4 -3
  114. package/dist/server/app-fallback-renderer.d.ts +2 -1
  115. package/dist/server/app-fallback-renderer.js +10 -6
  116. package/dist/server/app-hydration-cache-publication.d.ts +11 -0
  117. package/dist/server/app-hydration-cache-publication.js +43 -0
  118. package/dist/server/app-middleware.d.ts +4 -3
  119. package/dist/server/app-middleware.js +8 -3
  120. package/dist/server/app-optimistic-routing.js +11 -4
  121. package/dist/server/app-page-boundary.js +2 -1
  122. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  123. package/dist/server/app-page-cache-finalizer.js +5 -4
  124. package/dist/server/app-page-cache-render.d.ts +1 -0
  125. package/dist/server/app-page-cache-render.js +8 -4
  126. package/dist/server/app-page-cache.d.ts +1 -0
  127. package/dist/server/app-page-cache.js +27 -7
  128. package/dist/server/app-page-dispatch.d.ts +1 -0
  129. package/dist/server/app-page-dispatch.js +26 -8
  130. package/dist/server/app-page-element-builder.d.ts +2 -1
  131. package/dist/server/app-page-element-builder.js +59 -4
  132. package/dist/server/app-page-execution.js +2 -1
  133. package/dist/server/app-page-probe.js +5 -0
  134. package/dist/server/app-page-render-identity.d.ts +2 -0
  135. package/dist/server/app-page-render-identity.js +3 -2
  136. package/dist/server/app-page-render.d.ts +2 -0
  137. package/dist/server/app-page-render.js +85 -16
  138. package/dist/server/app-page-request.d.ts +14 -0
  139. package/dist/server/app-page-request.js +69 -4
  140. package/dist/server/app-page-response.d.ts +7 -0
  141. package/dist/server/app-page-response.js +16 -4
  142. package/dist/server/app-page-route-wiring.d.ts +8 -1
  143. package/dist/server/app-page-route-wiring.js +32 -18
  144. package/dist/server/app-page-segment-state.d.ts +2 -1
  145. package/dist/server/app-page-segment-state.js +3 -1
  146. package/dist/server/app-page-stream.d.ts +7 -1
  147. package/dist/server/app-page-stream.js +3 -1
  148. package/dist/server/app-route-handler-execution.js +5 -1
  149. package/dist/server/app-route-handler-response.js +1 -0
  150. package/dist/server/app-route-handler-runtime.js +1 -1
  151. package/dist/server/app-route-tree-prefetch.d.ts +43 -0
  152. package/dist/server/app-route-tree-prefetch.js +187 -0
  153. package/dist/server/app-router-entry.js +9 -2
  154. package/dist/server/app-rsc-cache-busting.d.ts +2 -1
  155. package/dist/server/app-rsc-cache-busting.js +9 -4
  156. package/dist/server/app-rsc-handler.d.ts +7 -0
  157. package/dist/server/app-rsc-handler.js +148 -39
  158. package/dist/server/app-rsc-render-mode.d.ts +3 -2
  159. package/dist/server/app-rsc-render-mode.js +4 -1
  160. package/dist/server/app-rsc-request-normalization.d.ts +6 -6
  161. package/dist/server/app-rsc-request-normalization.js +10 -8
  162. package/dist/server/app-segment-config.d.ts +11 -0
  163. package/dist/server/app-segment-config.js +62 -6
  164. package/dist/server/app-server-action-execution.d.ts +1 -0
  165. package/dist/server/app-server-action-execution.js +61 -30
  166. package/dist/server/app-ssr-entry.d.ts +3 -0
  167. package/dist/server/app-ssr-entry.js +13 -5
  168. package/dist/server/app-ssr-stream.d.ts +7 -3
  169. package/dist/server/app-ssr-stream.js +10 -6
  170. package/dist/server/app-visited-response-cache.d.ts +6 -0
  171. package/dist/server/app-visited-response-cache.js +3 -1
  172. package/dist/server/cache-control.d.ts +3 -1
  173. package/dist/server/cache-control.js +13 -1
  174. package/dist/server/client-trace-metadata.js +26 -0
  175. package/dist/server/default-global-not-found-module.d.ts +14 -0
  176. package/dist/server/default-global-not-found-module.js +14 -0
  177. package/dist/server/dev-route-files.js +4 -0
  178. package/dist/server/dev-server.d.ts +11 -1
  179. package/dist/server/dev-server.js +94 -35
  180. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  181. package/dist/server/dev-stack-sourcemap.js +1 -1
  182. package/dist/server/fetch-handler.d.ts +2 -0
  183. package/dist/server/fetch-handler.js +18 -0
  184. package/dist/server/headers.d.ts +7 -15
  185. package/dist/server/headers.js +11 -18
  186. package/dist/server/image-optimization.d.ts +51 -1
  187. package/dist/server/image-optimization.js +52 -2
  188. package/dist/server/implicit-tags.js +1 -1
  189. package/dist/server/isr-cache.d.ts +3 -2
  190. package/dist/server/isr-cache.js +9 -5
  191. package/dist/server/metadata-routes.d.ts +3 -1
  192. package/dist/server/metadata-routes.js +12 -2
  193. package/dist/server/middleware-runtime.js +6 -1
  194. package/dist/server/navigation-planner.d.ts +1 -0
  195. package/dist/server/navigation-planner.js +14 -3
  196. package/dist/server/pages-api-route.js +2 -2
  197. package/dist/server/pages-asset-tags.d.ts +4 -6
  198. package/dist/server/pages-asset-tags.js +12 -12
  199. package/dist/server/pages-client-assets.d.ts +12 -0
  200. package/dist/server/pages-client-assets.js +10 -0
  201. package/dist/server/pages-data-route.d.ts +4 -2
  202. package/dist/server/pages-data-route.js +18 -4
  203. package/dist/server/pages-dev-module-url.d.ts +2 -1
  204. package/dist/server/pages-dev-module-url.js +6 -3
  205. package/dist/server/pages-node-compat.d.ts +19 -1
  206. package/dist/server/pages-node-compat.js +81 -4
  207. package/dist/server/pages-page-data.d.ts +33 -1
  208. package/dist/server/pages-page-data.js +62 -33
  209. package/dist/server/pages-page-handler.d.ts +2 -1
  210. package/dist/server/pages-page-handler.js +38 -19
  211. package/dist/server/pages-page-response.d.ts +8 -0
  212. package/dist/server/pages-page-response.js +7 -3
  213. package/dist/server/pages-request-pipeline.d.ts +9 -5
  214. package/dist/server/pages-request-pipeline.js +55 -7
  215. package/dist/server/pages-router-entry.d.ts +30 -0
  216. package/dist/server/pages-router-entry.js +108 -0
  217. package/dist/server/prerender-manifest.d.ts +3 -1
  218. package/dist/server/prerender-route-params.js +1 -1
  219. package/dist/server/prod-server.d.ts +5 -3
  220. package/dist/server/prod-server.js +68 -39
  221. package/dist/server/request-pipeline.js +2 -1
  222. package/dist/server/seed-cache.js +4 -4
  223. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  224. package/dist/shims/app-router-scroll-state.js +1 -0
  225. package/dist/shims/app-router-scroll.js +2 -1
  226. package/dist/shims/cache-handler.js +8 -1
  227. package/dist/shims/cache.js +22 -15
  228. package/dist/shims/cdn-cache.js +1 -1
  229. package/dist/shims/dynamic-preload-chunks.js +2 -1
  230. package/dist/shims/fetch-cache.d.ts +3 -1
  231. package/dist/shims/fetch-cache.js +77 -52
  232. package/dist/shims/form.d.ts +4 -2
  233. package/dist/shims/form.js +37 -43
  234. package/dist/shims/headers.d.ts +7 -1
  235. package/dist/shims/headers.js +17 -3
  236. package/dist/shims/image.js +75 -14
  237. package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +10 -0
  238. package/dist/shims/internal/app-prefetch-fetch-queue.js +61 -0
  239. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  240. package/dist/shims/internal/app-route-detection.js +4 -17
  241. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  242. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  243. package/dist/shims/internal/hybrid-client-route-owner.d.ts +3 -15
  244. package/dist/shims/internal/hybrid-client-route-owner.js +40 -58
  245. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +10 -5
  246. package/dist/shims/internal/pages-data-fetch-dedup.js +84 -14
  247. package/dist/shims/internal/pages-data-target.d.ts +18 -12
  248. package/dist/shims/internal/pages-data-target.js +97 -13
  249. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  250. package/dist/shims/internal/pages-router-components.js +13 -0
  251. package/dist/shims/layout-segment-context.d.ts +4 -1
  252. package/dist/shims/layout-segment-context.js +18 -4
  253. package/dist/shims/link.d.ts +1 -1
  254. package/dist/shims/link.js +224 -58
  255. package/dist/shims/navigation.d.ts +19 -3
  256. package/dist/shims/navigation.js +245 -47
  257. package/dist/shims/request-context.js +18 -0
  258. package/dist/shims/root-params.d.ts +15 -1
  259. package/dist/shims/root-params.js +21 -1
  260. package/dist/shims/router.d.ts +5 -7
  261. package/dist/shims/router.js +387 -102
  262. package/dist/shims/server.js +3 -2
  263. package/dist/shims/slot.js +3 -6
  264. package/dist/shims/unified-request-context.js +1 -0
  265. package/dist/typegen.js +1 -1
  266. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  267. package/dist/utils/client-runtime-metadata.js +31 -22
  268. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  269. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  270. package/dist/utils/domain-locale.d.ts +6 -3
  271. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  272. package/dist/{server → utils}/middleware-request-headers.js +3 -3
  273. package/dist/utils/project.d.ts +48 -2
  274. package/dist/utils/project.js +225 -4
  275. package/dist/utils/protocol-headers.d.ts +23 -0
  276. package/dist/utils/protocol-headers.js +23 -0
  277. package/dist/utils/react-version.d.ts +4 -0
  278. package/dist/utils/react-version.js +44 -0
  279. package/dist/utils/vite-version.d.ts +2 -0
  280. package/dist/utils/vite-version.js +11 -1
  281. package/package.json +47 -2
  282. package/dist/deploy.d.ts +0 -197
  283. package/dist/deploy.js +0 -1040
  284. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  285. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
@@ -0,0 +1,48 @@
1
+ //#region src/plugins/rsc-reference-validation-normalizer.ts
2
+ const REFERENCE_VALIDATION_ID_PREFIX = "\0virtual:vite-rsc/reference-validation?";
3
+ function parseReferenceValidationQuery(id) {
4
+ const queryStart = id.indexOf("?");
5
+ if (queryStart === -1) return null;
6
+ return Object.fromEntries(new URLSearchParams(id.slice(queryStart + 1)));
7
+ }
8
+ function normalizeReferenceKey(id) {
9
+ return id.replaceAll("\0", "__x00__");
10
+ }
11
+ function hasReference(referenceMetaMap, referenceId) {
12
+ if (!referenceMetaMap || !referenceId) return false;
13
+ const normalizedReferenceId = normalizeReferenceKey(referenceId);
14
+ return Object.values(referenceMetaMap).some((meta) => normalizeReferenceKey(meta.referenceKey) === normalizedReferenceId);
15
+ }
16
+ /**
17
+ * @vitejs/plugin-rsc stores dev virtual client-reference keys in Vite's encoded
18
+ * `/@id/__x00__...` form, but React's SSR consumer can ask validation for the
19
+ * decoded `/@id/\0...` form. Treat those as equivalent and fall through to the
20
+ * upstream validator for all other invalid references.
21
+ */
22
+ function createRscReferenceValidationNormalizerPlugin() {
23
+ let rscApi;
24
+ return {
25
+ name: "vinext:rsc-reference-validation-normalizer",
26
+ enforce: "pre",
27
+ apply(_config, env) {
28
+ return env.command === "serve" && env.isPreview !== true;
29
+ },
30
+ configResolved(config) {
31
+ rscApi = config.plugins.find((plugin) => plugin.name === "rsc:minimal")?.api;
32
+ },
33
+ load: {
34
+ filter: { id: /^\u0000virtual:vite-rsc\/reference-validation\?/ },
35
+ handler(id) {
36
+ if (!id.startsWith(REFERENCE_VALIDATION_ID_PREFIX)) return null;
37
+ const query = parseReferenceValidationQuery(id);
38
+ if (!query) return null;
39
+ const manager = rscApi?.manager;
40
+ if (query.type === "client" && hasReference(manager?.clientReferenceMetaMap, query.id)) return "export {}";
41
+ if (query.type === "server" && hasReference(manager?.serverReferenceMetaMap, query.id)) return "export {}";
42
+ return null;
43
+ }
44
+ }
45
+ };
46
+ }
47
+ //#endregion
48
+ export { createRscReferenceValidationNormalizerPlugin };
@@ -35,6 +35,22 @@ type VitePreprocessorOptions = {
35
35
  declare function createSassTildeImporter(root: string): {
36
36
  findFileUrl(url: string): URL | null;
37
37
  };
38
+ type SassLoadedStylesheet = {
39
+ contents: string;
40
+ syntax: "scss" | "indented" | "css";
41
+ };
42
+ /**
43
+ * Preserve source-asset provenance for `url()` references inside imported Sass
44
+ * partials. Vite's transform hook only sees the entry stylesheet after Sass has
45
+ * flattened its imports, at which point relative URLs from a partial have lost
46
+ * the partial's source filename. Marking the partial before compilation keeps
47
+ * byte-identical assets associated with their original basenames.
48
+ */
49
+ declare function createSassCssUrlAssetImporter(): {
50
+ canonicalize(url: string): URL | null;
51
+ load(canonicalUrl: URL): SassLoadedStylesheet | null;
52
+ rewriteImports(source: string, filename: string): string;
53
+ };
38
54
  declare function buildSassPreprocessorOptions(sassOptions: Record<string, unknown> | null | undefined): VitePreprocessorOptions | undefined;
39
55
  /**
40
56
  * Create a per-build binding of {@link SassAwareFileSystemLoader}.
@@ -59,4 +75,4 @@ declare function createSassAwareFileSystemLoader(): {
59
75
  setResolvedConfig: (config: ResolvedConfig) => void;
60
76
  };
61
77
  //#endregion
62
- export { buildSassPreprocessorOptions, createSassAwareFileSystemLoader, createSassTildeImporter };
78
+ export { buildSassPreprocessorOptions, createSassAwareFileSystemLoader, createSassCssUrlAssetImporter, createSassTildeImporter };
@@ -1,3 +1,4 @@
1
+ import { markCssUrlAssetReferences, rebaseCssUrlAssetReferences } from "../build/css-url-assets.js";
1
2
  import { createRequire } from "node:module";
2
3
  import fs from "node:fs";
3
4
  import path from "node:path";
@@ -75,6 +76,78 @@ function createSassTildeImporter(root) {
75
76
  }
76
77
  } };
77
78
  }
79
+ function sassStylesheetCandidates(importPath) {
80
+ const extension = path.extname(importPath);
81
+ const directory = path.dirname(importPath);
82
+ const basename = path.basename(importPath, extension);
83
+ const candidates = [];
84
+ const extensions = extension ? [extension] : [
85
+ ".scss",
86
+ ".sass",
87
+ ".css"
88
+ ];
89
+ for (const candidateExtension of extensions) {
90
+ const basePath = extension ? importPath : `${importPath}${candidateExtension}`;
91
+ candidates.push(basePath);
92
+ candidates.push(path.join(directory, `_${basename}${candidateExtension}`));
93
+ }
94
+ for (const candidateExtension of extensions) {
95
+ candidates.push(path.join(importPath, `index${candidateExtension}`));
96
+ candidates.push(path.join(importPath, `_index${candidateExtension}`));
97
+ }
98
+ return candidates;
99
+ }
100
+ function deriveSassNamespace(importUrl) {
101
+ const parts = importUrl.replaceAll("\\", "/").replace(/\/$/, "").split("/");
102
+ let basename = parts.pop() ?? "stylesheet";
103
+ basename = basename.replace(/^_/, "").replace(/\..*$/, "");
104
+ if (basename === "index" && parts.length > 0) basename = (parts.pop() ?? basename).replace(/^_/, "").replace(/\..*$/, "");
105
+ return basename;
106
+ }
107
+ /**
108
+ * Preserve source-asset provenance for `url()` references inside imported Sass
109
+ * partials. Vite's transform hook only sees the entry stylesheet after Sass has
110
+ * flattened its imports, at which point relative URLs from a partial have lost
111
+ * the partial's source filename. Marking the partial before compilation keeps
112
+ * byte-identical assets associated with their original basenames.
113
+ */
114
+ function createSassCssUrlAssetImporter() {
115
+ const markedStylesheets = /* @__PURE__ */ new Map();
116
+ const importUrlPrefix = "vinext-css-url-asset:";
117
+ const prepareStylesheet = (filename, entryDirectory) => {
118
+ const contents = fs.readFileSync(filename, "utf8");
119
+ const marked = markCssUrlAssetReferences(rebaseCssUrlAssetReferences(contents, path.dirname(filename), entryDirectory) ?? contents, filename);
120
+ if (marked === null) return null;
121
+ const extension = path.extname(filename).toLowerCase();
122
+ return {
123
+ contents: rewriteImports(marked, filename, entryDirectory),
124
+ syntax: extension === ".sass" ? "indented" : extension === ".css" ? "css" : "scss"
125
+ };
126
+ };
127
+ const rewriteImports = (source, filename, entryDirectory = path.dirname(filename)) => source.replace(/(@(import|use|forward)\s+)(["'])(\.[^"']+)\3([^;]*;?)/g, (match, prefix, rule, quote, importUrl, suffix) => {
128
+ const importPath = path.resolve(path.dirname(filename), importUrl);
129
+ for (const candidate of sassStylesheetCandidates(importPath)) {
130
+ if (!fs.statSync(candidate, { throwIfNoEntry: false })?.isFile()) continue;
131
+ const prepared = prepareStylesheet(candidate, entryDirectory);
132
+ if (prepared === null) return match;
133
+ const canonicalUrl = pathToFileURL(candidate);
134
+ markedStylesheets.set(canonicalUrl.href, prepared);
135
+ const namespace = rule === "use" && !/\bas\s+(?:\*|[-\w]+)/.test(suffix) ? ` as ${deriveSassNamespace(importUrl)}` : "";
136
+ return `${prefix}${quote}${importUrlPrefix}${encodeURIComponent(candidate)}${quote}${namespace}${suffix}`;
137
+ }
138
+ return match;
139
+ });
140
+ return {
141
+ canonicalize(url) {
142
+ if (!url.startsWith(importUrlPrefix)) return null;
143
+ return pathToFileURL(decodeURIComponent(url.slice(21)));
144
+ },
145
+ load(canonicalUrl) {
146
+ return markedStylesheets.get(canonicalUrl.href) ?? null;
147
+ },
148
+ rewriteImports
149
+ };
150
+ }
78
151
  function buildSassPreprocessorOptions(sassOptions) {
79
152
  if (!sassOptions || typeof sassOptions !== "object") return void 0;
80
153
  const { prependData, additionalData, includePaths, loadPaths, ...rest } = sassOptions;
@@ -265,4 +338,4 @@ function createSassAwareFileSystemLoader() {
265
338
  };
266
339
  }
267
340
  //#endregion
268
- export { buildSassPreprocessorOptions, createSassAwareFileSystemLoader, createSassTildeImporter };
341
+ export { buildSassPreprocessorOptions, createSassAwareFileSystemLoader, createSassCssUrlAssetImporter, createSassTildeImporter };
@@ -0,0 +1,16 @@
1
+ import { Plugin } from "vite";
2
+
3
+ //#region src/plugins/styled-jsx.d.ts
4
+ type NextSwcModule = {
5
+ loadBindings(): Promise<unknown>;
6
+ transform(source: string, options: Record<string, unknown>): Promise<{
7
+ code: string;
8
+ map?: string;
9
+ }>;
10
+ };
11
+ type StyledJsxPluginOptions = {
12
+ importModule?: (url: string) => Promise<NextSwcModule>;
13
+ };
14
+ declare function createStyledJsxPlugin(initialProjectRoot: string, options?: StyledJsxPluginOptions): Plugin;
15
+ //#endregion
16
+ export { createStyledJsxPlugin };
@@ -0,0 +1,149 @@
1
+ import { createRequire } from "node:module";
2
+ import path from "node:path";
3
+ import { parseAst } from "vite";
4
+ import { pathToFileURL } from "node:url";
5
+ //#region src/plugins/styled-jsx.ts
6
+ const STYLED_JSX_IMPORT_RE = /^styled-jsx(?:\/.*)?$/;
7
+ const NODE_MODULES_RE = /[\\/]node_modules[\\/]/;
8
+ const STYLED_JSX_SOURCE_RE = /(?:<style\b|from\s+["']styled-jsx\/css["']|require\s*\(\s*["']styled-jsx\/css["']\s*\))/;
9
+ const STYLED_JSX_CSS_RE = /(?:from\s+["']styled-jsx\/css["']|require\s*\(\s*["']styled-jsx\/css["']\s*\))/;
10
+ function hasStyledJsxTag(source, id) {
11
+ const cleanId = id.split("?")[0];
12
+ const extension = path.extname(cleanId);
13
+ const lang = extension === ".ts" || extension === ".mts" || extension === ".cts" ? "ts" : "tsx";
14
+ let ast;
15
+ try {
16
+ ast = parseAst(source, { lang });
17
+ } catch {
18
+ return false;
19
+ }
20
+ const pending = [ast];
21
+ const visited = /* @__PURE__ */ new Set();
22
+ while (pending.length > 0) {
23
+ const value = pending.pop();
24
+ if (!value || typeof value !== "object" || visited.has(value)) continue;
25
+ visited.add(value);
26
+ const node = value;
27
+ if (node.type === "JSXOpeningElement") {
28
+ const name = node.name;
29
+ if (name?.type === "JSXIdentifier" && name.name === "style") {
30
+ if (node.attributes?.some((attribute) => {
31
+ if (attribute.type !== "JSXAttribute") return false;
32
+ const attributeName = attribute.name;
33
+ return attributeName?.type === "JSXIdentifier" && attributeName.name === "jsx";
34
+ })) return true;
35
+ }
36
+ }
37
+ for (const child of Object.values(node)) if (Array.isArray(child)) pending.push(...child);
38
+ else if (child && typeof child === "object") pending.push(child);
39
+ }
40
+ return false;
41
+ }
42
+ function createProjectRequire(projectRoot) {
43
+ return createRequire(path.join(projectRoot, "package.json"));
44
+ }
45
+ function resolveNextRequire(projectRoot) {
46
+ try {
47
+ return createRequire(createProjectRequire(projectRoot).resolve("next/package.json"));
48
+ } catch {
49
+ return null;
50
+ }
51
+ }
52
+ function parserOptions(id) {
53
+ const extension = path.extname(id.split("?")[0]);
54
+ if (extension === ".ts" || extension === ".tsx") return {
55
+ syntax: "typescript",
56
+ tsx: extension === ".tsx",
57
+ decorators: true
58
+ };
59
+ return {
60
+ syntax: "ecmascript",
61
+ jsx: true
62
+ };
63
+ }
64
+ function createStyledJsxPlugin(initialProjectRoot, options = {}) {
65
+ let projectRoot = initialProjectRoot;
66
+ let development = false;
67
+ let nextRequire;
68
+ let compilerPromise = null;
69
+ const importModule = options.importModule ?? ((url) => import(url));
70
+ function getNextRequire() {
71
+ nextRequire ??= resolveNextRequire(projectRoot);
72
+ return nextRequire;
73
+ }
74
+ async function getCompiler() {
75
+ if (!compilerPromise) {
76
+ const requireFromNext = getNextRequire();
77
+ if (!requireFromNext) throw new Error("[vinext] styled-jsx requires an installed next package so vinext can use its matching compiler.");
78
+ compilerPromise = importModule(pathToFileURL(requireFromNext.resolve("next/dist/build/swc")).href).then(async (compiler) => {
79
+ await compiler.loadBindings();
80
+ return compiler;
81
+ });
82
+ }
83
+ return compilerPromise;
84
+ }
85
+ return {
86
+ name: "vinext:styled-jsx",
87
+ enforce: "pre",
88
+ configResolved(config) {
89
+ development = config.command === "serve";
90
+ if (config.root !== projectRoot) {
91
+ projectRoot = config.root;
92
+ nextRequire = void 0;
93
+ compilerPromise = null;
94
+ }
95
+ },
96
+ resolveId: {
97
+ filter: { id: STYLED_JSX_IMPORT_RE },
98
+ handler(source) {
99
+ try {
100
+ return getNextRequire()?.resolve(source) ?? null;
101
+ } catch {}
102
+ try {
103
+ return createProjectRequire(projectRoot).resolve(source);
104
+ } catch {
105
+ return null;
106
+ }
107
+ }
108
+ },
109
+ transform: {
110
+ filter: {
111
+ id: {
112
+ include: /\.[cm]?[jt]sx?(?:\?.*)?$/,
113
+ exclude: NODE_MODULES_RE
114
+ },
115
+ code: STYLED_JSX_SOURCE_RE
116
+ },
117
+ async handler(source, id) {
118
+ if (NODE_MODULES_RE.test(id.split("?")[0])) return null;
119
+ const hasStyledJsxCss = STYLED_JSX_CSS_RE.test(source);
120
+ const hasStyledJsxElement = !hasStyledJsxCss && hasStyledJsxTag(source, id);
121
+ if (!hasStyledJsxCss && !hasStyledJsxElement) return null;
122
+ if (!getNextRequire()) throw new Error("[vinext] styled-jsx requires an installed next package so vinext can use its matching compiler.");
123
+ const result = await (await getCompiler()).transform(source, {
124
+ filename: id.split("?")[0],
125
+ sourceMaps: true,
126
+ module: { type: "es6" },
127
+ styledJsx: { useLightningcss: false },
128
+ jsc: {
129
+ parser: parserOptions(id),
130
+ transform: {
131
+ react: {
132
+ runtime: "automatic",
133
+ development,
134
+ useBuiltins: true
135
+ },
136
+ optimizer: { simplify: false }
137
+ }
138
+ }
139
+ });
140
+ return {
141
+ code: result.code,
142
+ map: result.map ?? null
143
+ };
144
+ }
145
+ }
146
+ };
147
+ }
148
+ //#endregion
149
+ export { createStyledJsxPlugin };
@@ -6,7 +6,7 @@ type EnvironmentLike = {
6
6
  };
7
7
  };
8
8
  declare function getTypeofWindowReplacement(environment: EnvironmentLike): WindowType;
9
- declare function replaceTypeofWindow(code: string, replacement: WindowType): {
9
+ declare function replaceTypeofWindow(code: string, replacement: WindowType, id?: string): {
10
10
  code: string;
11
11
  map: import("magic-string").SourceMap;
12
12
  } | null;
@@ -1,55 +1,17 @@
1
1
  import { collectBindingNames, forEachAstChild, hasRange, isAstRecord, isIdentifierNamed, nodeArray } from "./ast-utils.js";
2
+ import { collectDirectScopeBindings, collectLoopScopeBindings, collectSwitchScopeBindings, collectVarScopeBindings, createAstScope, hasAstBinding, isFunctionNode } from "./ast-scope.js";
3
+ import path from "node:path";
2
4
  import { parseAst } from "vite";
3
5
  import MagicString from "magic-string";
4
6
  //#region src/plugins/typeof-window.ts
5
- function createScope(parent) {
6
- return {
7
- parent,
8
- bindings: /* @__PURE__ */ new Set()
9
- };
10
- }
11
- function hasBinding(scope, name) {
12
- for (let current = scope; current; current = current.parent) if (current.bindings.has(name)) return true;
13
- return false;
14
- }
15
- function collectScopeBindings(node, scope) {
16
- forEachAstChild(node, (child) => {
17
- if (child.type === "ExportNamedDeclaration" || child.type === "ExportDefaultDeclaration") {
18
- if (isAstRecord(child.declaration)) collectScopeBindings(child, scope);
19
- return;
20
- }
21
- if (child.type === "FunctionDeclaration" || child.type === "ClassDeclaration") {
22
- collectBindingNames(child.id, scope.bindings);
23
- return;
24
- }
25
- if (child.type === "VariableDeclaration") {
26
- for (const declaration of nodeArray(child.declarations)) if (isAstRecord(declaration)) collectBindingNames(declaration.id, scope.bindings);
27
- return;
28
- }
29
- if (child.type === "ImportDeclaration") {
30
- for (const specifier of nodeArray(child.specifiers)) if (isAstRecord(specifier)) collectBindingNames(specifier.local, scope.bindings);
31
- }
32
- });
33
- }
34
- function collectVarBindings(node, scope, isRoot = true) {
35
- if (!isRoot && (node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression")) return;
36
- if (node.type === "VariableDeclaration" && node.kind === "var") {
37
- for (const declaration of nodeArray(node.declarations)) if (isAstRecord(declaration)) collectBindingNames(declaration.id, scope.bindings);
38
- }
39
- forEachAstChild(node, (child) => collectVarBindings(child, scope, false));
40
- }
41
- function isFunctionNode(node) {
42
- return node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
43
- }
44
7
  function createChildScope(node, parent) {
45
- if (node.type !== "Program" && node.type !== "BlockStatement" && node.type !== "StaticBlock" && node.type !== "SwitchStatement" && node.type !== "CatchClause" && node.type !== "ForStatement" && node.type !== "ForInStatement" && node.type !== "ForOfStatement" && node.type !== "ClassDeclaration" && node.type !== "ClassExpression") return null;
46
- const scope = createScope(parent);
8
+ if (node.type !== "Program" && node.type !== "BlockStatement" && node.type !== "StaticBlock" && node.type !== "TSModuleBlock" && node.type !== "CatchClause" && node.type !== "ForStatement" && node.type !== "ForInStatement" && node.type !== "ForOfStatement" && node.type !== "ClassDeclaration" && node.type !== "ClassExpression") return null;
9
+ const scope = createAstScope(parent);
47
10
  if (node.type === "ClassDeclaration" || node.type === "ClassExpression") collectBindingNames(node.id, scope.bindings);
48
11
  else if (node.type === "CatchClause") collectBindingNames(node.param, scope.bindings);
49
- collectScopeBindings(node, scope);
50
- if (node.type === "SwitchStatement") {
51
- for (const switchCase of nodeArray(node.cases)) if (isAstRecord(switchCase)) collectScopeBindings(switchCase, scope);
52
- }
12
+ collectDirectScopeBindings(node, scope);
13
+ if (node.type === "StaticBlock" || node.type === "TSModuleBlock") collectVarScopeBindings(node, scope);
14
+ if (node.type === "ForStatement" || node.type === "ForInStatement" || node.type === "ForOfStatement") collectLoopScopeBindings(node, scope);
53
15
  return scope;
54
16
  }
55
17
  function getTypeofWindowReplacement(environment) {
@@ -70,42 +32,52 @@ function evaluateTypeofWindowComparison(node, replacement, scope) {
70
32
  ].includes(String(node.operator))) return null;
71
33
  const left = isAstRecord(node.left) ? node.left : null;
72
34
  const right = isAstRecord(node.right) ? node.right : null;
73
- const leftIsTypeofWindow = left?.type === "UnaryExpression" && left.operator === "typeof" && isIdentifierNamed(left.argument, "window") && !hasBinding(scope, "window");
74
- const rightIsTypeofWindow = right?.type === "UnaryExpression" && right.operator === "typeof" && isIdentifierNamed(right.argument, "window") && !hasBinding(scope, "window");
35
+ const leftIsTypeofWindow = left?.type === "UnaryExpression" && left.operator === "typeof" && isIdentifierNamed(left.argument, "window") && !hasAstBinding(scope, "window");
36
+ const rightIsTypeofWindow = right?.type === "UnaryExpression" && right.operator === "typeof" && isIdentifierNamed(right.argument, "window") && !hasAstBinding(scope, "window");
75
37
  const comparedValue = leftIsTypeofWindow ? stringLiteralValue(right) : rightIsTypeofWindow ? stringLiteralValue(left) : null;
76
38
  if (comparedValue === null) return null;
77
39
  const equal = replacement === comparedValue;
78
40
  return node.operator === "==" || node.operator === "===" ? equal : !equal;
79
41
  }
80
- function replaceTypeofWindow(code, replacement) {
42
+ function replaceTypeofWindow(code, replacement, id = "file.js") {
81
43
  if (!/typeof\s+window/.test(code)) return null;
44
+ const extension = path.extname(id.split("?", 1)[0]);
45
+ const lang = extension === ".ts" || extension === ".mts" || extension === ".cts" ? "ts" : extension === ".tsx" ? "tsx" : extension === ".jsx" ? "jsx" : "js";
82
46
  let ast;
83
47
  try {
84
- ast = parseAst(code);
48
+ ast = parseAst(code, { lang });
85
49
  } catch {
86
50
  return null;
87
51
  }
88
52
  const output = new MagicString(code);
89
53
  let changed = false;
90
54
  if (!isAstRecord(ast)) return null;
91
- const rootScope = createScope(null);
92
- collectScopeBindings(ast, rootScope);
93
- collectVarBindings(ast, rootScope);
55
+ const rootScope = createAstScope(null);
56
+ collectDirectScopeBindings(ast, rootScope);
57
+ collectVarScopeBindings(ast, rootScope);
94
58
  function visit(node, parentScope) {
95
59
  if (isFunctionNode(node)) {
96
- const parameterScope = createScope(parentScope);
60
+ const parameterScope = createAstScope(parentScope);
97
61
  collectBindingNames(node.id, parameterScope.bindings);
98
62
  for (const parameter of nodeArray(node.params)) {
99
63
  collectBindingNames(parameter, parameterScope.bindings);
100
64
  if (isAstRecord(parameter)) visit(parameter, parameterScope);
101
65
  }
102
66
  if (isAstRecord(node.body)) if (node.body.type === "BlockStatement") {
103
- const bodyScope = createScope(parameterScope);
104
- collectVarBindings(node.body, bodyScope);
67
+ const bodyScope = createAstScope(parameterScope);
68
+ collectDirectScopeBindings(node.body, bodyScope);
69
+ collectVarScopeBindings(node.body, bodyScope);
105
70
  visit(node.body, bodyScope);
106
71
  } else visit(node.body, parameterScope);
107
72
  return;
108
73
  }
74
+ if (node.type === "SwitchStatement") {
75
+ if (isAstRecord(node.discriminant)) visit(node.discriminant, parentScope);
76
+ const switchScope = createAstScope(parentScope);
77
+ collectSwitchScopeBindings(node, switchScope);
78
+ for (const switchCase of nodeArray(node.cases)) if (isAstRecord(switchCase)) visit(switchCase, switchScope);
79
+ return;
80
+ }
109
81
  const scope = createChildScope(node, parentScope) ?? parentScope;
110
82
  if (node.type === "IfStatement" && hasRange(node)) {
111
83
  const result = evaluateTypeofWindowComparison(node.test, replacement, scope);
@@ -132,7 +104,7 @@ function replaceTypeofWindow(code, replacement) {
132
104
  return;
133
105
  }
134
106
  }
135
- if (node.type === "UnaryExpression" && node.operator === "typeof" && isIdentifierNamed(node.argument, "window") && !hasBinding(scope, "window") && hasRange(node)) {
107
+ if (node.type === "UnaryExpression" && node.operator === "typeof" && isIdentifierNamed(node.argument, "window") && !hasAstBinding(scope, "window") && hasRange(node)) {
136
108
  output.overwrite(node.start, node.end, JSON.stringify(replacement));
137
109
  changed = true;
138
110
  return;
@@ -83,7 +83,12 @@ type AppRoute = {
83
83
  routePath: string | null; /** Ordered list of layout files from root to leaf */
84
84
  layouts: string[]; /** Ordered list of all discovered template files from root to leaf (not necessarily aligned 1:1 with layouts) */
85
85
  templates: string[]; /** Parallel route slots (from @slot directories at the route's directory level) */
86
- parallelSlots: ParallelSlot[];
86
+ parallelSlots: ParallelSlot[]; /** Stable implicit children-slot identity for parallel-slot sub-route families. */
87
+ childrenSlot?: {
88
+ id: string;
89
+ ownerTreePath: string;
90
+ state: "active" | "default" | "unmatched";
91
+ };
87
92
  /**
88
93
  * Interception markers not wrapped in an `@slot` directory.
89
94
  * On soft-nav, the intercepting page replaces the entire page response.
@@ -122,7 +127,16 @@ type AppRoute = {
122
127
  * Includes route groups and dynamic segments (as template strings like "[id]").
123
128
  * Used at render time to compute the child segments for useSelectedLayoutSegments().
124
129
  */
125
- routeSegments: string[]; /** Tree position (directory depth from app/ root) for each template. */
130
+ routeSegments: string[];
131
+ /**
132
+ * Active filesystem segments for the default `children` slot.
133
+ *
134
+ * Synthetic routes materialized only from named parallel-slot pages still
135
+ * use the full `routeSegments` for URL matching, params, and route identity,
136
+ * but their children slot renders the parent's default.tsx. In that case the
137
+ * active children segments remain at the parent route.
138
+ */
139
+ childrenRouteSegments?: string[]; /** Tree position (directory depth from app/ root) for each template. */
126
140
  templateTreePositions?: number[];
127
141
  /**
128
142
  * Tree position (directory depth from app/ root) for each layout.
@@ -276,6 +290,13 @@ type RouteManifest = {
276
290
  graphVersion: GraphVersion;
277
291
  segmentGraph: StaticSegmentGraph;
278
292
  };
293
+ /**
294
+ * Build the App Router route graph by scanning `appDir`.
295
+ *
296
+ * `appDir` must be forward-slash. Every path in the graph is derived from it
297
+ * with `path.posix.*` and `findFile`, so a native appDir would produce mixed
298
+ * separators on Windows. Production callers normalize it at their entry.
299
+ */
279
300
  declare function buildAppRouteGraph(appDir: string, matcher: ValidFileMatcher): Promise<{
280
301
  routes: AppRouteGraphRoute[];
281
302
  routeManifest: RouteManifest;