@qzsy/vinext 0.1.12 → 0.1.80

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 (225) hide show
  1. package/README.md +19 -5
  2. package/dist/build/inject-pregenerated-paths.d.ts +4 -0
  3. package/dist/build/inject-pregenerated-paths.js +18 -0
  4. package/dist/build/pages-client-assets-module.d.ts +11 -0
  5. package/dist/build/pages-client-assets-module.js +27 -0
  6. package/dist/build/prerender.d.ts +2 -1
  7. package/dist/build/prerender.js +11 -4
  8. package/dist/build/report.d.ts +2 -1
  9. package/dist/build/report.js +2 -1
  10. package/dist/build/run-prerender.d.ts +7 -0
  11. package/dist/build/run-prerender.js +9 -0
  12. package/dist/build/standalone.js +2 -0
  13. package/dist/check.d.ts +18 -0
  14. package/dist/check.js +77 -19
  15. package/dist/cli-dev-config.d.ts +12 -0
  16. package/dist/cli-dev-config.js +23 -0
  17. package/dist/cli.js +64 -28
  18. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  19. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  20. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  21. package/dist/{server → client}/dev-error-overlay.js +2 -2
  22. package/dist/cloudflare/deploy-config.d.ts +51 -0
  23. package/dist/cloudflare/deploy-config.js +153 -0
  24. package/dist/cloudflare/index.d.ts +1 -1
  25. package/dist/cloudflare/index.js +1 -1
  26. package/dist/cloudflare/project.d.ts +41 -0
  27. package/dist/cloudflare/project.js +243 -0
  28. package/dist/cloudflare/tpr.js +1 -1
  29. package/dist/config/config-matchers.js +14 -10
  30. package/dist/config/next-config.d.ts +6 -3
  31. package/dist/config/next-config.js +47 -1
  32. package/dist/config/server-external-packages.d.ts +4 -0
  33. package/dist/config/server-external-packages.js +91 -0
  34. package/dist/deploy.d.ts +2 -122
  35. package/dist/deploy.js +20 -793
  36. package/dist/entries/app-rsc-entry.d.ts +2 -1
  37. package/dist/entries/app-rsc-entry.js +70 -12
  38. package/dist/entries/app-rsc-manifest.js +8 -0
  39. package/dist/entries/pages-client-entry.d.ts +1 -0
  40. package/dist/entries/pages-client-entry.js +2 -1
  41. package/dist/entries/pages-server-entry.js +6 -2
  42. package/dist/image/image-adapters-virtual.d.ts +59 -0
  43. package/dist/image/image-adapters-virtual.js +50 -0
  44. package/dist/index.d.ts +12 -0
  45. package/dist/index.js +158 -109
  46. package/dist/init-cloudflare.d.ts +43 -0
  47. package/dist/init-cloudflare.js +1000 -0
  48. package/dist/init-platform.d.ts +38 -0
  49. package/dist/init-platform.js +150 -0
  50. package/dist/init.d.ts +14 -37
  51. package/dist/init.js +205 -95
  52. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  53. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  54. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  55. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  56. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
  57. package/dist/plugins/ast-scope.d.ts +16 -0
  58. package/dist/plugins/ast-scope.js +62 -0
  59. package/dist/plugins/ast-utils.js +3 -0
  60. package/dist/plugins/css-module-imports.d.ts +14 -0
  61. package/dist/plugins/css-module-imports.js +59 -0
  62. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  63. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  64. package/dist/plugins/middleware-server-only.d.ts +8 -6
  65. package/dist/plugins/middleware-server-only.js +8 -7
  66. package/dist/plugins/optimize-imports.js +1 -1
  67. package/dist/plugins/typeof-window.d.ts +1 -1
  68. package/dist/plugins/typeof-window.js +28 -56
  69. package/dist/routing/app-route-graph.d.ts +13 -2
  70. package/dist/routing/app-route-graph.js +116 -32
  71. package/dist/routing/app-router.d.ts +5 -0
  72. package/dist/routing/app-router.js +5 -0
  73. package/dist/routing/file-matcher.d.ts +8 -0
  74. package/dist/routing/file-matcher.js +10 -1
  75. package/dist/routing/pages-router.js +2 -2
  76. package/dist/server/app-browser-action-result.d.ts +2 -1
  77. package/dist/server/app-browser-action-result.js +5 -1
  78. package/dist/server/app-browser-entry.js +17 -12
  79. package/dist/server/app-browser-history-controller.d.ts +2 -1
  80. package/dist/server/app-browser-history-controller.js +6 -2
  81. package/dist/server/app-browser-interception-context.d.ts +1 -0
  82. package/dist/server/app-browser-interception-context.js +4 -2
  83. package/dist/server/app-browser-navigation-controller.js +1 -0
  84. package/dist/server/app-browser-server-action-client.js +2 -3
  85. package/dist/server/app-browser-state.d.ts +1 -0
  86. package/dist/server/app-browser-state.js +3 -2
  87. package/dist/server/app-fallback-renderer.d.ts +3 -2
  88. package/dist/server/app-fallback-renderer.js +12 -7
  89. package/dist/server/app-middleware.d.ts +2 -3
  90. package/dist/server/app-middleware.js +3 -2
  91. package/dist/server/app-optimistic-routing.js +1 -1
  92. package/dist/server/app-page-boundary-render.d.ts +1 -0
  93. package/dist/server/app-page-boundary-render.js +12 -3
  94. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  95. package/dist/server/app-page-cache-finalizer.js +10 -3
  96. package/dist/server/app-page-cache-render.d.ts +1 -0
  97. package/dist/server/app-page-cache-render.js +8 -4
  98. package/dist/server/app-page-cache.d.ts +1 -0
  99. package/dist/server/app-page-cache.js +4 -1
  100. package/dist/server/app-page-dispatch.d.ts +11 -3
  101. package/dist/server/app-page-dispatch.js +55 -15
  102. package/dist/server/app-page-element-builder.d.ts +5 -1
  103. package/dist/server/app-page-element-builder.js +57 -20
  104. package/dist/server/app-page-head.d.ts +12 -0
  105. package/dist/server/app-page-head.js +42 -19
  106. package/dist/server/app-page-params.d.ts +2 -1
  107. package/dist/server/app-page-params.js +8 -1
  108. package/dist/server/app-page-probe.d.ts +1 -0
  109. package/dist/server/app-page-probe.js +6 -1
  110. package/dist/server/app-page-render-identity.d.ts +1 -0
  111. package/dist/server/app-page-render-identity.js +1 -1
  112. package/dist/server/app-page-render.d.ts +4 -1
  113. package/dist/server/app-page-render.js +8 -3
  114. package/dist/server/app-page-request.d.ts +22 -1
  115. package/dist/server/app-page-request.js +89 -13
  116. package/dist/server/app-page-route-wiring.d.ts +6 -1
  117. package/dist/server/app-page-route-wiring.js +31 -15
  118. package/dist/server/app-page-search-params-observation.d.ts +4 -2
  119. package/dist/server/app-page-search-params-observation.js +11 -7
  120. package/dist/server/app-page-segment-state.js +2 -0
  121. package/dist/server/app-route-handler-dispatch.js +1 -0
  122. package/dist/server/app-route-handler-execution.js +7 -2
  123. package/dist/server/app-route-handler-response.js +1 -0
  124. package/dist/server/app-route-handler-runtime.js +1 -1
  125. package/dist/server/app-route-module-loader.d.ts +2 -0
  126. package/dist/server/app-route-module-loader.js +1 -0
  127. package/dist/server/app-router-entry.d.ts +12 -0
  128. package/dist/server/app-router-entry.js +22 -8
  129. package/dist/server/app-router-image-optimization.d.ts +37 -0
  130. package/dist/server/app-router-image-optimization.js +40 -0
  131. package/dist/server/app-rsc-errors.js +7 -1
  132. package/dist/server/app-rsc-handler.js +27 -14
  133. package/dist/server/app-rsc-route-matching.d.ts +7 -0
  134. package/dist/server/app-rsc-route-matching.js +36 -3
  135. package/dist/server/app-segment-config.d.ts +12 -0
  136. package/dist/server/app-segment-config.js +91 -5
  137. package/dist/server/app-server-action-execution.d.ts +5 -0
  138. package/dist/server/app-server-action-execution.js +94 -33
  139. package/dist/server/app-ssr-entry.js +12 -1
  140. package/dist/server/app-static-generation.d.ts +1 -0
  141. package/dist/server/app-static-generation.js +1 -0
  142. package/dist/server/client-trace-metadata.js +26 -0
  143. package/dist/server/default-global-not-found-module.d.ts +14 -0
  144. package/dist/server/default-global-not-found-module.js +14 -0
  145. package/dist/server/dev-server.js +8 -15
  146. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  147. package/dist/server/dev-stack-sourcemap.js +1 -1
  148. package/dist/server/headers.d.ts +5 -15
  149. package/dist/server/headers.js +4 -15
  150. package/dist/server/image-optimization.d.ts +51 -1
  151. package/dist/server/image-optimization.js +52 -2
  152. package/dist/server/isr-cache.d.ts +1 -1
  153. package/dist/server/isr-cache.js +2 -2
  154. package/dist/server/middleware-runtime.js +6 -1
  155. package/dist/server/navigation-planner.d.ts +1 -0
  156. package/dist/server/navigation-planner.js +14 -3
  157. package/dist/server/pages-asset-tags.d.ts +4 -6
  158. package/dist/server/pages-asset-tags.js +12 -12
  159. package/dist/server/pages-client-assets.d.ts +12 -0
  160. package/dist/server/pages-client-assets.js +10 -0
  161. package/dist/server/pages-page-data.d.ts +23 -1
  162. package/dist/server/pages-page-data.js +43 -24
  163. package/dist/server/pages-page-handler.d.ts +2 -1
  164. package/dist/server/pages-page-handler.js +10 -4
  165. package/dist/server/pages-request-pipeline.d.ts +2 -0
  166. package/dist/server/pages-request-pipeline.js +25 -1
  167. package/dist/server/prerender-manifest.d.ts +3 -1
  168. package/dist/server/prerender-route-params.js +1 -1
  169. package/dist/server/prod-server.d.ts +1 -1
  170. package/dist/server/prod-server.js +47 -25
  171. package/dist/server/request-pipeline.js +1 -0
  172. package/dist/server/seed-cache.js +4 -4
  173. package/dist/server/worker-utils.d.ts +2 -1
  174. package/dist/server/worker-utils.js +7 -1
  175. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  176. package/dist/shims/app-router-scroll-state.js +1 -0
  177. package/dist/shims/app-router-scroll.js +2 -1
  178. package/dist/shims/cache.js +19 -15
  179. package/dist/shims/cdn-cache.js +1 -1
  180. package/dist/shims/dynamic-preload-chunks.js +2 -1
  181. package/dist/shims/error-boundary.d.ts +19 -1
  182. package/dist/shims/error-boundary.js +11 -1
  183. package/dist/shims/form.d.ts +3 -1
  184. package/dist/shims/form.js +37 -43
  185. package/dist/shims/headers.d.ts +9 -1
  186. package/dist/shims/headers.js +31 -6
  187. package/dist/shims/image-optimization-url.d.ts +4 -0
  188. package/dist/shims/image-optimization-url.js +33 -1
  189. package/dist/shims/image.js +46 -13
  190. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  191. package/dist/shims/internal/app-route-detection.js +4 -17
  192. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  193. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  194. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -5
  195. package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
  196. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  197. package/dist/shims/internal/pages-router-components.js +13 -0
  198. package/dist/shims/link.js +23 -16
  199. package/dist/shims/metadata.d.ts +3 -2
  200. package/dist/shims/metadata.js +8 -4
  201. package/dist/shims/navigation.js +4 -2
  202. package/dist/shims/root-params.d.ts +15 -1
  203. package/dist/shims/root-params.js +21 -1
  204. package/dist/shims/router.d.ts +2 -5
  205. package/dist/shims/router.js +41 -22
  206. package/dist/shims/server.js +3 -2
  207. package/dist/typegen.js +6 -5
  208. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  209. package/dist/utils/client-runtime-metadata.js +31 -22
  210. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  211. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  212. package/dist/utils/domain-locale.d.ts +6 -3
  213. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  214. package/dist/{server → utils}/middleware-request-headers.js +2 -2
  215. package/dist/utils/path.d.ts +2 -1
  216. package/dist/utils/path.js +1 -1
  217. package/dist/utils/project.d.ts +9 -1
  218. package/dist/utils/project.js +21 -4
  219. package/dist/utils/protocol-headers.d.ts +17 -0
  220. package/dist/utils/protocol-headers.js +17 -0
  221. package/dist/utils/react-version.d.ts +4 -0
  222. package/dist/utils/react-version.js +44 -0
  223. package/package.json +6 -1
  224. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  225. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
