@vistagenic/vista 0.3.2 → 0.3.4

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 (118) hide show
  1. package/bin/vista.js +79 -109
  2. package/dist/ai/embeddings.d.ts +11 -11
  3. package/dist/ai/embeddings.js +71 -71
  4. package/dist/ai/index.d.ts +10 -10
  5. package/dist/ai/index.js +26 -26
  6. package/dist/ai/providers/base.js +85 -85
  7. package/dist/ai/react/react-server.d.ts +1 -1
  8. package/dist/ai/react/react-server.js +17 -17
  9. package/dist/ai/react/use-agent.js +138 -138
  10. package/dist/auth/core.d.ts +140 -140
  11. package/dist/auth/core.js +165 -165
  12. package/dist/auth/index.d.ts +20 -20
  13. package/dist/auth/index.js +369 -369
  14. package/dist/auth/react-server.d.ts +1 -1
  15. package/dist/auth/react-server.js +10 -10
  16. package/dist/auth/react.d.ts +18 -18
  17. package/dist/auth/react.js +71 -71
  18. package/dist/bin/build-rsc-flashpack.js +6 -0
  19. package/dist/bin/build-rsc.js +555 -492
  20. package/dist/bin/build.js +365 -353
  21. package/dist/bin/generate.js +513 -510
  22. package/dist/bin/webpack.config.d.ts +3 -1
  23. package/dist/bin/webpack.config.js +7 -4
  24. package/dist/build/manifest.d.ts +169 -169
  25. package/dist/build/manifest.js +423 -423
  26. package/dist/build/rsc/client-manifest.d.ts +62 -62
  27. package/dist/build/rsc/client-manifest.js +295 -295
  28. package/dist/build/rsc/compiler.d.ts +3 -1
  29. package/dist/build/rsc/compiler.js +12 -7
  30. package/dist/build/rsc/native-scanner.d.ts +135 -135
  31. package/dist/build/rsc/native-scanner.js +203 -203
  32. package/dist/build/rsc/react-client-reference-manifest.d.ts +35 -28
  33. package/dist/build/rsc/react-client-reference-manifest.js +366 -240
  34. package/dist/build/standalone.js +260 -254
  35. package/dist/client/dynamic.react-server.d.ts +2 -2
  36. package/dist/client/dynamic.react-server.js +23 -23
  37. package/dist/client/link.js +1 -1
  38. package/dist/client/link.react-server.d.ts +2 -2
  39. package/dist/client/link.react-server.js +11 -11
  40. package/dist/client/navigation.js +2 -2
  41. package/dist/client/navigation.react-server.d.ts +1 -1
  42. package/dist/client/navigation.react-server.js +17 -17
  43. package/dist/client/router.react-server.d.ts +1 -1
  44. package/dist/client/router.react-server.js +17 -17
  45. package/dist/client/rsc-router.d.ts +1 -3
  46. package/dist/client/rsc-router.js +98 -45
  47. package/dist/client/rsc-router.react-server.d.ts +1 -1
  48. package/dist/client/rsc-router.react-server.js +17 -17
  49. package/dist/client/script.react-server.d.ts +2 -2
  50. package/dist/client/script.react-server.js +23 -23
  51. package/dist/config.d.ts +1 -1
  52. package/dist/config.js +1 -7
  53. package/dist/deploy/adapters/cloudflare.js +42 -41
  54. package/dist/deploy/adapters/docker.d.ts +1 -0
  55. package/dist/deploy/adapters/docker.js +5 -4
  56. package/dist/deploy/adapters/netlify.js +60 -27
  57. package/dist/deploy/adapters/vercel.js +80 -50
  58. package/dist/deploy/preflight.js +4 -3
  59. package/dist/deploy/runtime-pack.d.ts +11 -0
  60. package/dist/deploy/runtime-pack.js +300 -0
  61. package/dist/deploy/utils.d.ts +7 -1
  62. package/dist/deploy/utils.js +95 -3
  63. package/dist/flashpack/command.js +1 -0
  64. package/dist/flashpack/runtime.js +2 -1
  65. package/dist/image/get-img-props.js +21 -11
  66. package/dist/image/image-config.d.ts +2 -0
  67. package/dist/image/image-config.js +17 -0
  68. package/dist/image/index.d.ts +18 -3
  69. package/dist/image/index.js +1 -1
  70. package/dist/image/react-server.d.ts +1 -2
  71. package/dist/image/react-server.js +1 -1
  72. package/dist/index.d.ts +23 -23
  73. package/dist/index.js +61 -61
  74. package/dist/server/app-dir.d.ts +22 -0
  75. package/dist/server/app-dir.js +77 -0
  76. package/dist/server/app-router-runtime.d.ts +1 -0
  77. package/dist/server/app-router-runtime.js +34 -9
  78. package/dist/server/cookie-parse.d.ts +4 -4
  79. package/dist/server/cookie-parse.js +14 -14
  80. package/dist/server/engine.js +5 -5
  81. package/dist/server/hydration-chunks.d.ts +7 -0
  82. package/dist/server/hydration-chunks.js +49 -0
  83. package/dist/server/image-optimizer.js +2 -1
  84. package/dist/server/index.d.ts +109 -109
  85. package/dist/server/index.js +315 -315
  86. package/dist/server/middleware-runner.d.ts +125 -125
  87. package/dist/server/middleware-runner.js +607 -615
  88. package/dist/server/middleware-security.d.ts +36 -36
  89. package/dist/server/middleware-security.js +183 -183
  90. package/dist/server/module-compile-hook.js +706 -695
  91. package/dist/server/root-resolver.js +6 -5
  92. package/dist/server/rsc-engine-flashpack.d.ts +3 -1
  93. package/dist/server/rsc-engine-flashpack.js +12 -1
  94. package/dist/server/rsc-engine.d.ts +6 -1
  95. package/dist/server/rsc-engine.js +217 -280
  96. package/dist/server/rsc-upstream.js +900 -892
  97. package/dist/server/ssr-webpack-shim.d.ts +6 -0
  98. package/dist/server/ssr-webpack-shim.js +29 -0
  99. package/dist/server/static-generator.d.ts +2 -0
  100. package/dist/server/static-generator.js +33 -32
  101. package/dist/server/structure-validator.js +2 -1
  102. package/dist/server/structure-watch.js +2 -0
  103. package/dist/server/typed-api-runtime.js +639 -635
  104. package/dist/server/vista-import-map.js +134 -134
  105. package/dist/stack/index.d.ts +34 -34
  106. package/dist/stack/index.js +49 -49
  107. package/dist/stack/server/caller.d.ts +13 -13
  108. package/dist/stack/server/caller.js +42 -42
  109. package/dist/stack/server/executor.d.ts +40 -40
  110. package/dist/stack/server/executor.js +222 -222
  111. package/dist/stack/server/index.d.ts +11 -11
  112. package/dist/stack/server/index.js +24 -24
  113. package/dist/stack/server/procedure.d.ts +20 -20
  114. package/dist/stack/server/procedure.js +66 -66
  115. package/dist/stack/server/types.d.ts +113 -113
  116. package/dist/theme/react-server.d.ts +10 -10
  117. package/dist/theme/react-server.js +16 -16
  118. package/package.json +1 -1
