vinext 0.2.1 → 1.0.0-beta.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 (79) hide show
  1. package/README.md +50 -29
  2. package/dist/build/client-build-config.d.ts +13 -92
  3. package/dist/build/client-build-config.js +17 -95
  4. package/dist/build/prerender-paths.d.ts +23 -0
  5. package/dist/build/prerender-paths.js +296 -0
  6. package/dist/build/prerender.d.ts +12 -1
  7. package/dist/build/prerender.js +1 -1
  8. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  9. package/dist/cache/cache-adapters-virtual.js +26 -2
  10. package/dist/check.js +5 -0
  11. package/dist/cli.js +33 -53
  12. package/dist/config/next-config.js +1 -2
  13. package/dist/config/prerender.d.ts +11 -1
  14. package/dist/config/prerender.js +19 -1
  15. package/dist/config/tsconfig-paths.js +5 -1
  16. package/dist/image/image-adapters-virtual.js +1 -0
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.js +248 -146
  19. package/dist/init-cloudflare.js +12 -3
  20. package/dist/init-platform.d.ts +10 -1
  21. package/dist/init-platform.js +78 -12
  22. package/dist/init.d.ts +11 -3
  23. package/dist/init.js +129 -31
  24. package/dist/server/app-browser-entry.js +4 -6
  25. package/dist/server/app-browser-navigation-controller.js +6 -3
  26. package/dist/server/app-browser-state.js +1 -1
  27. package/dist/server/app-browser-visible-commit.js +1 -1
  28. package/dist/server/app-layout-param-observation.d.ts +1 -1
  29. package/dist/server/app-page-cache-render.d.ts +1 -1
  30. package/dist/server/app-page-dispatch.d.ts +1 -1
  31. package/dist/server/app-page-dispatch.js +3 -3
  32. package/dist/server/app-page-render.d.ts +1 -1
  33. package/dist/server/app-page-route-wiring.js +3 -3
  34. package/dist/server/app-route-handler-execution.d.ts +1 -1
  35. package/dist/server/app-route-handler-execution.js +1 -1
  36. package/dist/server/app-rsc-cache-busting.js +0 -1
  37. package/dist/server/app-rsc-handler.js +1 -1
  38. package/dist/server/app-rsc-render-mode.d.ts +2 -5
  39. package/dist/server/app-rsc-render-mode.js +2 -12
  40. package/dist/server/app-server-action-execution.js +4 -4
  41. package/dist/server/app-ssr-entry.js +2 -2
  42. package/dist/server/dev-module-runner.js +1 -1
  43. package/dist/server/dev-origin-check.d.ts +2 -2
  44. package/dist/server/dev-origin-check.js +2 -2
  45. package/dist/server/dev-server.js +4 -4
  46. package/dist/server/image-optimization.d.ts +12 -1
  47. package/dist/server/image-optimization.js +13 -1
  48. package/dist/server/isr-cache.d.ts +12 -4
  49. package/dist/server/isr-cache.js +2 -2
  50. package/dist/server/pages-page-data.js +1 -1
  51. package/dist/server/pages-page-response.js +2 -2
  52. package/dist/server/pages-request-pipeline.js +1 -1
  53. package/dist/server/prerender-manifest.d.ts +15 -1
  54. package/dist/server/prerender-manifest.js +29 -1
  55. package/dist/server/prod-server.d.ts +6 -5
  56. package/dist/server/prod-server.js +6 -7
  57. package/dist/server/static-file-cache.js +1 -1
  58. package/dist/shims/cache.d.ts +1 -1
  59. package/dist/shims/cdn-cache.d.ts +2 -7
  60. package/dist/shims/cdn-cache.js +2 -14
  61. package/dist/shims/form.d.ts +1 -1
  62. package/dist/shims/navigation.react-server.js +1 -1
  63. package/dist/shims/request-state-types.d.ts +2 -2
  64. package/dist/shims/unified-request-context.d.ts +1 -1
  65. package/dist/utils/project.d.ts +1 -1
  66. package/dist/utils/vite-version.d.ts +3 -13
  67. package/dist/utils/vite-version.js +38 -30
  68. package/package.json +31 -13
  69. package/dist/cloudflare/index.d.ts +0 -3
  70. package/dist/cloudflare/index.js +0 -3
  71. package/dist/packages/cloudflare/src/cache/cdn-adapter.runtime.js +0 -102
  72. package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +0 -126
  73. package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.js +0 -442
  74. package/dist/packages/cloudflare/src/deploy-config.js +0 -150
  75. package/dist/packages/cloudflare/src/deploy-help.js +0 -55
  76. package/dist/packages/cloudflare/src/deploy.js +0 -272
  77. package/dist/packages/cloudflare/src/tpr.d.ts +0 -45
  78. package/dist/packages/cloudflare/src/tpr.js +0 -582
  79. package/dist/packages/cloudflare/src/utils/cache-control-metadata.js +0 -20
@@ -1,12 +1,13 @@
1
1
  import { detectProject } from "./utils/project.js";
2
+ import { createRequire } from "node:module";
2
3
  import fs from "node:fs";
3
4
  import path from "node:path";
4
- import { parseSync } from "vite";
5
5
  import MagicString from "magic-string";
6
6
  //#region src/init-cloudflare.ts
7
+ const require = createRequire(import.meta.url);
7
8
  const DEFAULT_CLOUDFLARE_INIT_OPTIONS = {
8
9
  dataCache: "kv",
9
- cdnCache: "data-cache",
10
+ cdnCache: "workers-cache",
10
11
  imageOptimization: "cloudflare-images"
11
12
  };
