vinext 1.1.0 → 1.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 (288) hide show
  1. package/README.md +22 -10
  2. package/dist/build/client-build-config.d.ts +10 -0
  3. package/dist/build/client-build-config.js +18 -2
  4. package/dist/build/output-root-externals.d.ts +21 -0
  5. package/dist/build/output-root-externals.js +40 -0
  6. package/dist/build/pages-client-assets-module.d.ts +8 -0
  7. package/dist/build/pages-client-assets-module.js +21 -1
  8. package/dist/build/prerender-paths.js +6 -4
  9. package/dist/build/prerender.js +1 -1
  10. package/dist/build/run-prerender.js +1 -1
  11. package/dist/build/ssr-manifest.d.ts +2 -0
  12. package/dist/build/ssr-manifest.js +6 -2
  13. package/dist/check.js +12 -12
  14. package/dist/cli-dev-config.js +3 -3
  15. package/dist/cli.js +3 -2
  16. package/dist/client/client-redirect-matcher.d.ts +14 -0
  17. package/dist/client/client-redirect-matcher.js +37 -0
  18. package/dist/client/client-redirects.d.ts +27 -0
  19. package/dist/client/client-redirects.js +28 -0
  20. package/dist/client/client-rewrites.d.ts +2 -1
  21. package/dist/client/client-rewrites.js +1 -1
  22. package/dist/config/config-matchers.d.ts +26 -11
  23. package/dist/config/config-matchers.js +90 -88
  24. package/dist/config/destination-params.d.ts +47 -0
  25. package/dist/config/destination-params.js +116 -0
  26. package/dist/config/next-config.d.ts +7 -0
  27. package/dist/config/next-config.js +3 -0
  28. package/dist/entries/app-rsc-entry.d.ts +4 -0
  29. package/dist/entries/app-rsc-entry.js +20 -6
  30. package/dist/entries/pages-client-entry.js +3 -1
  31. package/dist/entries/pages-server-entry.js +13 -37
  32. package/dist/index.d.ts +3 -1
  33. package/dist/index.js +246 -136
  34. package/dist/init-cloudflare.d.ts +9 -0
  35. package/dist/init-cloudflare.js +107 -31
  36. package/dist/init-platform.d.ts +4 -0
  37. package/dist/init-platform.js +27 -2
  38. package/dist/init.d.ts +2 -1
  39. package/dist/init.js +153 -9
  40. package/dist/plugins/ast-scope.d.ts +7 -0
  41. package/dist/plugins/ast-scope.js +59 -3
  42. package/dist/plugins/ast-utils.d.ts +53 -2
  43. package/dist/plugins/ast-utils.js +90 -2
  44. package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
  45. package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
  46. package/dist/plugins/commonjs-esm-facade.js +2 -2
  47. package/dist/plugins/css-module-imports.js +13 -20
  48. package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
  49. package/dist/plugins/dynamic-preload-metadata.js +11 -11
  50. package/dist/plugins/extensionless-dynamic-import.js +2 -3
  51. package/dist/plugins/fonts.d.ts +1 -1
  52. package/dist/plugins/fonts.js +3 -3
  53. package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
  54. package/dist/plugins/ignore-dynamic-requests.js +5 -7
  55. package/dist/plugins/import-meta-url.js +3 -4
  56. package/dist/plugins/instrumentation-client.js +3 -2
  57. package/dist/plugins/middleware-export-validation.js +2 -3
  58. package/dist/plugins/middleware-server-only.d.ts +5 -4
  59. package/dist/plugins/middleware-server-only.js +8 -5
  60. package/dist/plugins/og-harfbuzz.js +2 -3
  61. package/dist/plugins/optimize-imports.js +3 -4
  62. package/dist/plugins/pages-node-externals.js +3 -4
  63. package/dist/plugins/remove-console.js +2 -18
  64. package/dist/plugins/require-condition-resolution.js +3 -3
  65. package/dist/plugins/require-context.js +2 -3
  66. package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
  67. package/dist/plugins/rsc-scan-glob-imports.js +50 -0
  68. package/dist/plugins/strip-server-exports.js +265 -102
  69. package/dist/plugins/styled-jsx.js +2 -3
  70. package/dist/plugins/transform-result.d.ts +9 -5
  71. package/dist/plugins/transitive-externals.js +1 -1
  72. package/dist/plugins/typeof-window.d.ts +2 -2
  73. package/dist/plugins/use-cache-callable.d.ts +21 -2
  74. package/dist/plugins/use-cache-callable.js +84 -35
  75. package/dist/plugins/worker-image-imports.js +30 -33
  76. package/dist/plugins/worker-server-only-imports.d.ts +20 -0
  77. package/dist/plugins/worker-server-only-imports.js +31 -0
  78. package/dist/plugins/worker-use-server.d.ts +25 -0
  79. package/dist/plugins/worker-use-server.js +153 -0
  80. package/dist/server/api-handler.d.ts +1 -0
  81. package/dist/server/api-handler.js +3 -2
  82. package/dist/server/app-action-forwarding.js +2 -2
  83. package/dist/server/app-browser-action-result.d.ts +1 -1
  84. package/dist/server/app-browser-action-result.js +9 -2
  85. package/dist/server/app-browser-entry.js +3 -3
  86. package/dist/server/app-browser-interception-context.js +1 -1
  87. package/dist/server/app-browser-navigation-controller.js +1 -1
  88. package/dist/server/app-browser-prefetch-response.js +2 -2
  89. package/dist/server/app-browser-server-action-client.js +1 -1
  90. package/dist/server/app-browser-state.js +1 -1
  91. package/dist/server/app-browser-supplemental-refresh.js +1 -1
  92. package/dist/server/app-middleware.d.ts +11 -0
  93. package/dist/server/app-middleware.js +17 -2
  94. package/dist/server/app-optimistic-routing.js +1 -1
  95. package/dist/server/app-page-cache.d.ts +1 -1
  96. package/dist/server/app-page-cache.js +1 -1
  97. package/dist/server/app-page-dispatch.d.ts +3 -1
  98. package/dist/server/app-page-dispatch.js +5 -4
  99. package/dist/server/app-page-ppr-runtime.js +1 -1
  100. package/dist/server/app-page-render-observation.js +1 -1
  101. package/dist/server/app-page-render.js +1 -1
  102. package/dist/server/app-page-request.js +53 -15
  103. package/dist/server/app-page-route-wiring.js +2 -2
  104. package/dist/server/app-pages-bridge.d.ts +1 -1
  105. package/dist/server/app-pages-bridge.js +3 -4
  106. package/dist/server/app-prerender-endpoints.js +9 -6
  107. package/dist/server/app-render-abort-error.d.ts +19 -0
  108. package/dist/server/app-render-abort-error.js +31 -1
  109. package/dist/server/app-request-stage-dispatch.js +6 -2
  110. package/dist/server/app-request-stage-independent-entry.js +29 -9
  111. package/dist/server/app-response-stage-entry.js +11 -3
  112. package/dist/server/app-route-handler-cache.d.ts +1 -0
  113. package/dist/server/app-route-handler-cache.js +1 -0
  114. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  115. package/dist/server/app-route-handler-dispatch.js +5 -2
  116. package/dist/server/app-route-handler-execution.d.ts +1 -0
  117. package/dist/server/app-route-handler-execution.js +1 -0
  118. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  119. package/dist/server/app-route-handler-runtime.js +46 -25
  120. package/dist/server/app-router-entry.js +29 -10
  121. package/dist/server/app-rsc-cache-busting.d.ts +16 -0
  122. package/dist/server/app-rsc-cache-busting.js +30 -13
  123. package/dist/server/app-rsc-errors.js +20 -16
  124. package/dist/server/app-rsc-handler.d.ts +7 -0
  125. package/dist/server/app-rsc-handler.js +89 -39
  126. package/dist/server/app-rsc-request-normalization.js +3 -3
  127. package/dist/server/app-rsc-response-stage.js +5 -3
  128. package/dist/server/app-segment-config.d.ts +2 -1
  129. package/dist/server/app-server-action-execution.d.ts +2 -1
  130. package/dist/server/app-server-action-execution.js +62 -23
  131. package/dist/server/app-ssr-entry.js +7 -5
  132. package/dist/server/app-visited-response-cache.js +2 -2
  133. package/dist/server/app-worker-stages.d.ts +5 -0
  134. package/dist/server/app-worker-stages.js +1 -1
  135. package/dist/server/cacheability-request.js +2 -2
  136. package/dist/server/client-build-files.d.ts +16 -0
  137. package/dist/server/client-build-files.js +36 -0
  138. package/dist/server/client-reuse-manifest.js +1 -1
  139. package/dist/server/config-headers.js +1 -1
  140. package/dist/server/defer-until-stream-consumed.d.ts +2 -1
  141. package/dist/server/defer-until-stream-consumed.js +3 -1
  142. package/dist/server/dev-server.js +39 -28
  143. package/dist/server/dev-stack-sourcemap.js +18 -23
  144. package/dist/server/document-initial-head.d.ts +0 -11
  145. package/dist/server/document-initial-head.js +1 -1
  146. package/dist/server/forwarded-middleware-context.d.ts +5 -0
  147. package/dist/server/forwarded-middleware-context.js +22 -0
  148. package/dist/server/headers.d.ts +4 -1
  149. package/dist/server/headers.js +4 -1
  150. package/dist/server/http-conditional.d.ts +11 -0
  151. package/dist/server/http-conditional.js +10 -1
  152. package/dist/server/http-error-responses.d.ts +1 -1
  153. package/dist/server/image-optimization.d.ts +38 -0
  154. package/dist/server/image-optimization.js +94 -4
  155. package/dist/server/isr-cache.d.ts +10 -0
  156. package/dist/server/isr-cache.js +41 -6
  157. package/dist/server/metadata-route-response.js +11 -10
  158. package/dist/server/middleware-matcher.d.ts +2 -0
  159. package/dist/server/middleware-matcher.js +23 -2
  160. package/dist/server/middleware-path-to-regexp.js +1 -1
  161. package/dist/server/middleware-runtime.d.ts +13 -0
  162. package/dist/server/middleware-runtime.js +38 -25
  163. package/dist/server/middleware.d.ts +1 -1
  164. package/dist/server/middleware.js +3 -1
  165. package/dist/server/multi-stage.d.ts +11 -0
  166. package/dist/server/navigation-planner.js +1 -1
  167. package/dist/server/normalize-path.d.ts +0 -13
  168. package/dist/server/normalize-path.js +1 -34
  169. package/dist/server/open-redirect.d.ts +11 -4
  170. package/dist/server/open-redirect.js +11 -4
  171. package/dist/server/pages-api-route.d.ts +3 -2
  172. package/dist/server/pages-api-route.js +6 -5
  173. package/dist/server/pages-cache-tag.d.ts +12 -0
  174. package/dist/server/pages-cache-tag.js +19 -0
  175. package/dist/server/pages-client-assets.d.ts +2 -0
  176. package/dist/server/pages-data-route.d.ts +10 -0
  177. package/dist/server/pages-data-route.js +21 -3
  178. package/dist/server/pages-document-asset-props.d.ts +5 -1
  179. package/dist/server/pages-document-asset-props.js +13 -5
  180. package/dist/server/pages-document-splice.d.ts +19 -0
  181. package/dist/server/pages-document-splice.js +55 -0
  182. package/dist/server/pages-i18n.d.ts +12 -1
  183. package/dist/server/pages-i18n.js +18 -4
  184. package/dist/server/pages-node-compat.d.ts +16 -5
  185. package/dist/server/pages-node-compat.js +20 -12
  186. package/dist/server/pages-page-data.d.ts +32 -24
  187. package/dist/server/pages-page-data.js +51 -121
  188. package/dist/server/pages-page-handler.d.ts +0 -6
  189. package/dist/server/pages-page-handler.js +189 -127
  190. package/dist/server/pages-page-response.d.ts +12 -6
  191. package/dist/server/pages-page-response.js +42 -35
  192. package/dist/server/pages-request-pipeline.d.ts +10 -2
  193. package/dist/server/pages-request-pipeline.js +41 -22
  194. package/dist/server/pages-request-stage-entry.d.ts +6 -0
  195. package/dist/server/pages-request-stage-entry.js +75 -16
  196. package/dist/server/pages-response-stage-entry.js +4 -0
  197. package/dist/server/pages-revalidate.js +3 -3
  198. package/dist/server/pages-router-entry.js +5 -4
  199. package/dist/server/prerender-manifest.d.ts +3 -3
  200. package/dist/server/prerender-manifest.js +4 -3
  201. package/dist/server/prerender-work-unit-setup.js +4 -0
  202. package/dist/server/prod-server.d.ts +12 -0
  203. package/dist/server/prod-server.js +204 -74
  204. package/dist/server/proper-error.d.ts +4 -0
  205. package/dist/server/proper-error.js +31 -0
  206. package/dist/server/request-pipeline.d.ts +4 -1
  207. package/dist/server/request-pipeline.js +3 -2
  208. package/dist/server/revalidation-request.d.ts +1 -0
  209. package/dist/server/revalidation-request.js +1 -1
  210. package/dist/server/rsc-stream-hints.d.ts +1 -1
  211. package/dist/server/rsc-stream-hints.js +52 -5
  212. package/dist/server/seed-cache.d.ts +1 -0
  213. package/dist/server/seed-cache.js +5 -4
  214. package/dist/server/server-reference-loader.d.ts +4 -0
  215. package/dist/server/server-reference-loader.js +29 -0
  216. package/dist/server/socket-error-backstop.d.ts +9 -1
  217. package/dist/server/socket-error-backstop.js +46 -17
  218. package/dist/server/static-file-signal.d.ts +15 -4
  219. package/dist/server/static-file-signal.js +46 -12
  220. package/dist/server/worker-image-optimization.d.ts +34 -0
  221. package/dist/server/worker-image-optimization.js +99 -0
  222. package/dist/server/worker-stages.d.ts +1 -1
  223. package/dist/server/worker-stages.js +2 -2
  224. package/dist/server/worker-utils.d.ts +8 -3
  225. package/dist/server/worker-utils.js +12 -7
  226. package/dist/shims/app-router-scroll.js +4 -1
  227. package/dist/shims/app-router-tree-context.d.ts +5 -0
  228. package/dist/shims/app-router-tree-context.js +27 -0
  229. package/dist/shims/cache-callable-runtime.d.ts +4 -2
  230. package/dist/shims/cache-callable-runtime.js +21 -12
  231. package/dist/shims/cache-handler.js +1 -9
  232. package/dist/shims/cache-runtime.d.ts +6 -1
  233. package/dist/shims/cache-runtime.js +2 -1
  234. package/dist/shims/cache.d.ts +2 -2
  235. package/dist/shims/cache.js +40 -13
  236. package/dist/shims/cdn-cache.d.ts +8 -0
  237. package/dist/shims/cdn-cache.js +17 -1
  238. package/dist/shims/disable-smooth-scroll.d.ts +3 -0
  239. package/dist/shims/disable-smooth-scroll.js +36 -0
  240. package/dist/shims/document-placeholders.d.ts +19 -0
  241. package/dist/shims/document-placeholders.js +45 -0
  242. package/dist/shims/document.js +21 -5
  243. package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
  244. package/dist/shims/dynamic-preload-chunks.js +13 -9
  245. package/dist/shims/dynamic.d.ts +1 -1
  246. package/dist/shims/dynamic.js +60 -8
  247. package/dist/shims/fetch-cache-state.d.ts +66 -0
  248. package/dist/shims/fetch-cache-state.js +92 -0
  249. package/dist/shims/fetch-cache.d.ts +3 -67
  250. package/dist/shims/fetch-cache.js +160 -125
  251. package/dist/shims/head.d.ts +10 -6
  252. package/dist/shims/head.js +16 -14
  253. package/dist/shims/headers.js +2 -2
  254. package/dist/shims/image.js +2 -1
  255. package/dist/shims/internal/hybrid-client-route-owner-direct.js +1 -1
  256. package/dist/shims/internal/hybrid-client-route-owner.js +1 -0
  257. package/dist/shims/internal/work-store-scope.d.ts +5 -0
  258. package/dist/shims/internal/work-store-scope.js +24 -0
  259. package/dist/shims/link-prefetch.js +5 -4
  260. package/dist/shims/link.js +2 -2
  261. package/dist/shims/navigation.js +34 -9
  262. package/dist/shims/request-context.d.ts +2 -0
  263. package/dist/shims/request-state-types.d.ts +2 -1
  264. package/dist/shims/router.js +21 -32
  265. package/dist/shims/server.d.ts +27 -4
  266. package/dist/shims/server.js +65 -9
  267. package/dist/shims/unified-request-context.d.ts +1 -1
  268. package/dist/shims/url-utils.d.ts +9 -0
  269. package/dist/shims/url-utils.js +15 -4
  270. package/dist/utils/client-runtime-metadata.js +1 -1
  271. package/dist/utils/domain-locale.js +1 -1
  272. package/dist/utils/hash.d.ts +7 -0
  273. package/dist/utils/hash.js +11 -1
  274. package/dist/utils/package-name.d.ts +6 -0
  275. package/dist/utils/package-name.js +12 -1
  276. package/dist/utils/plugin-rsc-version.d.ts +6 -0
  277. package/dist/utils/plugin-rsc-version.js +41 -0
  278. package/dist/utils/prerender-output-paths.js +15 -4
  279. package/dist/utils/public-file-path.d.ts +10 -2
  280. package/dist/utils/public-file-path.js +13 -9
  281. package/dist/utils/public-routes.js +2 -2
  282. package/dist/utils/react-version.d.ts +10 -0
  283. package/dist/utils/react-version.js +39 -16
  284. package/package.json +11 -7
  285. package/dist/build/nitro-route-rules.d.ts +0 -47
  286. package/dist/build/nitro-route-rules.js +0 -79
  287. package/dist/plugins/cache-flight-codec.d.ts +0 -19
  288. package/dist/plugins/cache-flight-codec.js +0 -68
