@vistagenic/vista 0.3.6 → 0.3.8

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 (68) hide show
  1. package/bin/flashpack-agent-playground.mjs +134 -0
  2. package/bin/flashpack-boot.mjs +504 -0
  3. package/bin/flashpack-ssr-loader.mjs +42 -0
  4. package/bin/flashpack-ssr.mjs +81 -0
  5. package/bin/flashpack-vendor.mjs +97 -0
  6. package/bin/vista.js +56 -42
  7. package/dist/ai/providers/base.js +7 -1
  8. package/dist/bin/build-rsc.js +16 -0
  9. package/dist/bin/build.js +17 -11
  10. package/dist/bin/deploy.js +7 -0
  11. package/dist/bin/dev-client-runtime.d.ts +6 -0
  12. package/dist/bin/dev-client-runtime.js +99 -0
  13. package/dist/bin/dev-error-overlay-snippet.js +79 -21
  14. package/dist/bin/dev-error-overlay-snippet.ts +840 -0
  15. package/dist/bin/devtools-indicator-snippet.js +29 -13
  16. package/dist/bin/file-scanner.js +7 -24
  17. package/dist/bin/generate.js +94 -2
  18. package/dist/bin/webpack.config.js +3 -1
  19. package/dist/build/rsc/compiler.d.ts +14 -0
  20. package/dist/build/rsc/compiler.js +66 -6
  21. package/dist/build/rsc/server-manifest.js +5 -4
  22. package/dist/config.d.ts +5 -0
  23. package/dist/config.js +15 -1
  24. package/dist/deploy/adapters/render.js +2 -2
  25. package/dist/deploy/index.d.ts +1 -0
  26. package/dist/deploy/index.js +3 -0
  27. package/dist/deploy/runtime-pack.js +22 -1
  28. package/dist/deploy/utils.js +16 -6
  29. package/dist/flashpack/command.d.ts +1 -0
  30. package/dist/flashpack/command.js +42 -76
  31. package/dist/flashpack/runtime.d.ts +12 -0
  32. package/dist/flashpack/runtime.js +124 -22
  33. package/dist/metadata/generate.d.ts +1 -0
  34. package/dist/metadata/generate.js +117 -21
  35. package/dist/metadata/index.d.ts +5 -0
  36. package/dist/metadata/index.js +15 -1
  37. package/dist/metadata/json-ld.d.ts +15 -0
  38. package/dist/metadata/json-ld.js +19 -0
  39. package/dist/metadata/merge.d.ts +17 -0
  40. package/dist/metadata/merge.js +161 -0
  41. package/dist/metadata/routes.d.ts +66 -0
  42. package/dist/metadata/routes.js +143 -0
  43. package/dist/metadata/types.d.ts +1 -1
  44. package/dist/metadata/types.js +3 -1
  45. package/dist/og/image-response.d.ts +38 -0
  46. package/dist/og/image-response.js +88 -0
  47. package/dist/og/index.d.ts +2 -0
  48. package/dist/og/index.js +5 -0
  49. package/dist/rust/index.d.ts +13 -0
  50. package/dist/rust/index.js +132 -0
  51. package/dist/server/engine.js +13 -3
  52. package/dist/server/logger.js +2 -1
  53. package/dist/server/project-alias-resolver.d.ts +7 -0
  54. package/dist/server/project-alias-resolver.js +70 -0
  55. package/dist/server/rsc-engine.js +93 -16
  56. package/dist/server/static-generator.js +4 -3
  57. package/dist/server/typed-api-runtime.js +92 -0
  58. package/docs/ai.md +69 -0
  59. package/docs/app.md +30 -0
  60. package/docs/cli.md +29 -0
  61. package/docs/index.md +18 -0
  62. package/docs/rag.md +54 -0
  63. package/native/win32-x64/flashpack-cli.exe +0 -0
  64. package/package.json +196 -178
  65. package/skills/README.md +9 -0
  66. package/skills/vista-agent/SKILL.md +28 -0
  67. package/skills/vista-dev-loop/SKILL.md +25 -0
  68. package/skills/vista-rag/SKILL.md +26 -0
@@ -134,23 +134,33 @@ function flattenPrerenderedFlight(pagesDir, targetDir) {
134
134
  fs_1.default.copyFileSync(absolutePath, dest);
135
135
  });
136
136
  }