12
13
  function validateCloudflarePlatformSetup(context, cloudflare) {
@@ -382,6 +383,14 @@ export default defineConfig({
382
383
  `;
383
384
  }
384
385
  function parseViteConfig(filePath, code) {
386
+ let parseSync;
387
+ try {
388
+ ({parseSync} = require("vite"));
389
+ } catch (error) {
390
+ const maybeNodeError = error;
391
+ if (maybeNodeError.code === "MODULE_NOT_FOUND" && maybeNodeError.message.includes("vite")) throw new Error(`Could not update ${path.basename(filePath)} because the "vite" package is not available to parse the existing config. Install dependencies first, or remove the existing Vite config and rerun vinext init.`);
392
+ throw error;
393
+ }
385
394
  const extension = path.extname(filePath).slice(1);
386
395
  const lang = extension === "ts" || extension === "mts" || extension === "cts" ? "ts" : "js";
387
396
  const parsed = parseSync(path.basename(filePath), code, {
@@ -758,7 +767,7 @@ function updateViteConfigForCloudflare(filePath, code, options) {
758
767
  const program = parseViteConfig(filePath, code);
759
768
  const cacheOptions = options.cache ?? {
760
769
  dataCache: "none",
761
- cdnCache: "data-cache",
770
+ cdnCache: "workers-cache",
762
771
  imageOptimization: "cloudflare-images"
763
772
  };
764
773
  const config = findConfigObject(program);
@@ -9,6 +9,7 @@ type CloudflareInitOptions = {
9
9
  dataCache: InitDataCache;
10
10
  cdnCache: InitCdnCache;
11
11
  imageOptimization: InitImageOptimization;
12
+ warmCdnCache?: boolean;
12
13
  };
13
14
  declare const INIT_PLATFORMS: {
14
15
  cloudflare: {
@@ -27,14 +28,22 @@ type PlatformPromptOptions = {
27
28
  isInteractive?: boolean;
28
29
  question?: (prompt: string) => Promise<string>;
29
30
  };
31
+ type ResolvedInitOptions = {
32
+ platform: InitPlatform;
33
+ cloudflare?: CloudflareInitOptions;
34
+ prerender: boolean;
35
+ };
30
36
  declare function isAgentEnvironment(env?: Record<string, string | undefined>): boolean;
31
37
  declare function parsePlatformArg(args: string[]): InitPlatform | undefined;
32
38
  declare function parseDataCacheArg(args: string[]): InitDataCache | undefined;
33
39
  declare function parseCdnCacheArg(args: string[]): InitCdnCache | undefined;
34
40
  declare function parseImageOptimizationArg(args: string[]): InitImageOptimization | undefined;
35
41
  declare function parsePrerenderArg(args: string[]): boolean | undefined;
42
+ declare function parseWarmCdnCacheArg(args: string[]): boolean | undefined;
36
43
  declare function resolveInitPlatform(args: string[], options?: PlatformPromptOptions): Promise<InitPlatform>;
44
+ declare function resolveInitOptions(args: string[], options?: PlatformPromptOptions): Promise<ResolvedInitOptions>;
37
45
  declare function resolveInitPrerender(args: string[], options?: PlatformPromptOptions): Promise<boolean>;
46
+ declare function resolveInitWarmCdnCache(args: string[], options?: PlatformPromptOptions): Promise<boolean>;
38
47
  declare function resolveCloudflareInitOptions(args: string[], options?: PlatformPromptOptions): Promise<CloudflareInitOptions>;
39
48
  //#endregion
40
- export { CloudflareInitOptions, INIT_PLATFORMS, InitCdnCache, InitDataCache, InitImageOptimization, InitPlatform, isAgentEnvironment, parseCdnCacheArg, parseDataCacheArg, parseImageOptimizationArg, parsePlatformArg, parsePrerenderArg, resolveCloudflareInitOptions, resolveInitPlatform, resolveInitPrerender };
49
+ export { CloudflareInitOptions, INIT_PLATFORMS, InitCdnCache, InitDataCache, InitImageOptimization, InitPlatform, PlatformPromptOptions, ResolvedInitOptions, isAgentEnvironment, parseCdnCacheArg, parseDataCacheArg, parseImageOptimizationArg, parsePlatformArg, parsePrerenderArg, parseWarmCdnCacheArg, resolveCloudflareInitOptions, resolveInitOptions, resolveInitPlatform, resolveInitPrerender, resolveInitWarmCdnCache };
@@ -52,20 +52,26 @@ function parseDataCacheArg(args) {
52
52
  return parseChoiceArg(args, "--data-cache", ["kv", "none"]);
53
53
  }
54
54
  function parseCdnCacheArg(args) {
55
- return parseChoiceArg(args, "--cdn-cache", ["data-cache", "workers-cache"], ["data-cache"]);
55
+ return parseChoiceArg(args, "--cdn-cache", ["workers-cache", "data-cache"]);
56
56
  }
57
57
  function parseImageOptimizationArg(args) {
58
58
  return parseChoiceArg(args, "--image-optimization", ["cloudflare-images", "none"]);
59
59
  }
60
60
  function parsePrerenderArg(args) {
61
+ return parseBooleanArg(args, "--prerender", "--no-prerender", "--prerender expects true or false when using the \"--prerender=value\" form.");
62
+ }
63
+ function parseWarmCdnCacheArg(args) {
64
+ return parseBooleanArg(args, "--experimental-warm-cdn-cache", "--no-experimental-warm-cdn-cache", "--experimental-warm-cdn-cache expects true or false when using the \"--experimental-warm-cdn-cache=value\" form.");
65
+ }
66
+ function parseBooleanArg(args, enabledFlag, disabledFlag, errorMessage) {
61
67
  for (const arg of args) {
62
- if (arg === "--prerender") return true;
63
- if (arg === "--no-prerender") return false;
64
- if (!arg.startsWith("--prerender=")) continue;
65
- const value = arg.slice(12).toLowerCase();
68
+ if (arg === enabledFlag) return true;
69
+ if (arg === disabledFlag) return false;
70
+ if (!arg.startsWith(`${enabledFlag}=`)) continue;
71
+ const value = arg.slice(enabledFlag.length + 1).toLowerCase();
66
72
  if (value === "true" || value === "yes" || value === "1") return true;
67
73
  if (value === "false" || value === "no" || value === "0") return false;
68
- throw new Error("--prerender expects true or false when using the \"--prerender=value\" form.");
74
+ throw new Error(errorMessage);
69
75
  }
70
76
  }
71
77
  async function resolveInitPlatform(args, options = {}) {
@@ -98,6 +104,24 @@ async function resolveInitPlatform(args, options = {}) {
98
104
  readline?.close();
99
105
  }
100
106
  }
107
+ async function resolveInitOptions(args, options = {}) {
108
+ const platform = await resolveInitPlatform(args, options);
109
+ const platformOptions = await INIT_PLATFORMS[platform].options(args, options);
110
+ const explicitWarmCdnCache = parseWarmCdnCacheArg(args);
111
+ if (platform === "cloudflare" && platformOptions?.cdnCache !== "workers-cache") {
112
+ if (explicitWarmCdnCache === true) throw new Error("--experimental-warm-cdn-cache requires --cdn-cache=workers-cache.");
113
+ }
114
+ const prerender = await resolveInitPrerender(args, options);
115
+ const warmCdnCache = platform === "cloudflare" && platformOptions?.cdnCache === "workers-cache" ? await resolveInitWarmCdnCache(args, options) : false;
116
+ return {
117
+ platform,
118
+ prerender,
119
+ cloudflare: platform === "cloudflare" && platformOptions ? {
120
+ ...platformOptions,
121
+ warmCdnCache
122
+ } : void 0
123
+ };
124
+ }
101
125
  async function resolveInitPrerender(args, options = {}) {
102
126
  const explicitPrerender = parsePrerenderArg(args);
103
127
  if (explicitPrerender !== void 0) return explicitPrerender;
@@ -132,21 +156,55 @@ async function resolveInitPrerender(args, options = {}) {
132
156
  readline?.close();
133
157
  }
134
158
  }
159
+ async function resolveInitWarmCdnCache(args, options = {}) {
160
+ const explicitWarmCdnCache = parseWarmCdnCacheArg(args);
161
+ if (explicitWarmCdnCache !== void 0) return explicitWarmCdnCache;
162
+ const env = options.env ?? process.env;
163
+ const input = options.input ?? process.stdin;
164
+ const output = options.output ?? process.stdout;
165
+ const isInteractive = options.isInteractive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
166
+ if (isAgentEnvironment(env) || !isInteractive) return false;
167
+ const readline = options.question ? void 0 : createInterface({
168
+ input,
169
+ output
170
+ });
171
+ const question = options.question ?? ((prompt) => readline.question(prompt));
172
+ try {
173
+ while (true) {
174
+ const answer = (await question(" Enable Workers Cache experimental pre-warm during deploy? [y/N]: ")).trim().toLowerCase();
175
+ if (answer === "") {
176
+ output.write("\n");
177
+ return false;
178
+ }
179
+ if (answer === "y" || answer === "yes") {
180
+ output.write("\n");
181
+ return true;
182
+ }
183
+ if (answer === "n" || answer === "no") {
184
+ output.write("\n");
185
+ return false;
186
+ }
187
+ output.write(" Please answer yes or no.\n");
188
+ }
189
+ } finally {
190
+ readline?.close();
191
+ }
192
+ }
135
193
  async function resolveCloudflareInitOptions(args, options = {}) {
136
194
  const explicitDataCache = parseDataCacheArg(args);
137
195
  const explicitCdnCache = parseCdnCacheArg(args);
138
196
  const explicitImageOptimization = parseImageOptimizationArg(args);
139
- if (explicitDataCache && explicitImageOptimization) return {
197
+ if (explicitCdnCache && explicitDataCache && explicitImageOptimization) return {
140
198
  dataCache: explicitDataCache,
141
- cdnCache: explicitCdnCache ?? "data-cache",
199
+ cdnCache: explicitCdnCache,
142
200
  imageOptimization: explicitImageOptimization
143
201
  };
144
- if (isAgentEnvironment(options.env ?? process.env)) throw new Error("vinext init needs Cloudflare cache and image choices. Ask the user which data cache (kv or none) and image optimization (cloudflare-images or none) they want, then re-run with --data-cache=... and --image-optimization=....");
202
+ if (isAgentEnvironment(options.env ?? process.env)) throw new Error("vinext init needs Cloudflare cache and image choices. Ask the user which CDN cache (workers-cache or data-cache), data cache (kv or none), and image optimization (cloudflare-images or none) they want, then re-run with --cdn-cache=..., --data-cache=..., and --image-optimization=....");
145
203
  const input = options.input ?? process.stdin;
146
204
  const output = options.output ?? process.stdout;
147
205
  if (!(options.isInteractive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY))) return {
148
206
  dataCache: explicitDataCache ?? "kv",
149
- cdnCache: explicitCdnCache ?? "data-cache",
207
+ cdnCache: explicitCdnCache ?? "workers-cache",
150
208
  imageOptimization: explicitImageOptimization ?? "cloudflare-images"
151
209
  };
152
210
  const readline = options.question ? void 0 : createInterface({
@@ -171,6 +229,14 @@ async function resolveCloudflareInitOptions(args, options = {}) {
171
229
  output.write(` ${error}\n`);
172
230
  }
173
231
  };
232
+ const cdnCache = await promptChoice(explicitCdnCache, " Choose a CDN cache:\n 1. Workers Cache (default)\n 2. Data cache\n CDN cache [1]: ", {
233
+ "1": "workers-cache",
234
+ "workers-cache": "workers-cache",
235
+ workers: "workers-cache",
236
+ "2": "data-cache",
237
+ "data-cache": "data-cache",
238
+ data: "data-cache"
239
+ }, "workers-cache", "Please choose Workers Cache (1) or Data cache (2).");
174
240
  return {
175
241
  dataCache: await promptChoice(explicitDataCache, " Choose a data cache:\n 1. Cloudflare KV (default)\n 2. None\n Data cache [1]: ", {
176
242
  "1": "kv",
@@ -178,7 +244,7 @@ async function resolveCloudflareInitOptions(args, options = {}) {
178
244
  "2": "none",
179
245
  none: "none"
180
246
  }, "kv", "Please choose Cloudflare KV (1) or None (2)."),
181
- cdnCache: explicitCdnCache ?? "data-cache",
247
+ cdnCache,
182
248
  imageOptimization: await promptChoice(explicitImageOptimization, " Choose image optimization:\n 1. Cloudflare Images (default)\n 2. None\n Image optimization [1]: ", {
183
249
  "1": "cloudflare-images",
184
250
  "cloudflare-images": "cloudflare-images",
@@ -192,4 +258,4 @@ async function resolveCloudflareInitOptions(args, options = {}) {
192
258
  }
193
259
  }
194
260
  //#endregion
195
- export { INIT_PLATFORMS, isAgentEnvironment, parseCdnCacheArg, parseDataCacheArg, parseImageOptimizationArg, parsePlatformArg, parsePrerenderArg, resolveCloudflareInitOptions, resolveInitPlatform, resolveInitPrerender };
261
+ export { INIT_PLATFORMS, isAgentEnvironment, parseCdnCacheArg, parseDataCacheArg, parseImageOptimizationArg, parsePlatformArg, parsePrerenderArg, parseWarmCdnCacheArg, resolveCloudflareInitOptions, resolveInitOptions, resolveInitPlatform, resolveInitPrerender, resolveInitWarmCdnCache };
package/dist/init.d.ts CHANGED
@@ -9,7 +9,8 @@ type InitOptions = {
9
9
  force?: boolean; /** Deployment target selected by the user */
10
10
  platform?: InitPlatform; /** Configure build-time pre-rendering for all discovered static routes */
11
11
  prerender?: boolean; /** Cloudflare cache and image choices. */
12
- cloudflare?: CloudflareInitOptions; /** @internal override exec for testing (avoids ESM spy issues) */
12
+ cloudflare?: CloudflareInitOptions; /** Install missing dependencies with the detected package manager (default: true). */
13
+ install?: boolean; /** @internal — override exec for testing (avoids ESM spy issues) */
13
14
  _exec?: (cmd: string, opts: {
14
15
  cwd: string;
15
16
  stdio: string;
@@ -33,7 +34,14 @@ declare function generateViteConfig(_isAppRouter: boolean, prerender?: boolean):
33
34
  * Add vinext scripts to package.json without overwriting existing scripts.
34
35
  * Returns the list of script names that were added.
35
36
  */
36
- declare function addScripts(root: string, port: number): string[];
37
+ declare function addScripts(root: string, port: number, platform?: InitPlatform, options?: {
38
+ warmCdnCache?: boolean;
39
+ }): string[];
40
+ type InitDependencyGroups = {
41
+ dependencies: string[];
42
+ devDependencies: string[];
43
+ };
44
+ declare function getInitDependencyGroups(isAppRouter: boolean, platform: InitPlatform): InitDependencyGroups;
37
45
  declare function getInitDeps(isAppRouter: boolean, platform: InitPlatform): string[];
38
46
  declare function isDepInstalled(root: string, dep: string): boolean;
39
47
  /**
@@ -44,4 +52,4 @@ declare function isDepInstalled(root: string, dep: string): boolean;
44
52
  declare function updateGitignore(root: string, platform?: InitPlatform): boolean;
45
53
  declare function init(options: InitOptions): Promise<InitResult>;
46
54
  //#endregion
47
- export { InitOptions, addScripts, generateViteConfig, getInitDeps, getReactUpgradeDeps, init, isDepInstalled, updateGitignore };
55
+ export { InitDependencyGroups, InitOptions, addScripts, generateViteConfig, getInitDependencyGroups, getInitDeps, getReactUpgradeDeps, init, isDepInstalled, updateGitignore };
package/dist/init.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { detectPackageManager, detectPackageManagerName, detectProject, ensureESModule, findViteConfigPath, hasViteConfig, renameCJSConfigs } from "./utils/project.js";
2
- import { formatReport, runCheck } from "./check.js";
3
2
  import { setupCloudflarePlatform, usesCommonJsViteConfig, validateCloudflarePlatformSetup } from "./init-cloudflare.js";
4
3
  import { getReactUpgradeDeps } from "./utils/react-version.js";
5
4
  import fs from "node:fs";
@@ -71,7 +70,7 @@ export default defineConfig({
71
70
  * Add vinext scripts to package.json without overwriting existing scripts.
72
71
  * Returns the list of script names that were added.
73
72
  */
74
- function addScripts(root, port) {
73
+ function addScripts(root, port, platform = "node", options = {}) {
75
74
  const pkgPath = path.join(root, "package.json");
76
75
  if (!fs.existsSync(pkgPath)) return [];
77
76
  try {
@@ -88,27 +87,38 @@ function addScripts(root, port) {
88
87
  added.push("build:vinext");
89
88
  }
90
89
  if (!pkg.scripts["start:vinext"]) {
91
- pkg.scripts["start:vinext"] = "vinext start";
90
+ pkg.scripts["start:vinext"] = platform === "cloudflare" ? "wrangler dev --config dist/server/wrangler.json" : "vinext start";
92
91
  added.push("start:vinext");
93
92
  }
93
+ if (platform === "cloudflare" && !pkg.scripts["deploy:vinext"]) {
94
+ pkg.scripts["deploy:vinext"] = options.warmCdnCache ? "vinext-cloudflare deploy --config dist/server/wrangler.json --experimental-warm-cdn-cache" : "vinext-cloudflare deploy --config dist/server/wrangler.json";
95
+ added.push("deploy:vinext");
96
+ }
94
97
  if (added.length > 0) fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
95
98
  return added;
96
99
  } catch {
97
100
  return [];
98
101
  }
99
102
  }
100
- function getInitDeps(isAppRouter, platform) {
101
- const deps = [
102
- "vinext",
103
- "vite",
104
- "@vitejs/plugin-react"
105
- ];
103
+ function getInitDependencyGroups(isAppRouter, platform) {
104
+ const dependencies = ["vinext"];
105
+ const devDependencies = ["vite", "@vitejs/plugin-react"];
106
106
  if (isAppRouter) {
107
- deps.push("@vitejs/plugin-rsc");
108
- deps.push("react-server-dom-webpack");
107
+ dependencies.push("react-server-dom-webpack");
108
+ devDependencies.push("@vitejs/plugin-rsc");
109
+ }
110
+ if (platform === "cloudflare") {
111
+ dependencies.push("@vinext/cloudflare");
112
+ devDependencies.push("@cloudflare/vite-plugin", "wrangler");
109
113
  }
110
- if (platform === "cloudflare") deps.push("@cloudflare/vite-plugin", "@vinext/cloudflare", "wrangler");
111
- return deps;
114
+ return {
115
+ dependencies,
116
+ devDependencies
117
+ };
118
+ }
119
+ function getInitDeps(isAppRouter, platform) {
120
+ const groups = getInitDependencyGroups(isAppRouter, platform);
121
+ return [...groups.dependencies, ...groups.devDependencies];
112
122
  }
113
123
  function isDepInstalled(root, dep) {
114
124
  const pkgPath = path.join(root, "package.json");
@@ -124,6 +134,55 @@ function isDepInstalled(root, dep) {
124
134
  return false;
125
135
  }
126
136
  }
137
+ function parseDependencySpecifier(specifier) {
138
+ if (specifier.startsWith("@")) {
139
+ const versionSeparator = specifier.indexOf("@", 1);
140
+ if (versionSeparator !== -1) return {
141
+ name: specifier.slice(0, versionSeparator),
142
+ version: specifier.slice(versionSeparator + 1),
143
+ hasExplicitVersion: true
144
+ };
145
+ return {
146
+ name: specifier,
147
+ version: "latest",
148
+ hasExplicitVersion: false
149
+ };
150
+ }
151
+ const versionSeparator = specifier.indexOf("@");
152
+ if (versionSeparator !== -1) return {
153
+ name: specifier.slice(0, versionSeparator),
154
+ version: specifier.slice(versionSeparator + 1),
155
+ hasExplicitVersion: true
156
+ };
157
+ return {
158
+ name: specifier,
159
+ version: "latest",
160
+ hasExplicitVersion: false
161
+ };
162
+ }
163
+ function addDependencyEntries(root, deps, { dev }) {
164
+ if (deps.length === 0) return [];
165
+ const pkgPath = path.join(root, "package.json");
166
+ if (!fs.existsSync(pkgPath)) return [];
167
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
168
+ const targetKey = dev ? "devDependencies" : "dependencies";
169
+ const target = pkg[targetKey] ??= {};
170
+ const added = [];
171
+ for (const dep of deps) {
172
+ const { name, version, hasExplicitVersion } = parseDependencySpecifier(dep);
173
+ const existingTarget = pkg.dependencies?.[name] !== void 0 ? pkg.dependencies : pkg.devDependencies?.[name] !== void 0 ? pkg.devDependencies : void 0;
174
+ if (existingTarget) {
175
+ if (!hasExplicitVersion || existingTarget[name] === version) continue;
176
+ existingTarget[name] = version;
177
+ added.push(name);
178
+ continue;
179
+ }
180
+ target[name] = version;
181
+ added.push(name);
182
+ }
183
+ if (added.length > 0) fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
184
+ return added;
185
+ }
127
186
  /**
128
187
  * Check if react/react-dom need upgrading for react-server-dom-webpack compatibility.
129
188
  *
@@ -260,6 +319,7 @@ async function init(options) {
260
319
  const viteConfigExists = hasViteConfig(root);
261
320
  const isApp = detectProject(root).isAppRouter;
262
321
  const pmName = detectPackageManagerName(root);
322
+ const shouldInstall = options.install ?? true;
263
323
  if (platform === "cloudflare") validateCloudflarePlatformSetup({
264
324
  root,
265
325
  isAppRouter: isApp,
@@ -269,6 +329,7 @@ async function init(options) {
269
329
  }, options.cloudflare);
270
330
  if (!options.skipCheck) {
271
331
  console.log(" Running compatibility check...\n");
332
+ const { runCheck, formatReport } = await import("./check.js");
272
333
  const checkResult = runCheck(root);
273
334
  console.log(formatReport(checkResult, { calledFromInit: true }));
274
335
  console.log();
@@ -281,7 +342,7 @@ async function init(options) {
281
342
  existingViteConfigPath = renamedPath;
282
343
  }
283
344
  const addedTypeModule = ensureESModule(root);
284
- const addedScripts = addScripts(root, port);
345
+ const addedScripts = addScripts(root, port, platform, { warmCdnCache: options.cloudflare?.warmCdnCache ?? false });
285
346
  const setupContext = {
286
347
  root,
287
348
  isAppRouter: isApp,
@@ -294,41 +355,76 @@ async function init(options) {
294
355
  const platformSetup = platform === "cloudflare" ? setupCloudflarePlatform(setupContext, options.cloudflare) : setupNodePlatform(setupContext);
295
356
  const { generatedViteConfig, skippedViteConfig, generatedPlatformFiles } = platformSetup;
296
357
  const updatedGitignore = updateGitignore(root, platform);
297
- const missingDeps = getInitDeps(isApp, platform).filter((dep) => !isDepInstalled(root, dep));
358
+ const neededDeps = getInitDependencyGroups(isApp, platform);
359
+ const missingDependencies = neededDeps.dependencies.filter((dep) => !isDepInstalled(root, dep));
360
+ const missingDevDependencies = neededDeps.devDependencies.filter((dep) => !isDepInstalled(root, dep));
298
361
  let dependencyInstallNeedsApproval = false;
299
- let dependenciesAdded = false;
300
- if (isApp && missingDeps.includes("react-server-dom-webpack")) {
362
+ const dependencyEntriesAdded = [];
363
+ const devDependencyEntriesAdded = [];
364
+ if (isApp && missingDependencies.includes("react-server-dom-webpack")) {
301
365
  const reactUpgrade = getReactUpgradeDeps(root);
302
366
  if (reactUpgrade.length > 0) {
303
367
  console.log(` ${terminalStyle.cyan(terminalStyle.bold("Upgrading dependencies:"))}`);
304
368
  console.log(formatList(reactUpgrade.map((dep) => dep.replace(/@latest$/, "")), " "));
305
369
  try {
306
- if (isApproveBuildsError(await installDeps(root, reactUpgrade, exec, { dev: false }))) dependencyInstallNeedsApproval = true;
370
+ if (shouldInstall) {
371
+ if (isApproveBuildsError(await installDeps(root, reactUpgrade, exec, { dev: false }))) dependencyInstallNeedsApproval = true;
372
+ } else {
373
+ const added = addDependencyEntries(root, reactUpgrade, { dev: false });
374
+ dependencyEntriesAdded.push(...added);
375
+ }
307
376
  } catch (error) {
308
377
  if (pmName !== "pnpm" || !isApproveBuildsError(error)) throw error;
309
378
  dependencyInstallNeedsApproval = true;
310
379
  }
311
380
  }
312
381
  }
313
- if (missingDeps.length > 0) {
382
+ if (missingDependencies.length > 0) {
314
383
  console.log(` ${terminalStyle.cyan(terminalStyle.bold("Installing dependencies:"))}`);
315
- console.log(formatList(missingDeps, " "));
384
+ console.log(formatList(missingDependencies, " "));
316
385
  try {
317
- const installOutput = await installDeps(root, missingDeps, exec);
318
- dependenciesAdded = true;
319
- if (isApproveBuildsError(installOutput)) dependencyInstallNeedsApproval = true;
386
+ if (shouldInstall) {
387
+ const installOutput = await installDeps(root, missingDependencies, exec, { dev: false });
388
+ dependencyEntriesAdded.push(...missingDependencies);
389
+ if (isApproveBuildsError(installOutput)) dependencyInstallNeedsApproval = true;
390
+ } else {
391
+ const added = addDependencyEntries(root, missingDependencies, { dev: false });
392
+ dependencyEntriesAdded.push(...added);
393
+ }
320
394
  } catch (error) {
321
395
  if (pmName !== "pnpm" || !isApproveBuildsError(error)) throw error;
322
396
  dependencyInstallNeedsApproval = true;
323
397
  }
324
398
  console.log();
325
399
  }
326
- if (pmName === "pnpm" && !dependencyInstallNeedsApproval && !options._exec && hasAutomaticallyIgnoredBuilds(inspectPnpmIgnoredBuilds(root))) dependencyInstallNeedsApproval = true;
327
- else if (pmName === "pnpm" && !dependencyInstallNeedsApproval && options._inspectPnpmIgnoredBuilds && hasAutomaticallyIgnoredBuilds(options._inspectPnpmIgnoredBuilds(root))) dependencyInstallNeedsApproval = true;
400
+ if (missingDevDependencies.length > 0) {
401
+ console.log(` ${terminalStyle.cyan(terminalStyle.bold("Installing devDependencies:"))}`);
402
+ console.log(formatList(missingDevDependencies, " "));
403
+ try {
404
+ if (shouldInstall) {
405
+ const installOutput = await installDeps(root, missingDevDependencies, exec);
406
+ devDependencyEntriesAdded.push(...missingDevDependencies);
407
+ if (isApproveBuildsError(installOutput)) dependencyInstallNeedsApproval = true;
408
+ } else {
409
+ const added = addDependencyEntries(root, missingDevDependencies, { dev: true });
410
+ devDependencyEntriesAdded.push(...added);
411
+ }
412
+ } catch (error) {
413
+ if (pmName !== "pnpm" || !isApproveBuildsError(error)) throw error;
414
+ dependencyInstallNeedsApproval = true;
415
+ }
416
+ console.log();
417
+ }
418
+ if (pmName === "pnpm" && shouldInstall && !dependencyInstallNeedsApproval && !options._exec && hasAutomaticallyIgnoredBuilds(inspectPnpmIgnoredBuilds(root))) dependencyInstallNeedsApproval = true;
419
+ else if (pmName === "pnpm" && shouldInstall && !dependencyInstallNeedsApproval && options._inspectPnpmIgnoredBuilds && hasAutomaticallyIgnoredBuilds(options._inspectPnpmIgnoredBuilds(root))) dependencyInstallNeedsApproval = true;
328
420
  console.log(` ${terminalStyle.green(terminalStyle.bold("vinext init complete!"))}\n`);
329
- if (dependenciesAdded) {
421
+ if (dependencyEntriesAdded.length > 0) {
422
+ console.log(` ${terminalStyle.green("✓")} Added dependencies to dependencies:`);
423
+ console.log(formatList(dependencyEntriesAdded, " "));
424
+ }
425
+ if (devDependencyEntriesAdded.length > 0) {
330
426
  console.log(` ${terminalStyle.green("✓")} Added dependencies to devDependencies:`);
331
- console.log(formatList(missingDeps, " "));
427
+ console.log(formatList(devDependencyEntriesAdded, " "));
332
428
  }
333
429
  if (dependencyInstallNeedsApproval) console.log(` ${terminalStyle.yellow("!")} Dependency installation is waiting for build-script approval`);
334
430
  if (addedTypeModule) console.log(` ${terminalStyle.green("✓")} Added "type": "module" to package.json`);
@@ -340,16 +436,18 @@ async function init(options) {
340
436
  if (updatedGitignore) console.log(` ${terminalStyle.green("✓")} Added vinext output directories to .gitignore`);
341
437
  const nextSteps = [...platformSetup.nextSteps];
342
438
  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");
439
+ const deployCommandStep = platform === "cloudflare" ? ` ${pmName} run deploy:vinext Deploy to Cloudflare Workers\n` : "";
440
+ const startCommandDescription = platform === "cloudflare" ? "Start the built Worker locally with Wrangler" : "Start vinext production server";
343
441
  console.log(`
344
442
  ${terminalStyle.cyan(terminalStyle.bold("Next steps:"))}
345
443
  ${nextSteps.map((step) => ` ${step}`).join("\n")}${nextSteps.length > 0 ? "\n" : ""}
346
444
  ${pmName} run dev:vinext Start the vinext dev server
347
445
  ${pmName} run build:vinext Build production output
348
- ${pmName} run start:vinext Start vinext production server
349
- ${pmName} run dev Start Next.js (still works as before)
446
+ ${pmName} run start:vinext ${startCommandDescription}
447
+ ${deployCommandStep} ${pmName} run dev Start Next.js (still works as before)
350
448
  `);
351
449
  return {
352
- installedDeps: dependenciesAdded ? missingDeps : [],
450
+ installedDeps: [...new Set([...dependencyEntriesAdded, ...devDependencyEntriesAdded])],
353
451
  addedTypeModule,
354
452
  renamedConfigs,
355
453
  addedScripts,
@@ -361,4 +459,4 @@ ${nextSteps.map((step) => ` ${step}`).join("\n")}${nextSteps.length > 0 ? "\n
361
459
  };
362
460
  }
363
461
  //#endregion
364
- export { addScripts, generateViteConfig, getInitDeps, getReactUpgradeDeps, init, isDepInstalled, updateGitignore };
462
+ export { addScripts, generateViteConfig, getInitDependencyGroups, getInitDeps, getReactUpgradeDeps, init, isDepInstalled, updateGitignore };
@@ -1,6 +1,5 @@
1
1
  import { VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RSC_REDIRECT_HEADER } from "./headers.js";
2
2
  import { AppElementsWire } from "./app-elements-wire.js";
3
- import { APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI } from "./app-rsc-render-mode.js";
4
3
  import { getMountedSlotIdsHeader, resolveVisitedResponseInterceptionContext } from "./app-elements.js";
5
4
  import { AppRouterContext } from "../shims/internal/app-router-context.js";
6
5
  import { installWindowNext, setWindowNextInternalSourcePage } from "../client/window-next.js";
@@ -17,6 +16,9 @@ import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscR
17
16
  import { getNavigationRuntime, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
18
17
  import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
19
18
  import "../client/instrumentation-client.js";
19
+ import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
20
+ import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, resolveServerActionOperationLane } from "./app-browser-action-result.js";
21
+ import { createClientReuseManifestHeaderFromVisibleAppState } from "./app-browser-client-reuse-manifest.js";
20
22
  import { resolveManifestNavigationInterceptionContext, resolveMiddlewareRewriteNavigationInterceptionContext } from "./app-browser-interception-context.js";
21
23
  import { readHistoryStatePreviousNextUrl } from "./app-history-state.js";
22
24
  import { AppBrowserMpaNavigationScheduler } from "./app-browser-mpa-navigation.js";
@@ -24,9 +26,6 @@ import { blockDangerousStreamedRscRedirect } from "./app-browser-rsc-redirect.js
24
26
  import { navigationPlanner } from "./navigation-planner.js";
25
27
  import { resolveHybridClientRewriteHref } from "../shims/internal/hybrid-client-route-owner.js";
26
28
  import { DYNAMIC_NAVIGATION_CACHE_TTL, PREFETCH_CACHE_TTL, __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, deletePrefetchResponseSnapshot, getClientNavigationRenderContext, getMountedSlotsHeader, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setPendingPathname, useRouter } from "../shims/navigation.js";
27
- import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
28
- import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, resolveServerActionOperationLane } from "./app-browser-action-result.js";
29
- import { createClientReuseManifestHeaderFromVisibleAppState } from "./app-browser-client-reuse-manifest.js";
30
29
  import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
31
30
  import { COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, isCacheRestorableAppPayloadMetadata, isCompleteAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl } from "./app-browser-state.js";
32
31
  import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch } from "./app-browser-navigation-controller.js";
@@ -888,8 +887,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
888
887
  const shouldBypassNavigationCache = earlyIntentDecision?.kind === "flightNavigation" && earlyIntentDecision.bypassNavigationCache;
889
888
  const requestHeaders = createRscRequestHeaders({
890
889
  interceptionContext: requestInterceptionContext,
891
- mountedSlotsHeader,
892
- renderMode: navigationKind === "refresh" ? APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI : void 0
890
+ mountedSlotsHeader
893
891
  });
894
892
  const rscUrl = await createRscRequestUrl(url.pathname + url.search, requestHeaders);
895
893
  const rewrittenNavigationHref = navigationKind === "navigate" ? resolveHybridClientRewriteHref(currentHref, __basePath) : null;
@@ -1,8 +1,8 @@
1
1
  import { stripBasePath } from "../utils/base-path.js";
2
2
  import { clearAppNavigationFailureTarget, getAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
3
3
  import { claimAppRouterScrollIntentForCommit, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
4
- import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
5
4
  import { resolveServerActionOperationLane, shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
5
+ import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
6
6
  import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, createPendingNavigationCommit } from "./app-browser-state.js";
7
7
  import { applyApprovedVisibleCommit, approveHmrVisibleCommit, approvePendingNavigationCommit, resolveAndClassifyNavigationCommit } from "./app-browser-visible-commit.js";
8
8
  import { startTransition, useInsertionEffect, useLayoutEffect } from "react";
@@ -449,8 +449,11 @@ function createAppBrowserNavigationController(deps = {}) {
449
449
  return;
450
450
  }
451
451
  if (latestApproval.approvedCommit) {
452
- dispatchSynchronousVisibleCommit(latestApproval.approvedCommit);
453
- syncHistoryStatePreviousNextUrl(latestApproval.approvedCommit.previousNextUrl, latestApproval.approvedCommit.action.bfcacheIds);
452
+ const approvedRevalidationCommit = latestApproval.approvedCommit;
453
+ startTransition(() => {
454
+ dispatchSynchronousVisibleCommit(approvedRevalidationCommit);
455
+ });
456
+ syncHistoryStatePreviousNextUrl(approvedRevalidationCommit.previousNextUrl, approvedRevalidationCommit.action.bfcacheIds);
454
457
  } else notifyDiscardedServerActionRevalidation(lifecycleOptions);
455
458
  } else if (decision.disposition === "no-commit") notifyDiscardedServerActionRevalidation(lifecycleOptions);
456
459
  if (returnValue) {
@@ -6,12 +6,12 @@ import { AppElementsWire } from "./app-elements-wire.js";
6
6
  import { getMountedSlotIds, getMountedSlotIdsHeader } from "./app-elements.js";
7
7
  import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
8
8
  import { createCacheEntryReuseProof } from "./cache-proof.js";
9
+ import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
9
10
  import { createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
10
11
  import { NavigationTraceReasonCodes, createNavigationLifecycleTraceFields, createNavigationTrace } from "./navigation-trace.js";
11
12
  import { verifyOperationTokenForCommit } from "./operation-token.js";
12
13
  import { navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts } from "./navigation-planner.js";
13
14
  import { createSnapshotPathAndSearch } from "../shims/navigation.js";
14
- import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
15
15
  //#region src/server/app-browser-state.ts
16
16
  const COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "committed-cache" };
17
17
  const FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "fresh" };
@@ -1,8 +1,8 @@
1
1
  import { normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
2
2
  import "./app-elements.js";
3
3
  import { mergeElements } from "../shims/slot.js";
4
- import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
5
4
  import { preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
5
+ import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
6
6
  import { createPendingNavigationCommit, resolvePendingNavigationCommitDispositionDecision } from "./app-browser-state.js";
7
7
  //#region src/server/app-browser-visible-commit.ts
8
8
  const approvedVisibleCommitBrand = Symbol("ApprovedVisibleCommit");
@@ -1,7 +1,7 @@
1
- import { UnstableCacheObservation } from "../shims/cache-request-state.js";
2
1
  import { RenderRequestApiKind } from "./cache-proof.js";
3
2
  import { ClientReuseManifestRejectionCode, ClientReuseManifestTraceFields } from "./client-reuse-manifest.js";
4
3
  import { ThenableParamsObserver } from "../shims/thenable-params.js";
4
+ import { UnstableCacheObservation } from "../shims/cache-request-state.js";
5
5
 
6
6
  //#region src/server/app-layout-param-observation.d.ts
7
7
  type AppLayoutParamAccessObservation = Readonly<{
@@ -1,8 +1,8 @@
1
- import { CacheControlMetadata } from "../shims/cache-handler.js";
2
1
  import { NavigationContext } from "../shims/navigation-context-state.js";
3
2
  import { AppPageFontPreload } from "./app-page-execution.js";
4
3
  import { RootParams } from "../shims/root-params.js";
5
4
  import { AppPageSsrHandler } from "./app-page-stream.js";
5
+ import { CacheControlMetadata } from "../shims/cache-handler.js";
6
6
  import { createAppPageRenderObservation } from "./app-page-render-observation.js";
7
7
  import { ReactNode } from "react";
8
8
 
@@ -1,5 +1,4 @@
1
1
  import { ClassificationReason } from "../build/layout-classification-types.js";
2
- import { CachedAppPageValue } from "../shims/cache-handler.js";
3
2
  import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
4
3
  import { AppOutgoingElements } from "./app-elements-wire.js";
5
4
  import { NavigationContext } from "../shims/navigation-context-state.js";
@@ -8,6 +7,7 @@ import { AppPageMiddlewareContext } from "./app-page-response.js";
8
7
  import { RootParams } from "../shims/root-params.js";
9
8
  import { AppPageSsrHandler } from "./app-page-stream.js";
10
9
  import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
10
+ import { CachedAppPageValue } from "../shims/cache-handler.js";
11
11
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
12
12
  import { ISRCacheEntry } from "./isr-cache.js";
13
13
  import { PprFallbackShellState } from "../shims/ppr-fallback-shell.js";