package/dist/init.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import path, { toSlash } from "./deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import { detectPackageManager, detectPackageManagerName, detectProject, ensureESModule, findViteConfigPath, hasViteConfig, renameCJSConfigs } from "./utils/project.js";
3
- import { compactResourceName, cssModulesConfigSource, setupCloudflarePlatform, updateViteConfigForCssModules, usesCommonJsViteConfig, validateCloudflarePlatformSetup } from "./init-cloudflare.js";
3
+ import { compactResourceName, cssModulesConfigSource, findConfigKeepingWorkerName, setupCloudflarePlatform, updateViteConfigForCssModules, usesCommonJsViteConfig, validateCloudflarePlatformSetup } from "./init-cloudflare.js";
4
4
  import { getReactUpgradeDeps } from "./utils/react-version.js";
5
5
  import fs from "node:fs";
6
6
  import { spawn, spawnSync } from "node:child_process";
@@ -14,7 +14,8 @@ import { spawn, spawnSync } from "node:child_process";
14
14
  * 2. Add "type": "module" to package.json
15
15
  * 3. Rename CJS config files to .cjs
16
16
  * 4. Add vinext scripts to package.json
17
- * 5. Generate vite.config.ts and platform files
17
+ * 5. Generate vite.config.ts and platform files, plus a Tailwind PostCSS
18
+ * config when Tailwind is only set up as a Turbopack loader
18
19
  * 6. Update .gitignore to include /dist/ and .vinext/