137
- function writeStaticRscRedirects(targetDir) {
137
+ function writeStaticRscRedirects(pagesDir, targetDir) {
138
138
  const redirectsPath = path_1.default.join(targetDir, '_redirects');
139
139
  const lines = [
140
140
  '/rsc /rsc/index.rsc 200',
141
141
  '/rsc/ /rsc/index.rsc 200',
142
- '/rsc/*.rsc /rsc/:splat.rsc 200',
143
- '/rsc/* /rsc/:splat.rsc 200',
144
142
  ];
143
+ walkFiles(pagesDir, (_absolutePath, relativePath) => {
144
+ const posix = relativePath.replace(/\\/g, '/');
145
+ if (!posix.endsWith('.rsc'))
146
+ return;
147
+ const routePath = posix.replace(/\.rsc$/, '');
148
+ const flightPath = `/rsc/${posix}`;
149
+ lines.push(`${flightPath} ${flightPath} 200`);
150
+ if (routePath === 'index')
151
+ return;
152
+ lines.push(`/rsc/${routePath} ${flightPath} 200`);
153
+ });
145
154
  fs_1.default.writeFileSync(redirectsPath, `${lines.join('\n')}\n`, 'utf8');
146
155
  }
147
156
  /** Copy webpack assets to `/_vista/static` and flatten HTML + Flight for file-based CDNs. */
148
157
  function prepareStaticCdnOutput(targetDir) {
149
158
  const staticDir = path_1.default.join(targetDir, 'static');
159
+ const pagesDir = path_1.default.join(staticDir, 'pages');
150
160
  copyDirectoryRecursive(staticDir, path_1.default.join(targetDir, '_vista', 'static'));
151
- flattenPrerenderedPages(path_1.default.join(staticDir, 'pages'), targetDir);
152
- flattenPrerenderedFlight(path_1.default.join(staticDir, 'pages'), targetDir);
153
- writeStaticRscRedirects(targetDir);
161
+ flattenPrerenderedPages(pagesDir, targetDir);
162
+ flattenPrerenderedFlight(pagesDir, targetDir);
163
+ writeStaticRscRedirects(pagesDir, targetDir);
154
164
  }
155
165
  function copyStaticHostAssets(cwd, vistaDir, targetDir) {
156
166
  copyDirectoryRecursive(path_1.default.join(cwd, 'public'), targetDir);
@@ -3,6 +3,7 @@ interface RunFlashpackCommandOptions {
3
3
  cwd?: string;
4
4
  port?: string | number;
5
5
  strict?: boolean;
6
+ action?: 'prepare' | 'run';
6
7
  }
7
8
  export declare function runFlashpackEngineCommand(phase: FlashpackCommandPhase, options?: RunFlashpackCommandOptions): Promise<void>;
8
9
  export default runFlashpackEngineCommand;
@@ -4,10 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.runFlashpackEngineCommand = runFlashpackEngineCommand;
7
- const path_1 = __importDefault(require("path"));
8
7
  const child_process_1 = require("child_process");
9
- const build_rsc_1 = require("../bin/build-rsc");
10
- const rsc_engine_1 = require("../server/rsc-engine");
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const module_1 = require("module");
10
+ const os_1 = __importDefault(require("os"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const dev_client_runtime_1 = require("../bin/dev-client-runtime");
11
13
  const spawn_permissions_1 = require("../server/spawn-permissions");
12
14
  const runtime_1 = require("./runtime");
13
15
  function resolveMode(phase) {
@@ -16,70 +18,47 @@ function resolveMode(phase) {
16
18
  }
17
19
  return process.env.NODE_ENV === 'development' ? 'development' : 'production';
18
20
  }
19
- function getRunnerPath() {
20
- return path_1.default.resolve(__dirname, '..', 'bin', 'flashpack-runner.js');
21
- }
22
21
  function formatRustFailure(message) {
23
22
  return `[flashpack] Rust command unavailable: ${message}`;
24
23
  }
25
- async function fallbackToCore(phase, port) {
26
- const normalizedPort = Number(port || process.env.PORT || 3003) || 3003;
27
- process.env.VISTA_ENGINE = 'flashpack';
28
- process.env.VISTA_ENGINE_VARIANT = 'flashpack';
29
- process.env.VISTA_FLASHPACK = 'true';
30
- process.env.VISTA_FLASHPACK_PIPELINE = 'js-fallback';
31
- console.warn(`[flashpack] Using explicit webpack Flight SSR fallback for ${phase} (same inline-Flight contract; not renderToString).`);
32
- if (phase === 'build') {
33
- await (0, build_rsc_1.buildRSC)(false);
34
- return;
24
+ function vistaVersion() {
25
+ try {
26
+ const require = (0, module_1.createRequire)(__filename);
27
+ const pkg = require('../../package.json');
28
+ return pkg.version || '0.3.8';
35
29
  }
36
- if (phase === 'dev') {
37
- const result = await (0, build_rsc_1.buildRSC)(true);
38
- (0, rsc_engine_1.startRSCServer)({
39
- port: normalizedPort,
40
- compiler: result.clientCompiler,
41
- });
42
- return;
30
+ catch {
31
+ return '0.3.8';
43
32
  }
44
- (0, rsc_engine_1.startRSCServer)({
45
- port: normalizedPort,
46
- });
33
+ }
34
+ function installDevClient(cwd) {
35
+ const file = path_1.default.join(cwd, '.flash', 'dev', 'vista-dev.js');
36
+ fs_1.default.mkdirSync(path_1.default.dirname(file), { recursive: true });
37
+ fs_1.default.writeFileSync(file, (0, dev_client_runtime_1.getSharedDevClientSource)(String(Date.now())));
38
+ }
39
+ function networkHost() {
40
+ const interfaces = os_1.default.networkInterfaces();
41
+ for (const name of Object.keys(interfaces)) {
42
+ for (const iface of interfaces[name] || []) {
43
+ if (iface.family === 'IPv4' && !iface.internal)
44
+ return iface.address;
45
+ }
46
+ }
47
+ return '';
47
48
  }
48
49
  async function runFlashpackEngineCommand(phase, options = {}) {
49
50
  const cwd = options.cwd || process.cwd();
50
- const strict = options.strict ?? process.env.VISTA_FLASHPACK_STRICT !== 'false';
51
51
  const mode = resolveMode(phase);
52
- const runnerPath = getRunnerPath();
53
52
  const port = options.port || process.env.PORT || 3003;
54
- const prepare = (0, runtime_1.runFlashpackRustCli)({
55
- cwd,
56
- phase: phase,
57
- mode,
58
- action: 'prepare',
59
- });
60
- if (prepare.error || prepare.status !== 0) {
61
- if (strict) {
62
- throw new Error(formatRustFailure(prepare.error || 'unknown failure'));
63
- }
64
- await fallbackToCore(phase, port);
65
- return;
66
- }
67
- const workspaceRoot = prepare.workspaceRoot;
68
- const cargoCommand = prepare.cargoCommand;
69
- if (!workspaceRoot || !cargoCommand) {
70
- if (strict) {
71
- throw new Error('[flashpack] Rust workspace unavailable for flashpack command.');
72
- }
73
- await fallbackToCore(phase, port);
74
- return;
53
+ const action = options.action || 'run';
54
+ const launch = (0, runtime_1.resolveFlashpackLaunch)(cwd);
55
+ const ssrRunner = action === 'run' ? (0, runtime_1.resolveFlashpackSsrRunner)(cwd) : null;
56
+ if (action === 'run') {
57
+ installDevClient(cwd);
75
58
  }
76
59
  await new Promise((resolve, reject) => {
77
- const child = (0, child_process_1.spawn)(cargoCommand, [
78
- 'run',
79
- '-q',
80
- '-p',
81
- 'flashpack-cli',
82
- '--',
60
+ const child = (0, child_process_1.spawn)(launch.command, [
61
+ ...launch.args,
83
62
  '--cwd',
84
63
  cwd,
85
64
  '--phase',
@@ -87,40 +66,27 @@ async function runFlashpackEngineCommand(phase, options = {}) {
87
66
  '--mode',
88
67
  mode,
89
68
  '--action',
90
- 'run',
91
- '--node',
92
- process.execPath,
93
- '--runner',
94
- runnerPath,
95
- '--port',
96
- String(port),
69
+ action,
70
+ ...(action === 'run' ? ['--port', String(port)] : []),
71
+ ...(ssrRunner ? ['--ssr-runner', ssrRunner] : []),
97
72
  ], {
98
- cwd: workspaceRoot,
73
+ cwd: launch.cwd,
99
74
  env: {
100
75
  ...process.env,
101
76
  VISTA_ENGINE: 'flashpack',
102
77
  VISTA_ENGINE_VARIANT: 'flashpack',
103
78
  VISTA_FLASHPACK: 'true',
104
- VISTA_FLASHPACK_PIPELINE: 'rust-cli',
79
+ VISTA_FLASHPACK_PIPELINE: 'rust-swc',
80
+ VISTA_VERSION: vistaVersion(),
81
+ VISTA_NETWORK_HOST: networkHost(),
105
82
  },
106
83
  stdio: 'inherit',
107
84
  windowsHide: true,
108
85
  });
109
- child.once('error', async (error) => {
86
+ child.once('error', (error) => {
110
87
  const message = (0, spawn_permissions_1.isPermissionDeniedSpawnError)(error)
111
88
  ? formatRustFailure(`spawn blocked by environment permissions (${(0, spawn_permissions_1.getErrorMessage)(error)})`)
112
89
  : formatRustFailure((0, spawn_permissions_1.getErrorMessage)(error));
113
- if (!strict) {
114
- try {
115
- await fallbackToCore(phase, port);
116
- resolve();
117
- return;
118
- }
119
- catch (fallbackError) {
120
- reject(fallbackError);
121
- return;
122
- }
123
- }
124
90
  reject(new Error(message));
125
91
  });
126
92
  child.once('exit', (code, signal) => {
@@ -12,6 +12,17 @@ export interface FlashpackPrepareResult {
12
12
  workspaceRoot: string | null;
13
13
  graphPath: string;
14
14
  }
15
+ export declare function flashpackPlatformTriple(): string;
16
+ export declare function flashpackBinaryName(): string;
17
+ export declare function findBundledFlashpackBinary(startCwd?: string): string | null;
18
+ export declare function resolveFlashpackSsrRunner(startCwd?: string): string | null;
19
+ export interface FlashpackLaunch {
20
+ command: string;
21
+ args: string[];
22
+ cwd: string;
23
+ source: 'binary' | 'workspace';
24
+ }
25
+ export declare function resolveFlashpackLaunch(startCwd?: string): FlashpackLaunch;
15
26
  export declare function findFlashpackWorkspaceRoot(startCwd: string): string | null;
16
27
  export declare function bootstrapFlashDirectories(cwd: string): string;
17
28
  export declare function resolveCargoCommand(): string;
@@ -36,4 +47,5 @@ export interface FlashpackRustCliResult {
36
47
  status: number | null;
37
48
  }
38
49
  export declare function runFlashpackRustCli(options: FlashpackRustCliOptions): FlashpackRustCliResult;
50
+ export declare function flashpackCratesBound(flashDir: string): boolean;
39
51
  export declare function prepareFlashpackRuntime(options: FlashpackPrepareOptions): FlashpackPrepareResult;
@@ -3,10 +3,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.flashpackPlatformTriple = flashpackPlatformTriple;
7
+ exports.flashpackBinaryName = flashpackBinaryName;
8
+ exports.findBundledFlashpackBinary = findBundledFlashpackBinary;
9
+ exports.resolveFlashpackSsrRunner = resolveFlashpackSsrRunner;
10
+ exports.resolveFlashpackLaunch = resolveFlashpackLaunch;
6
11
  exports.findFlashpackWorkspaceRoot = findFlashpackWorkspaceRoot;
7
12
  exports.bootstrapFlashDirectories = bootstrapFlashDirectories;
8
13
  exports.resolveCargoCommand = resolveCargoCommand;
9
14
  exports.runFlashpackRustCli = runFlashpackRustCli;
15
+ exports.flashpackCratesBound = flashpackCratesBound;
10
16
  exports.prepareFlashpackRuntime = prepareFlashpackRuntime;
11
17
  const fs_1 = __importDefault(require("fs"));
12
18
  const path_1 = __importDefault(require("path"));
@@ -33,6 +39,86 @@ function removeLegacyFlashArtifacts(cwd, flashDir) {
33
39
  fs_1.default.rmSync(legacyPath, { recursive: true, force: true });
34
40
  }
35
41
  }
42
+ function flashpackPlatformTriple() {
43
+ return `${process.platform}-${process.arch}`;
44
+ }
45
+ function flashpackBinaryName() {
46
+ return process.platform === 'win32' ? 'flashpack-cli.exe' : 'flashpack-cli';
47
+ }
48
+ function pushPackageRoot(roots, root) {
49
+ const resolved = path_1.default.resolve(root);
50
+ if (!roots.includes(resolved))
51
+ roots.push(resolved);
52
+ try {
53
+ const real = fs_1.default.realpathSync(resolved);
54
+ if (!roots.includes(real))
55
+ roots.push(real);
56
+ }
57
+ catch {
58
+ // The package root may not exist at this path.
59
+ }
60
+ }
61
+ function vistaPackageRoots() {
62
+ const roots = [];
63
+ pushPackageRoot(roots, path_1.default.resolve(__dirname, '..', '..'));
64
+ if (process.argv[1]) {
65
+ pushPackageRoot(roots, path_1.default.resolve(path_1.default.dirname(process.argv[1]), '..'));
66
+ }
67
+ return roots;
68
+ }
69
+ function findBundledFlashpackBinary(startCwd = process.cwd()) {
70
+ const relative = path_1.default.join('native', flashpackPlatformTriple(), flashpackBinaryName());
71
+ // Prefer the monorepo package binary over a stale pnpm store copy.
72
+ const workspaceRoot = findFlashpackWorkspaceRoot(startCwd);
73
+ const roots = [
74
+ ...(workspaceRoot ? [path_1.default.join(workspaceRoot, 'packages', 'vista')] : []),
75
+ ...vistaPackageRoots(),
76
+ ];
77
+ for (const root of roots) {
78
+ const binary = path_1.default.join(root, relative);
79
+ if (fs_1.default.existsSync(binary))
80
+ return binary;
81
+ }
82
+ return null;
83
+ }
84
+ function resolveFlashpackSsrRunner(startCwd = process.cwd()) {
85
+ // Prefer the workspace package so newly added bin/*.mjs files (e.g. agent playground)
86
+ // are visible even when pnpm's store copy is stale.
87
+ const workspaceRoot = findFlashpackWorkspaceRoot(startCwd);
88
+ const roots = [
89
+ ...(workspaceRoot ? [path_1.default.join(workspaceRoot, 'packages', 'vista')] : []),
90
+ ...vistaPackageRoots(),
91
+ ];
92
+ for (const root of roots) {
93
+ const runner = path_1.default.join(root, 'bin', 'flashpack-ssr.mjs');
94
+ if (fs_1.default.existsSync(runner))
95
+ return runner;
96
+ }
97
+ return null;
98
+ }
99
+ function resolveFlashpackLaunch(startCwd = process.cwd()) {
100
+ const fromSource = process.env.VISTA_FLASHPACK_FROM_SOURCE === '1';
101
+ const binary = findBundledFlashpackBinary(startCwd);
102
+ if (binary && !fromSource) {
103
+ return {
104
+ command: binary,
105
+ args: [],
106
+ cwd: startCwd,
107
+ source: 'binary',
108
+ };
109
+ }
110
+ const workspaceRoot = findFlashpackWorkspaceRoot(startCwd);
111
+ if (workspaceRoot) {
112
+ return {
113
+ command: resolveCargoCommand(),
114
+ args: ['run', '-q', '-p', 'flashpack-cli', '--'],
115
+ cwd: workspaceRoot,
116
+ source: 'workspace',
117
+ };
118
+ }
119
+ throw new Error(`[flashpack] Native binary for ${flashpackPlatformTriple()} is not in this vista package. ` +
120
+ 'The published package ships it under native/<platform>/. Reinstall @vistagenic/vista.');
121
+ }
36
122
  function findFlashpackWorkspaceRoot(startCwd) {
37
123
  let current = path_1.default.resolve(startCwd);
38
124
  while (true) {
@@ -93,13 +179,9 @@ function resolveCargoCommand() {
93
179
  }
94
180
  return 'cargo';
95
181
  }
96
- function buildRustCliArgs(options, graphPath) {
182
+ function buildRustCliArgs(options, launch) {
97
183
  const args = [
98
- 'run',
99
- '-q',
100
- '-p',
101
- 'flashpack-cli',
102
- '--',
184
+ ...launch.args,
103
185
  '--cwd',
104
186
  options.cwd,
105
187
  '--phase',
@@ -122,11 +204,14 @@ function buildRustCliArgs(options, graphPath) {
122
204
  }
123
205
  function runFlashpackRustCli(options) {
124
206
  const flashDir = bootstrapFlashDirectories(options.cwd);
125
- const workspaceRoot = findFlashpackWorkspaceRoot(options.cwd);
126
207
  const graphPath = path_1.default.join(flashDir, 'graph', `${options.phase}-rust.json`);
127
208
  const runtimeManifestPath = path_1.default.join(flashDir, 'runtime', `${options.phase}-manifest.json`);
128
209
  const logPath = path_1.default.join(flashDir, 'logs', `${options.phase}-cli.log`);
129
- if (!workspaceRoot) {
210
+ let launch;
211
+ try {
212
+ launch = resolveFlashpackLaunch(options.cwd);
213
+ }
214
+ catch (error) {
130
215
  return {
131
216
  flashDir,
132
217
  workspaceRoot: null,
@@ -135,20 +220,20 @@ function runFlashpackRustCli(options) {
135
220
  logPath,
136
221
  graphPath,
137
222
  runtimeManifestPath,
138
- error: `Rust workspace not found from ${options.cwd}. Expected flashpack/xtask/Cargo.toml in an ancestor directory.`,
223
+ error: error instanceof Error ? error.message : String(error),
139
224
  status: null,
140
225
  };
141
226
  }
142
- const cargoCommand = resolveCargoCommand();
143
- const args = buildRustCliArgs(options, graphPath);
144
- const result = (0, child_process_1.spawnSync)(cargoCommand, args, {
145
- cwd: workspaceRoot,
227
+ const workspaceRoot = launch.source === 'workspace' ? launch.cwd : findFlashpackWorkspaceRoot(options.cwd);
228
+ const args = buildRustCliArgs(options, launch);
229
+ const result = (0, child_process_1.spawnSync)(launch.command, args, {
230
+ cwd: launch.cwd,
146
231
  encoding: 'utf-8',
147
232
  stdio: 'pipe',
148
233
  });
149
234
  const log = [
150
- `[flashpack] workspace=${workspaceRoot}`,
151
- `[flashpack] command=${cargoCommand} ${args.join(' ')}`,
235
+ `[flashpack] source=${launch.source}`,
236
+ `[flashpack] command=${launch.command} ${args.join(' ')}`,
152
237
  `[flashpack] status=${result.status ?? 'null'}`,
153
238
  `[flashpack] error=${result.error ? result.error.message : ''}`,
154
239
  '[flashpack] stdout:',
@@ -160,7 +245,7 @@ function runFlashpackRustCli(options) {
160
245
  return {
161
246
  flashDir,
162
247
  workspaceRoot,
163
- cargoCommand,
248
+ cargoCommand: launch.command,
164
249
  args,
165
250
  logPath,
166
251
  graphPath,
@@ -173,6 +258,18 @@ function runFlashpackRustCli(options) {
173
258
  status: result.status ?? null,
174
259
  };
175
260
  }
261
+ function flashpackCratesBound(flashDir) {
262
+ try {
263
+ const parsed = JSON.parse(fs_1.default.readFileSync(path_1.default.join(flashDir, 'pipeline', 'bound.json'), 'utf8'));
264
+ return (parsed.pipeline === 'flashpack-cli' &&
265
+ Array.isArray(parsed.crates) &&
266
+ parsed.crates.includes('flashpack-ecmascript') &&
267
+ parsed.crates.includes('flashpack-resolve'));
268
+ }
269
+ catch {
270
+ return false;
271
+ }
272
+ }
176
273
  function prepareFlashpackRuntime(options) {
177
274
  const { cwd, phase, mode, allowFallback = true } = options;
178
275
  const flashDir = bootstrapFlashDirectories(cwd);
@@ -215,12 +312,6 @@ function prepareFlashpackRuntime(options) {
215
312
  errors: nativeScan.errors.length,
216
313
  },
217
314
  });
218
- return {
219
- flashDir,
220
- rustPipelineUsed: true,
221
- workspaceRoot: null,
222
- graphPath: nativeGraphPath,
223
- };
224
315
  }
225
316
  }
226
317
  const rustResult = runFlashpackRustCli({
@@ -241,6 +332,17 @@ function prepareFlashpackRuntime(options) {
241
332
  graphPath,
242
333
  };
243
334
  }
335
+ if (!flashpackCratesBound(flashDir)) {
336
+ if (!allowFallback) {
337
+ throw new Error('[flashpack] Rust pipeline did not bind the Flashpack crates.');
338
+ }
339
+ return {
340
+ flashDir,
341
+ rustPipelineUsed: false,
342
+ workspaceRoot: rustResult.workspaceRoot,
343
+ graphPath,
344
+ };
345
+ }
244
346
  return {
245
347
  flashDir,
246
348
  rustPipelineUsed: true,
@@ -17,6 +17,7 @@ export interface MetadataRendererProps {
17
17
  export declare function MetadataRenderer({ metadata, parentTemplate, }: MetadataRendererProps): React.ReactElement;
18
18
  /**
19
19
  * Converts metadata to HTML string for SSR injection.
20
+ * Applies title template from merged metadata when parentTemplate is omitted.
20
21
  */
21
22
  export declare function generateMetadataHtml(metadata: Metadata, parentTemplate?: string): string;
22
23
  export default MetadataRenderer;