vinext 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/README.md +21 -9
  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/pages-client-assets-module.d.ts +8 -0
  5. package/dist/build/pages-client-assets-module.js +21 -1
  6. package/dist/build/prerender-paths.js +5 -3
  7. package/dist/build/run-prerender.js +1 -1
  8. package/dist/build/ssr-manifest.d.ts +2 -0
  9. package/dist/build/ssr-manifest.js +6 -2
  10. package/dist/check.js +7 -6
  11. package/dist/cli.js +2 -1
  12. package/dist/client/client-redirect-matcher.d.ts +14 -0
  13. package/dist/client/client-redirect-matcher.js +37 -0
  14. package/dist/client/client-redirects.d.ts +27 -0
  15. package/dist/client/client-redirects.js +28 -0
  16. package/dist/client/client-rewrites.d.ts +2 -1
  17. package/dist/client/client-rewrites.js +1 -1
  18. package/dist/config/config-matchers.d.ts +26 -11
  19. package/dist/config/config-matchers.js +78 -81
  20. package/dist/config/destination-params.d.ts +47 -0
  21. package/dist/config/destination-params.js +116 -0
  22. package/dist/config/next-config.d.ts +7 -0
  23. package/dist/config/next-config.js +3 -0
  24. package/dist/entries/app-rsc-entry.d.ts +4 -0
  25. package/dist/entries/app-rsc-entry.js +20 -6
  26. package/dist/entries/pages-client-entry.js +3 -1
  27. package/dist/entries/pages-server-entry.js +13 -37
  28. package/dist/index.d.ts +3 -1
  29. package/dist/index.js +134 -43
  30. package/dist/init-cloudflare.d.ts +9 -0
  31. package/dist/init-cloudflare.js +107 -31
  32. package/dist/init-platform.d.ts +4 -0
  33. package/dist/init-platform.js +27 -2
  34. package/dist/init.d.ts +1 -0
  35. package/dist/init.js +67 -3
  36. package/dist/plugins/ast-scope.d.ts +7 -0
  37. package/dist/plugins/ast-scope.js +59 -3
  38. package/dist/plugins/cache-flight-codec.d.ts +1 -1
  39. package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
  40. package/dist/plugins/dynamic-preload-metadata.js +9 -8
  41. package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
  42. package/dist/plugins/ignore-dynamic-requests.js +3 -4
  43. package/dist/plugins/middleware-server-only.d.ts +5 -4
  44. package/dist/plugins/middleware-server-only.js +8 -5
  45. package/dist/plugins/pages-node-externals.js +1 -1
  46. package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
  47. package/dist/plugins/rsc-scan-glob-imports.js +50 -0
  48. package/dist/plugins/strip-server-exports.js +262 -98
  49. package/dist/plugins/transform-result.d.ts +9 -5
  50. package/dist/plugins/transitive-externals.js +1 -1
  51. package/dist/plugins/typeof-window.d.ts +2 -2
  52. package/dist/plugins/use-cache-callable.js +8 -2
  53. package/dist/plugins/worker-server-only-imports.d.ts +20 -0
  54. package/dist/plugins/worker-server-only-imports.js +31 -0
  55. package/dist/plugins/worker-use-server.d.ts +25 -0
  56. package/dist/plugins/worker-use-server.js +129 -0
  57. package/dist/server/api-handler.d.ts +1 -0
  58. package/dist/server/api-handler.js +2 -1
  59. package/dist/server/app-browser-action-result.d.ts +1 -1
  60. package/dist/server/app-browser-action-result.js +9 -2
  61. package/dist/server/app-browser-navigation-controller.js +1 -1
  62. package/dist/server/app-browser-server-action-client.js +1 -1
  63. package/dist/server/app-middleware.d.ts +11 -0
  64. package/dist/server/app-middleware.js +17 -2
  65. package/dist/server/app-page-cache.d.ts +1 -1
  66. package/dist/server/app-page-cache.js +1 -1
  67. package/dist/server/app-page-dispatch.d.ts +3 -1
  68. package/dist/server/app-page-dispatch.js +4 -3
  69. package/dist/server/app-page-ppr-runtime.js +1 -1
  70. package/dist/server/app-page-render-observation.js +1 -1
  71. package/dist/server/app-page-request.js +53 -15
  72. package/dist/server/app-page-route-wiring.js +2 -2
  73. package/dist/server/app-pages-bridge.d.ts +1 -1
  74. package/dist/server/app-pages-bridge.js +2 -3
  75. package/dist/server/app-prerender-endpoints.js +9 -6
  76. package/dist/server/app-request-stage-dispatch.js +6 -2
  77. package/dist/server/app-request-stage-independent-entry.js +25 -5
  78. package/dist/server/app-response-stage-entry.js +10 -2
  79. package/dist/server/app-route-handler-cache.d.ts +1 -0
  80. package/dist/server/app-route-handler-cache.js +1 -0
  81. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  82. package/dist/server/app-route-handler-dispatch.js +5 -2
  83. package/dist/server/app-route-handler-execution.d.ts +1 -0
  84. package/dist/server/app-route-handler-execution.js +1 -0
  85. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  86. package/dist/server/app-route-handler-runtime.js +45 -24
  87. package/dist/server/app-router-entry.js +24 -5
  88. package/dist/server/app-rsc-cache-busting.js +1 -1
  89. package/dist/server/app-rsc-errors.js +20 -16
  90. package/dist/server/app-rsc-handler.d.ts +7 -0
  91. package/dist/server/app-rsc-handler.js +85 -35
  92. package/dist/server/app-rsc-response-stage.js +4 -2
  93. package/dist/server/app-segment-config.d.ts +2 -1
  94. package/dist/server/app-server-action-execution.d.ts +2 -1
  95. package/dist/server/app-server-action-execution.js +61 -22
  96. package/dist/server/app-ssr-entry.js +2 -1
  97. package/dist/server/app-worker-stages.d.ts +5 -0
  98. package/dist/server/app-worker-stages.js +1 -1
  99. package/dist/server/cacheability-request.js +2 -2
  100. package/dist/server/client-build-files.d.ts +16 -0
  101. package/dist/server/client-build-files.js +36 -0
  102. package/dist/server/client-reuse-manifest.js +1 -1
  103. package/dist/server/dev-server.js +38 -27
  104. package/dist/server/dev-stack-sourcemap.js +18 -23
  105. package/dist/server/document-initial-head.d.ts +0 -11
  106. package/dist/server/document-initial-head.js +1 -1
  107. package/dist/server/forwarded-middleware-context.d.ts +5 -0
  108. package/dist/server/forwarded-middleware-context.js +22 -0
  109. package/dist/server/headers.d.ts +4 -1
  110. package/dist/server/headers.js +4 -1
  111. package/dist/server/http-conditional.d.ts +11 -0
  112. package/dist/server/http-conditional.js +10 -1
  113. package/dist/server/http-error-responses.d.ts +1 -1
  114. package/dist/server/image-optimization.d.ts +38 -0
  115. package/dist/server/image-optimization.js +93 -4
  116. package/dist/server/isr-cache.d.ts +10 -0
  117. package/dist/server/isr-cache.js +41 -6
  118. package/dist/server/metadata-route-response.js +9 -8
  119. package/dist/server/middleware-matcher.d.ts +2 -0
  120. package/dist/server/middleware-matcher.js +23 -2
  121. package/dist/server/middleware-runtime.d.ts +13 -0
  122. package/dist/server/middleware-runtime.js +33 -20
  123. package/dist/server/middleware.d.ts +1 -1
  124. package/dist/server/middleware.js +3 -1
  125. package/dist/server/multi-stage.d.ts +11 -0
  126. package/dist/server/normalize-path.d.ts +0 -13
  127. package/dist/server/normalize-path.js +1 -34
  128. package/dist/server/pages-api-route.d.ts +3 -2
  129. package/dist/server/pages-api-route.js +4 -3
  130. package/dist/server/pages-cache-tag.d.ts +12 -0
  131. package/dist/server/pages-cache-tag.js +19 -0
  132. package/dist/server/pages-client-assets.d.ts +2 -0
  133. package/dist/server/pages-data-route.d.ts +10 -0
  134. package/dist/server/pages-data-route.js +19 -2
  135. package/dist/server/pages-document-asset-props.d.ts +5 -1
  136. package/dist/server/pages-document-asset-props.js +13 -5
  137. package/dist/server/pages-document-splice.d.ts +19 -0
  138. package/dist/server/pages-document-splice.js +55 -0
  139. package/dist/server/pages-i18n.d.ts +12 -1
  140. package/dist/server/pages-i18n.js +18 -4
  141. package/dist/server/pages-node-compat.d.ts +16 -5
  142. package/dist/server/pages-node-compat.js +20 -12
  143. package/dist/server/pages-page-data.d.ts +32 -24
  144. package/dist/server/pages-page-data.js +50 -120
  145. package/dist/server/pages-page-handler.d.ts +0 -6
  146. package/dist/server/pages-page-handler.js +188 -126
  147. package/dist/server/pages-page-response.d.ts +12 -6
  148. package/dist/server/pages-page-response.js +41 -34
  149. package/dist/server/pages-request-pipeline.d.ts +10 -2
  150. package/dist/server/pages-request-pipeline.js +37 -18
  151. package/dist/server/pages-request-stage-entry.d.ts +6 -0
  152. package/dist/server/pages-request-stage-entry.js +71 -12
  153. package/dist/server/pages-response-stage-entry.js +4 -0
  154. package/dist/server/pages-revalidate.js +1 -1
  155. package/dist/server/pages-router-entry.js +4 -3
  156. package/dist/server/prerender-manifest.d.ts +3 -3
  157. package/dist/server/prerender-manifest.js +4 -3
  158. package/dist/server/prerender-work-unit-setup.js +4 -0
  159. package/dist/server/prod-server.d.ts +12 -0
  160. package/dist/server/prod-server.js +199 -69
  161. package/dist/server/proper-error.d.ts +4 -0
  162. package/dist/server/proper-error.js +31 -0
  163. package/dist/server/request-pipeline.d.ts +4 -1
  164. package/dist/server/request-pipeline.js +3 -2
  165. package/dist/server/revalidation-request.d.ts +1 -0
  166. package/dist/server/revalidation-request.js +1 -1
  167. package/dist/server/rsc-stream-hints.js +31 -2
  168. package/dist/server/seed-cache.d.ts +1 -0
  169. package/dist/server/seed-cache.js +5 -4
  170. package/dist/server/server-reference-loader.d.ts +4 -0
  171. package/dist/server/server-reference-loader.js +29 -0
  172. package/dist/server/socket-error-backstop.d.ts +9 -1
  173. package/dist/server/socket-error-backstop.js +46 -17
  174. package/dist/server/static-file-signal.d.ts +15 -4
  175. package/dist/server/static-file-signal.js +46 -12
  176. package/dist/server/worker-image-optimization.d.ts +34 -0
  177. package/dist/server/worker-image-optimization.js +86 -0
  178. package/dist/server/worker-stages.d.ts +1 -1
  179. package/dist/server/worker-stages.js +2 -2
  180. package/dist/server/worker-utils.d.ts +8 -3
  181. package/dist/server/worker-utils.js +12 -7
  182. package/dist/shims/app-router-scroll.js +4 -1
  183. package/dist/shims/app-router-tree-context.d.ts +5 -0
  184. package/dist/shims/app-router-tree-context.js +27 -0
  185. package/dist/shims/cache-callable-runtime.d.ts +4 -2
  186. package/dist/shims/cache-callable-runtime.js +21 -12
  187. package/dist/shims/cache-handler.js +1 -9
  188. package/dist/shims/cache-runtime.d.ts +6 -1
  189. package/dist/shims/cache-runtime.js +2 -1
  190. package/dist/shims/cache.d.ts +2 -2
  191. package/dist/shims/cache.js +40 -13
  192. package/dist/shims/cdn-cache.d.ts +8 -0
  193. package/dist/shims/cdn-cache.js +17 -1
  194. package/dist/shims/disable-smooth-scroll.d.ts +3 -0
  195. package/dist/shims/disable-smooth-scroll.js +36 -0
  196. package/dist/shims/document-placeholders.d.ts +19 -0
  197. package/dist/shims/document-placeholders.js +45 -0
  198. package/dist/shims/document.js +21 -5
  199. package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
  200. package/dist/shims/dynamic-preload-chunks.js +13 -9
  201. package/dist/shims/dynamic.d.ts +1 -1
  202. package/dist/shims/dynamic.js +60 -8
  203. package/dist/shims/fetch-cache-state.d.ts +66 -0
  204. package/dist/shims/fetch-cache-state.js +92 -0
  205. package/dist/shims/fetch-cache.d.ts +3 -67
  206. package/dist/shims/fetch-cache.js +160 -125
  207. package/dist/shims/head.d.ts +10 -6
  208. package/dist/shims/head.js +15 -13
  209. package/dist/shims/image.js +2 -1
  210. package/dist/shims/internal/work-store-scope.d.ts +5 -0
  211. package/dist/shims/internal/work-store-scope.js +24 -0
  212. package/dist/shims/navigation.js +31 -5
  213. package/dist/shims/request-context.d.ts +2 -0
  214. package/dist/shims/request-state-types.d.ts +2 -1
  215. package/dist/shims/router.js +12 -20
  216. package/dist/shims/server.d.ts +16 -0
  217. package/dist/shims/server.js +24 -4
  218. package/dist/shims/unified-request-context.d.ts +1 -1
  219. package/dist/shims/url-utils.d.ts +2 -0
  220. package/dist/shims/url-utils.js +3 -1
  221. package/dist/utils/client-runtime-metadata.js +1 -1
  222. package/dist/utils/hash.d.ts +7 -0
  223. package/dist/utils/hash.js +11 -1
  224. package/dist/utils/package-name.d.ts +6 -0
  225. package/dist/utils/package-name.js +12 -1
  226. package/dist/utils/plugin-rsc-version.d.ts +4 -0
  227. package/dist/utils/plugin-rsc-version.js +15 -0
  228. package/dist/utils/prerender-output-paths.js +15 -4
  229. package/dist/utils/public-file-path.d.ts +10 -2
  230. package/dist/utils/public-file-path.js +13 -9
  231. package/dist/utils/public-routes.js +2 -2
  232. package/dist/utils/react-version.d.ts +3 -0
  233. package/dist/utils/react-version.js +1 -1
  234. package/package.json +7 -3