19
20
  * 7. Install dependencies (vite, @vitejs/plugin-react, and App Router deps)
20
21
  * 8. Print summary
@@ -94,6 +95,77 @@ function scanCssModuleFiles(root) {
94
95
  exclude: (entry) => entry.isDirectory() && (CSS_MODULE_IGNORES.has(entry.name) || toSlash(entry.parentPath) === canonicalRoot && CSS_MODULE_ROOT_IGNORES.has(entry.name))
95
96
  }).some((entry) => /\.module\.(css|scss|sass)$/.test(entry.name));
96
97
  }
98
+ const NEXT_CONFIG_FILES = [
99
+ "next.config.ts",
100
+ "next.config.mts",
101
+ "next.config.mjs",
102
+ "next.config.js",
103
+ "next.config.cjs"
104
+ ];
105
+ const TAILWIND_LOADERS = ["@tailwindcss/turbopack", "@tailwindcss/webpack"];
106
+ const TAILWIND_POSTCSS_CONFIG = `const config = {
107
+ plugins: {
108
+ "@tailwindcss/postcss": {},
109
+ },
110
+ };
111
+
112
+ export default config;
113
+ `;
114
+ /**
115
+ * Whether the project gets Tailwind from a Turbopack loader (as create-next-app
116
+ * 16.4+ sets up in `turbopack.rules`) rather than from PostCSS, which is the
117
+ * only way vinext compiles Tailwind. The config is not evaluated: a Next config
118
+ * that names the loader, or a declared loader package, is enough.
119
+ */
120
+ function usesTailwindTurbopackLoader(root) {
121
+ for (const file of NEXT_CONFIG_FILES) {
122
+ const configPath = path.join(root, file);
123
+ if (!fs.existsSync(configPath)) continue;
124
+ const source = fs.readFileSync(configPath, "utf-8");
125
+ if (TAILWIND_LOADERS.some((loader) => source.includes(loader))) return true;
126
+ }
127
+ return TAILWIND_LOADERS.some((loader) => isDepInstalled(root, loader));
128
+ }
129
+ const POSTCSS_CONFIG_SEARCH_ORDER = [
130
+ ".postcssrc",
131
+ ".postcssrc.json",
132
+ ".postcssrc.yaml",
133
+ ".postcssrc.yml",
134
+ ".postcssrc.ts",
135
+ ".postcssrc.cts",
136
+ ".postcssrc.mts",
137
+ ".postcssrc.js",
138
+ ".postcssrc.cjs",
139
+ ".postcssrc.mjs",
140
+ "postcss.config.ts",
141
+ "postcss.config.cts",
142
+ "postcss.config.mts",
143
+ "postcss.config.js",
144
+ "postcss.config.cjs",
145
+ "postcss.config.mjs"
146
+ ];
147
+ /** The source of the PostCSS config Vite would load, which init never replaces. */
148
+ function readPostcssConfig(root) {
149
+ try {
150
+ const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf-8"));
151
+ if (pkg.postcss) return JSON.stringify(pkg.postcss);
152
+ } catch {}
153
+ for (const file of POSTCSS_CONFIG_SEARCH_ORDER) {
154
+ const configPath = path.join(root, file);
155
+ if (!fs.existsSync(configPath)) continue;
156
+ const source = fs.readFileSync(configPath, "utf-8");
157
+ if (source.trim() !== "") return source;
158
+ }
159
+ }
160
+ function getTailwindPostcssSetup(root, viteConfigPath) {
161
+ if (!usesTailwindTurbopackLoader(root)) return "none";
162
+ const viteConfig = viteConfigPath ? fs.readFileSync(viteConfigPath, "utf-8") : "";
163
+ const config = /postcss|lightningcss|tailwindcss/.test(viteConfig) ? viteConfig : readPostcssConfig(root);
164
+ if (config === void 0) return "generate";
165
+ if (/lightningcss/.test(config) && !config.includes("@tailwindcss/vite")) return "manual";
166
+ if (config.includes("@tailwindcss/postcss")) return "install";
167
+ return config.includes("tailwindcss") ? "none" : "manual";
168
+ }
97
169
  /**
98
170
  * Add Vite scripts to package.json without overwriting custom scripts.
99
171
  * Exact scripts generated by older vinext versions are migrated in place.
@@ -123,7 +195,7 @@ function addScripts(root, port, platform = "node", options = {}) {
123
195
  if (platform === "cloudflare") {
124
196
  addScript("deploy", !options.legacyWrangler ? options.warmCdnCache ? "vinext-cloudflare deploy --warm-cache" : "vinext-cloudflare deploy" : options.warmCdnCache ? "vinext-cloudflare deploy --config dist/server/wrangler.json --warm-cache" : "vinext-cloudflare deploy --config dist/server/wrangler.json");
125
197
  if (options.deployResponseStore && !pkg.scripts["deploy:response-store"]) {
126
- pkg.scripts["deploy:response-store"] = !options.legacyWrangler ? `cf deploy --prebuilt --mode production --worker ${compactResourceName(detectProject(root).projectName, "-response-store", 63)}` : "wrangler deploy --config wrangler.response-store.jsonc";
198
+ pkg.scripts["deploy:response-store"] = !options.legacyWrangler ? `cf deploy --prebuilt --mode production --worker ${compactResourceName(options.workerName ?? detectProject(root).projectName, "-response-store", 63)}` : "wrangler deploy --config wrangler.response-store.jsonc";
127
199
  added.push("deploy:response-store");
128
200
  }
129
201
  }
@@ -133,7 +205,7 @@ function addScripts(root, port, platform = "node", options = {}) {
133
205
  return [];
134
206
  }
135
207
  }
136
- function getInitDependencyGroups(isAppRouter, platform, cloudflare, hasCssModules = false) {
208
+ function getInitDependencyGroups(isAppRouter, platform, cloudflare, hasCssModules = false, tailwindPostcss = false) {
137
209
  const dependencies = ["vinext"];
138
210
  const devDependencies = ["vite", "@vitejs/plugin-react"];
139
211
  if (isAppRouter) {
@@ -149,6 +221,7 @@ function getInitDependencyGroups(isAppRouter, platform, cloudflare, hasCssModule
149
221
  } else devDependencies.push("@cloudflare/vite-plugin@1", "wrangler");
150
222
  }
151
223
  if (hasCssModules) devDependencies.push("vite-css-modules", "postcss");
224
+ if (tailwindPostcss) devDependencies.push("@tailwindcss/postcss");
152
225
  return {
153
226
  dependencies,
154
227
  devDependencies
@@ -227,7 +300,7 @@ function addDependencyEntries(root, deps, { dev }) {
227
300
  * Check if react/react-dom need upgrading for react-server-dom-webpack compatibility.
228
301
  *
229
302
  * react-server-dom-webpack versions are pinned to match their React version
230
- * (e.g. rsdw@19.2.6 requires react@^19.2.6). When a project has an older
303
+ * (e.g. rsdw@19.3.1 requires react@^19.3.1). When a project has an older
231
304
  * React (e.g. create-next-app ships react@19.2.3), we need to upgrade
232
305
  * react/react-dom BEFORE installing rsdw to avoid peer-dep conflicts.
233
306
  *
@@ -302,6 +375,64 @@ function updateGitignore(root, platform = "node", legacyWrangler = false) {
302
375
  fs.writeFileSync(gitignorePath, content + separator + missingEntries.join("\n") + "\n", "utf-8");
303
376
  return true;
304
377
  }
378
+ /**
379
+ * Read `output` from the Next.js config as `vinext build` does: an inline
380
+ * `vinext({ nextConfig })` in the Vite config wins over next.config, and both
381
+ * are evaluated with NODE_ENV set to production and `.env.production` loaded as
382
+ * the build loads it. The Vite config is read as written, without running
383
+ * plugin `config` hooks, so a plugin that changes `root`, `envDir` or `mode` is
384
+ * not seen. A config that cannot load here keeps the Worker-first default.
385
+ * The loader is imported lazily because it needs Vite, which create-vinext-app
386
+ * runs without.
387
+ */
388
+ async function resolvesToStaticExport(root, viteConfigPath) {
389
+ let configModule;
390
+ let dotenvModule;
391
+ try {
392
+ [configModule, dotenvModule] = await Promise.all([import("./config/next-config.js"), import("./config/dotenv.js")]);
393
+ } catch {
394
+ return false;
395
+ }
396
+ const { findVinextNextConfigInPlugins, loadNextConfig, PHASE_PRODUCTION_BUILD, resolveNextConfigInput } = configModule;
397
+ const savedEnv = { ...process.env };
398
+ Reflect.set(process.env, "NODE_ENV", "production");
399
+ try {
400
+ dotenvModule.loadDotenv({
401
+ root,
402
+ mode: "production"
403
+ });
404
+ let mode = "production";
405
+ let inline = null;
406
+ let configRoot = root;
407
+ let envDir;
408
+ if (viteConfigPath) try {
409
+ const { loadConfigFromFile } = await import("vite");
410
+ const loaded = await loadConfigFromFile({
411
+ command: "build",
412
+ mode: "production",
413
+ isSsrBuild: false,
414
+ isPreview: false
415
+ }, viteConfigPath, root, "silent");
416
+ if (typeof loaded?.config.mode === "string") mode = loaded.config.mode;
417
+ if (typeof loaded?.config.root === "string") configRoot = path.resolve(root, loaded.config.root);
418
+ const configuredEnvDir = loaded?.config.envDir;
419
+ if (configuredEnvDir === false) envDir = false;
420
+ else if (typeof configuredEnvDir === "string") envDir = path.resolve(root, configuredEnvDir);
421
+ inline = await findVinextNextConfigInPlugins(loaded?.config.plugins);
422
+ } catch {}
423
+ if (envDir !== false) dotenvModule.loadDotenv({
424
+ root: envDir ?? configRoot,
425
+ mode
426
+ });
427
+ Reflect.set(process.env, "NODE_ENV", "production");
428
+ return (inline ? await resolveNextConfigInput(inline, PHASE_PRODUCTION_BUILD) : await loadNextConfig(configRoot, PHASE_PRODUCTION_BUILD))?.output === "export";
429
+ } catch {
430
+ return false;
431
+ } finally {
432
+ for (const key of Object.keys(process.env)) if (!Object.hasOwn(savedEnv, key)) delete process.env[key];
433
+ Object.assign(process.env, savedEnv);
434
+ }
435
+ }
305
436
  function setupNodePlatform(context) {
306
437
  if (context.viteConfigExists && !context.force) {
307
438
  if (context.hasCssModules && context.existingViteConfigPath) {
@@ -387,16 +518,20 @@ async function init(options) {
387
518
  const viteConfigExists = hasViteConfig(root);
388
519
  const isApp = detectProject(root).isAppRouter;
389
520
  const hasCssModules = !options.skipCssModules && scanCssModuleFiles(root);
521
+ const tailwindPostcssSetup = getTailwindPostcssSetup(root, platform === "node" && options.force ? void 0 : existingViteConfigPath);
390
522
  const pmName = detectPackageManagerName(root);
391
523
  const shouldInstall = options.install ?? true;
524
+ const isStaticExport = platform === "cloudflare" && await resolvesToStaticExport(root, existingViteConfigPath);
392
525
  if (platform === "cloudflare") validateCloudflarePlatformSetup({
393
526
  root,
394
527
  isAppRouter: isApp,
395
528
  existingViteConfigPath,
396
529
  hasCssModules,
530
+ isStaticExport,
397
531
  today: options._today
398
532
  }, cloudflareOptions);
399
533
  else if (hasCssModules && existingViteConfigPath && !options.force) updateViteConfigForCssModules(existingViteConfigPath, fs.readFileSync(existingViteConfigPath, "utf-8"));
534
+ const configKeepingWorkerName = platform === "cloudflare" ? findConfigKeepingWorkerName(root, cloudflareOptions) : void 0;
400
535
  if (!options.skipCheck) {
401
536
  console.log(" Running compatibility check...\n");
402
537
  const { runCheck, formatReport } = await import("./check.js");
@@ -417,7 +552,8 @@ async function init(options) {
417
552
  deployResponseStore,
418
553
  warmCdnCache: options.cloudflare?.warmCdnCache ?? false,
419
554
  legacyWrangler: options.cloudflare?.legacyWrangler,
420
- scriptNames: options.scriptNames
555
+ scriptNames: options.scriptNames,
556
+ workerName: configKeepingWorkerName ? void 0 : options.cloudflare?.name
421
557
  });
422
558
  const setupContext = {
423
559
  root,
@@ -428,19 +564,24 @@ async function init(options) {
428
564
  force: options.force ?? false,
429
565
  prerender: options.prerender,
430
566
  hasCssModules,
567
+ isStaticExport,
431
568
  today: options._today
432
569
  };
433
570
  const platformSetup = platform === "cloudflare" ? setupCloudflarePlatform(setupContext, cloudflareOptions) : setupNodePlatform(setupContext);
434
571
  const { generatedViteConfig, skippedViteConfig, generatedPlatformFiles } = platformSetup;
572
+ if (tailwindPostcssSetup === "generate") fs.writeFileSync(path.join(root, "postcss.config.mjs"), TAILWIND_POSTCSS_CONFIG, "utf-8");
435
573
  const updatedGitignore = updateGitignore(root, platform, options.cloudflare?.legacyWrangler);
436
- const neededDeps = getInitDependencyGroups(isApp, platform, options.cloudflare, hasCssModules);
574
+ const neededDeps = getInitDependencyGroups(isApp, platform, options.cloudflare, hasCssModules, tailwindPostcssSetup === "generate" || tailwindPostcssSetup === "install");
437
575
  const missingDependencies = neededDeps.dependencies.filter((dep) => !isDepInstalled(root, dep));
438
576
  const missingDevDependencies = neededDeps.devDependencies.filter((dep) => !isDepInstalled(root, dep));
439
577
  let dependencyInstallNeedsApproval = false;
440
578
  const dependencyEntriesAdded = [];
441
579
  const devDependencyEntriesAdded = [];
442
- if (isApp && (!shouldInstall || missingDependencies.includes("react-server-dom-webpack"))) {
443
- const reactUpgrade = getReactUpgradeDeps(root, { fromManifest: !shouldInstall });
580
+ if (isApp) {
581
+ const reactUpgrade = shouldInstall ? [.../* @__PURE__ */ new Set([...getReactUpgradeDeps(root), ...getReactUpgradeDeps(root, {
582
+ fromManifest: true,
583
+ installing: true
584
+ })])] : getReactUpgradeDeps(root, { fromManifest: true });
444
585
  if (reactUpgrade.length > 0) {
445
586
  console.log(` ${terminalStyle.cyan(terminalStyle.bold("Upgrading dependencies:"))}`);
446
587
  console.log(formatList(reactUpgrade.map((dep) => dep.replace(/@latest$/, "")), " "));
@@ -513,6 +654,9 @@ async function init(options) {
513
654
  if (skippedViteConfig) console.log(` ${terminalStyle.yellow("-")} Skipped vite.config.ts (already exists, use --force to overwrite)`);
514
655
  if (updatedGitignore) console.log(` ${terminalStyle.green("✓")} Added vinext output directories to .gitignore`);
515
656
  if (hasCssModules) console.log(` ${terminalStyle.green("✓")} Configured vite-css-modules for CSS Modules`);
657
+ if (tailwindPostcssSetup === "generate") console.log(` ${terminalStyle.green("✓")} Generated postcss.config.mjs for Tailwind CSS (vinext does not run turbopack.rules loaders)`);
658
+ else if (tailwindPostcssSetup === "manual") console.log(` ${terminalStyle.yellow("!")} Tailwind CSS is set up as a Turbopack loader, which vinext does not run; set up "@tailwindcss/postcss" or "@tailwindcss/vite" for vinext`);
659
+ if (configKeepingWorkerName) console.log(` ${terminalStyle.yellow("!")} Kept the Worker name in the existing ${configKeepingWorkerName}; --name was not applied, so update it there if it should be "${cloudflareOptions.name}"`);
516
660
  if (platformSetup.preservedExistingGenerateScopedName) console.log(` ${terminalStyle.yellow("!")} Preserved existing css.modules.generateScopedName; verify it produces identical class names in SSR and client builds`);
517
661
  const nextSteps = [...platformSetup.nextSteps];
518
662
  if (dependencyInstallNeedsApproval) nextSteps.push("Dependency installation is incomplete because pnpm blocked dependency build scripts:", "1. Review and approve the required build scripts:", " pnpm approve-builds", "2. Finish installing dependencies:", " pnpm install");
@@ -11,4 +11,11 @@ export declare function collectDirectScopeBindings(node: ESTree.Node, scope: Ast
11
11
  export declare function collectLoopScopeBindings(node: ESTree.ForStatement | ESTree.ForInStatement | ESTree.ForOfStatement, scope: AstScope, onVariableDeclarator?: (declaration: ESTree.VariableDeclaration, declarator: ESTree.VariableDeclarator) => void): void;
12
12
  export declare function collectSwitchScopeBindings(node: ESTree.SwitchStatement, scope: AstScope, onVariableDeclarator?: (declaration: ESTree.VariableDeclaration, declarator: ESTree.VariableDeclarator) => void): void;
13
13
  export declare function collectVarScopeBindings(node: ESTree.Node, scope: AstScope, root?: boolean): void;
14
+ /** The nearest scope declaring `name`, or `null` for an unbound (global) name. */
15
+ export declare function findAstBindingScope(scope: AstScope, name: string): AstScope | null;
16
+ /**
17
+ * Visit every node with the scope it is evaluated in. The root scope holds the
18
+ * program's own bindings, including every `var` outside a function.
19
+ */
20
+ export declare function walkAstScopes(root: ESTree.Program, visitor: (node: ESTree.Node, scope: AstScope) => void): AstScope;
14
21
  //#endregion
@@ -23,7 +23,7 @@ function collectDirectScopeBindings(node, scope, onVariableDeclarator) {
23
23
  for (const specifier of declaration.specifiers) if (specifier.type !== "ImportSpecifier" || specifier.importKind !== "type") collectBindingNames(specifier.local, scope.bindings);
24
24
  } else if (declaration.type === "TSImportEqualsDeclaration" && declaration.importKind !== "type") collectBindingNames(declaration.id, scope.bindings);
25
25
  else if (declaration.type === "VariableDeclaration" && declaration.declare !== true) for (const declarator of declaration.declarations) {
26
- collectBindingNames(declarator.id, scope.bindings);
26
+ if (declaration.kind !== "var") collectBindingNames(declarator.id, scope.bindings);
27
27
  onVariableDeclarator?.(declaration, declarator);
28
28
  }
29
29
  else if ((declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") && declaration.declare !== true) collectBindingNames(declaration.id, scope.bindings);
@@ -34,7 +34,7 @@ function collectLoopScopeBindings(node, scope, onVariableDeclarator) {
34
34
  const declarationValue = node.type === "ForStatement" ? node.init : node.left;
35
35
  if (!declarationValue || declarationValue.type !== "VariableDeclaration" || declarationValue.declare === true) return;
36
36
  for (const declarator of declarationValue.declarations) {
37
- collectBindingNames(declarator.id, scope.bindings);
37
+ if (declarationValue.kind !== "var") collectBindingNames(declarator.id, scope.bindings);
38
38
  onVariableDeclarator?.(declarationValue, declarator);
39
39
  }
40
40
  }
@@ -46,5 +46,61 @@ function collectVarScopeBindings(node, scope, root = true) {
46
46
  if (node.type === "VariableDeclaration" && node.kind === "var" && node.declare !== true) for (const declarator of node.declarations) collectBindingNames(declarator.id, scope.bindings);
47
47
  forEachAstChild(node, (child) => collectVarScopeBindings(child, scope, false));
48
48
  }
49
+ /** The nearest scope declaring `name`, or `null` for an unbound (global) name. */
50
+ function findAstBindingScope(scope, name) {
51
+ for (let current = scope; current; current = current.parent) if (current.bindings.has(name)) return current;
52
+ return null;
53
+ }
54
+ /**
55
+ * Visit every node with the scope it is evaluated in. The root scope holds the
56
+ * program's own bindings, including every `var` outside a function.
57
+ */
58
+ function walkAstScopes(root, visitor) {
59
+ const rootScope = createAstScope(null);
60
+ collectDirectScopeBindings(root, rootScope);
61
+ collectVarScopeBindings(root, rootScope);
62
+ function visit(node, parentScope) {
63
+ visitor(node, parentScope);
64
+ let scope = parentScope;
65
+ if (isFunctionNode(node)) {
66
+ const parameterScope = createAstScope(parentScope);
67
+ if (node.type === "FunctionExpression") collectBindingNames(node.id, parameterScope.bindings);
68
+ for (const parameter of node.params) collectBindingNames(parameter, parameterScope.bindings);
69
+ if (node.id) visit(node.id, node.type === "FunctionExpression" ? parameterScope : parentScope);
70
+ for (const parameter of node.params) visit(parameter, parameterScope);
71
+ if (!node.body) return;
72
+ const bodyScope = createAstScope(parameterScope);
73
+ collectDirectScopeBindings(node.body, bodyScope);
74
+ collectVarScopeBindings(node.body, bodyScope);
75
+ if (node.body.type === "BlockStatement") for (const statement of node.body.body) visit(statement, bodyScope);
76
+ else visit(node.body, bodyScope);
77
+ return;
78
+ }
79
+ if (node.type === "SwitchStatement") {
80
+ visit(node.discriminant, parentScope);
81
+ const switchScope = createAstScope(parentScope);
82
+ collectSwitchScopeBindings(node, switchScope);
83
+ for (const switchCase of node.cases) visit(switchCase, switchScope);
84
+ return;
85
+ }
86
+ if (node.type === "BlockStatement" || node.type === "StaticBlock" || node.type === "TSModuleBlock") {
87
+ scope = createAstScope(parentScope);
88
+ collectDirectScopeBindings(node, scope);
89
+ if (node.type === "StaticBlock" || node.type === "TSModuleBlock") collectVarScopeBindings(node, scope);
90
+ } else if (node.type === "CatchClause") {
91
+ scope = createAstScope(parentScope);
92
+ collectBindingNames(node.param, scope.bindings);
93
+ } else if (node.type === "ForStatement" || node.type === "ForInStatement" || node.type === "ForOfStatement") {
94
+ scope = createAstScope(parentScope);
95
+ collectLoopScopeBindings(node, scope);
96
+ } else if (node.type === "ClassExpression" && node.id) {
97
+ scope = createAstScope(parentScope);
98
+ collectBindingNames(node.id, scope.bindings);
99
+ }
100
+ forEachAstChild(node, (child) => visit(child, scope));
101
+ }
102
+ for (const statement of root.body) visit(statement, rootScope);
103
+ return rootScope;
104
+ }
49
105
  //#endregion
50
- export { collectDirectScopeBindings, collectLoopScopeBindings, collectSwitchScopeBindings, collectVarScopeBindings, createAstScope, hasAstBinding, isFunctionNode };
106
+ export { collectDirectScopeBindings, collectLoopScopeBindings, collectSwitchScopeBindings, collectVarScopeBindings, createAstScope, findAstBindingScope, hasAstBinding, isFunctionNode, walkAstScopes };
@@ -1,4 +1,4 @@
1
- import { ESTree } from "vite";
1
+ import { ESTree, ParseResult, ParserOptions } from "vite";
2
2
  //#region src/plugins/ast-utils.d.ts
3
3
  export type ScriptParserLanguage = "js" | "jsx" | "ts" | "tsx";
4
4
  export declare const SCRIPT_MODULE_ID_RE: RegExp;
@@ -8,7 +8,7 @@ export declare const SCRIPT_MODULE_ID_RE: RegExp;
8
8
  * Static imports — `import x from "..."`, `import { ... } from "..."`,
9
9
  * `import "..."` — never place a `(` (nor a comment leading to one) immediately
10
10
  * after the `import` keyword. Plugins that act only on dynamic `import(...)` use
11
- * this to skip `parseAst` for the overwhelming majority of modules in a large
11
+ * this to skip parsing for the overwhelming majority of modules in a large
12
12
  * app: at ~5k routes, where almost every module is a static-import-only page,
13
13
  * it removes most of the build's AST-parse/GC cost. This is a deliberate,
14
14
  * measured performance filter — keep it a regex, never a parse.
@@ -36,6 +36,57 @@ export declare function mayContainDynamicImport(code: string): boolean;
36
36
  * necessarily been lowered.
37
37
  */
38
38
  export declare function scriptParserLanguage(id: string): ScriptParserLanguage | null;
39
+ /** The import/export record oxc builds alongside the AST. */
40
+ export type ModuleRecord = ParseResult["module"];
41
+ /**
42
+ * Parse `code` into an ESTree program, throwing on syntax errors.
43
+ *
44
+ * Replaces Vite's deprecated `parseAst` with the same defaults and contract.
45
+ * Callers that only need import/export declarations should use
46
+ * {@link parseModuleRecord}, which skips building the JS AST.
47
+ */
48
+ export declare function parseProgram(code: string, options?: ParserOptions): ESTree.Program;
49
+ /** Async {@link parseProgram}; replaces Vite's deprecated `parseAstAsync`. */
50
+ export declare function parseProgramAsync(code: string, options?: ParserOptions): Promise<ESTree.Program>;
51
+ /**
52
+ * Parse `code` and return only its static import/export and dynamic import
53
+ * record, or `null` when it has syntax errors.
54
+ *
55
+ * Reading the record never deserializes the JS AST, which is most of the cost
56
+ * of a parse (about 4x cheaper than {@link parseProgram} on large modules).
57
+ * The record omits import attributes; see {@link hasImportAttributes}.
58
+ */
59
+ export declare function parseModuleRecord(code: string, lang: ParserOptions["lang"]): ModuleRecord | null;
60
+ /**
61
+ * One whitespace character or comment. Each alternative can only match one
62
+ * way (a block comment stops at the first `*\/`, a line comment runs to the
63
+ * line end), so repeating it cannot backtrack exponentially.
64
+ */
65
+ export declare const TRIVIA_PATTERN: string;
66
+ /** Leading whitespace and comments. */
67
+ export declare const LEADING_TRIVIA_RE: RegExp;
68
+ /**
69
+ * Whether the static import/export statement ending at `statementEnd` has
70
+ * `with { ... }` (or legacy `assert { ... }`) attributes after its source
71
+ * string, which ends at `sourceEnd`. The module record does not report
72
+ * attributes.
73
+ */
74
+ export declare function hasImportAttributes(code: string, sourceEnd: number, statementEnd: number): boolean;
75
+ /**
76
+ * Whether a static import is erased by TypeScript: every binding is
77
+ * type-only, or it is `import type {} from "x"`, which the module record
78
+ * reports with no entries (like a runtime `import {} from "x"`).
79
+ */
80
+ export declare function isTypeOnlyImport(code: string, statement: ModuleRecord["staticImports"][number]): boolean;
81
+ /**
82
+ * The value of the string literal or expression-free template literal spanning
83
+ * `span`, or `null` for any other expression. The module record gives only the
84
+ * span of a dynamic import's source.
85
+ */
86
+ export declare function quotedStringAt(code: string, span: {
87
+ start: number;
88
+ end: number;
89
+ }): string | null;
39
90
  export declare function isIdentifierNamed(value: ESTree.Node | null | undefined, name: string): boolean;
40
91
  export declare function getAstName(node: ESTree.Node | null | undefined): string | null;
41
92
  /** Remove syntax-only wrappers while preserving the underlying expression. */
@@ -1,3 +1,4 @@
1
+ import { parse, parseSync } from "vite";
1
2
  //#region src/plugins/ast-utils.ts
2
3
  const SCRIPT_MODULE_EXTENSION_RE = /^\.(?:[cm]?[jt]s|[jt]sx)$/i;
3
4
  const SCRIPT_MODULE_ID_RE = /\.(?:[cm]?[jt]s|[jt]sx)(?:[?#].*)?$/i;
@@ -7,7 +8,7 @@ const SCRIPT_MODULE_ID_RE = /\.(?:[cm]?[jt]s|[jt]sx)(?:[?#].*)?$/i;
7
8
  * Static imports — `import x from "..."`, `import { ... } from "..."`,
8
9
  * `import "..."` — never place a `(` (nor a comment leading to one) immediately
9
10
  * after the `import` keyword. Plugins that act only on dynamic `import(...)` use
10
- * this to skip `parseAst` for the overwhelming majority of modules in a large
11
+ * this to skip parsing for the overwhelming majority of modules in a large
11
12
  * app: at ~5k routes, where almost every module is a static-import-only page,
12
13
  * it removes most of the build's AST-parse/GC cost. This is a deliberate,
13
14
  * measured performance filter — keep it a regex, never a parse.
@@ -46,6 +47,93 @@ function scriptParserLanguage(id) {
46
47
  if (extension === ".tsx") return "tsx";
47
48
  return "jsx";
48
49
  }
50
+ const PROGRAM_PARSER_DEFAULTS = {
51
+ lang: "js",
52
+ preserveParens: false
53
+ };
54
+ const PARSE_FILENAME = "file.js";
55
+ function programOrThrow(result) {
56
+ if (result.errors.length > 0) {
57
+ const frames = result.errors.slice(0, 5).map((error) => error.codeframe ?? error.message);
58
+ throw new SyntaxError(`Parse failed with ${result.errors.length} error${result.errors.length === 1 ? "" : "s"}:\n${frames.join("\n")}`);
59
+ }
60
+ return result.program;
61
+ }
62
+ /**
63
+ * Parse `code` into an ESTree program, throwing on syntax errors.
64
+ *
65
+ * Replaces Vite's deprecated `parseAst` with the same defaults and contract.
66
+ * Callers that only need import/export declarations should use
67
+ * {@link parseModuleRecord}, which skips building the JS AST.
68
+ */
69
+ function parseProgram(code, options) {
70
+ return programOrThrow(parseSync(PARSE_FILENAME, code, {
71
+ ...PROGRAM_PARSER_DEFAULTS,
72
+ ...options
73
+ }));
74
+ }
75
+ /** Async {@link parseProgram}; replaces Vite's deprecated `parseAstAsync`. */
76
+ async function parseProgramAsync(code, options) {
77
+ return programOrThrow(await parse(PARSE_FILENAME, code, {
78
+ ...PROGRAM_PARSER_DEFAULTS,
79
+ ...options
80
+ }));
81
+ }
82
+ /**
83
+ * Parse `code` and return only its static import/export and dynamic import
84
+ * record, or `null` when it has syntax errors.
85
+ *
86
+ * Reading the record never deserializes the JS AST, which is most of the cost
87
+ * of a parse (about 4x cheaper than {@link parseProgram} on large modules).
88
+ * The record omits import attributes; see {@link hasImportAttributes}.
89
+ */
90
+ function parseModuleRecord(code, lang) {
91
+ const result = parseSync(PARSE_FILENAME, code, { lang });
92
+ return result.errors.length > 0 ? null : result.module;
93
+ }
94
+ /**
95
+ * One whitespace character or comment. Each alternative can only match one
96
+ * way (a block comment stops at the first `*\/`, a line comment runs to the
97
+ * line end), so repeating it cannot backtrack exponentially.
98
+ */
99
+ const TRIVIA_PATTERN = String.raw`(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/|\/\/[^\n\r\u2028\u2029]*(?![^\n\r\u2028\u2029]))`;
100
+ /** Leading whitespace and comments. */
101
+ const LEADING_TRIVIA_RE = new RegExp(`^${TRIVIA_PATTERN}*`);
102
+ /**
103
+ * Whether the static import/export statement ending at `statementEnd` has
104
+ * `with { ... }` (or legacy `assert { ... }`) attributes after its source
105
+ * string, which ends at `sourceEnd`. The module record does not report
106
+ * attributes.
107
+ */
108
+ function hasImportAttributes(code, sourceEnd, statementEnd) {
109
+ const afterSource = code.slice(sourceEnd, statementEnd);
110
+ const triviaLength = LEADING_TRIVIA_RE.exec(afterSource)?.[0].length ?? 0;
111
+ return /^(?:with|assert)\b/.test(afterSource.slice(triviaLength));
112
+ }
113
+ const EMPTY_TYPE_IMPORT_RE = new RegExp(String.raw`^import${TRIVIA_PATTERN}*type${TRIVIA_PATTERN}*\{`);
114
+ /**
115
+ * Whether a static import is erased by TypeScript: every binding is
116
+ * type-only, or it is `import type {} from "x"`, which the module record
117
+ * reports with no entries (like a runtime `import {} from "x"`).
118
+ */
119
+ function isTypeOnlyImport(code, statement) {
120
+ if (statement.entries.length > 0) return statement.entries.every((entry) => entry.isType);
121
+ return EMPTY_TYPE_IMPORT_RE.test(code.slice(statement.start, statement.moduleRequest.start));
122
+ }
123
+ /**
124
+ * The value of the string literal or expression-free template literal spanning
125
+ * `span`, or `null` for any other expression. The module record gives only the
126
+ * span of a dynamic import's source.
127
+ */
128
+ function quotedStringAt(code, span) {
129
+ const text = code.slice(span.start, span.end);
130
+ const match = /^(?:"([^"\\\r\n]*)"|'([^'\\\r\n]*)'|`([^`\\$]*)`)$/.exec(text);
131
+ if (match) return match[1] ?? match[2] ?? match[3];
132
+ if (!/^["'`]/.test(text)) return null;
133
+ const result = parseSync(PARSE_FILENAME, `(${text})`, PROGRAM_PARSER_DEFAULTS);
134
+ const statement = result.errors.length > 0 ? void 0 : result.program.body[0];
135
+ return statement?.type === "ExpressionStatement" ? staticStringValue(statement.expression) : null;
136
+ }
49
137
  const SKIP_CHILD_KEYS = /* @__PURE__ */ new Set([
50
138
  "type",
51
139
  "parent",
@@ -137,4 +225,4 @@ function collectBindingNames(node, target) {
137
225
  }
138
226
  }
139
227
  //#endregion
140
- export { DYNAMIC_IMPORT_PRESCAN, SCRIPT_MODULE_ID_RE, booleanLiteralValue, collectBindingNames, forEachAstChild, getAstName, isIdentifierNamed, mayContainDynamicImport, scriptParserLanguage, staticStringValue, stringLiteralValue, unwrapExpression, walkAst };
228
+ export { DYNAMIC_IMPORT_PRESCAN, LEADING_TRIVIA_RE, SCRIPT_MODULE_ID_RE, TRIVIA_PATTERN, booleanLiteralValue, collectBindingNames, forEachAstChild, getAstName, hasImportAttributes, isIdentifierNamed, isTypeOnlyImport, mayContainDynamicImport, parseModuleRecord, parseProgram, parseProgramAsync, quotedStringAt, scriptParserLanguage, staticStringValue, stringLiteralValue, unwrapExpression, walkAst };
@@ -0,0 +1,41 @@
1
+ import { Plugin } from "vite";
2
+ //#region src/plugins/cloudflare-dev-module-urls.d.ts
3
+ /**
4
+ * Vite's internal middlewares that serve module requests (`/@vite/client`,
5
+ * `/@id/*`, JS and CSS source files) and `/@fs/*` paths, preceded by the one
6
+ * that strips a non-root `base` from the URL and the one that answers the HMR
7
+ * client's reconnect ping (`Accept: text/x-vite-ping`) with a 204 instead of
8
+ * the Worker rendering a page for it. If Vite renames them, none are found and
9
+ * every request falls through, which is the behavior without this plugin.
10
+ *
11
+ * `viteServePublicMiddleware` is deliberately excluded so that `public/` files
12
+ * reach the Worker and middleware, as they do in production. Without it, the
13
+ * transform middleware reports a public `.js` or `.css` file as an
14
+ * `ERR_LOAD_PUBLIC_URL` error, which is treated as a fall-through.
15
+ */
16
+ export declare const VITE_MODULE_MIDDLEWARE_NAMES: Set<string>;
17
+ /**
18
+ * Vite's internal middleware that serves files under the project root. Vite
19
+ * gives imported assets root-relative URLs (`import logo from "./logo.svg"`
20
+ * and CSS `url(./bg.png)` both resolve to paths like `/app/logo.svg`), and only
21
+ * this middleware serves them. It also serves every other project file, and a
22
+ * Worker route can share its path with one (e.g. an `api/` directory and an
23
+ * `/api/*` route handler), so it only runs for referenced assets. See
24
+ * `isReferencedAsset`. Navigations to a referenced asset
25
+ * are served too: in production its URL is under `/_next/static/`, which never
26
+ * reaches the Worker.
27
+ */
28
+ export declare const VITE_STATIC_MIDDLEWARE_NAME = "viteServeStaticMiddleware";
29
+ type CloudflareDevModuleUrlsOptions = {
30
+ /** Whether the Cloudflare Vite plugin is present. Read when the dev server starts. */
31
+ isEnabled: () => boolean;
32
+ };
33
+ /**
34
+ * Creates the plugin that lets Vite serve its module URLs before the Cloudflare
35
+ * plugin's `runWorkerFirst` routing in dev.
36
+ *
37
+ * @param options - Plugin options
38
+ * @returns The Vite plugin
39
+ */
40
+ export declare function createCloudflareDevModuleUrlsPlugin(options: CloudflareDevModuleUrlsOptions): Plugin;
41
+ //#endregion