package/dist/cli.js CHANGED
@@ -2,14 +2,19 @@
2
2
  import { detectPackageManager, ensureViteConfigCompatibility, hasAppDir, hasViteConfig } from "./utils/project.js";
3
3
  import { formatReport, runCheck } from "./check.js";
4
4
  import { parseArgs } from "./cli-args.js";
5
+ import { createDevServerConfigPlugin, normalizeDevServerHostname } from "./cli-dev-config.js";
6
+ import { normalizePathSeparators } from "./utils/path.js";
5
7
  import { PHASE_PRODUCTION_BUILD } from "./shims/constants.js";
6
8
  import { createRscCompatibilityId, loadNextConfig, resolveNextConfig } from "./config/next-config.js";
7
9
  import { generateRouteTypes } from "./typegen.js";
8
- import { getReactUpgradeDeps, init } from "./init.js";
10
+ import { clearPagesClientAssetsBuildMetadata } from "./build/pages-client-assets-module.js";
11
+ import vinext from "./index.js";
9
12
  import { runPrerender } from "./build/run-prerender.js";
10
13
  import { loadDotenv } from "./config/dotenv.js";
11
14
  import { deploy, parseDeployArgs } from "./deploy.js";
12
- import vinext from "./index.js";
15
+ import { getReactUpgradeDeps } from "./utils/react-version.js";
16
+ import { init } from "./init.js";
17
+ import { INIT_PLATFORMS, resolveInitPlatform } from "./init-platform.js";
13
18
  import { resolveVinextPackageRoot } from "./utils/vinext-root.js";