@@ -1,5 +1,6 @@
1
1
  import path from "./deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import { detectProject } from "./utils/project.js";
3
+ import { validateWorkerName } from "./init-platform.js";
3
4
  import { isUnknownRecord } from "./utils/record.js";
4
5
  import { createRequire } from "node:module";
5
6
  import fs from "node:fs";
@@ -13,6 +14,10 @@ const DEFAULT_CLOUDFLARE_INIT_OPTIONS = {
13
14
  imageOptimization: "cloudflare-images"
14
15
  };
15
16
  const DEFAULT_VERSION_METADATA_BINDING = "CF_VERSION_METADATA";
17
+ const BUILD_OUTPUT_EXCLUSIONS = ["!/_next/static/*", "!/*/_next/static/*"];
18
+ const DEFAULT_RUN_WORKER_FIRST = ["/*", ...BUILD_OUTPUT_EXCLUSIONS];
19
+ const HTML_HANDLING = "none";
20
+ const STATIC_ASSETS_CACHE_ROUTE = "/_vinext/static-cache/*";
16
21
  const RESPONSE_STORE_WRANGLER_CONFIG = "wrangler.response-store.jsonc";
17
22
  const RESPONSE_STORE_BINDING = "RESPONSE_STORE";
18
23
  const RESPONSE_STORE_ENTRYPOINT = "ResponseStoreService";