@@ -8,12 +8,13 @@ const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const cli_runner_1 = require("../cli-runner");
10
10
  const preflight_1 = require("../preflight");
11
+ const runtime_pack_1 = require("../runtime-pack");
11
12
  const utils_1 = require("../utils");
12
13
  const NETLIFY_OUTPUT_DIR = '.vista/deploy/netlify';
13
14
  function getNetlifyOutputDir(ctx) {
14
15
  return path_1.default.join(ctx.cwd, NETLIFY_OUTPUT_DIR);
15
16
  }
16
- function writeNetlifyToml(ctx) {
17
+ function writeStaticNetlifyToml(ctx) {
17
18
  const targetFile = path_1.default.join(ctx.cwd, 'netlify.toml');
18
19
  const content = `[build]
19
20
  command = "npm run build"
@@ -26,38 +27,74 @@ function writeNetlifyToml(ctx) {
26
27
  (0, utils_1.writeFileIfAllowed)(targetFile, content, ctx.force);
27
28
  return targetFile;
28
29
  }
29
- function writeRedirects(outputDir) {
30
- const redirectsPath = path_1.default.join(outputDir, '_redirects');
31
- const lines = [
32
- '/_vista/* /:splat 200',
33
- '/ /static/pages/index.html 200',
34
- '/rsc /static/pages/index.rsc 200',
35
- '/_rsc/* /static/pages/:splat.rsc 200',
36
- '/* /static/pages/:splat.html 200',
37
- ];
38
- fs_1.default.writeFileSync(redirectsPath, `${lines.join('\n')}\n`, 'utf8');
39
- return redirectsPath;
30
+ function writeFullRuntimeNetlifyToml(ctx) {
31
+ const targetFile = path_1.default.join(ctx.cwd, 'netlify.toml');
32
+ const content = `[build]
33
+ command = "npm run build"
34
+ publish = ".vista/deploy/netlify"
35
+ functions = "netlify/functions"
36
+
37
+ [functions]
38
+ node_bundler = "none"
39
+ included_files = ["netlify/functions/.vista/**", "netlify/functions/node_modules/**"]
40
+
41
+ [dev]
42
+ command = "npm run dev"
43
+ port = 3003
44
+
45
+ [[redirects]]
46
+ from = "/_vista/*"
47
+ to = "/_vista/:splat"
48
+ status = 200
49
+
50
+ [[redirects]]
51
+ from = "/*"
52
+ to = "/.netlify/functions/ssr"
53
+ status = 200
54
+ `;
55
+ (0, utils_1.writeFileIfAllowed)(targetFile, content, ctx.force);
56
+ return targetFile;
40
57
  }
41
58
  exports.netlifyAdapter = {
42
59
  id: 'netlify',
43
- requiredOutput: 'static',
44
- supportsFullRuntime: false,
60
+ requiredOutput: 'standalone',
61
+ supportsFullRuntime: true,
45
62
  async preflight(ctx) {
46
- return (0, preflight_1.runStaticHostPreflight)(ctx);
63
+ if ((0, runtime_pack_1.isStaticOnlyDeploy)(ctx)) {
64
+ return (0, preflight_1.runStaticHostPreflight)(ctx);
65
+ }
66
+ return (0, preflight_1.runStandalonePreflight)(ctx);
47
67
  },
48
68
  async emit(ctx) {
49
69
  const outputDir = getNetlifyOutputDir(ctx);
50
70
  fs_1.default.rmSync(outputDir, { recursive: true, force: true });
51
71
  (0, utils_1.ensureDir)(outputDir);
72
+ if ((0, runtime_pack_1.isStaticOnlyDeploy)(ctx)) {
73
+ (0, utils_1.copyStaticHostAssets)(ctx.cwd, ctx.vistaDir, outputDir);
74
+ (0, utils_1.prepareStaticCdnOutput)(outputDir);
75
+ const netlifyTomlPath = writeStaticNetlifyToml(ctx);
76
+ return {
77
+ status: 'emitted',
78
+ target: 'netlify',
79
+ artifactPaths: [outputDir, netlifyTomlPath],
80
+ instructions: ['Static mode: Netlify serves pre-rendered pages only.'],
81
+ };
82
+ }
52
83
  (0, utils_1.copyStaticHostAssets)(ctx.cwd, ctx.vistaDir, outputDir);
53
- const redirectsPath = writeRedirects(outputDir);
54
- const netlifyTomlPath = writeNetlifyToml(ctx);
84
+ (0, utils_1.copyDirectoryRecursive)(path_1.default.join(ctx.vistaDir, 'static'), path_1.default.join(outputDir, '_vista', 'static'));
85
+ const functionDir = path_1.default.join(ctx.cwd, 'netlify', 'functions');
86
+ fs_1.default.rmSync(functionDir, { recursive: true, force: true });
87
+ (0, runtime_pack_1.writeNetlifySsrHandler)(functionDir);
88
+ (0, utils_1.copyDirectoryRecursive)(ctx.vistaDir, path_1.default.join(functionDir, '.vista'));
89
+ (0, runtime_pack_1.packRuntimeNodeModules)(ctx.cwd, functionDir);
90
+ const netlifyTomlPath = writeFullRuntimeNetlifyToml(ctx);
55
91
  return {
56
92
  status: 'emitted',
57
93
  target: 'netlify',
58
- artifactPaths: [outputDir, redirectsPath, netlifyTomlPath],
94
+ artifactPaths: [outputDir, functionDir, netlifyTomlPath],
59
95
  instructions: [
60
- 'Netlify deploy uses pre-rendered static output from .vista/deploy/netlify.',
96
+ 'Netlify Functions run the Vista Flight SSR server.',
97
+ 'Deploy with: netlify deploy --prod --dir=".vista/deploy/netlify" --functions="netlify/functions"',
61
98
  ],
62
99
  };
63
100
  },
@@ -75,7 +112,6 @@ exports.netlifyAdapter = {
75
112
  warnings: [...warnings, ...errors],
76
113
  };
77
114
  }
78
- const outputDir = getNetlifyOutputDir(ctx);
79
115
  if (!(0, cli_runner_1.isCliAvailable)('netlify')) {
80
116
  return {
81
117
  status: 'emitted',
@@ -84,13 +120,13 @@ exports.netlifyAdapter = {
84
120
  warnings: [...warnings, 'Netlify CLI not found. Install with: npm i -g netlify-cli'],
85
121
  instructions: [
86
122
  'Install Netlify CLI: npm i -g netlify-cli',
87
- `Then run: netlify deploy --prod --dir="${outputDir}"`,
123
+ 'Then run: netlify deploy --prod --dir=".vista/deploy/netlify" --functions="netlify/functions"',
88
124
  ],
89
125
  };
90
126
  }
91
127
  const command = ctx.prod
92
- ? `netlify deploy --prod --dir="${outputDir}"`
93
- : `netlify deploy --dir="${outputDir}"`;
128
+ ? 'netlify deploy --prod --dir=".vista/deploy/netlify" --functions="netlify/functions"'
129
+ : 'netlify deploy --dir=".vista/deploy/netlify" --functions="netlify/functions"';
94
130
  const result = (0, cli_runner_1.runCliCommand)(command, { cwd: ctx.cwd, dryRun: ctx.dryRun });
95
131
  if (!result.ok) {
96
132
  return {
@@ -98,10 +134,7 @@ exports.netlifyAdapter = {
98
134
  target: 'netlify',
99
135
  artifactPaths: emitted.artifactPaths,
100
136
  warnings: [...warnings, result.stderr || 'Netlify deploy failed.'],
101
- instructions: [
102
- 'Run: netlify login',
103
- 'Or set NETLIFY_AUTH_TOKEN in your environment.',
104
- ],
137
+ instructions: ['Run: netlify login', 'Or set NETLIFY_AUTH_TOKEN.'],
105
138
  };
106
139
  }
107
140
  return {
@@ -11,6 +11,7 @@ const fs_1 = __importDefault(require("fs"));
11
11
  const path_1 = __importDefault(require("path"));
12
12
  const cli_runner_1 = require("../cli-runner");
13
13
  const preflight_1 = require("../preflight");
14
+ const runtime_pack_1 = require("../runtime-pack");
14
15
  const utils_1 = require("../utils");
15
16
  function isVercelBuildEnvironment() {
16
17
  return process.env.VERCEL === '1' || process.env.NOW_REGION !== undefined;
@@ -23,81 +24,114 @@ function writeVercelBuildOutput(options) {
23
24
  if (!force && !isVercelBuildEnvironment()) {
24
25
  return false;
25
26
  }
26
- if (!force && hasUserVercelConfig(cwd)) {
27
- if (debug) {
28
- console.log('[vista:deploy] Found custom vercel.json, skipping internal Vercel output.');
27
+ const standaloneServer = path_1.default.join(vistaDir, 'standalone', 'server.js');
28
+ const staticOnly = !fs_1.default.existsSync(standaloneServer);
29
+ if (staticOnly) {
30
+ if (!force && hasUserVercelConfig(cwd)) {
31
+ if (debug) {
32
+ console.log('[vista:deploy] Found custom vercel.json, skipping internal Vercel output.');
33
+ }
34
+ return false;
29
35
  }
30
- return false;
36
+ const vercelOutputDir = path_1.default.join(cwd, '.vercel', 'output');
37
+ const vercelStaticDir = path_1.default.join(vercelOutputDir, 'static');
38
+ fs_1.default.rmSync(vercelOutputDir, { recursive: true, force: true });
39
+ (0, utils_1.ensureDir)(vercelStaticDir);
40
+ (0, utils_1.copyStaticHostAssets)(cwd, vistaDir, vercelStaticDir);
41
+ fs_1.default.writeFileSync(path_1.default.join(vercelOutputDir, 'config.json'), JSON.stringify({ version: 3, routes: utils_1.STATIC_HOST_ROUTE_RULES }, null, 2));
42
+ return true;
31
43
  }
32
- const vercelOutputDir = path_1.default.join(cwd, '.vercel', 'output');
33
- const vercelStaticDir = path_1.default.join(vercelOutputDir, 'static');
34
- fs_1.default.rmSync(vercelOutputDir, { recursive: true, force: true });
35
- (0, utils_1.ensureDir)(vercelStaticDir);
36
- (0, utils_1.copyStaticHostAssets)(cwd, vistaDir, vercelStaticDir);
37
- const config = {
38
- version: 3,
39
- routes: utils_1.STATIC_HOST_ROUTE_RULES,
40
- };
41
- fs_1.default.writeFileSync(path_1.default.join(vercelOutputDir, 'config.json'), JSON.stringify(config, null, 2));
44
+ (0, runtime_pack_1.packVercelFullRuntime)({
45
+ cwd,
46
+ vistaDir,
47
+ config: {},
48
+ deployConfig: {
49
+ target: 'vercel',
50
+ output: 'standalone',
51
+ prod: true,
52
+ preferBuildOutputApi: true,
53
+ },
54
+ target: 'vercel',
55
+ dryRun: true,
56
+ skipBuild: true,
57
+ prod: true,
58
+ preview: false,
59
+ force: true,
60
+ debug,
61
+ });
42
62
  if (debug) {
43
- console.log('[vista:deploy] Generated internal Vercel Build Output at .vercel/output/');
63
+ console.log('[vista:deploy] Generated Vercel Node SSR output at .vercel/output/');
44
64
  }
45
65
  return true;
46
66
  }
47
- function writeLegacyVercelJson(ctx) {
67
+ function writeVercelJson(ctx, fullRuntime) {
48
68
  const targetFile = path_1.default.join(ctx.cwd, 'vercel.json');
49
- const payload = {
50
- version: 2,
51
- buildCommand: 'npm run build',
52
- outputDirectory: '.vista',
53
- framework: null,
54
- installCommand: 'npm install --legacy-peer-deps --no-audit --no-fund',
55
- devCommand: 'npm run dev',
56
- routes: utils_1.STATIC_HOST_ROUTE_RULES,
57
- };
69
+ const payload = fullRuntime
70
+ ? {
71
+ version: 2,
72
+ buildCommand: 'npm run build',
73
+ installCommand: 'npm install --legacy-peer-deps --no-audit --no-fund',
74
+ framework: null,
75
+ }
76
+ : {
77
+ version: 2,
78
+ buildCommand: 'npm run build',
79
+ outputDirectory: '.vista',
80
+ framework: null,
81
+ installCommand: 'npm install --legacy-peer-deps --no-audit --no-fund',
82
+ devCommand: 'npm run dev',
83
+ routes: utils_1.STATIC_HOST_ROUTE_RULES,
84
+ };
58
85
  const result = (0, utils_1.writeFileIfAllowed)(targetFile, `${JSON.stringify(payload, null, 2)}\n`, ctx.force);
59
86
  return result.written || result.skipped ? targetFile : null;
60
87
  }
61
88
  exports.vercelAdapter = {
62
89
  id: 'vercel',
63
- requiredOutput: 'static',
64
- supportsFullRuntime: false,
90
+ requiredOutput: 'standalone',
91
+ supportsFullRuntime: true,
65
92
  async preflight(ctx) {
66
- return (0, preflight_1.runStaticHostPreflight)(ctx);
93
+ if ((0, runtime_pack_1.isStaticOnlyDeploy)(ctx)) {
94
+ return (0, preflight_1.runStaticHostPreflight)(ctx);
95
+ }
96
+ return (0, preflight_1.runStandalonePreflight)(ctx);
67
97
  },
68
98
  async emit(ctx) {
69
99
  const artifactPaths = [];
70
100
  const warnings = [];
71
- if (ctx.deployConfig.preferBuildOutputApi) {
101
+ const staticOnly = (0, runtime_pack_1.isStaticOnlyDeploy)(ctx);
102
+ if (staticOnly) {
72
103
  const wrote = writeVercelBuildOutput({
73
104
  cwd: ctx.cwd,
74
105
  vistaDir: ctx.vistaDir,
75
106
  debug: ctx.debug,
76
107
  force: true,
77
108
  });
78
- if (wrote) {
109
+ if (wrote)
79
110
  artifactPaths.push(path_1.default.join(ctx.cwd, '.vercel', 'output'));
80
- }
81
- }
82
- else if (!hasUserVercelConfig(ctx.cwd) || ctx.force) {
83
- const legacyPath = writeLegacyVercelJson(ctx);
84
- if (legacyPath)
85
- artifactPaths.push(legacyPath);
111
+ artifactPaths.push(path_1.default.join(ctx.vistaDir, 'static'));
86
112
  }
87
113
  else {
88
- artifactPaths.push(path_1.default.join(ctx.cwd, 'vercel.json'));
114
+ artifactPaths.push(...(0, runtime_pack_1.packVercelFullRuntime)(ctx));
89
115
  }
90
- (0, utils_1.copyStaticHostAssets)(ctx.cwd, ctx.vistaDir, path_1.default.join(ctx.vistaDir));
91
- artifactPaths.push(path_1.default.join(ctx.vistaDir, 'static'));
116
+ const vercelJson = writeVercelJson(ctx, !staticOnly);
117
+ if (vercelJson)
118
+ artifactPaths.push(vercelJson);
92
119
  return {
93
120
  status: 'emitted',
94
121
  target: 'vercel',
95
122
  artifactPaths,
96
123
  warnings,
97
- instructions: [
98
- 'Vercel deploy uses pre-rendered static pages from .vista/static.',
99
- 'For full SSR, server actions, and typed API, deploy with --target render or --target docker.',
100
- ],
124
+ instructions: staticOnly
125
+ ? [
126
+ 'Static mode: Vercel serves pre-rendered pages from .vista/static.',
127
+ 'For Flight SSR, omit deploy.output "static" (default is standalone).',
128
+ ]
129
+ : [
130
+ 'Vercel Build Output includes a Node.js serverless function that runs Flight SSR.',
131
+ 'Deploy with: vercel deploy --prebuilt --prod',
132
+ 'Connect the Git repo on Vercel; build command is "npm run build".',
133
+ 'Cold start spawns the Flight upstream in-process. Raise maxDuration in .vc-config.json if pages are slow.',
134
+ ],
101
135
  };
102
136
  },
103
137
  async deploy(ctx) {
@@ -134,8 +168,8 @@ exports.vercelAdapter = {
134
168
  ],
135
169
  instructions: [
136
170
  'Install Vercel CLI: npm i -g vercel',
137
- 'Then run: vercel deploy --prod',
138
- 'Or connect this repository in the Vercel dashboard with buildCommand "npm run build".',
171
+ 'Then run: vercel login && vercel deploy --prebuilt --prod',
172
+ 'Or import the Git repository in the Vercel dashboard (build: npm run build).',
139
173
  ],
140
174
  };
141
175
  }
@@ -146,11 +180,7 @@ exports.vercelAdapter = {
146
180
  target: 'vercel',
147
181
  artifactPaths: emitted.artifactPaths,
148
182
  warnings: [...warnings, result.stderr || 'Vercel deploy failed.'],
149
- instructions: [
150
- 'Ensure you are logged in: vercel login',
151
- 'Or set VERCEL_TOKEN in your environment.',
152
- 'You can also deploy from the Vercel dashboard using npm run build.',
153
- ],
183
+ instructions: ['Ensure you are logged in: vercel login', 'Or set VERCEL_TOKEN.'],
154
184
  };
155
185
  }
156
186
  return {
@@ -11,6 +11,7 @@ const fs_1 = __importDefault(require("fs"));
11
11
  const path_1 = __importDefault(require("path"));
12
12
  const config_1 = require("../config");
13
13
  const artifact_validator_1 = require("../server/artifact-validator");
14
+ const app_dir_1 = require("../server/app-dir");
14
15
  const utils_1 = require("./utils");
15
16
  function hasDynamicOnlyRoutes(vistaDir) {
16
17
  const routesManifest = (0, utils_1.readJsonSafe)(path_1.default.join(vistaDir, 'routes-manifest.json'));
@@ -42,13 +43,13 @@ async function runStaticHostPreflight(ctx) {
42
43
  errors.push('No pre-rendered pages found at .vista/static/pages. Static hosts require SSG output from "vista build".');
43
44
  }
44
45
  if (hasDynamicOnlyRoutes(ctx.vistaDir)) {
45
- errors.push('This app appears to rely on dynamic server rendering without static fallbacks. Deploy to Render or Docker for full runtime support.');
46
+ errors.push('This app appears to rely on dynamic server rendering without static fallbacks. Use the default standalone deploy (Vercel Node, Netlify Functions, Cloudflare Containers, Render, or Docker) instead of deploy.output "static".');
46
47
  }
47
48
  const typedApi = (0, config_1.resolveTypedApiConfig)(ctx.config);
48
49
  if (typedApi.enabled) {
49
- errors.push('Typed API is enabled. Static CDN hosts cannot run typed API runtime. Use deploy.target "render" or "docker".');
50
+ errors.push('Typed API is enabled. Static CDN hosts cannot run typed API runtime. Omit deploy.output "static" so the Node Flight server is packed.');
50
51
  }
51
- const appApiDir = path_1.default.join(ctx.cwd, 'app', 'api');
52
+ const appApiDir = path_1.default.join((0, app_dir_1.resolveAppDir)(ctx.cwd), 'api');
52
53
  if (fs_1.default.existsSync(appApiDir)) {
53
54
  warnings.push('Found app/api routes. Server-side API routes are not supported on static CDN deploy targets.');
54
55
  }
@@ -0,0 +1,11 @@
1
+ import type { DeployContext } from './types';
2
+ export declare function isStaticOnlyDeploy(ctx: DeployContext): boolean;
3
+ export declare function resolveStandaloneServerPath(ctx: DeployContext): string;
4
+ export declare function copyStandaloneRuntime(ctx: DeployContext, targetDir: string): void;
5
+ export declare function packRuntimeNodeModules(cwd: string, destDir: string): void;
6
+ export declare const VERCEL_SSR_FUNCTION_NAME = "index";
7
+ export declare function writeVercelNodeHandler(funcDir: string): void;
8
+ export declare function writeNetlifySsrHandler(functionDir: string): void;
9
+ export declare function writeCloudflareContainerWorker(outputDir: string): void;
10
+ export declare function writeCloudflareFullRuntimeToml(ctx: DeployContext): string;
11
+ export declare function packVercelFullRuntime(ctx: DeployContext): string[];
@@ -0,0 +1,300 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.VERCEL_SSR_FUNCTION_NAME = void 0;
7
+ exports.isStaticOnlyDeploy = isStaticOnlyDeploy;
8
+ exports.resolveStandaloneServerPath = resolveStandaloneServerPath;
9
+ exports.copyStandaloneRuntime = copyStandaloneRuntime;
10
+ exports.packRuntimeNodeModules = packRuntimeNodeModules;
11
+ exports.writeVercelNodeHandler = writeVercelNodeHandler;
12
+ exports.writeNetlifySsrHandler = writeNetlifySsrHandler;
13
+ exports.writeCloudflareContainerWorker = writeCloudflareContainerWorker;
14
+ exports.writeCloudflareFullRuntimeToml = writeCloudflareFullRuntimeToml;
15
+ exports.packVercelFullRuntime = packVercelFullRuntime;
16
+ const fs_1 = __importDefault(require("fs"));
17
+ const path_1 = __importDefault(require("path"));
18
+ const utils_1 = require("./utils");
19
+ function isStaticOnlyDeploy(ctx) {
20
+ return ctx.deployConfig.output === 'static';
21
+ }
22
+ function resolveStandaloneServerPath(ctx) {
23
+ return path_1.default.join(ctx.vistaDir, 'standalone', 'server.js');
24
+ }
25
+ function copyStandaloneRuntime(ctx, targetDir) {
26
+ const standaloneDir = path_1.default.join(ctx.vistaDir, 'standalone');
27
+ (0, utils_1.copyDirectoryRecursive)(standaloneDir, targetDir);
28
+ }
29
+ function packRuntimeNodeModules(cwd, destDir) {
30
+ const nodeModules = path_1.default.join(cwd, 'node_modules');
31
+ if (fs_1.default.existsSync(nodeModules)) {
32
+ (0, utils_1.copyDirectoryRecursive)(nodeModules, path_1.default.join(destDir, 'node_modules'));
33
+ }
34
+ const packageJson = path_1.default.join(cwd, 'package.json');
35
+ if (fs_1.default.existsSync(packageJson)) {
36
+ fs_1.default.copyFileSync(packageJson, path_1.default.join(destDir, 'package.json'));
37
+ }
38
+ }
39
+ exports.VERCEL_SSR_FUNCTION_NAME = 'index';
40
+ function writeVercelNodeHandler(funcDir) {
41
+ (0, utils_1.ensureDir)(funcDir);
42
+ const handler = `#!/usr/bin/env node
43
+ const path = require('path');
44
+
45
+ process.env.NODE_ENV = process.env.NODE_ENV || 'production';
46
+ process.env.VISTA_ARTIFACT_ROOT = process.env.VISTA_ARTIFACT_ROOT || __dirname;
47
+ process.chdir(__dirname);
48
+
49
+ const standalone = require(path.join(__dirname, '.vista', 'standalone', 'server.js'));
50
+ const listener = standalone.createRequestListener
51
+ ? standalone.createRequestListener()
52
+ : standalone.startStandaloneServer({ listen: false });
53
+
54
+ module.exports = function vistaHandler(req, res) {
55
+ return listener(req, res);
56
+ };
57
+ `;
58
+ fs_1.default.writeFileSync(path_1.default.join(funcDir, 'index.js'), handler, 'utf8');
59
+ fs_1.default.writeFileSync(path_1.default.join(funcDir, '.vc-config.json'), JSON.stringify({
60
+ runtime: 'nodejs20.x',
61
+ handler: 'index.js',
62
+ launcherType: 'Nodejs',
63
+ shouldAddHelpers: false,
64
+ supportsResponseStreaming: true,
65
+ maxDuration: 60,
66
+ memory: 1024,
67
+ }, null, 2), 'utf8');
68
+ }
69
+ function writeNetlifySsrHandler(functionDir) {
70
+ (0, utils_1.ensureDir)(functionDir);
71
+ const handler = `const path = require('path');
72
+ const http = require('http');
73
+ const stream = require('stream');
74
+
75
+ process.env.NODE_ENV = process.env.NODE_ENV || 'production';
76
+ process.env.VISTA_ARTIFACT_ROOT = process.env.VISTA_ARTIFACT_ROOT || __dirname;
77
+ process.chdir(__dirname);
78
+
79
+ const standalone = require(path.join(__dirname, '.vista', 'standalone', 'server.js'));
80
+ const listener = standalone.createRequestListener
81
+ ? standalone.createRequestListener()
82
+ : standalone.startStandaloneServer({ listen: false });
83
+
84
+ function queryFromEvent(event) {
85
+ if (event.rawQuery) return '?' + event.rawQuery;
86
+ const params = event.multiValueQueryStringParameters || event.queryStringParameters || {};
87
+ const search = new URLSearchParams();
88
+ for (const [key, value] of Object.entries(params)) {
89
+ if (Array.isArray(value)) {
90
+ value.forEach((entry) => search.append(key, String(entry)));
91
+ } else if (value != null) {
92
+ search.append(key, String(value));
93
+ }
94
+ }
95
+ const encoded = search.toString();
96
+ return encoded ? '?' + encoded : '';
97
+ }
98
+
99
+ function normalizeHeaders(raw) {
100
+ const headers = {};
101
+ for (const [key, value] of Object.entries(raw || {})) {
102
+ if (value == null) continue;
103
+ headers[String(key).toLowerCase()] = Array.isArray(value) ? value.join(',') : String(value);
104
+ }
105
+ return headers;
106
+ }
107
+
108
+ function createIncomingMessage(event) {
109
+ const socket = new stream.Duplex({
110
+ read() {},
111
+ write(_chunk, _enc, cb) { cb(); },
112
+ });
113
+ socket.remoteAddress = event.headers?.['x-nf-client-connection-ip'] || event.headers?.['x-forwarded-for'] || '127.0.0.1';
114
+ socket.encrypted = true;
115
+ socket.destroy = function destroy() {};
116
+
117
+ const req = new http.IncomingMessage(socket);
118
+ req.method = event.httpMethod || event.method || 'GET';
119
+ req.url = (event.path || event.rawPath || '/') + queryFromEvent(event);
120
+ req.headers = normalizeHeaders(event.headers);
121
+ req.httpVersion = '1.1';
122
+ req.httpVersionMajor = 1;
123
+ req.httpVersionMinor = 1;
124
+
125
+ const body = event.body
126
+ ? event.isBase64Encoded
127
+ ? Buffer.from(event.body, 'base64')
128
+ : Buffer.from(event.body)
129
+ : null;
130
+ if (body && body.length) {
131
+ req.push(body);
132
+ }
133
+ req.push(null);
134
+ return req;
135
+ }
136
+
137
+ function createServerResponse(req) {
138
+ const chunks = [];
139
+ const res = new http.ServerResponse(req);
140
+ const sink = new stream.Writable({
141
+ write(chunk, _enc, cb) {
142
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
143
+ cb();
144
+ },
145
+ });
146
+ res.assignSocket(sink);
147
+ res.flushHeaders = res.flushHeaders || function flushHeaders() {
148
+ if (!this._header) this._implicitHeader();
149
+ };
150
+ return {
151
+ res,
152
+ getBody() {
153
+ return Buffer.concat(chunks);
154
+ },
155
+ };
156
+ }
157
+
158
+ function toLambdaResponse(res, body) {
159
+ const headers = {};
160
+ const multiValueHeaders = {};
161
+ const raw = typeof res.getHeaders === 'function' ? res.getHeaders() : {};
162
+ for (const [key, value] of Object.entries(raw)) {
163
+ if (Array.isArray(value)) {
164
+ multiValueHeaders[key] = value.map((entry) => String(entry));
165
+ } else if (value != null) {
166
+ headers[key] = String(value);
167
+ }
168
+ }
169
+ return {
170
+ statusCode: res.statusCode || 200,
171
+ headers,
172
+ multiValueHeaders,
173
+ body: body.toString('base64'),
174
+ isBase64Encoded: true,
175
+ };
176
+ }
177
+
178
+ exports.handler = async function handler(event) {
179
+ const req = createIncomingMessage(event);
180
+ const { res, getBody } = createServerResponse(req);
181
+
182
+ return await new Promise((resolve, reject) => {
183
+ let settled = false;
184
+ const finish = () => {
185
+ if (settled) return;
186
+ settled = true;
187
+ resolve(toLambdaResponse(res, getBody()));
188
+ };
189
+ res.once('finish', finish);
190
+ res.once('close', finish);
191
+ res.once('error', reject);
192
+ try {
193
+ const handled = listener(req, res);
194
+ if (handled && typeof handled.then === 'function') {
195
+ handled.catch(reject);
196
+ }
197
+ } catch (error) {
198
+ reject(error);
199
+ }
200
+ });
201
+ };
202
+ `;
203
+ fs_1.default.writeFileSync(path_1.default.join(functionDir, 'ssr.js'), handler, 'utf8');
204
+ }
205
+ function writeCloudflareContainerWorker(outputDir) {
206
+ (0, utils_1.ensureDir)(outputDir);
207
+ const worker = `export class VistaSSR {
208
+ constructor(ctx, env) {
209
+ this.ctx = ctx;
210
+ this.env = env;
211
+ }
212
+
213
+ async fetch(request) {
214
+ const container = this.ctx.container;
215
+ if (!container) {
216
+ return new Response(
217
+ 'Vista SSR container is not available. Enable Cloudflare Containers or run the generated Dockerfile on a Node host.',
218
+ { status: 503, headers: { 'content-type': 'text/plain; charset=utf-8' } }
219
+ );
220
+ }
221
+
222
+ if (!container.running) {
223
+ await container.start({
224
+ env: {
225
+ NODE_ENV: 'production',
226
+ PORT: '3003',
227
+ },
228
+ });
229
+ }
230
+
231
+ return container.getTcpPort(3003).fetch(request);
232
+ }
233
+ }
234
+
235
+ export default {
236
+ async fetch(request, env) {
237
+ const id = env.VISTA_SSR.idFromName('vista');
238
+ return env.VISTA_SSR.get(id).fetch(request);
239
+ },
240
+ };
241
+ `;
242
+ fs_1.default.writeFileSync(path_1.default.join(outputDir, 'worker.js'), worker, 'utf8');
243
+ }
244
+ function writeCloudflareFullRuntimeToml(ctx) {
245
+ const targetFile = path_1.default.join(ctx.cwd, 'wrangler.toml');
246
+ const content = `name = "vista-app"
247
+ compatibility_date = "2026-09-20"
248
+ main = ".vista/deploy/cloudflare/worker.js"
249
+
250
+ [vars]
251
+ VISTA_RUNTIME = "standalone"
252
+
253
+ # Full Flight SSR runs in a Node container (same image as vista deploy --target docker).
254
+ [[containers]]
255
+ class_name = "VistaSSR"
256
+ image = "./Dockerfile"
257
+ max_instances = 4
258
+
259
+ [[durable_objects.bindings]]
260
+ name = "VISTA_SSR"
261
+ class_name = "VistaSSR"
262
+
263
+ [[migrations]]
264
+ tag = "v1"
265
+ new_sqlite_classes = ["VistaSSR"]
266
+ `;
267
+ (0, utils_1.writeFileIfAllowed)(targetFile, content, ctx.force);
268
+ return targetFile;
269
+ }
270
+ function packVercelFullRuntime(ctx) {
271
+ const outputDir = path_1.default.join(ctx.cwd, '.vercel', 'output');
272
+ const staticDir = path_1.default.join(outputDir, 'static');
273
+ const funcDir = path_1.default.join(outputDir, 'functions', `${exports.VERCEL_SSR_FUNCTION_NAME}.func`);
274
+ fs_1.default.rmSync(outputDir, { recursive: true, force: true });
275
+ (0, utils_1.ensureDir)(staticDir);
276
+ (0, utils_1.ensureDir)(funcDir);
277
+ (0, utils_1.copyStaticHostAssets)(ctx.cwd, ctx.vistaDir, staticDir);
278
+ const vistaStatic = path_1.default.join(ctx.vistaDir, 'static');
279
+ if (fs_1.default.existsSync(vistaStatic)) {
280
+ (0, utils_1.copyDirectoryRecursive)(vistaStatic, path_1.default.join(staticDir, '_vista', 'static'));
281
+ }
282
+ // Keep the standalone layout: <root>/.vista/standalone/server.js so projectRoot is <root>.
283
+ (0, utils_1.copyDirectoryRecursive)(ctx.vistaDir, path_1.default.join(funcDir, '.vista'));
284
+ packRuntimeNodeModules(ctx.cwd, funcDir);
285
+ writeVercelNodeHandler(funcDir);
286
+ const config = {
287
+ version: 3,
288
+ routes: [
289
+ {
290
+ src: '^/_vista/static/(.*)$',
291
+ headers: { 'cache-control': 'public, max-age=31536000, immutable' },
292
+ dest: '/_vista/static/$1',
293
+ },
294
+ { handle: 'filesystem' },
295
+ { src: '/(.*)', dest: '/' },
296
+ ],
297
+ };
298
+ fs_1.default.writeFileSync(path_1.default.join(outputDir, 'config.json'), JSON.stringify(config, null, 2));
299
+ return [outputDir, funcDir, staticDir];
300
+ }