14
19
  import { emitStandaloneOutput } from "./build/standalone.js";
15
20
  import { cleanBuildOutput } from "./build/clean-output.js";
@@ -179,20 +184,20 @@ async function dev() {
179
184
  });
180
185
  applyViteConfigCompatibility(process.cwd());
181
186
  const vite = await loadVite();
182
- const port = parsed.port ?? 3e3;
183
- const host = parsed.hostname ?? "localhost";
187
+ const initialPort = parsed.port ?? 3e3;
188
+ const initialHost = parsed.hostname ?? "localhost";
184
189
  let lockfile;
185
190
  const startedAt = Date.now();
186
191
  if (process.env.VINEXT_NO_DEV_LOCK !== "1") {
187
192
  const root = process.cwd();
188
- const initialDisplayHost = host === "0.0.0.0" ? "localhost" : host;
193
+ const initialDisplayHost = initialHost === "0.0.0.0" ? "localhost" : initialHost;
189
194
  const acquired = tryAcquireLockfile({
190
195
  root,
191
196
  info: {
192
197
  pid: process.pid,
193
- port,
194
- hostname: host,
195
- appUrl: `http://${initialDisplayHost}:${port}`,
198
+ port: initialPort,
199
+ hostname: initialHost,
200
+ appUrl: `http://${initialDisplayHost}:${initialPort}`,
196
201
  startedAt,
197
202
  cwd: root
198
203
  }
@@ -208,13 +213,21 @@ async function dev() {
208
213
  lockfile = acquired.lockfile;
209
214
  }
210
215
  console.log(`\n vinext dev (Vite ${getViteVersion()})\n`);
211
- const config = buildViteConfig({ server: {
212
- port,
213
- host
214
- } });
216
+ const config = buildViteConfig();
217
+ (config.plugins ??= []).push(createDevServerConfigPlugin(parsed));
215
218
  let server;
216
219
  try {
217
220
  server = await vite.createServer(config);
221
+ const port = server.config.server.port ?? 3e3;
222
+ const host = normalizeDevServerHostname(server.config.server.host);
223
+ lockfile?.update({
224
+ pid: process.pid,
225
+ port,
226
+ hostname: host,
227
+ appUrl: `http://${host === "0.0.0.0" ? "localhost" : host}:${port}`,
228
+ startedAt,
229
+ cwd: process.cwd()
230
+ });
218
231
  await server.listen();
219
232
  } catch (err) {
220
233
  lockfile?.release();
@@ -222,8 +235,10 @@ async function dev() {
222
235
  }
223
236
  server.printUrls();
224
237
  if (lockfile) {
238
+ const configuredPort = server.config.server.port ?? 3e3;
239
+ const configuredHost = normalizeDevServerHostname(server.config.server.host);
225
240
  const resolved = server.resolvedUrls?.local[0];
226
- let actualPort = port;
241
+ let actualPort = configuredPort;
227
242
  let appUrl;
228
243
  if (resolved) {
229
244
  appUrl = resolved.replace(/\/$/, "");
@@ -233,13 +248,13 @@ async function dev() {
233
248
  } catch {}
234
249
  } else {
235
250
  const address = server.httpServer?.address();
236
- actualPort = typeof address === "object" && address ? address.port : port;
237
- appUrl = `http://${host === "0.0.0.0" ? "localhost" : host}:${actualPort}`;
251
+ actualPort = typeof address === "object" && address ? address.port : configuredPort;
252
+ appUrl = `http://${configuredHost === "0.0.0.0" ? "localhost" : configuredHost}:${actualPort}`;
238
253
  }
239
254
  lockfile.update({
240
255
  pid: process.pid,
241
256
  port: actualPort,
242
- hostname: host,
257
+ hostname: configuredHost,
243
258
  appUrl,
244
259
  startedAt,
245
260
  cwd: process.cwd()
@@ -260,7 +275,7 @@ async function buildApp() {
260
275
  const withBuildBundlerOptions = (bundlerOptions) => viteMajorVersion >= 8 ? { rolldownOptions: bundlerOptions } : { rollupOptions: bundlerOptions };
261
276
  console.log(`\n vinext build (Vite ${getViteVersion()})\n`);
262
277
  const root = process.cwd();
263
- const isApp = hasAppDir(process.cwd());
278
+ const isApp = hasAppDir(normalizePathSeparators(root));
264
279
  const resolvedNextConfig = await resolveNextConfig(await loadNextConfig(root, PHASE_PRODUCTION_BUILD), root);
265
280
  process.env.__VINEXT_SHARED_BUILD_ID = resolvedNextConfig.buildId;
266
281
  process.env.__VINEXT_SHARED_RSC_COMPATIBILITY_ID = createRscCompatibilityId(resolvedNextConfig);
@@ -292,10 +307,13 @@ async function buildApp() {
292
307
  outDir: distDir,
293
308
  emptyOutDir: await loadBuildEmptyOutDir(vite, root)
294
309
  });
295
- const config = buildViteConfig({}, logger);
296
- await (await vite.createBuilder(config)).buildApp();
297
- if (isApp) {
298
- if (hasPagesDir()) {
310
+ const isHybrid = isApp && hasPagesDir();
311
+ const pagesClientAssetsBuildSession = isHybrid ? randomBytes(16).toString("hex") : null;
312
+ if (pagesClientAssetsBuildSession) process.env.__VINEXT_PAGES_CLIENT_ASSETS_BUILD_SESSION = pagesClientAssetsBuildSession;
313
+ try {
314
+ const config = buildViteConfig({}, logger);
315
+ await (await vite.createBuilder(config)).buildApp();
316
+ if (isHybrid) {
299
317
  console.log(" Building Pages Router server (hybrid)...");
300
318
  const root = process.cwd();
301
319
  let userTransformPlugins = [];
@@ -326,6 +344,11 @@ async function buildApp() {
326
344
  }
327
345
  });
328
346
  }
347
+ } finally {
348
+ if (pagesClientAssetsBuildSession) {
349
+ clearPagesClientAssetsBuildMetadata(pagesClientAssetsBuildSession);
350
+ if (process.env.__VINEXT_PAGES_CLIENT_ASSETS_BUILD_SESSION === pagesClientAssetsBuildSession) delete process.env.__VINEXT_PAGES_CLIENT_ASSETS_BUILD_SESSION;
351
+ }
329
352
  }
330
353
  if (outputMode === "standalone") {
331
354
  const standalone = emitStandaloneOutput({
@@ -346,14 +369,14 @@ async function buildApp() {
346
369
  process.stdout.write("\x1B[0m");
347
370
  console.log(` ${label}`);
348
371
  prerenderResult = await runPrerender({
349
- root: process.cwd(),
372
+ root: normalizePathSeparators(process.cwd()),
350
373
  concurrency: parsed.prerenderConcurrency
351
374
  });
352
375
  }
353
376
  process.stdout.write("\x1B[0m");
354
377
  const { printBuildReport } = await import("./build/report.js");
355
378
  await printBuildReport({
356
- root: process.cwd(),
379
+ root: normalizePathSeparators(process.cwd()),
357
380
  pageExtensions: resolvedNextConfig.pageExtensions,
358
381
  prerenderResult: prerenderResult ?? void 0
359
382
  });
@@ -440,10 +463,9 @@ async function deployCommand() {
440
463
  }
441
464
  async function check() {
442
465
  if (parseArgs(rawArgs).help) return printHelp("check");
443
- const root = process.cwd();
444
466
  console.log(`\n vinext check\n`);
445
467
  console.log(" Scanning project...\n");
446
- const result = runCheck(root);
468
+ const result = runCheck(normalizePathSeparators(process.cwd()));
447
469
  console.log(formatReport(result));
448
470
  }
449
471
  async function typegen() {
@@ -467,11 +489,15 @@ async function initCommand() {
467
489
  const port = parsed.port ?? 3001;
468
490
  const skipCheck = rawArgs.includes("--skip-check");
469
491
  const force = rawArgs.includes("--force");
492
+ const platform = await resolveInitPlatform(rawArgs);
493
+ const platformOptions = await INIT_PLATFORMS[platform].options(rawArgs);
470
494
  await init({
471
495
  root: process.cwd(),
472
496
  port,
473
497
  skipCheck,
474
- force
498
+ force,
499
+ platform,
500
+ cloudflare: platform === "cloudflare" ? platformOptions : void 0
475
501
  });
476
502
  }
477
503
  function printHelp(cmd) {
@@ -568,7 +594,7 @@ function printHelp(cmd) {
568
594
  vinext deploy Build and deploy to production
569
595
  vinext deploy --preview Deploy to a preview URL
570
596
  vinext deploy --env staging Deploy using wrangler env.staging
571
- vinext deploy --dry-run See what files would be generated
597
+ vinext deploy --dry-run Validate setup without building or deploying
572
598
  vinext deploy --name my-app Deploy with a custom Worker name
573
599
  vinext deploy --experimental-tpr Enable TPR during deploy
574
600
  vinext deploy --experimental-tpr --tpr-coverage 95 Cover 95% of traffic
@@ -605,10 +631,20 @@ function printHelp(cmd) {
605
631
  -p, --port <port> Dev server port for the vinext script (default: 3001)
606
632
  --skip-check Skip the compatibility check step
607
633
  --force Overwrite existing vite.config.ts
634
+ --platform <target> Deployment target: cloudflare or node
635
+ --data-cache <type> Cloudflare data cache: kv or none (default: kv)
636
+ --image-optimization <type>
637
+ Cloudflare image optimization: cloudflare-images or none
608
638
  -h, --help Show this help
609
639
 
610
640
  Examples:
611
- vinext init Migrate with defaults
641
+ vinext init Prompt for a deployment platform
642
+ vinext init --platform=cloudflare Configure Cloudflare Workers (default)
643
+ vinext init --platform=cloudflare --data-cache=kv
644
+ Configure the default Cloudflare cache handlers
645
+ vinext init --platform=cloudflare --image-optimization=none
646
+ Do not configure Cloudflare Images
647
+ vinext init --platform=node Configure a Node deployment
612
648
  vinext init -p 4000 Use port 4000 for dev:vinext
613
649
  vinext init --force Overwrite existing vite.config.ts
614
650
  vinext init --skip-check Skip the compatibility report
@@ -1,4 +1,4 @@
1
- //#region src/server/dev-error-overlay-store.d.ts
1
+ //#region src/client/dev-error-overlay-store.d.ts
2
2
  type Source = "server" | "vite" | "uncaught" | "caught" | "window-error" | "unhandledrejection";
3
3
  type ReportedError = {
4
4
  id: number;
@@ -1,4 +1,4 @@
1
- //#region src/server/dev-error-overlay-store.ts
1
+ //#region src/client/dev-error-overlay-store.ts
2
2
  const MAX_DEV_OVERLAY_ERRORS = 50;
3
3
  let snapshot = {
4
4
  errors: [],
@@ -1,6 +1,6 @@
1
1
  import { ReportedError, dismissOverlay } from "./dev-error-overlay-store.js";
2
2
 
3
- //#region src/server/dev-error-overlay.d.ts
3
+ //#region src/client/dev-error-overlay.d.ts
4
4
  declare const DEV_ERROR_OVERLAY_HOST_ID = "__vinext_dev_error_overlay_root";
5
5
  declare const DEV_ERROR_OVERLAY_MOUNT_ID = "__vinext_dev_error_overlay_mount";
6
6
  declare function installDevErrorOverlay(): void;
@@ -1,11 +1,11 @@
1
1
  import { VINEXT_DEV_ERROR_RECOVERY_EVENT } from "../utils/dev-error-recovery-event.js";
2
2
  import { isNavigationSignalError } from "../utils/navigation-signal.js";
3
- import { VINEXT_ORIGINAL_STACK_TRACE_ENDPOINT } from "./dev-stack-sourcemap-endpoint.js";
3
+ import { VINEXT_ORIGINAL_STACK_TRACE_ENDPOINT } from "../utils/dev-stack-sourcemap-endpoint.js";
4
4
  import { dismissOverlay, expandOverlay, getOverlaySnapshot, minimizeOverlay, reportToOverlay, setOverlayIndex, subscribeOverlay, updateOverlayErrorStack } from "./dev-error-overlay-store.js";
5
5
  import { Fragment, useEffect, useMemo, useState, useSyncExternalStore } from "react";
6
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
7
  import { createRoot } from "react-dom/client";
8
- //#region src/server/dev-error-overlay.tsx
8
+ //#region src/client/dev-error-overlay.tsx
9
9
  const DEV_ERROR_OVERLAY_HOST_ID = "__vinext_dev_error_overlay_root";
10
10
  const DEV_ERROR_OVERLAY_MOUNT_ID = "__vinext_dev_error_overlay_mount";
11
11
  const VITE_ERROR_HANDLER_DATA_KEY = "__vinext_vite_error_handler__";
@@ -0,0 +1,51 @@
1
+ //#region src/cloudflare/deploy-config.d.ts
2
+ declare function formatMissingCloudflarePluginError(options: {
3
+ isAppRouter: boolean;
4
+ configFile?: string;
5
+ }): string;
6
+ /**
7
+ * Check whether an existing vite.config file already imports and uses the
8
+ * Cloudflare Vite plugin. This is a heuristic text scan — it doesn't execute
9
+ * the config — so it may produce false negatives for unusual configurations.
10
+ *
11
+ * Returns true when the config both imports the package and invokes
12
+ * `cloudflare(...)` in the plugin list.
13
+ */
14
+ declare function viteConfigHasCloudflarePlugin(root: string): boolean;
15
+ /**
16
+ * Detect whether the Vite config assigns a CDN or data cache adapter — i.e. the
17
+ * `cdn` or `data` field of the `vinext({ cache })` option is given a value.
18
+ * This is a source-level check on those exact object fields, not a fuzzy scan
19
+ * for adapter names. Mirrors {@link viteConfigHasCloudflarePlugin}'s leniency:
20
+ * an unreadable or absent config is treated as configured so a deploy is never
21
+ * blocked on a false negative.
22
+ */
23
+ declare function viteConfigHasCacheAdapter(root: string): boolean;
24
+ declare function viteConfigHasImageAdapter(root: string): boolean;
25
+ /**
26
+ * Detect whether an existing user-authored Worker entry wires up a cache
27
+ * backend imperatively via one of the `setCacheHandler` / `setDataCacheHandler`
28
+ * / `setCdnCacheAdapter` setters. These setters are deprecated in favour of the
29
+ * declarative `vinext({ cache })` option, but older apps that scaffolded a KV
30
+ * cache handler into their Worker entry must keep working — so a deploy should
31
+ * not be blocked when the Worker entry already configures a backend.
32
+ *
33
+ * This is a heuristic text scan (it doesn't execute the entry), mirroring
34
+ * {@link viteConfigHasCacheAdapter}'s leniency: an unreadable Worker entry is
35
+ * treated as configured so a deploy is never blocked on a false negative. A
36
+ * missing Worker entry returns false (nothing to inspect — defer to other
37
+ * checks).
38
+ */
39
+ declare function workerEntryHasCacheHandler(root: string): boolean;
40
+ /**
41
+ * Build the error thrown when an ISR/cached app is deployed without a cache
42
+ * adapter configured in the Vite config. Production deployments need a
43
+ * persistent cache backend; vinext no longer scaffolds one into the Worker
44
+ * entry, so it must be declared via `vinext({ cache })`.
45
+ */
46
+ declare function formatMissingCacheAdapterError(options: {
47
+ configFile?: string;
48
+ }): string;
49
+ declare function formatImageOptimizationHint(): string;
50
+ //#endregion
51
+ export { formatImageOptimizationHint, formatMissingCacheAdapterError, formatMissingCloudflarePluginError, viteConfigHasCacheAdapter, viteConfigHasCloudflarePlugin, viteConfigHasImageAdapter, workerEntryHasCacheHandler };
@@ -0,0 +1,153 @@
1
+ import { findViteConfigPath } from "../utils/project.js";
2
+ import { escapeRegExp } from "../utils/regex.js";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ //#region src/cloudflare/deploy-config.ts
6
+ function formatMissingCloudflarePluginError(options) {
7
+ const cfArg = options.isAppRouter ? "{\n viteEnvironment: { name: \"rsc\", childEnvironments: [\"ssr\"] },\n }" : "";
8
+ const configRef = options.configFile ? options.configFile : "your Vite config";
9
+ return `[vinext] Missing @cloudflare/vite-plugin in ${configRef}.\n\n Cloudflare Workers builds require the cloudflare() plugin.\n Run \`vinext init --platform=cloudflare\` to update ${configRef}.\n\n Expected plugin shape:\n\n cloudflare(${cfArg})`;
10
+ }
11
+ /**
12
+ * Check whether an existing vite.config file already imports and uses the
13
+ * Cloudflare Vite plugin. This is a heuristic text scan — it doesn't execute
14
+ * the config — so it may produce false negatives for unusual configurations.
15
+ *
16
+ * Returns true when the config both imports the package and invokes
17
+ * `cloudflare(...)` in the plugin list.
18
+ */
19
+ function viteConfigHasCloudflarePlugin(root) {
20
+ const configPath = findViteConfigPath(root);
21
+ if (!configPath) return false;
22
+ try {
23
+ const content = fs.readFileSync(configPath, "utf-8").replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
24
+ const requireBinding = content.match(/(?:const|let|var)\s*{([^}]*)}\s*=\s*require\s*\(\s*["']@cloudflare\/vite-plugin["']\s*\)/)?.[1];
25
+ if (requireBinding) {
26
+ const requireMatch = requireBinding.match(/(?:^|,)\s*cloudflare\s*(?::\s*([A-Za-z_$][\w$]*))?\s*(?:,|$)/);
27
+ if (requireMatch) {
28
+ const binding = requireMatch[1] ?? "cloudflare";
29
+ return new RegExp(`\\b${escapeRegExp(binding)}\\s*\\(`).test(content);
30
+ }
31
+ }
32
+ const namedImports = content.match(/import\s*{([^}]*)}\s*from\s*["']@cloudflare\/vite-plugin["']/)?.[1];
33
+ if (!namedImports) return false;
34
+ const importMatch = namedImports.match(/(?:^|,)\s*cloudflare\s*(?:as\s+([A-Za-z_$][\w$]*))?\s*(?:,|$)/);
35
+ if (!importMatch) return false;
36
+ const binding = importMatch[1] ?? "cloudflare";
37
+ return new RegExp(`\\b${escapeRegExp(binding)}\\s*\\(`).test(content);
38
+ } catch {
39
+ return false;
40
+ }
41
+ }
42
+ /**
43
+ * Extract the object-literal text of the `cache:` key (the `{ ... }` passed as
44
+ * `vinext({ cache })`) from a Vite config source, via brace matching. Returns
45
+ * null if there is no `cache:` object literal.
46
+ */
47
+ function extractCacheBlock(content) {
48
+ const m = /\bcache\s*:\s*\{/.exec(content);
49
+ if (!m) return null;
50
+ const open = m.index + m[0].length - 1;
51
+ let depth = 0;
52
+ for (let i = open; i < content.length; i++) {
53
+ const ch = content[i];
54
+ if (ch === "{") depth++;
55
+ else if (ch === "}" && --depth === 0) return content.slice(open, i + 1);
56
+ }
57
+ return null;
58
+ }
59
+ /**
60
+ * Whether a `cdn` / `data` field inside the cache object is assigned a real
61
+ * value (not absent, `undefined`, or `null`). Reads the value up to the next
62
+ * comma / closing brace / newline, which is enough to tell an assignment like
63
+ * `data: kvDataAdapter()` from `data: undefined`.
64
+ */
65
+ function cacheFieldAssigned(cacheBlock, field) {
66
+ const m = new RegExp(`\\b${field}\\s*:\\s*([^,}\\n]+)`).exec(cacheBlock);
67
+ if (!m) return false;
68
+ const value = m[1].trim();
69
+ return value.length > 0 && value !== "undefined" && value !== "null";
70
+ }
71
+ /**
72
+ * Detect whether the Vite config assigns a CDN or data cache adapter — i.e. the
73
+ * `cdn` or `data` field of the `vinext({ cache })` option is given a value.
74
+ * This is a source-level check on those exact object fields, not a fuzzy scan
75
+ * for adapter names. Mirrors {@link viteConfigHasCloudflarePlugin}'s leniency:
76
+ * an unreadable or absent config is treated as configured so a deploy is never
77
+ * blocked on a false negative.
78
+ */
79
+ function viteConfigHasCacheAdapter(root) {
80
+ const configPath = findViteConfigPath(root);
81
+ if (!configPath) return true;
82
+ let content;
83
+ try {
84
+ content = fs.readFileSync(configPath, "utf-8");
85
+ } catch {
86
+ return true;
87
+ }
88
+ const block = extractCacheBlock(content);
89
+ if (!block) return false;
90
+ return cacheFieldAssigned(block, "cdn") || cacheFieldAssigned(block, "data");
91
+ }
92
+ function viteConfigHasImageAdapter(root) {
93
+ const configPath = findViteConfigPath(root);
94
+ if (!configPath) return true;
95
+ try {
96
+ const content = fs.readFileSync(configPath, "utf-8");
97
+ const match = /\bimages\s*:\s*\{/.exec(content);
98
+ if (!match) return false;
99
+ const open = match.index + match[0].length - 1;
100
+ let depth = 0;
101
+ for (let index = open; index < content.length; index++) if (content[index] === "{") depth++;
102
+ else if (content[index] === "}" && --depth === 0) {
103
+ const optimizer = /\boptimizer\s*:\s*([^,}\n]+)/.exec(content.slice(open, index + 1))?.[1];
104
+ return Boolean(optimizer && !/^(?:undefined|null)$/.test(optimizer.trim()));
105
+ }
106
+ return false;
107
+ } catch {
108
+ return true;
109
+ }
110
+ }
111
+ /**
112
+ * Detect whether an existing user-authored Worker entry wires up a cache
113
+ * backend imperatively via one of the `setCacheHandler` / `setDataCacheHandler`
114
+ * / `setCdnCacheAdapter` setters. These setters are deprecated in favour of the
115
+ * declarative `vinext({ cache })` option, but older apps that scaffolded a KV
116
+ * cache handler into their Worker entry must keep working — so a deploy should
117
+ * not be blocked when the Worker entry already configures a backend.
118
+ *
119
+ * This is a heuristic text scan (it doesn't execute the entry), mirroring
120
+ * {@link viteConfigHasCacheAdapter}'s leniency: an unreadable Worker entry is
121
+ * treated as configured so a deploy is never blocked on a false negative. A
122
+ * missing Worker entry returns false (nothing to inspect — defer to other
123
+ * checks).
124
+ */
125
+ function workerEntryHasCacheHandler(root) {
126
+ const candidates = [path.join(root, "worker", "index.ts"), path.join(root, "worker", "index.js")];
127
+ for (const candidate of candidates) {
128
+ if (!fs.existsSync(candidate)) continue;
129
+ let content;
130
+ try {
131
+ content = fs.readFileSync(candidate, "utf-8");
132
+ } catch {
133
+ return true;
134
+ }
135
+ return /\b(?:setCacheHandler|setDataCacheHandler|setCdnCacheAdapter)\s*\(/.test(content);
136
+ }
137
+ return false;
138
+ }
139
+ /**
140
+ * Build the error thrown when an ISR/cached app is deployed without a cache
141
+ * adapter configured in the Vite config. Production deployments need a
142
+ * persistent cache backend; vinext no longer scaffolds one into the Worker
143
+ * entry, so it must be declared via `vinext({ cache })`.
144
+ */
145
+ function formatMissingCacheAdapterError(options) {
146
+ const configRef = options.configFile ? options.configFile : "your Vite config";
147
+ return `[vinext] This app uses ISR / caching but no cache adapter is configured in ${configRef}.\n\n Production deployments need a persistent cache backend. Declare one on the\n vinext() plugin in ${configRef}:\n\n import { kvDataAdapter } from "@vinext/cloudflare/cache/kv-data-adapter";\n\n export default defineConfig({\n plugins: [\n vinext({\n cache: {\n data: kvDataAdapter(), // KV-backed data cache (binding: VINEXT_KV_CACHE)\n },\n }),\n cloudflare(),\n ],\n });\n\n The VINEXT_KV_CACHE namespace binding is added to wrangler.jsonc for you.\n Create the namespace with:\n\n npx wrangler kv namespace create VINEXT_KV_CACHE`;
148
+ }
149
+ function formatImageOptimizationHint() {
150
+ return " [vinext] next/image is served unoptimized. To enable edge image\n optimization via Cloudflare Images, run:\n\n vinext init --platform=cloudflare --image-optimization=cloudflare-images\n\n This adds the imagesOptimizer() option to your Vite config and the matching\n IMAGES binding to your Wrangler config without replacing existing settings.";
151
+ }
152
+ //#endregion
153
+ export { formatImageOptimizationHint, formatMissingCacheAdapterError, formatMissingCloudflarePluginError, viteConfigHasCacheAdapter, viteConfigHasCloudflarePlugin, viteConfigHasImageAdapter, workerEntryHasCacheHandler };
@@ -1,3 +1,3 @@
1
- import { KVCacheHandler } from "./src/cache/kv-data-adapter.runtime.js";
1
+ import { KVCacheHandler } from "../packages/cloudflare/src/cache/kv-data-adapter.runtime.js";
2
2
  import { TPROptions, TPRResult, runTPR } from "./tpr.js";
3
3
  export { KVCacheHandler, type TPROptions, type TPRResult, runTPR };
@@ -1,3 +1,3 @@
1
- import { KVCacheHandler } from "./src/cache/kv-data-adapter.runtime.js";
1
+ import { KVCacheHandler } from "../packages/cloudflare/src/cache/kv-data-adapter.runtime.js";
2
2
  import { runTPR } from "./tpr.js";
3
3
  export { KVCacheHandler, runTPR };
@@ -0,0 +1,41 @@
1
+ //#region src/cloudflare/project.d.ts
2
+ type ProjectInfo = {
3
+ root: string;
4
+ isAppRouter: boolean;
5
+ isPagesRouter: boolean;
6
+ hasViteConfig: boolean;
7
+ hasWranglerConfig: boolean;
8
+ hasWorkerEntry: boolean;
9
+ hasCloudflarePlugin: boolean;
10
+ hasRscPlugin: boolean;
11
+ hasWrangler: boolean;
12
+ projectName: string; /** Pages that use `revalidate` (ISR) */
13
+ hasISR: boolean; /** package.json has "type": "module" */
14
+ hasTypeModule: boolean; /** .mdx files detected in app/ or pages/ */
15
+ hasMDX: boolean; /** CodeHike is a dependency */
16
+ hasCodeHike: boolean; /** Native Node modules that need stubbing for Workers */
17
+ nativeModulesToStub: string[];
18
+ };
19
+ /** Check whether a wrangler config file exists in the given directory. */
20
+ declare function hasWranglerConfig(root: string): boolean;
21
+ /**
22
+ * Detect the project structure (router, config, worker entry, package name).
23
+ *
24
+ * `root` is an OS-native filesystem path.
25
+ */
26
+ declare function detectProject(root: string): ProjectInfo;
27
+ type MissingDep = {
28
+ name: string;
29
+ version: string;
30
+ };
31
+ /**
32
+ * Check if a package is resolvable from a given root directory using
33
+ * Node's module resolution (createRequire). Handles hoisting, pnpm
34
+ * symlinks, monorepos, and Yarn PnP correctly.
35
+ */
36
+ declare function isPackageResolvable(root: string, packageName: string): boolean;
37
+ declare function getMissingDeps(info: ProjectInfo, /** Override for testing — defaults to `isPackageResolvable` */
38
+
39
+ _isResolvable?: (root: string, pkg: string) => boolean): MissingDep[];
40
+ //#endregion
41
+ export { ProjectInfo, detectProject, getMissingDeps, hasWranglerConfig, isPackageResolvable };