@@ -26,6 +31,7 @@ const CACHE_METADATA_EXPORT = {
26
31
  };
27
32
  const CTX_EXPORTS_DEFAULT_DATE = "2025-11-17";
28
33
  function validateCloudflarePlatformSetup(context, cloudflare) {
34
+ if (cloudflare.name !== void 0) validateWorkerName(cloudflare.name);
29
35
  if (!cloudflare.legacyWrangler) {
30
36
  const existingWrangler = [
31
37
  "wrangler.toml",
@@ -54,7 +60,10 @@ function validateCloudflarePlatformSetup(context, cloudflare) {
54
60
  const wranglerPath = ["wrangler.jsonc", "wrangler.json"].map((fileName) => path.join(context.root, fileName)).find((candidate) => fs.existsSync(candidate));
55
61
  const wranglerCode = wranglerPath ? fs.readFileSync(wranglerPath, "utf-8") : void 0;
56
62
  if (!wranglerCode && cloudflare.cdnCache === "response-store" && (cloudflare.responseStoreMode ?? "service-binding") === "service-binding" && fs.existsSync(path.join(context.root, RESPONSE_STORE_WRANGLER_CONFIG))) readResponseStoreServiceName(context.root, {});
57
- const updatedWranglerCode = wranglerCode ? updateWranglerConfigForCloudflare(wranglerCode, cloudflare, { root: context.root }) : void 0;
63
+ const updatedWranglerCode = wranglerCode ? updateWranglerConfigForCloudflare(wranglerCode, cloudflare, {
64
+ root: context.root,
65
+ isStaticExport: context.isStaticExport
66
+ }) : void 0;
58
67
  const imagesBinding = updatedWranglerCode ? getWranglerImagesBinding(updatedWranglerCode) : "IMAGES";
59
68
  const assetsBinding = updatedWranglerCode ? getWranglerAssetsBinding(updatedWranglerCode) : "ASSETS";
60
69
  const assetsDirectory = updatedWranglerCode ? getWranglerAssetsDirectory(updatedWranglerCode) : "dist/client";
@@ -74,10 +83,13 @@ function validateCloudflarePlatformSetup(context, cloudflare) {
74
83
  }
75
84
  function setupCloudflarePlatform(context, cloudflare) {
76
85
  if (!cloudflare.legacyWrangler) return setupCfPlatform(context, cloudflare);
77
- const projectInfo = detectProject(context.root);
86
+ const projectInfo = detectCloudflareProject(context.root, cloudflare);
78
87
  const wranglerPath = ["wrangler.jsonc", "wrangler.json"].map((fileName) => path.join(context.root, fileName)).find((candidate) => fs.existsSync(candidate));
79
88
  const wranglerCode = wranglerPath ? fs.readFileSync(wranglerPath, "utf-8") : void 0;
80
- const updatedWranglerCode = wranglerCode ? updateWranglerConfigForCloudflare(wranglerCode, cloudflare, { root: context.root }) : void 0;
89
+ const updatedWranglerCode = wranglerCode ? updateWranglerConfigForCloudflare(wranglerCode, cloudflare, {
90
+ root: context.root,
91
+ isStaticExport: context.isStaticExport
92
+ }) : void 0;
81
93
  const imagesBinding = updatedWranglerCode ? getWranglerImagesBinding(updatedWranglerCode) : "IMAGES";
82
94
  const assetsBinding = updatedWranglerCode ? getWranglerAssetsBinding(updatedWranglerCode) : "ASSETS";
83
95
  const assetsDirectory = updatedWranglerCode ? getWranglerAssetsDirectory(updatedWranglerCode) : "dist/client";
@@ -112,7 +124,10 @@ function setupCloudflarePlatform(context, cloudflare) {
112
124
  }
113
125
  const generatedPlatformFiles = [];
114
126
  if (!wranglerPath) {
115
- fs.writeFileSync(path.join(context.root, "wrangler.jsonc"), generateWranglerConfig(projectInfo, cloudflare, context.today), "utf-8");
127
+ fs.writeFileSync(path.join(context.root, "wrangler.jsonc"), generateWranglerConfig({
128
+ ...projectInfo,
129
+ isStaticExport: context.isStaticExport
130
+ }, cloudflare, context.today), "utf-8");
116
131
  generatedPlatformFiles.push("wrangler.jsonc");
117
132
  } else if (wranglerCode && updatedWranglerCode) {
118
133
  if (updatedWranglerCode !== wranglerCode) {
@@ -139,8 +154,23 @@ function setupCloudflarePlatform(context, cloudflare) {
139
154
  preservedExistingGenerateScopedName
140
155
  };
141
156
  }
157
+ /**
158
+ * The existing config that keeps its own Worker name, if `--name` was given.
159
+ * Init doesn't rename the Worker in an existing config, so callers warn instead.
160
+ */
161
+ function findConfigKeepingWorkerName(root, cloudflare) {
162
+ if (cloudflare.name === void 0) return void 0;
163
+ return (cloudflare.legacyWrangler ? ["wrangler.jsonc", "wrangler.json"] : ["cloudflare.config.ts"]).find((name) => fs.existsSync(path.join(root, name)));
164
+ }
165
+ function detectCloudflareProject(root, cloudflare) {
166
+ const projectInfo = detectProject(root);
167
+ return cloudflare.name ? {
168
+ ...projectInfo,
169
+ projectName: cloudflare.name
170
+ } : projectInfo;
171
+ }
142
172
  function setupCfPlatform(context, cloudflare) {
143
- const projectInfo = detectProject(context.root);
173
+ const projectInfo = detectCloudflareProject(context.root, cloudflare);
144
174
  const serviceBinding = cloudflare.cdnCache === "response-store" && (cloudflare.responseStoreMode ?? "service-binding") === "service-binding";
145
175
  let generatedViteConfig = false;
146
176
  let preservedExistingGenerateScopedName = false;
@@ -168,7 +198,10 @@ function setupCfPlatform(context, cloudflare) {
168
198
  const configPath = path.join(context.root, "cloudflare.config.ts");
169
199
  const generatedPlatformFiles = [];
170
200
  if (!fs.existsSync(configPath)) {
171
- fs.writeFileSync(configPath, generateTypedCloudflareConfig(projectInfo, cloudflare, context.today));
201
+ fs.writeFileSync(configPath, generateTypedCloudflareConfig({
202
+ ...projectInfo,
203
+ isStaticExport: context.isStaticExport
204
+ }, cloudflare, context.today));
172
205
  generatedPlatformFiles.push("cloudflare.config.ts");
173
206
  }
174
207
  const nextSteps = [];
@@ -215,6 +248,12 @@ export const responseStoreServiceBinding = responseStore.serviceBindingWorker;
215
248
  ...options.imageOptimization === "cloudflare-images" ? ["IMAGES: bindings.images()"] : [],
216
249
  ...options.dataCache === "kv" ? ["VINEXT_KV_CACHE: bindings.kv()"] : []
217
250
  ];
251
+ const routing = defaultAssetRouting(info, options);
252
+ const assetLines = [
253
+ ...routing.htmlHandling ? [`htmlHandling: ${JSON.stringify(routing.htmlHandling)}`] : [],
254
+ "notFoundHandling: \"none\"",
255
+ ...routing.runWorkerFirst ? [`runWorkerFirst: [${routing.runWorkerFirst.map((pattern) => JSON.stringify(pattern)).join(", ")}]`] : []
256
+ ];
218
257
  return `${imports.join("\n")}
219
258
 
220
259
  ${shared}export default defineConfig({
@@ -223,7 +262,9 @@ ${shared}export default defineConfig({
223
262
  entrypoint: ${JSON.stringify(resolveWorkerEntry(info.root))},
224
263
  compatibilityDate: ${JSON.stringify(today)},
225
264
  compatibilityFlags: ["nodejs_compat"],
226
- assets: { notFoundHandling: "none"${options.cdnCache === "static-assets" ? ", runWorkerFirst: [\"/_vinext/static-cache/*\"]" : ""} },
265
+ assets: {
266
+ ${assetLines.join(",\n ")},
267
+ },
227
268
  env: {
228
269
  ${envBindings.join(",\n ")},
229
270
  },
@@ -242,8 +283,21 @@ function resolveWorkerEntry(root) {
242
283
  if (fs.existsSync(path.join(root, "worker", "index.js"))) return "./worker/index.js";
243
284
  return "vinext/server/fetch-handler";
244
285
  }
286
+ /**
287
+ * Next.js runs no middleware for a static export, and an export with
288
+ * `trailingSlash` relies on the default html_handling to serve `/about/` from
289
+ * `about/index.html`, so export apps keep asset-first serving.
290
+ */
291
+ function defaultAssetRouting(info, options) {
292
+ if (!info.isStaticExport) return {
293
+ htmlHandling: HTML_HANDLING,
294
+ runWorkerFirst: DEFAULT_RUN_WORKER_FIRST
295
+ };
296
+ return options.cdnCache === "static-assets" ? { runWorkerFirst: [STATIC_ASSETS_CACHE_ROUTE] } : {};
297
+ }
245
298
  function generateWranglerConfig(info, options = DEFAULT_CLOUDFLARE_INIT_OPTIONS, today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0]) {
246
299
  const workerEntry = resolveWorkerEntry(info.root);
300
+ const routing = defaultAssetRouting(info, options);
247
301
  const config = {
248
302
  $schema: "node_modules/wrangler/config-schema.json",
249
303
  name: info.projectName,
@@ -252,15 +306,13 @@ function generateWranglerConfig(info, options = DEFAULT_CLOUDFLARE_INIT_OPTIONS,
252
306
  main: workerEntry,
253
307
  assets: {
254
308
  directory: "dist/client",
309
+ ...routing.htmlHandling ? { html_handling: routing.htmlHandling } : {},
255
310
  not_found_handling: "none",
256
311
  binding: "ASSETS",
257
- ...options.cdnCache === "static-assets" ? { run_worker_first: ["/_vinext/static-cache/*"] } : {}
312
+ ...routing.runWorkerFirst ? { run_worker_first: routing.runWorkerFirst } : {}
258
313
  }
259
314
  };
260
- if (options.cdnCache === "workers-cache") {
261
- config.cache = { enabled: true };
262
- config.version_metadata = { binding: DEFAULT_VERSION_METADATA_BINDING };
263
- }
315
+ if (options.cdnCache === "workers-cache") config.version_metadata = { binding: DEFAULT_VERSION_METADATA_BINDING };
264
316
  if (options.imageOptimization === "cloudflare-images") config.images = { binding: "IMAGES" };
265
317
  if (options.dataCache === "kv") config.kv_namespaces = [{ binding: "VINEXT_KV_CACHE" }];
266
318
  const code = `${JSON.stringify(config, null, 2)}\n`;
@@ -305,6 +357,19 @@ function stripJsonComments(code) {
305
357
  }
306
358
  return output.replace(/,\s*([}\]])/g, "$1");
307
359
  }
360
+ /** Offset of the first JSONC token in `code`, after whitespace and comments. */
361
+ function skipJsonWhitespaceAndComments(code) {
362
+ let index = 0;
363
+ while (index < code.length) if (/\s/.test(code[index])) index++;
364
+ else if (code.startsWith("//", index)) {
365
+ const lineEnd = code.indexOf("\n", index);
366
+ index = lineEnd === -1 ? code.length : lineEnd;
367
+ } else if (code.startsWith("/*", index)) {
368
+ const commentEnd = code.indexOf("*/", index + 2);
369
+ index = commentEnd === -1 ? code.length : commentEnd + 2;
370
+ } else break;
371
+ return index;
372
+ }
308
373
  function findTopLevelJsonProperty(code, name) {
309
374
  let depth = 0;
310
375
  let inString = false;
@@ -457,7 +522,7 @@ function readResponseStoreServiceName(root, appConfig) {
457
522
  const durableBindings = isUnknownRecord(responseStoreConfig.durable_objects) ? responseStoreConfig.durable_objects.bindings : void 0;
458
523
  const hasCacheMetadata = Array.isArray(durableBindings) && durableBindings.some((binding) => isUnknownRecord(binding) && binding.name === CACHE_METADATA_BINDING && binding.class_name === CACHE_METADATA_CLASS && binding.script_name === void 0);
459
524
  const hasNoMigrations = responseStoreConfig.migrations === void 0 || Array.isArray(responseStoreConfig.migrations) && responseStoreConfig.migrations.length === 0;
460
- if (!isUnknownRecord(responseStoreConfig.cache) || responseStoreConfig.cache.enabled !== true || !isUnknownRecord(responseStoreExport) || !isUnknownRecord(responseStoreExport.cache) || responseStoreExport.cache.enabled !== true || !hasCacheBodies || !hasCacheMetadata || !isCacheMetadataExport(cacheMetadataExport) || !hasNoMigrations) throw new Error(`${RESPONSE_STORE_WRANGLER_CONFIG} is missing required Response Store bindings.`);
525
+ if (responseStoreConfig.cache !== void 0 && (!isUnknownRecord(responseStoreConfig.cache) || typeof responseStoreConfig.cache.enabled !== "boolean") || !isUnknownRecord(responseStoreExport) || !isUnknownRecord(responseStoreExport.cache) || responseStoreExport.cache.enabled !== true || !hasCacheBodies || !hasCacheMetadata || !isCacheMetadataExport(cacheMetadataExport) || !hasNoMigrations) throw new Error(`${RESPONSE_STORE_WRANGLER_CONFIG} is missing required Response Store bindings.`);
461
526
  const compatibilityFlags = responseStoreConfig.compatibility_flags;
462
527
  if (compatibilityFlags !== void 0 && (!Array.isArray(compatibilityFlags) || compatibilityFlags.some((flag) => typeof flag !== "string"))) throw new Error(`${RESPONSE_STORE_WRANGLER_CONFIG} has invalid compatibility flags.`);
463
528
  const flags = compatibilityFlags ?? [];
@@ -481,7 +546,7 @@ function configureResponseStoreWrangler(code, config, mode, root) {
481
546
  if (cache !== void 0 && !isUnknownRecord(cache)) throw new Error("The existing Wrangler config has an invalid cache value.");
482
547
  code = setTopLevelJsonProperty(code, "cache", {
483
548
  ...cache,
484
- enabled: mode === "self-contained"
549
+ enabled: false
485
550
  });
486
551
  const exportsConfig = config.exports;
487
552
  if (exportsConfig !== void 0 && !isUnknownRecord(exportsConfig)) throw new Error("The existing Wrangler config has an invalid exports value.");
@@ -593,7 +658,7 @@ function generateResponseStoreWranglerConfig(appWranglerCode, root) {
593
658
  compatibility_flags: compatibilityFlags,
594
659
  workers_dev: false,
595
660
  preview_urls: false,
596
- cache: { enabled: true },
661
+ cache: { enabled: false },
597
662
  exports: {
598
663
  default: {
599
664
  type: "worker",
@@ -629,15 +694,25 @@ function updateWranglerConfigForCloudflare(code, options, context = {}) {
629
694
  const workerEntry = resolveWorkerEntry(context.root ?? process.cwd());
630
695
  output = appendTopLevelJsonProperty(output, ` "main": ${JSON.stringify(workerEntry)}`);
631
696
  }
632
- if (!findTopLevelJsonProperty(output, "assets")) output = appendTopLevelJsonProperty(output, " \"assets\": { \"directory\": \"dist/client\", \"not_found_handling\": \"none\", \"binding\": \"ASSETS\" }");
697
+ if (!findTopLevelJsonProperty(output, "assets")) {
698
+ const routing = defaultAssetRouting(context, {});
699
+ const assets = JSON.stringify({
700
+ directory: "dist/client",
701
+ ...routing.htmlHandling ? { html_handling: routing.htmlHandling } : {},
702
+ not_found_handling: "none",
703
+ binding: "ASSETS",
704
+ ...routing.runWorkerFirst ? { run_worker_first: routing.runWorkerFirst } : {}
705
+ }, null, 2).replaceAll("\n", "\n ");
706
+ output = appendTopLevelJsonProperty(output, ` "assets": ${assets}`);
707
+ }
633
708
  if (options.cdnCache === "static-assets") {
634
709
  const assetsProperty = findTopLevelJsonProperty(output, "assets");
635
710
  const assets = JSON.parse(stripJsonComments(output.slice(assetsProperty.valueStart, assetsProperty.valueEnd)));
636
711
  if (!assets || typeof assets !== "object" || Array.isArray(assets)) throw new Error("The existing Wrangler config has an invalid assets value.");
637
712
  const workerFirst = assets.run_worker_first;
638
713
  if (workerFirst !== void 0 && typeof workerFirst !== "boolean" && !Array.isArray(workerFirst)) throw new Error("The existing Wrangler config has an invalid assets.run_worker_first value.");
639
- if (Array.isArray(workerFirst) && workerFirst.some((pattern) => typeof pattern !== "string" || pattern.startsWith("!"))) throw new Error("Static Assets cache requires run_worker_first without exclusion patterns. Use true or an array of positive path patterns.");
640
- const protectedRouting = workerFirst === true ? true : [.../* @__PURE__ */ new Set([...Array.isArray(workerFirst) ? workerFirst : [], "/_vinext/static-cache/*"])];
714
+ if (Array.isArray(workerFirst) && workerFirst.some((pattern) => typeof pattern !== "string" || pattern.startsWith("!") && !BUILD_OUTPUT_EXCLUSIONS.includes(pattern))) throw new Error(`Static Assets cache requires run_worker_first without exclusion patterns other than ${BUILD_OUTPUT_EXCLUSIONS.join(" and ")}. Use an array of positive path patterns, optionally with those exclusions.`);
715
+ const protectedRouting = workerFirst === true ? true : Array.isArray(workerFirst) && workerFirst.includes("/*") ? workerFirst : [.../* @__PURE__ */ new Set([...Array.isArray(workerFirst) ? workerFirst : [], STATIC_ASSETS_CACHE_ROUTE])];
641
716
  if (typeof assets.directory !== "string" || assets.directory.length === 0 || typeof assets.binding !== "string" || assets.binding.length === 0 || JSON.stringify(workerFirst) !== JSON.stringify(protectedRouting)) {
642
717
  const updatedAssets = JSON.stringify({
643
718
  ...assets,
@@ -649,18 +724,6 @@ function updateWranglerConfigForCloudflare(code, options, context = {}) {
649
724
  }
650
725
  }
651
726
  if (options.cdnCache === "workers-cache") {
652
- const cacheProperty = findTopLevelJsonProperty(output, "cache");
653
- if (!cacheProperty) output = appendTopLevelJsonProperty(output, " \"cache\": { \"enabled\": true }");
654
- else {
655
- const cache = JSON.parse(stripJsonComments(output.slice(cacheProperty.valueStart, cacheProperty.valueEnd)));
656
- if (!cache || cache.enabled !== true) {
657
- const updatedCache = JSON.stringify({
658
- ...cache,
659
- enabled: true
660
- });
661
- output = `${output.slice(0, cacheProperty.valueStart)}${updatedCache}${output.slice(cacheProperty.valueEnd)}`;
662
- }
663
- }
664
727
  const versionMetadataProperty = findTopLevelJsonProperty(output, "version_metadata");
665
728
  if (!versionMetadataProperty) output = appendTopLevelJsonProperty(output, ` "version_metadata": { "binding": "${DEFAULT_VERSION_METADATA_BINDING}" }`);
666
729
  else {
@@ -668,6 +731,19 @@ function updateWranglerConfigForCloudflare(code, options, context = {}) {
668
731
  if (!versionMetadata || typeof versionMetadata.binding !== "string" || versionMetadata.binding.length === 0) output = `${output.slice(0, versionMetadataProperty.valueStart)}{ "binding": "${DEFAULT_VERSION_METADATA_BINDING}" }${output.slice(versionMetadataProperty.valueEnd)}`;
669
732
  }
670
733
  }
734
+ if (options.cdnCache !== "response-store") {
735
+ const cacheProperty = findTopLevelJsonProperty(output, "cache");
736
+ if (cacheProperty) {
737
+ const cacheCode = output.slice(cacheProperty.valueStart, cacheProperty.valueEnd);
738
+ const cache = JSON.parse(stripJsonComments(cacheCode));
739
+ const enabledProperty = findTopLevelJsonProperty(cacheCode, "enabled");
740
+ const enabledToken = enabledProperty ? enabledProperty.valueStart + skipJsonWhitespaceAndComments(cacheCode.slice(enabledProperty.valueStart, enabledProperty.valueEnd)) : -1;
741
+ if (isUnknownRecord(cache) && cache.enabled === true && cacheCode.startsWith("true", enabledToken)) {
742
+ const enabledStart = cacheProperty.valueStart + enabledToken;
743
+ output = `${output.slice(0, enabledStart)}false${output.slice(enabledStart + 4)}`;
744
+ }
745
+ }
746
+ }
671
747
  if (options.imageOptimization === "cloudflare-images") {
672
748
  const imagesProperty = findTopLevelJsonProperty(output, "images");
673
749
  if (!imagesProperty) output = appendTopLevelJsonProperty(output, " \"images\": { \"binding\": \"IMAGES\" }");
@@ -1540,4 +1616,4 @@ function usesCommonJsViteConfig(filePath, code) {
1540
1616
  return parseViteConfig(filePath, code).body.some((statement) => statement.type === "ExpressionStatement" && statement.expression.type === "AssignmentExpression" && statement.expression.left.type === "MemberExpression" && statement.expression.left.object.type === "Identifier" && statement.expression.left.object.name === "module" && statement.expression.left.property.type === "Identifier" && statement.expression.left.property.name === "exports");
1541
1617
  }
1542
1618
  //#endregion
1543
- export { compactResourceName, cssModulesConfigSource, generateAppRouterViteConfig, generatePagesRouterViteConfig, generateResponseStoreWranglerConfig, generateWranglerConfig, getWranglerImagesBinding, getWranglerVersionMetadataBinding, setupCloudflarePlatform, updateViteConfigForCloudflare, updateViteConfigForCssModules, updateWranglerConfigForCloudflare, usesCommonJsViteConfig, validateCloudflarePlatformSetup };
1619
+ export { compactResourceName, cssModulesConfigSource, findConfigKeepingWorkerName, generateAppRouterViteConfig, generatePagesRouterViteConfig, generateResponseStoreWranglerConfig, generateWranglerConfig, getWranglerImagesBinding, getWranglerVersionMetadataBinding, setupCloudflarePlatform, updateViteConfigForCloudflare, updateViteConfigForCssModules, updateWranglerConfigForCloudflare, usesCommonJsViteConfig, validateCloudflarePlatformSetup };
@@ -13,6 +13,8 @@ export type CloudflareInitOptions = {
13
13
  warmCdnCache?: boolean;
14
14
  legacyWrangler?: boolean;
15
15
  prerender?: boolean;
16
+ /** Worker name for generated config, instead of one derived from package.json. */
17
+ name?: string;
16
18
  };
17
19
  export declare const INIT_PLATFORMS: {
18
20
  cloudflare: {
@@ -38,6 +40,8 @@ export type ResolvedInitOptions = {
38
40
  };
39
41
  export declare function isAgentEnvironment(env?: Record<string, string | undefined>): boolean;
40
42
  export declare function parsePlatformArg(args: string[]): InitPlatform | undefined;
43
+ export declare function parseNameArg(args: string[]): string | undefined;
44
+ export declare function validateWorkerName(value: string): void;
41
45
  export declare function parseDataCacheArg(args: string[]): InitDataCache | undefined;
42
46
  export declare function parseCdnCacheArg(args: string[]): InitCdnCache | undefined;
43
47
  export declare function parseImageOptimizationArg(args: string[]): InitImageOptimization | undefined;
@@ -31,6 +31,28 @@ function parsePlatformArg(args) {
31
31
  }
32
32
  }
33
33
  }
34
+ const WORKER_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
35
+ const WORKER_NAME_MAX_LENGTH = 63;
36
+ function parseNameArg(args) {
37
+ for (let index = 0; index < args.length; index++) {
38
+ const arg = args[index];
39
+ let value;
40
+ if (arg === "--name") {
41
+ value = args[index + 1];
42
+ if (!value || value.startsWith("-")) throw new Error("--name requires a Worker name.");
43
+ } else if (arg.startsWith("--name=")) {
44
+ value = arg.slice(7);
45
+ if (!value) throw new Error("--name requires a Worker name.");
46
+ }
47
+ if (value) {
48
+ validateWorkerName(value);
49
+ return value;
50
+ }
51
+ }
52
+ }
53
+ function validateWorkerName(value) {
54
+ if (value.length > WORKER_NAME_MAX_LENGTH || !WORKER_NAME_PATTERN.test(value)) throw new Error(`Invalid --name value "${value}". Worker names must be at most ${WORKER_NAME_MAX_LENGTH} characters of lowercase letters, numbers, and dashes, and cannot start or end with a dash.`);
55
+ }
34
56
  function parseChoiceArg(args, flag, choices, displayedChoices = choices) {
35
57
  for (let index = 0; index < args.length; index++) {
36
58
  const arg = args[index];
@@ -115,10 +137,12 @@ async function resolveInitPlatform(args, options = {}) {
115
137
  }
116
138
  async function resolveInitOptions(args, options = {}) {
117
139
  const legacyWrangler = parseBooleanArg(args, "--legacy-wrangler-cloudflare-init", void 0, "--legacy-wrangler-cloudflare-init expects true or false when using the \"--legacy-wrangler-cloudflare-init=value\" form.");
140
+ const name = parseNameArg(args);
118
141
  const platform = legacyWrangler && !parsePlatformArg(args) ? "cloudflare" : await resolveInitPlatform(args, options);
119
142
  const platformOptions = await INIT_PLATFORMS[platform].options(args, options);
120
143
  const explicitWarmCdnCache = parseWarmCdnCacheArg(args);
121
144
  if (legacyWrangler && platform !== "cloudflare") throw new Error("--legacy-wrangler-cloudflare-init requires --platform=cloudflare.");
145
+ if (name && platform !== "cloudflare") throw new Error("--name requires --platform=cloudflare.");
122
146
  const explicitPrerender = parsePrerenderArg(args);
123
147
  if (platform === "cloudflare" && platformOptions?.cdnCache === "static-assets" && explicitPrerender === false) throw new Error("--no-prerender cannot be used with --cdn-cache=static-assets, which requires build-time prerendering.");
124
148
  const supportsWarmCdnCache = platformOptions?.cdnCache === "response-store" || platformOptions?.cdnCache === "workers-cache";
@@ -134,7 +158,8 @@ async function resolveInitOptions(args, options = {}) {
134
158
  ...platformOptions,
135
159
  warmCdnCache,
136
160
  ...legacyWrangler ? { legacyWrangler } : {},
137
- ...prerender ? { prerender: true } : {}
161
+ ...prerender ? { prerender: true } : {},
162
+ ...name ? { name } : {}
138
163
  } : void 0
139
164
  };
140
165
  }
@@ -314,4 +339,4 @@ async function resolveCloudflareInitOptions(args, options = {}) {
314
339
  }
315
340
  }
316
341
  //#endregion
317
- export { INIT_PLATFORMS, isAgentEnvironment, parseCdnCacheArg, parseDataCacheArg, parseImageOptimizationArg, parsePlatformArg, parsePrerenderArg, parseResponseStoreModeArg, parseWarmCdnCacheArg, resolveCloudflareInitOptions, resolveInitOptions, resolveInitPlatform, resolveInitPrerender, resolveInitWarmCdnCache };
342
+ export { INIT_PLATFORMS, isAgentEnvironment, parseCdnCacheArg, parseDataCacheArg, parseImageOptimizationArg, parseNameArg, parsePlatformArg, parsePrerenderArg, parseResponseStoreModeArg, parseWarmCdnCacheArg, resolveCloudflareInitOptions, resolveInitOptions, resolveInitPlatform, resolveInitPrerender, resolveInitWarmCdnCache, validateWorkerName };
package/dist/init.d.ts CHANGED
@@ -64,6 +64,7 @@ export declare function addScripts(root: string, port?: number | false, platform
64
64
  warmCdnCache?: boolean;
65
65
  legacyWrangler?: boolean;
66
66
  scriptNames?: "namespaced" | "standard";
67
+ workerName?: string;
67
68
  }): string[];
68
69
  export type InitDependencyGroups = {
69
70
  dependencies: string[];
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";
@@ -123,7 +123,7 @@ function addScripts(root, port, platform = "node", options = {}) {
123
123
  if (platform === "cloudflare") {
124
124
  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
125
  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";
126
+ 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
127
  added.push("deploy:response-store");
128
128
  }
129
129
  }
@@ -302,6 +302,64 @@ function updateGitignore(root, platform = "node", legacyWrangler = false) {
302
302
  fs.writeFileSync(gitignorePath, content + separator + missingEntries.join("\n") + "\n", "utf-8");
303
303
  return true;
304
304
  }
305
+ /**
306
+ * Read `output` from the Next.js config as `vinext build` does: an inline
307
+ * `vinext({ nextConfig })` in the Vite config wins over next.config, and both
308
+ * are evaluated with NODE_ENV set to production and `.env.production` loaded as
309
+ * the build loads it. The Vite config is read as written, without running
310
+ * plugin `config` hooks, so a plugin that changes `root`, `envDir` or `mode` is
311
+ * not seen. A config that cannot load here keeps the Worker-first default.
312
+ * The loader is imported lazily because it needs Vite, which create-vinext-app
313
+ * runs without.
314
+ */
315
+ async function resolvesToStaticExport(root, viteConfigPath) {
316
+ let configModule;
317
+ let dotenvModule;
318
+ try {
319
+ [configModule, dotenvModule] = await Promise.all([import("./config/next-config.js"), import("./config/dotenv.js")]);
320
+ } catch {
321
+ return false;
322
+ }
323
+ const { findVinextNextConfigInPlugins, loadNextConfig, PHASE_PRODUCTION_BUILD, resolveNextConfigInput } = configModule;
324
+ const savedEnv = { ...process.env };
325
+ Reflect.set(process.env, "NODE_ENV", "production");
326
+ try {
327
+ dotenvModule.loadDotenv({
328
+ root,
329
+ mode: "production"
330
+ });
331
+ let mode = "production";
332
+ let inline = null;
333
+ let configRoot = root;
334
+ let envDir;
335
+ if (viteConfigPath) try {
336
+ const { loadConfigFromFile } = await import("vite");
337
+ const loaded = await loadConfigFromFile({
338
+ command: "build",
339
+ mode: "production",
340
+ isSsrBuild: false,
341
+ isPreview: false
342
+ }, viteConfigPath, root, "silent");
343
+ if (typeof loaded?.config.mode === "string") mode = loaded.config.mode;
344
+ if (typeof loaded?.config.root === "string") configRoot = path.resolve(root, loaded.config.root);
345
+ const configuredEnvDir = loaded?.config.envDir;
346
+ if (configuredEnvDir === false) envDir = false;
347
+ else if (typeof configuredEnvDir === "string") envDir = path.resolve(root, configuredEnvDir);
348
+ inline = await findVinextNextConfigInPlugins(loaded?.config.plugins);
349
+ } catch {}
350
+ if (envDir !== false) dotenvModule.loadDotenv({
351
+ root: envDir ?? configRoot,
352
+ mode
353
+ });
354
+ Reflect.set(process.env, "NODE_ENV", "production");
355
+ return (inline ? await resolveNextConfigInput(inline, PHASE_PRODUCTION_BUILD) : await loadNextConfig(configRoot, PHASE_PRODUCTION_BUILD))?.output === "export";
356
+ } catch {
357
+ return false;
358
+ } finally {
359
+ for (const key of Object.keys(process.env)) if (!Object.hasOwn(savedEnv, key)) delete process.env[key];
360
+ Object.assign(process.env, savedEnv);
361
+ }
362
+ }
305
363
  function setupNodePlatform(context) {
306
364
  if (context.viteConfigExists && !context.force) {
307
365
  if (context.hasCssModules && context.existingViteConfigPath) {
@@ -389,14 +447,17 @@ async function init(options) {
389
447
  const hasCssModules = !options.skipCssModules && scanCssModuleFiles(root);
390
448
  const pmName = detectPackageManagerName(root);
391
449
  const shouldInstall = options.install ?? true;
450
+ const isStaticExport = platform === "cloudflare" && await resolvesToStaticExport(root, existingViteConfigPath);
392
451
  if (platform === "cloudflare") validateCloudflarePlatformSetup({
393
452
  root,
394
453
  isAppRouter: isApp,
395
454
  existingViteConfigPath,
396
455
  hasCssModules,
456
+ isStaticExport,
397
457
  today: options._today
398
458
  }, cloudflareOptions);
399
459
  else if (hasCssModules && existingViteConfigPath && !options.force) updateViteConfigForCssModules(existingViteConfigPath, fs.readFileSync(existingViteConfigPath, "utf-8"));
460
+ const configKeepingWorkerName = platform === "cloudflare" ? findConfigKeepingWorkerName(root, cloudflareOptions) : void 0;
400
461
  if (!options.skipCheck) {
401
462
  console.log(" Running compatibility check...\n");
402
463
  const { runCheck, formatReport } = await import("./check.js");
@@ -417,7 +478,8 @@ async function init(options) {
417
478
  deployResponseStore,
418
479
  warmCdnCache: options.cloudflare?.warmCdnCache ?? false,
419
480
  legacyWrangler: options.cloudflare?.legacyWrangler,
420
- scriptNames: options.scriptNames
481
+ scriptNames: options.scriptNames,
482
+ workerName: configKeepingWorkerName ? void 0 : options.cloudflare?.name
421
483
  });
422
484
  const setupContext = {
423
485
  root,
@@ -428,6 +490,7 @@ async function init(options) {
428
490
  force: options.force ?? false,
429
491
  prerender: options.prerender,
430
492
  hasCssModules,
493
+ isStaticExport,
431
494
  today: options._today
432
495
  };
433
496
  const platformSetup = platform === "cloudflare" ? setupCloudflarePlatform(setupContext, cloudflareOptions) : setupNodePlatform(setupContext);
@@ -513,6 +576,7 @@ async function init(options) {
513
576
  if (skippedViteConfig) console.log(` ${terminalStyle.yellow("-")} Skipped vite.config.ts (already exists, use --force to overwrite)`);
514
577
  if (updatedGitignore) console.log(` ${terminalStyle.green("✓")} Added vinext output directories to .gitignore`);
515
578
  if (hasCssModules) console.log(` ${terminalStyle.green("✓")} Configured vite-css-modules for CSS Modules`);
579
+ 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
580
  if (platformSetup.preservedExistingGenerateScopedName) console.log(` ${terminalStyle.yellow("!")} Preserved existing css.modules.generateScopedName; verify it produces identical class names in SSR and client builds`);
517
581
  const nextSteps = [...platformSetup.nextSteps];
518
582
  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 };
@@ -14,6 +14,6 @@ export declare function readFlightCodecVersion(id: string): string;
14
14
  * minimum supported version.
15
15
  * https://github.com/facebook/react/blob/v19.3.0/packages/react-client/src/ReactFlightReplyClient.js#L486
16
16
  */
17
- export declare function patchCacheFlightCodec(code: string, id: string, version?: string): MagicStringTransformResult | null;
17
+ export declare function patchCacheFlightCodec(code: string, id: string, version?: string): MagicStringTransformResult<import("magic-string").SourceMap> | null;
18
18
  export declare function cacheFlightCodecPlugin(): Plugin;
19
19
  //#endregion
@@ -7,5 +7,5 @@ type TransformResult = {
7
7
  };
8
8
  type ResolveDynamicImport = (specifier: string, importer: string) => Promise<string | null>;
9
9
  export declare function transformNextDynamicPreloadMetadata(code: string, id: string, root: string, resolveDynamicImport: ResolveDynamicImport): Promise<TransformResult | null>;
10
- export declare function createDynamicPreloadMetadataPlugin(): Plugin;
10
+ export declare function createDynamicPreloadMetadataPlugin(getTranspiledPackages: () => readonly string[]): Plugin;
11
11
  //#endregion