@vistagenic/vista 0.3.6 → 0.3.9

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 +506 -0
  3. package/bin/flashpack-ssr-loader.mjs +42 -0
  4. package/bin/flashpack-ssr.mjs +202 -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
@@ -47,21 +47,22 @@ function getDevToolsIndicatorBootstrapSource(bootSessionId) {
47
47
  style.id = '__vista-devtools-style';
48
48
  style.textContent = [
49
49
  '#__vista-devtools-root{position:fixed;left:28px;bottom:22px;z-index:2147482000;font-family:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;color:#fff;}',
50
- '#__vista-devtools-root [data-vista-trigger]{width:40px;height:40px;border-radius:9999px;border:1px solid rgba(255,255,255,0.2);background:rgba(0,0,0,0.82);display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 10px 24px rgba(0,0,0,0.4);position:relative;transition:transform 180ms ease,border-color 180ms ease,background 180ms ease,width 180ms ease,padding 180ms ease,gap 180ms ease;}',
51
- '#__vista-devtools-root [data-vista-trigger]:hover{transform:translateY(-1px);border-color:rgba(255,255,255,0.42);background:rgba(0,0,0,0.92);}',
52
- '#__vista-devtools-root [data-vista-trigger]:focus-visible{outline:2px solid rgba(255,255,255,0.65);outline-offset:2px;}',
53
- '#__vista-devtools-root [data-vista-trigger][data-busy="true"]{border-color:rgba(255,255,255,0.5);}',
54
- '#__vista-devtools-root [data-vista-trigger][data-error="true"]{width:86px;padding:0 8px;justify-content:flex-start;gap:6px;border-color:rgba(248,113,113,0.9);background:rgba(53,11,16,0.94);box-shadow:0 10px 24px rgba(248,113,113,0.24);}',
55
- '#__vista-devtools-root .vista-devtools-logo{display:block;width:16px;height:16px;}',
50
+ '#__vista-devtools-root [data-vista-trigger]{width:42px;height:42px;border-radius:9999px;border:1px solid rgba(255,255,255,0.16);background:rgba(12,12,12,0.88);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 8px 28px rgba(0,0,0,0.38),inset 0 1px 0 rgba(255,255,255,0.08);position:relative;gap:0;padding:0;transition:transform 200ms cubic-bezier(0.22,1,0.36,1),border-color 200ms ease,background 200ms ease,width 220ms cubic-bezier(0.22,1,0.36,1),padding 220ms cubic-bezier(0.22,1,0.36,1),gap 220ms cubic-bezier(0.22,1,0.36,1),box-shadow 220ms ease;}',
51
+ '#__vista-devtools-root [data-vista-trigger]:hover{transform:translateY(-2px);border-color:rgba(255,255,255,0.34);background:rgba(18,18,18,0.94);box-shadow:0 12px 32px rgba(0,0,0,0.45),inset 0 1px 0 rgba(255,255,255,0.1);}',
52
+ '#__vista-devtools-root [data-vista-trigger]:focus-visible{outline:2px solid rgba(255,255,255,0.55);outline-offset:3px;}',
53
+ '#__vista-devtools-root [data-vista-trigger][data-busy="true"]{border-color:rgba(255,255,255,0.42);}',
54
+ '#__vista-devtools-root [data-vista-trigger][data-error="true"]{width:auto;min-width:42px;height:42px;padding:0 12px 0 11px;justify-content:flex-start;gap:9px;border-color:rgba(255,255,255,0.14);background:linear-gradient(180deg,rgba(28,16,18,0.96),rgba(14,10,11,0.96));box-shadow:0 10px 30px rgba(0,0,0,0.42),0 0 0 1px rgba(255,90,90,0.18),inset 0 1px 0 rgba(255,255,255,0.06);}',
55
+ '#__vista-devtools-root [data-vista-trigger][data-error="true"]:hover{border-color:rgba(255,255,255,0.22);box-shadow:0 14px 34px rgba(0,0,0,0.48),0 0 0 1px rgba(255,90,90,0.28),inset 0 1px 0 rgba(255,255,255,0.08);}',
56
+ '#__vista-devtools-root .vista-devtools-logo{display:block;width:15px;height:15px;flex:0 0 auto;}',
56
57
  '#__vista-devtools-root .vista-devtools-logo svg{width:100%;height:100%;display:block;}',
57
- '#__vista-devtools-root [data-vista-trigger][data-error="true"] .vista-devtools-logo{width:14px;height:14px;}',
58
58
  '#__vista-devtools-root .vista-devtools-logo-fill{fill:#fff;opacity:1;transition:opacity 180ms ease;}',
59
59
  '#__vista-devtools-root .vista-devtools-logo-draw{fill:none;stroke:#fff;stroke-width:12;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:100;stroke-dashoffset:100;opacity:0;}',
60
60
  '#__vista-devtools-root [data-vista-trigger][data-busy="true"] .vista-devtools-logo-fill{opacity:0.18;}',
61
61
  '#__vista-devtools-root [data-vista-trigger][data-busy="true"] .vista-devtools-logo-draw{opacity:1;animation:vista-devtools-v-draw 900ms ease-in-out infinite;}',
62
- '#__vista-devtools-root .vista-devtools-error-pill{display:inline-flex;align-items:center;gap:4px;padding:2px 7px;border-radius:999px;border:1px solid rgba(248,113,113,0.65);background:rgba(248,113,113,0.16);color:#fecaca;font-size:11px;font-weight:670;font-variant-numeric:tabular-nums;line-height:1;}',
63
- '#__vista-devtools-root .vista-devtools-error-close{font-size:11px;line-height:1;color:#fca5a5;}',
64
- '#__vista-devtools-root [data-vista-panel]{position:absolute;left:0;bottom:50px;width:244px;padding:10px;border-radius:12px;border:1px solid rgba(255,255,255,0.18);background:rgba(8,8,8,0.94);backdrop-filter:blur(8px);box-shadow:0 16px 36px rgba(0,0,0,0.45);}',
62
+ '#__vista-devtools-root .vista-devtools-error-pill{display:inline-flex;align-items:center;gap:5px;height:22px;padding:0 8px;border-radius:999px;border:1px solid rgba(255,120,120,0.28);background:rgba(255,255,255,0.06);color:rgba(255,228,228,0.96);font-size:11px;font-weight:600;letter-spacing:0.01em;font-variant-numeric:tabular-nums;line-height:1;white-space:nowrap;}',
63
+ '#__vista-devtools-root .vista-devtools-error-dot{width:6px;height:6px;border-radius:999px;background:#ff6b6b;box-shadow:0 0 0 0 rgba(255,107,107,0.45);animation:vista-devtools-error-pulse 1.8s ease-out infinite;flex:0 0 auto;}',
64
+ '#__vista-devtools-root .vista-devtools-error-label{opacity:0.72;font-weight:550;}',
65
+ '#__vista-devtools-root [data-vista-panel]{position:absolute;left:0;bottom:54px;width:244px;padding:10px;border-radius:14px;border:1px solid rgba(255,255,255,0.14);background:rgba(10,10,10,0.94);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:0 18px 40px rgba(0,0,0,0.5);}',
65
66
  '#__vista-devtools-root [data-vista-panel][hidden]{display:none;}',
66
67
  '#__vista-devtools-root .vista-devtools-title{font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:rgba(255,255,255,0.72);margin:0 0 8px;}',
67
68
  '#__vista-devtools-root .vista-devtools-row{font-size:12px;display:flex;justify-content:space-between;gap:10px;margin:4px 0;color:rgba(255,255,255,0.92);}',
@@ -72,6 +73,7 @@ function getDevToolsIndicatorBootstrapSource(bootSessionId) {
72
73
  '#__vista-devtools-root [data-vista-hide]:hover{background:rgba(255,255,255,0.12);border-color:rgba(255,255,255,0.5);color:#fff;}',
73
74
  '#__vista-devtools-root .vista-hide-icon{width:12px;height:12px;display:block;}',
74
75
  '@keyframes vista-devtools-v-draw{0%{stroke-dashoffset:100;opacity:0.35;}45%{stroke-dashoffset:0;opacity:1;}72%{stroke-dashoffset:0;opacity:1;}100%{stroke-dashoffset:-100;opacity:0.35;}}',
76
+ '@keyframes vista-devtools-error-pulse{0%{box-shadow:0 0 0 0 rgba(255,107,107,0.45);}70%{box-shadow:0 0 0 7px rgba(255,107,107,0);}100%{box-shadow:0 0 0 0 rgba(255,107,107,0);}}',
75
77
  '@media (max-width:640px){#__vista-devtools-root{left:16px;bottom:14px;}#__vista-devtools-root [data-vista-panel]{width:220px;}}',
76
78
  ].join('');
77
79
  }
@@ -92,8 +94,9 @@ function getDevToolsIndicatorBootstrapSource(bootSessionId) {
92
94
  '</svg>' +
93
95
  '</span>' +
94
96
  '<span class="vista-devtools-error-pill" data-vista-error-pill hidden>' +
95
- '<span class="vista-devtools-error-close">×</span>' +
97
+ '<span class="vista-devtools-error-dot" aria-hidden="true"></span>' +
96
98
  '<span data-vista-error-count>1</span>' +
99
+ '<span class="vista-devtools-error-label" data-vista-error-label>issue</span>' +
97
100
  '</span>' +
98
101
  '</button>' +
99
102
  '<div data-vista-panel hidden>' +
@@ -123,6 +126,7 @@ function getDevToolsIndicatorBootstrapSource(bootSessionId) {
123
126
  var hideButton = null;
124
127
  var errorPill = null;
125
128
  var errorCountNode = null;
129
+ var errorLabelNode = null;
126
130
  var open = false;
127
131
  var pendingCount = 0;
128
132
  var busyStartedAt = 0;
@@ -143,6 +147,7 @@ function getDevToolsIndicatorBootstrapSource(bootSessionId) {
143
147
  hideButton = root.querySelector('[data-vista-hide]');
144
148
  errorPill = root.querySelector('[data-vista-error-pill]');
145
149
  errorCountNode = root.querySelector('[data-vista-error-count]');
150
+ errorLabelNode = root.querySelector('[data-vista-error-label]');
146
151
  }
147
152
 
148
153
  function ensureAttached() {
@@ -211,9 +216,16 @@ function getDevToolsIndicatorBootstrapSource(bootSessionId) {
211
216
  } else {
212
217
  errorCount = 1;
213
218
  }
214
- if (button) button.setAttribute('data-error', 'true');
219
+ if (button) {
220
+ button.setAttribute('data-error', 'true');
221
+ button.setAttribute(
222
+ 'aria-label',
223
+ 'Vista Dev Tools — ' + errorCount + (errorCount === 1 ? ' issue' : ' issues')
224
+ );
225
+ }
215
226
  if (errorPill) errorPill.hidden = false;
216
227
  if (errorCountNode) errorCountNode.textContent = String(errorCount);
228
+ if (errorLabelNode) errorLabelNode.textContent = errorCount === 1 ? 'issue' : 'issues';
217
229
  if (statusValue) statusValue.textContent = 'error';
218
230
  if (reasonValue)
219
231
  reasonValue.textContent =
@@ -223,8 +235,12 @@ function getDevToolsIndicatorBootstrapSource(bootSessionId) {
223
235
  function clearError() {
224
236
  ensureAttached();
225
237
  hasError = false;
226
- if (button) button.setAttribute('data-error', 'false');
238
+ if (button) {
239
+ button.setAttribute('data-error', 'false');
240
+ button.setAttribute('aria-label', 'Vista Dev Tools');
241
+ }
227
242
  if (errorPill) errorPill.hidden = true;
243
+ if (errorLabelNode) errorLabelNode.textContent = 'issue';
228
244
  errorCount = 1;
229
245
  setState(currentBusy, currentReason);
230
246
  }
@@ -53,6 +53,7 @@ exports.getVersion = getVersion;
53
53
  const fs = __importStar(require("fs"));
54
54
  const path = __importStar(require("path"));
55
55
  const native_scanner_1 = require("../build/rsc/native-scanner");
56
+ const rust_1 = require("../rust");
56
57
  const RESERVED_INTERNAL_SEGMENTS = new Set(['[not-found]']);
57
58
  function hasReservedInternalSegment(relativePath) {
58
59
  return relativePath
@@ -111,34 +112,16 @@ function getRouteTree(appDir) {
111
112
  // JS Fallback - build route tree from file system
112
113
  return buildRouteTreeJS(appDir, appDir);
113
114
  }
114
- function classifySegment(segment) {
115
- if (segment.startsWith('[[...') && segment.endsWith(']]'))
116
- return 'optional-catch-all';
117
- if (segment.startsWith('[...'))
118
- return 'catch-all';
119
- if (segment.startsWith('(.)') ||
120
- segment.startsWith('(..)') ||
121
- segment.startsWith('(..)(..)') ||
122
- segment.startsWith('(...)')) {
123
- return 'interception';
124
- }
125
- if (segment.startsWith('(') && segment.endsWith(')'))
126
- return 'group';
127
- if (segment.startsWith('@'))
128
- return 'parallel';
129
- if (segment.startsWith('['))
130
- return 'dynamic';
131
- return 'static';
132
- }
133
115
  /**
134
- * JS Fallback for building route tree when Rust bindings are unavailable
116
+ * JS Fallback for building route tree when Rust bindings are unavailable.
117
+ * Classification goes through `vista/rust`, which uses the native addon when it is loaded.
135
118
  */
136
119
  function buildRouteTreeJS(dir, appDir) {
137
- const segment = dir === appDir ? '' : path.basename(dir);
138
- const kind = classifySegment(segment);
120
+ const folder = dir === appDir ? '' : path.basename(dir);
121
+ const classified = folder === '' ? { kind: 'static', segment: '' } : (0, rust_1.classifyAppSegment)(folder);
139
122
  const node = {
140
- segment: kind === 'group' ? '' : segment,
141
- kind,
123
+ segment: classified.segment,
124
+ kind: classified.kind,
142
125
  children: [],
143
126
  };
144
127
  if (!fs.existsSync(dir)) {
@@ -62,7 +62,7 @@ function renderAgent(kebabName) {
62
62
  function renderAgentRoute(kebabName) {
63
63
  const camelName = toCamelCase(kebabName);
64
64
  return [
65
- `import { ${camelName}Agent } from '../../agents/${kebabName}/agent';`,
65
+ `import { ${camelName}Agent } from '../../../agents/${kebabName}/agent';`,
66
66
  '',
67
67
  'export async function POST(req: Request) {',
68
68
  ' const { prompt, messages, sessionId } = await req.json();',
@@ -116,6 +116,18 @@ function insertTypedApiConfigIntoObject(source, objectStartIndex) {
116
116
  if (closeBraceIndex < 0) {
117
117
  return null;
118
118
  }
119
+ const objectContent = source.slice(openBraceIndex, closeBraceIndex);
120
+ const expMatch = objectContent.match(/\bexperimental\s*:\s*\{/);
121
+ if (expMatch && typeof expMatch.index === 'number') {
122
+ const absExpBrace = openBraceIndex + expMatch.index + expMatch[0].lastIndexOf('{');
123
+ const expCloseBrace = findMatchingBrace(source, absExpBrace);
124
+ if (expCloseBrace >= 0) {
125
+ const expBefore = source.slice(0, expCloseBrace);
126
+ const expAfter = source.slice(expCloseBrace);
127
+ const insertion = ` typedApi: {\n enabled: true,\n },\n `;
128
+ return `${expBefore}${insertion}${expAfter}`;
129
+ }
130
+ }
119
131
  const before = source.slice(0, closeBraceIndex);
120
132
  const after = source.slice(closeBraceIndex);
121
133
  const insertion = `\n experimental: {\n typedApi: {\n enabled: true,\n },\n },`;
@@ -335,6 +347,8 @@ function renderSignInPage() {
335
347
  }
336
348
  function renderAccountPage() {
337
349
  return [
350
+ "export const dynamic = 'force-dynamic';",
351
+ '',
338
352
  "import { auth } from '../../auth';",
339
353
  '',
340
354
  'export default async function AccountPage() {',
@@ -384,6 +398,69 @@ function patchRootWithSessionProvider(cwd) {
384
398
  fs_1.default.writeFileSync(absolutePath, next, 'utf8');
385
399
  return { path: absolutePath, patched: true };
386
400
  }
401
+ function renderSeoRobots() {
402
+ return [
403
+ "import { robots } from 'vista/metadata';",
404
+ '',
405
+ 'const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || process.env.VISTA_SITE_URL || \'http://localhost:3003\';',
406
+ '',
407
+ 'export default function robotsTxt() {',
408
+ ' return robots({',
409
+ " rules: {",
410
+ " userAgent: '*',",
411
+ " allow: '/',",
412
+ ' },',
413
+ ' sitemap: `${siteUrl}/sitemap.xml`,',
414
+ ' host: new URL(siteUrl).host,',
415
+ ' });',
416
+ '}',
417
+ '',
418
+ ].join('\n');
419
+ }
420
+ function renderSeoSitemap() {
421
+ return [
422
+ "import { sitemap } from 'vista/metadata';",
423
+ '',
424
+ 'const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || process.env.VISTA_SITE_URL || \'http://localhost:3003\';',
425
+ '',
426
+ 'export default function sitemapXml() {',
427
+ ' return sitemap([',
428
+ ' {',
429
+ ' url: siteUrl,',
430
+ ' lastModified: new Date(),',
431
+ " changeFrequency: 'weekly',",
432
+ ' priority: 1,',
433
+ ' },',
434
+ ' ]);',
435
+ '}',
436
+ '',
437
+ ].join('\n');
438
+ }
439
+ function renderSeoManifest() {
440
+ return [
441
+ "import { manifest } from 'vista/metadata';",
442
+ '',
443
+ 'export default function webManifest() {',
444
+ ' return manifest({',
445
+ " name: 'My Vista App',",
446
+ " short_name: 'Vista App',",
447
+ " description: 'Built with Vista Framework',",
448
+ " start_url: '/',",
449
+ " display: 'standalone',",
450
+ " background_color: '#ffffff',",
451
+ " theme_color: '#111111',",
452
+ ' icons: [',
453
+ ' {',
454
+ " src: '/favicon.ico',",
455
+ " sizes: 'any',",
456
+ " type: 'image/x-icon',",
457
+ ' },',
458
+ ' ],',
459
+ ' });',
460
+ '}',
461
+ '',
462
+ ].join('\n');
463
+ }
387
464
  function printGenerateUsage(log) {
388
465
  log('Vista generator usage:');
389
466
  log(' vista g api-init');
@@ -391,13 +468,14 @@ function printGenerateUsage(log) {
391
468
  log(' vista g procedure <name> [get|post]');
392
469
  log(' vista g agent <name>');
393
470
  log(' vista g auth');
471
+ log(' vista g seo');
394
472
  }
395
473
  async function runGenerateCommand(args, options = {}) {
396
474
  const cwd = options.cwd ?? process.cwd();
397
475
  const log = options.log ?? console.log;
398
476
  const error = options.error ?? console.error;
399
477
  const command = (args[0] || '').toLowerCase();
400
- if (!command || !['api-init', 'router', 'procedure', 'agent', 'auth'].includes(command)) {
478
+ if (!command || !['api-init', 'router', 'procedure', 'agent', 'auth', 'seo'].includes(command)) {
401
479
  printGenerateUsage(log);
402
480
  return 1;
403
481
  }
@@ -508,6 +586,20 @@ async function runGenerateCommand(args, options = {}) {
508
586
  log('Credentials sign-in POSTs from /signin. OAuth honors callbackUrl. /account is auth-gated.');
509
587
  return 0;
510
588
  }
589
+ if (command === 'seo') {
590
+ const writes = [
591
+ writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'robots.ts'), renderSeoRobots()),
592
+ writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'sitemap.ts'), renderSeoSitemap()),
593
+ writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'manifest.ts'), renderSeoManifest()),
594
+ ];
595
+ writes.forEach((result) => {
596
+ const relativePath = path_1.default.relative(cwd, result.path).replace(/\\/g, '/');
597
+ log(`${result.created ? 'created' : 'skipped'} ${relativePath}`);
598
+ });
599
+ log('SEO routes: /robots.txt, /sitemap.xml, /manifest.webmanifest');
600
+ log('Set VISTA_SITE_URL (or NEXT_PUBLIC_SITE_URL) for absolute sitemap/robots URLs.');
601
+ return 0;
602
+ }
511
603
  printGenerateUsage(log);
512
604
  return 1;
513
605
  }
@@ -12,6 +12,7 @@ const server_component_plugin_1 = require("./server-component-plugin");
12
12
  const vista_flight_plugin_1 = require("../build/webpack/plugins/vista-flight-plugin");
13
13
  const constants_1 = require("../constants");
14
14
  const app_dir_1 = require("../server/app-dir");
15
+ const project_alias_resolver_1 = require("../server/project-alias-resolver");
15
16
  function createWebpackConfig(options) {
16
17
  const { cwd, isDev, engineVariant = 'default', cacheComponentsEnabled = false, imagesUnoptimized = false, deployOutput, } = options;
17
18
  const vistaDir = path_1.default.join(cwd, constants_1.BUILD_DIR);
@@ -76,6 +77,7 @@ function createWebpackConfig(options) {
76
77
  resolve: {
77
78
  extensions: ['.tsx', '.ts', '.jsx', '.js'],
78
79
  alias: {
80
+ ...(0, project_alias_resolver_1.loadProjectWebpackAliases)(cwd),
79
81
  react: reactPath,
80
82
  'react-dom': reactDomPath,
81
83
  'react/jsx-runtime': path_1.default.join(reactPath, 'jsx-runtime'),
@@ -177,7 +179,7 @@ function createWebpackConfig(options) {
177
179
  devtool: isDev ? 'eval-cheap-module-source-map' : 'source-map',
178
180
  stats: 'minimal',
179
181
  infrastructureLogging: {
180
- level: 'warn',
182
+ level: isDev ? 'none' : 'error',
181
183
  },
182
184
  };
183
185
  }
@@ -18,6 +18,19 @@ export interface RSCCompilerOptions {
18
18
  imagesUnoptimized?: boolean;
19
19
  deployOutput?: DeployOutput;
20
20
  }
21
+ type FlightClientReferenceOption = string | {
22
+ directory: string;
23
+ recursive: boolean;
24
+ include: RegExp;
25
+ };
26
+ /**
27
+ * Build ReactFlightWebpackPlugin `clientReferences`.
28
+ *
29
+ * Project roots (`app/`, `components/`, `lib/`, ...) are passed as watched
30
+ * directories so newly added `'use client'` files are registered without a full
31
+ * rebuild. Framework package paths stay as absolute files.
32
+ */
33
+ export declare function buildFlightClientReferenceOptions(cwd: string, explicitFiles?: string[]): FlightClientReferenceOption[];
21
34
  /**
22
35
  * Create Server-Side Webpack Configuration
23
36
  *
@@ -39,3 +52,4 @@ export declare function runRSCBuild(cwd: string, isDev: boolean): Promise<{
39
52
  serverCompiler: webpack.Compiler;
40
53
  clientCompiler: webpack.Compiler;
41
54
  }>;
55
+ export {};
@@ -10,6 +10,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
10
10
  return (mod && mod.__esModule) ? mod : { "default": mod };
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.buildFlightClientReferenceOptions = buildFlightClientReferenceOptions;
13
14
  exports.createServerWebpackConfig = createServerWebpackConfig;
14
15
  exports.createClientWebpackConfig = createClientWebpackConfig;
15
16
  exports.runRSCBuild = runRSCBuild;
@@ -22,6 +23,51 @@ const server_manifest_1 = require("./server-manifest");
22
23
  const react_client_reference_manifest_1 = require("./react-client-reference-manifest");
23
24
  const constants_1 = require("../../constants");
24
25
  const app_dir_1 = require("../../server/app-dir");
26
+ const project_alias_resolver_1 = require("../../server/project-alias-resolver");
27
+ function isPathInside(target, ancestor) {
28
+ const resolvedTarget = path_1.default.resolve(target);
29
+ const resolvedAncestor = path_1.default.resolve(ancestor);
30
+ if (resolvedTarget === resolvedAncestor)
31
+ return true;
32
+ const prefix = resolvedAncestor.endsWith(path_1.default.sep)
33
+ ? resolvedAncestor
34
+ : `${resolvedAncestor}${path_1.default.sep}`;
35
+ return resolvedTarget.startsWith(prefix);
36
+ }
37
+ /**
38
+ * Build ReactFlightWebpackPlugin `clientReferences`.
39
+ *
40
+ * Project roots (`app/`, `components/`, `lib/`, ...) are passed as watched
41
+ * directories so newly added `'use client'` files are registered without a full
42
+ * rebuild. Framework package paths stay as absolute files.
43
+ */
44
+ function buildFlightClientReferenceOptions(cwd, explicitFiles = []) {
45
+ const roots = (0, client_manifest_1.discoverProjectClientRoots)(cwd).filter((root) => fs_1.default.existsSync(root.dir));
46
+ const directoryRefs = roots.map((root) => ({
47
+ directory: path_1.default.resolve(root.dir),
48
+ recursive: true,
49
+ include: /\.[cm]?[jt]sx?$/,
50
+ }));
51
+ // Always include app/ even if discover somehow missed it (empty cwd edge cases).
52
+ const appDir = (0, app_dir_1.resolveAppDir)(cwd);
53
+ if (fs_1.default.existsSync(appDir) &&
54
+ !directoryRefs.some((entry) => typeof entry !== 'string' && path_1.default.resolve(entry.directory) === path_1.default.resolve(appDir))) {
55
+ directoryRefs.unshift({
56
+ directory: path_1.default.resolve(appDir),
57
+ recursive: true,
58
+ include: /\.[cm]?[jt]sx?$/,
59
+ });
60
+ }
61
+ const rootDirs = roots.map((root) => path_1.default.resolve(root.dir));
62
+ if (fs_1.default.existsSync(appDir)) {
63
+ rootDirs.push(path_1.default.resolve(appDir));
64
+ }
65
+ const externalFiles = Array.from(new Set(explicitFiles
66
+ .filter((entry) => typeof entry === 'string' && entry.length > 0)
67
+ .map((entry) => path_1.default.resolve(entry))
68
+ .filter((entry) => !rootDirs.some((dir) => isPathInside(entry, dir)))));
69
+ return [...directoryRefs, ...externalFiles];
70
+ }
25
71
  // Find module path (handles monorepo hoisting)
26
72
  const findModulePath = (moduleName, cwd) => {
27
73
  const localPath = path_1.default.resolve(cwd, 'node_modules', moduleName);
@@ -65,6 +111,7 @@ function createServerWebpackConfig(options) {
65
111
  const swcLoaderPath = resolveFromWorkspace('swc-loader', cwd);
66
112
  const nullLoaderPath = resolveFromWorkspace('null-loader', cwd);
67
113
  const cssLoaderPath = resolveFromWorkspace('css-loader', cwd);
114
+ const projectAliases = (0, project_alias_resolver_1.loadProjectWebpackAliases)(cwd);
68
115
  // Generate server manifest first
69
116
  const serverManifest = (0, server_manifest_1.generateServerManifest)(cwd, (0, app_dir_1.resolveAppDir)(cwd));
70
117
  fs_1.default.writeFileSync(path_1.default.join(vistaDirs.server, 'server-manifest.json'), JSON.stringify(serverManifest, null, 2));
@@ -109,12 +156,13 @@ function createServerWebpackConfig(options) {
109
156
  clean: !isDev,
110
157
  },
111
158
  externals: [
112
- // Don't bundle node_modules on server
159
+ // Don't bundle node_modules on server. Project path aliases (@/…) stay inside the bundle.
113
160
  ({ request }, callback) => {
114
161
  if (request &&
115
162
  !request.startsWith('.') &&
116
163
  !request.startsWith('/') &&
117
- !path_1.default.isAbsolute(request)) {
164
+ !path_1.default.isAbsolute(request) &&
165
+ !(0, project_alias_resolver_1.requestUsesProjectAlias)(request, projectAliases)) {
118
166
  // External - don't bundle
119
167
  return callback(null, 'commonjs ' + request);
120
168
  }
@@ -126,6 +174,7 @@ function createServerWebpackConfig(options) {
126
174
  : false,
127
175
  resolve: {
128
176
  extensions: ['.tsx', '.ts', '.jsx', '.js'],
177
+ alias: projectAliases,
129
178
  modules: [path_1.default.resolve(cwd, 'node_modules'), 'node_modules'],
130
179
  },
131
180
  module: {
@@ -189,6 +238,11 @@ function createServerWebpackConfig(options) {
189
238
  ],
190
239
  devtool: isDev ? 'source-map' : false,
191
240
  stats: 'minimal',
241
+ // Webpack's infrastructure logger prints `<i> [webpack-dev-middleware] …`.
242
+ // Vista logs compile failures itself.
243
+ infrastructureLogging: {
244
+ level: isDev ? 'none' : 'error',
245
+ },
192
246
  };
193
247
  }
194
248
  /**
@@ -211,9 +265,11 @@ function createClientWebpackConfig(options) {
211
265
  const reactFlightPluginPath = resolveFromWorkspace('react-server-dom-webpack/plugin', cwd);
212
266
  const reactFlightClientPath = resolveFromWorkspace('react-server-dom-webpack/client.browser', cwd);
213
267
  const ReactFlightWebpackPlugin = require(reactFlightPluginPath);
214
- const flightClientReferences = Array.from(new Set(clientReferenceFiles
215
- .filter((entry) => typeof entry === 'string' && entry.length > 0)
216
- .map((entry) => path_1.default.resolve(entry))));
268
+ const projectAliases = (0, project_alias_resolver_1.loadProjectWebpackAliases)(cwd);
269
+ // Prefer watched project directories over a frozen absolute-file list so that
270
+ // newly added `'use client'` modules under components/, lib/, etc. enter the
271
+ // Flight client manifest without restarting the compiler.
272
+ const flightClientReferences = buildFlightClientReferenceOptions(cwd, clientReferenceFiles);
217
273
  // Entry: Only client components
218
274
  const clientEntry = path_1.default.join(vistaDirs.root, 'rsc-client.tsx');
219
275
  return {
@@ -238,6 +294,7 @@ function createClientWebpackConfig(options) {
238
294
  resolve: {
239
295
  extensions: ['.tsx', '.ts', '.jsx', '.js'],
240
296
  alias: {
297
+ ...projectAliases,
241
298
  react: reactPath,
242
299
  'react-dom': reactDomPath,
243
300
  'react/jsx-runtime': path_1.default.join(reactPath, 'jsx-runtime'),
@@ -340,7 +397,7 @@ function createClientWebpackConfig(options) {
340
397
  {
341
398
  directory: (0, app_dir_1.resolveAppDir)(cwd),
342
399
  recursive: true,
343
- include: /\.[jt]sx?$/,
400
+ include: /\.[cm]?[jt]sx?$/,
344
401
  },
345
402
  ],
346
403
  }),
@@ -422,6 +479,9 @@ function createClientWebpackConfig(options) {
422
479
  ],
423
480
  devtool: isDev ? 'eval-cheap-module-source-map' : 'source-map',
424
481
  stats: 'minimal',
482
+ infrastructureLogging: {
483
+ level: isDev ? 'none' : 'error',
484
+ },
425
485
  };
426
486
  }
427
487
  /**
@@ -286,17 +286,18 @@ function scanForServerComponents(dir, appDir, components) {
286
286
  continue;
287
287
  try {
288
288
  const source = fs_1.default.readFileSync(fullPath, 'utf-8');
289
- // Only add if NOT a client component
290
- if (!hasClientDirective(source)) {
289
+ const componentType = getComponentType(item.name);
290
+ const isClient = hasClientDirective(source);
291
+ if (!isClient || componentType !== 'component') {
291
292
  const relativePath = (0, component_identity_1.relativeComponentPath)(appDir, fullPath);
292
- const moduleId = (0, component_identity_1.createComponentId)('server', relativePath);
293
+ const moduleId = (0, component_identity_1.createComponentId)(isClient ? 'client' : 'server', relativePath);
293
294
  const metadata = analyzeMetadata(source);
294
295
  const renderConfig = analyzeRenderConfig(source);
295
296
  components.push({
296
297
  id: moduleId,
297
298
  path: relativePath,
298
299
  absolutePath: fullPath,
299
- type: getComponentType(item.name),
300
+ type: componentType,
300
301
  hasMetadata: metadata.hasMetadata,
301
302
  hasGenerateMetadata: metadata.hasGenerateMetadata,
302
303
  hasGenerateStaticParams: renderConfig.hasGenerateStaticParams,
package/dist/config.d.ts CHANGED
@@ -12,6 +12,11 @@ export interface VistaEngineConfig {
12
12
  * Compatibility alias accepted: webpack.
13
13
  */
14
14
  variant?: VistaEngineVariant | VistaEngineAlias;
15
+ /**
16
+ * Flashpack crate pipeline launched by the vista package.
17
+ * Set by create-vista-app when the selected engine is flashpack.
18
+ */
19
+ pipeline?: 'flashpack-cli';
15
20
  }
16
21
  export interface StructureValidationConfig {
17
22
  /** Enable structure validation. Default: true */
package/dist/config.js CHANGED
@@ -90,8 +90,22 @@ function readEngineVariantFromEnv(env) {
90
90
  return 'default';
91
91
  return undefined;
92
92
  }
93
+ function readEngineVariantFromPackage(cwd) {
94
+ try {
95
+ const pkg = JSON.parse(fs_1.default.readFileSync(path_1.default.join(cwd, 'package.json'), 'utf8'));
96
+ const vista = pkg.vista;
97
+ const raw = typeof vista === 'string' ? vista : vista?.engine;
98
+ return normalizeEngineVariant(raw);
99
+ }
100
+ catch {
101
+ return undefined;
102
+ }
103
+ }
93
104
  function resolveEngineVariant(config, env = process.env) {
94
- return readEngineVariantFromEnv(env) || readEngineVariantFromConfig(config) || 'default';
105
+ return (readEngineVariantFromEnv(env) ||
106
+ readEngineVariantFromPackage(env.VISTA_ARTIFACT_ROOT || process.cwd()) ||
107
+ readEngineVariantFromConfig(config) ||
108
+ 'default');
95
109
  }
96
110
  function applyEngineVariantToEnv(variant, env = process.env) {
97
111
  env.VISTA_ENGINE = variant;
@@ -17,7 +17,7 @@ const RENDER_YAML_TEMPLATE = `services:
17
17
  buildCommand: |
18
18
  npm install --no-audit --no-fund
19
19
  npm run build
20
- startCommand: npm run start
20
+ startCommand: node .vista/standalone/server.js
21
21
  envVars:
22
22
  - key: NODE_ENV
23
23
  value: production
@@ -45,7 +45,7 @@ exports.renderAdapter = {
45
45
  artifactPaths,
46
46
  instructions: [
47
47
  'Connect this repository on Render and select Blueprint (render.yaml).',
48
- 'Or create a Web Service with buildCommand "npm run build" and startCommand "npm run start".',
48
+ 'Or create a Web Service with buildCommand "npm run build" and startCommand "node .vista/standalone/server.js".',
49
49
  ],
50
50
  };
51
51
  },
@@ -5,6 +5,7 @@ export type { DeployContext, DeployResult, DeployAdapter, ResolvedDeployTarget }
5
5
  export interface RunDeployOptions {
6
6
  cwd?: string;
7
7
  target?: string | null;
8
+ output?: 'standalone' | 'static' | 'hybrid';
8
9
  dryRun?: boolean;
9
10
  skipBuild?: boolean;
10
11
  prod?: boolean;
@@ -23,6 +23,9 @@ function createContext(options) {
23
23
  const cwd = options.cwd ?? process.cwd();
24
24
  const config = (0, config_1.loadConfig)(cwd);
25
25
  const deployConfig = (0, config_1.resolveDeployConfig)(config);
26
+ if (options.output) {
27
+ deployConfig.output = options.output;
28
+ }
26
29
  const target = (0, detect_1.resolveDeployTarget)(cwd, deployConfig, options.target ?? null);
27
30
  return {
28
31
  cwd,
@@ -17,7 +17,28 @@ const fs_1 = __importDefault(require("fs"));
17
17
  const path_1 = __importDefault(require("path"));
18
18
  const utils_1 = require("./utils");
19
19
  function isStaticOnlyDeploy(ctx) {
20
- return ctx.deployConfig.output === 'static';
20
+ if (ctx.deployConfig.output === 'static') {
21
+ return true;
22
+ }
23
+ if (ctx.target === 'cloudflare') {
24
+ if (ctx.config.deploy?.output === 'standalone') {
25
+ return false;
26
+ }
27
+ if (process.env.CF_PAGES === '1' || process.env.CLOUDFLARE_PAGES) {
28
+ return true;
29
+ }
30
+ const wranglerPath = path_1.default.join(ctx.cwd, 'wrangler.toml');
31
+ if (fs_1.default.existsSync(wranglerPath)) {
32
+ const content = fs_1.default.readFileSync(wranglerPath, 'utf8');
33
+ if (content.includes('pages_build_output_dir')) {
34
+ return true;
35
+ }
36
+ if (content.includes('[[containers]]') || content.includes('main =')) {
37
+ return false;
38
+ }
39
+ }
40
+ }
41
+ return false;
21
42
  }
22
43
  function resolveStandaloneServerPath(ctx) {
23
44
  return path_1.default.join(ctx.vistaDir, 'standalone', 'server.js');