@vistagenic/vista 0.1.0-alpha.1

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 (100) hide show
  1. package/bin/vista.js +98 -0
  2. package/dist/auth/index.d.ts +8 -0
  3. package/dist/auth/index.js +16 -0
  4. package/dist/bin/build-rsc.d.ts +17 -0
  5. package/dist/bin/build-rsc.js +320 -0
  6. package/dist/bin/build.d.ts +4 -0
  7. package/dist/bin/build.js +336 -0
  8. package/dist/bin/file-scanner.d.ts +66 -0
  9. package/dist/bin/file-scanner.js +399 -0
  10. package/dist/bin/server-component-plugin.d.ts +17 -0
  11. package/dist/bin/server-component-plugin.js +133 -0
  12. package/dist/bin/webpack.config.d.ts +6 -0
  13. package/dist/bin/webpack.config.js +138 -0
  14. package/dist/build/manifest.d.ts +95 -0
  15. package/dist/build/manifest.js +168 -0
  16. package/dist/build/rsc/client-manifest.d.ts +48 -0
  17. package/dist/build/rsc/client-manifest.js +191 -0
  18. package/dist/build/rsc/client-reference-plugin.d.ts +37 -0
  19. package/dist/build/rsc/client-reference-plugin.js +185 -0
  20. package/dist/build/rsc/compiler.d.ts +36 -0
  21. package/dist/build/rsc/compiler.js +311 -0
  22. package/dist/build/rsc/index.d.ts +16 -0
  23. package/dist/build/rsc/index.js +32 -0
  24. package/dist/build/rsc/native-scanner.d.ts +123 -0
  25. package/dist/build/rsc/native-scanner.js +165 -0
  26. package/dist/build/rsc/rsc-renderer.d.ts +99 -0
  27. package/dist/build/rsc/rsc-renderer.js +269 -0
  28. package/dist/build/rsc/server-component-loader.d.ts +19 -0
  29. package/dist/build/rsc/server-component-loader.js +147 -0
  30. package/dist/build/rsc/server-manifest.d.ts +63 -0
  31. package/dist/build/rsc/server-manifest.js +268 -0
  32. package/dist/build/webpack/loaders/vista-flight-loader.d.ts +17 -0
  33. package/dist/build/webpack/loaders/vista-flight-loader.js +93 -0
  34. package/dist/build/webpack/plugins/vista-flight-plugin.d.ts +36 -0
  35. package/dist/build/webpack/plugins/vista-flight-plugin.js +133 -0
  36. package/dist/client/dynamic.d.ts +25 -0
  37. package/dist/client/dynamic.js +68 -0
  38. package/dist/client/font.d.ts +98 -0
  39. package/dist/client/font.js +109 -0
  40. package/dist/client/head.d.ts +79 -0
  41. package/dist/client/head.js +261 -0
  42. package/dist/client/hydration.d.ts +45 -0
  43. package/dist/client/hydration.js +291 -0
  44. package/dist/client/link.d.ts +30 -0
  45. package/dist/client/link.js +188 -0
  46. package/dist/client/navigation.d.ts +28 -0
  47. package/dist/client/navigation.js +116 -0
  48. package/dist/client/router.d.ts +41 -0
  49. package/dist/client/router.js +190 -0
  50. package/dist/client/script.d.ts +51 -0
  51. package/dist/client/script.js +118 -0
  52. package/dist/components/client-island.d.ts +34 -0
  53. package/dist/components/client-island.js +75 -0
  54. package/dist/components/client.d.ts +29 -0
  55. package/dist/components/client.js +102 -0
  56. package/dist/components/index.d.ts +1 -0
  57. package/dist/components/index.js +8 -0
  58. package/dist/components/link.d.ts +6 -0
  59. package/dist/components/link.js +13 -0
  60. package/dist/config.d.ts +10 -0
  61. package/dist/config.js +31 -0
  62. package/dist/dev-error.d.ts +35 -0
  63. package/dist/dev-error.js +310 -0
  64. package/dist/image/get-img-props.d.ts +28 -0
  65. package/dist/image/get-img-props.js +49 -0
  66. package/dist/image/image-config.d.ts +20 -0
  67. package/dist/image/image-config.js +20 -0
  68. package/dist/image/image-loader.d.ts +7 -0
  69. package/dist/image/image-loader.js +14 -0
  70. package/dist/image/index.d.ts +6 -0
  71. package/dist/image/index.js +110 -0
  72. package/dist/image.d.ts +10 -0
  73. package/dist/image.js +7 -0
  74. package/dist/index.d.ts +20 -0
  75. package/dist/index.js +53 -0
  76. package/dist/metadata/generate.d.ts +22 -0
  77. package/dist/metadata/generate.js +324 -0
  78. package/dist/metadata/index.d.ts +7 -0
  79. package/dist/metadata/index.js +26 -0
  80. package/dist/metadata/types.d.ts +325 -0
  81. package/dist/metadata/types.js +15 -0
  82. package/dist/router/context.d.ts +8 -0
  83. package/dist/router/context.js +13 -0
  84. package/dist/router/index.d.ts +2 -0
  85. package/dist/router/index.js +18 -0
  86. package/dist/router/provider.d.ts +5 -0
  87. package/dist/router/provider.js +31 -0
  88. package/dist/server/client-boundary.d.ts +48 -0
  89. package/dist/server/client-boundary.js +133 -0
  90. package/dist/server/engine.d.ts +4 -0
  91. package/dist/server/engine.js +651 -0
  92. package/dist/server/index.d.ts +95 -0
  93. package/dist/server/index.js +177 -0
  94. package/dist/server/rsc-engine.d.ts +20 -0
  95. package/dist/server/rsc-engine.js +588 -0
  96. package/dist/server/rsc-module-system.d.ts +33 -0
  97. package/dist/server/rsc-module-system.js +119 -0
  98. package/dist/types/index.d.ts +4 -0
  99. package/dist/types/index.js +2 -0
  100. package/package.json +103 -0
@@ -0,0 +1,336 @@
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.compiler = void 0;
7
+ exports.buildClient = buildClient;
8
+ const path_1 = __importDefault(require("path"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const webpack_1 = __importDefault(require("webpack"));
11
+ const webpack_config_1 = require("./webpack.config");
12
+ const file_scanner_1 = require("./file-scanner");
13
+ // Helper to run PostCSS
14
+ function runPostCSS(cwd, vistaDir) {
15
+ const globalsCss = path_1.default.join(cwd, 'app/globals.css');
16
+ if (fs_1.default.existsSync(globalsCss)) {
17
+ console.log("Building CSS with PostCSS...");
18
+ const { execSync } = require('child_process');
19
+ try {
20
+ const cssOut = path_1.default.join(vistaDir, 'client.css');
21
+ execSync(`npx postcss app/globals.css -o "${cssOut}"`, { stdio: 'inherit', cwd });
22
+ console.log("CSS Built Successfully!");
23
+ }
24
+ catch (cssErr) {
25
+ console.error("CSS Build failed (PostCSS error).");
26
+ }
27
+ }
28
+ }
29
+ // Generate Client Entry File - TRUE RSC
30
+ // Only imports components with 'client load' directive
31
+ function generateClientEntry(cwd, vistaDir, clientComponents, isDev = false) {
32
+ const appDir = path_1.default.join(cwd, 'app');
33
+ // Generate imports ONLY for client components
34
+ const clientImports = [];
35
+ const clientRegistrations = [];
36
+ clientComponents.forEach((comp, index) => {
37
+ const relativePath = './' + path_1.default.relative(vistaDir, comp.absolutePath).replace(/\\/g, '/');
38
+ const componentName = `ClientComponent_${index}`;
39
+ const componentId = comp.relativePath.replace(/\\/g, '/').replace(/\.(tsx|ts|jsx|js)$/, '');
40
+ // Extract just the component name (e.g., "Navbar" from "components/Navbar")
41
+ const baseName = path_1.default.basename(comp.relativePath).replace(/\.(tsx|ts|jsx|js)$/, '');
42
+ const lowercaseName = baseName.toLowerCase();
43
+ clientImports.push(`import ${componentName} from "${relativePath}";`);
44
+ // Register by full path (for standard RSC)
45
+ clientRegistrations.push(` "${componentId}": ${componentName},`);
46
+ // Also register by lowercase name (for <Client> wrapper compatibility)
47
+ clientRegistrations.push(` "${lowercaseName}": ${componentName},`);
48
+ });
49
+ // Get Route Tree from Rust (but DON'T bundle server components)
50
+ const { getRouteTree } = require('./file-scanner');
51
+ let routeTree;
52
+ try {
53
+ routeTree = getRouteTree(appDir);
54
+ }
55
+ catch (e) {
56
+ console.error("Failed to generate route tree:", e);
57
+ process.exit(1);
58
+ }
59
+ // For RSC, we only serialize the STRUCTURE, not the components
60
+ // Components are loaded separately
61
+ function serializeRouteStructure(node) {
62
+ const props = [];
63
+ props.push(`segment: "${node.segment}"`);
64
+ props.push(`kind: "${node.kind}"`);
65
+ // Store paths as strings, NOT require() - server renders these
66
+ if (node.indexPath) {
67
+ const componentId = path_1.default.relative(appDir, node.indexPath).replace(/\\/g, '/').replace(/\.(tsx|ts|jsx|js)$/, '');
68
+ props.push(`indexId: "${componentId}"`);
69
+ }
70
+ if (node.layoutPath) {
71
+ const componentId = path_1.default.relative(appDir, node.layoutPath).replace(/\\/g, '/').replace(/\.(tsx|ts|jsx|js)$/, '');
72
+ props.push(`layoutId: "${componentId}"`);
73
+ }
74
+ if (node.loadingPath) {
75
+ const componentId = path_1.default.relative(appDir, node.loadingPath).replace(/\\/g, '/').replace(/\.(tsx|ts|jsx|js)$/, '');
76
+ props.push(`loadingId: "${componentId}"`);
77
+ }
78
+ if (node.children && node.children.length > 0) {
79
+ const childrenStr = node.children.map((child) => serializeRouteStructure(child)).join(',\n');
80
+ props.push(`children: [\n${childrenStr}\n]`);
81
+ }
82
+ else {
83
+ props.push(`children: []`);
84
+ }
85
+ return `{\n${props.join(',\n')}\n}`;
86
+ }
87
+ const routeStructure = serializeRouteStructure(routeTree);
88
+ // TRUE RSC CLIENT ENTRY
89
+ // Only client components are imported here
90
+ const clientEntryContent = `
91
+ // Vista Client Entry - TRUE RSC
92
+ // Only client components are bundled here
93
+ import * as React from 'react';
94
+ import { hydrateRoot } from 'react-dom/client';
95
+
96
+ // CLIENT COMPONENTS ONLY (marked with 'client load')
97
+ ${clientImports.join('\n')}
98
+
99
+ // Register client components for selective hydration
100
+ const CLIENT_COMPONENTS: Record<string, React.ComponentType<any>> = {
101
+ ${clientRegistrations.join('\n')}
102
+ };
103
+
104
+ // Route structure (NO server component code included)
105
+ const routeStructure = ${routeStructure};
106
+
107
+ // Selective Hydration - Only hydrate client component "islands"
108
+ function hydrateClientIslands() {
109
+ const islands = document.querySelectorAll('[data-vista-client]');
110
+
111
+ if (islands.length === 0) {
112
+ // No client islands, but we still need to hydrate for routing
113
+ const root = document.getElementById('root');
114
+ if (root && root.hasChildNodes()) {
115
+ console.log('[Vista RSC] Server-rendered content, minimal client JS loaded');
116
+ }
117
+ return;
118
+ }
119
+
120
+ console.log(\`[Vista RSC] Hydrating \${islands.length} client component(s)\`);
121
+
122
+ islands.forEach((island) => {
123
+ const componentId = island.getAttribute('data-vista-client');
124
+ const propsJson = island.getAttribute('data-props') || '{}';
125
+
126
+ if (componentId && CLIENT_COMPONENTS[componentId]) {
127
+ const Component = CLIENT_COMPONENTS[componentId];
128
+ const props = JSON.parse(propsJson);
129
+
130
+ // Hydrate this island
131
+ hydrateRoot(island as HTMLElement, React.createElement(Component, props));
132
+ island.removeAttribute('data-vista-client');
133
+ island.setAttribute('data-hydrated', 'true');
134
+ }
135
+ });
136
+ }
137
+
138
+ // Run hydration
139
+ if (document.readyState === 'loading') {
140
+ document.addEventListener('DOMContentLoaded', hydrateClientIslands);
141
+ } else {
142
+ hydrateClientIslands();
143
+ }
144
+
145
+ // Hot Module Replacement (HMR) Support
146
+ if ((module as any).hot) {
147
+ (module as any).hot.accept();
148
+ }
149
+
150
+ // Server-Side Live Reload (for server component changes)
151
+ ${isDev ? `
152
+ // Vista Error Overlay Logic
153
+ const VISTA_ERROR_ID = 'vista-compile-error';
154
+
155
+ function showCompileError(message) {
156
+ let div = document.getElementById(VISTA_ERROR_ID);
157
+ if (!div) {
158
+ div = document.createElement('div');
159
+ div.id = VISTA_ERROR_ID;
160
+ div.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.85);z-index:99999;display:flex;align-items:center;justify-content:center;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;backdrop-filter:blur(4px);';
161
+ document.body.appendChild(div);
162
+ }
163
+
164
+ div.innerHTML = \`
165
+ <div style="width:100%;max-width:900px;max-height:90vh;display:flex;flex-direction:column;background:#0a0a0a;border:1px solid #333;border-radius:12px;box-shadow:0 24px 48px -12px rgba(0,0,0,0.5);overflow:hidden;">
166
+ <div style="padding:16px 24px;background:#111;border-bottom:1px solid #333;display:flex;align-items:center;justify-content:space-between;">
167
+ <div style="display:flex;align-items:center;gap:12px;">
168
+ <span style="font-weight:600;color:#f87171;background:rgba(248,113,113,0.1);padding:4px 12px;border-radius:99px;font-size:12px;display:flex;align-items:center;gap:6px;">
169
+ <span style="width:8px;height:8px;background:currentColor;border-radius:50%;"></span>
170
+ BUILD ERROR
171
+ </span>
172
+ <span style="color:#666;font-size:13px;">Vista Dev</span>
173
+ </div>
174
+ </div>
175
+ <div style="padding:24px;overflow:auto;background:#0a0a0a;">
176
+ <pre style="margin:0;font-size:13px;line-height:1.6;color:#e5e7eb;white-space:pre-wrap;">\${message.replace(/</g, '&lt;').replace(/>/g, '&gt;')}</pre>
177
+ </div>
178
+ </div>
179
+ \`;
180
+ }
181
+
182
+ function hideCompileError() {
183
+ const div = document.getElementById(VISTA_ERROR_ID);
184
+ if (div) div.remove();
185
+ }
186
+
187
+ const sse = new EventSource('/__vista_reload');
188
+ sse.onmessage = (event) => {
189
+ if (event.data === 'reload') {
190
+ hideCompileError();
191
+ console.log('[Vista] Server component changed, reloading...');
192
+ window.location.reload();
193
+ return;
194
+ }
195
+
196
+ try {
197
+ const data = JSON.parse(event.data);
198
+ if (data.type === 'error') {
199
+ showCompileError(data.message);
200
+ } else if (data.type === 'ok') {
201
+ hideCompileError();
202
+ }
203
+ } catch (e) {
204
+ // Ignore JSON parse errors for non-JSON messages
205
+ }
206
+ };
207
+
208
+ sse.onerror = (e) => {
209
+ console.log('[Vista] SSE connection lost');
210
+ };
211
+ ` : '// SSE reload disabled in production'}
212
+
213
+ // Export for debugging
214
+ (window as any).__VISTA_CLIENT_COMPONENTS__ = CLIENT_COMPONENTS;
215
+ `;
216
+ fs_1.default.writeFileSync(path_1.default.join(vistaDir, 'client.tsx'), clientEntryContent);
217
+ console.log(`[Vista RSC] Generated client entry with ${clientComponents.length} client component(s)`);
218
+ }
219
+ // Webpack Compiler Instance (reused for watch mode)
220
+ let compiler = null;
221
+ exports.compiler = compiler;
222
+ async function buildClient(watch = false, onRebuild) {
223
+ const cwd = process.cwd();
224
+ const vistaDir = path_1.default.join(cwd, '.vista');
225
+ console.log(`Building Client (Watch Mode: ${watch}, Bundler: Webpack + SWC)...`);
226
+ // Ensure .vista directory exists
227
+ if (!fs_1.default.existsSync(vistaDir)) {
228
+ fs_1.default.mkdirSync(vistaDir);
229
+ }
230
+ // Scan app directory using Rust bindings to get client components
231
+ const appDir = path_1.default.join(cwd, 'app');
232
+ const componentsDir = path_1.default.join(cwd, 'components');
233
+ let clientComponents = [];
234
+ if (fs_1.default.existsSync(appDir)) {
235
+ console.log(`[Vista] Using ${(0, file_scanner_1.isNativeAvailable)() ? 'Rust native' : 'JS fallback'} scanner (v${(0, file_scanner_1.getVersion)()})`);
236
+ const scanResult = (0, file_scanner_1.scanAppDirectory)(appDir);
237
+ console.log(`[Vista] Found ${scanResult.clientComponents.length} client components, ${scanResult.serverComponents.length} server components in app/`);
238
+ // Store client components for entry generation
239
+ clientComponents = scanResult.clientComponents.map(c => ({
240
+ relativePath: c.relativePath,
241
+ absolutePath: c.absolutePath
242
+ }));
243
+ // Log client components
244
+ if (scanResult.clientComponents.length > 0) {
245
+ console.log(`[Vista] Client components ('client load') from app/:`);
246
+ scanResult.clientComponents.forEach(c => {
247
+ console.log(` - ${c.relativePath}`);
248
+ });
249
+ }
250
+ // Check for server component errors (using client hooks without 'client load')
251
+ if (scanResult.errors.length > 0) {
252
+ console.log('');
253
+ console.log('\x1b[41m\x1b[37m ERROR \x1b[0m \x1b[31mServer Component Error\x1b[0m');
254
+ console.log('');
255
+ for (const error of scanResult.errors) {
256
+ console.log(`\x1b[31m✗\x1b[0m ${error.file}`);
257
+ console.log(` You're importing a component that needs \x1b[33m${error.hooks.slice(0, 3).join(', ')}\x1b[0m.`);
258
+ console.log(` These only work in a Client Component.`);
259
+ console.log('');
260
+ console.log(` \x1b[36mTo fix:\x1b[0m Add \x1b[33m'client load'\x1b[0m at the top of your file:`);
261
+ console.log('');
262
+ console.log(` \x1b[32m'client load';\x1b[0m`);
263
+ console.log('');
264
+ }
265
+ }
266
+ }
267
+ // Also scan components directory (outside app folder) for client components
268
+ if (fs_1.default.existsSync(componentsDir)) {
269
+ console.log(`[Vista] Scanning components/ directory...`);
270
+ const componentsScanResult = (0, file_scanner_1.scanAppDirectory)(componentsDir);
271
+ // Map relativePath to include 'components/' prefix for proper resolution
272
+ const componentsClientList = componentsScanResult.clientComponents.map(c => ({
273
+ relativePath: 'components/' + c.relativePath,
274
+ absolutePath: c.absolutePath
275
+ }));
276
+ clientComponents = [...clientComponents, ...componentsClientList];
277
+ if (componentsScanResult.clientComponents.length > 0) {
278
+ console.log(`[Vista] Client components ('client load') from components/:`);
279
+ componentsScanResult.clientComponents.forEach(c => {
280
+ console.log(` - components/${c.relativePath}`);
281
+ });
282
+ }
283
+ }
284
+ console.log(`[Vista] Total client components: ${clientComponents.length}`);
285
+ // Generate client entry - TRUE RSC: only client components
286
+ generateClientEntry(cwd, vistaDir, clientComponents, watch);
287
+ // Create Webpack config
288
+ const config = (0, webpack_config_1.createWebpackConfig)({ cwd, isDev: watch });
289
+ // Create Webpack compiler
290
+ exports.compiler = compiler = (0, webpack_1.default)(config);
291
+ if (watch) {
292
+ // In watch mode, we return the compiler for use with dev middleware
293
+ // Initial CSS build
294
+ runPostCSS(cwd, vistaDir);
295
+ // Watch for CSS changes separately (simple approach)
296
+ const chokidar = require('chokidar');
297
+ try {
298
+ chokidar.watch(path_1.default.join(cwd, 'app/**/*.css'), { ignoreInitial: true })
299
+ .on('change', () => {
300
+ console.log('CSS changed, rebuilding...');
301
+ runPostCSS(cwd, vistaDir);
302
+ });
303
+ }
304
+ catch (e) {
305
+ // chokidar not installed, skip CSS watch
306
+ }
307
+ console.log("Webpack compiler ready for dev middleware.");
308
+ return compiler;
309
+ }
310
+ else {
311
+ // Production build
312
+ return new Promise((resolve, reject) => {
313
+ compiler.run((err, stats) => {
314
+ if (err) {
315
+ console.error("Webpack build error:", err);
316
+ reject(err);
317
+ return;
318
+ }
319
+ if (stats?.hasErrors()) {
320
+ console.error("Webpack compilation errors:", stats.toString('errors-only'));
321
+ reject(new Error("Compilation failed"));
322
+ return;
323
+ }
324
+ console.log("Webpack build complete!");
325
+ console.log(stats?.toString('minimal'));
326
+ // Build CSS
327
+ runPostCSS(cwd, vistaDir);
328
+ compiler.close((closeErr) => {
329
+ if (closeErr)
330
+ console.error("Error closing compiler:", closeErr);
331
+ resolve(null);
332
+ });
333
+ });
334
+ });
335
+ }
336
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Vista File Scanner
3
+ *
4
+ * Scans the app directory and categorizes files as client or server components
5
+ * using Rust NAPI bindings for fast detection.
6
+ *
7
+ * Server Component Rules:
8
+ * - By default, all components are Server Components
9
+ * - Using 'client load' directive makes it a Client Component
10
+ * - Using client hooks (useState, useEffect, etc.) without 'client load' is an ERROR
11
+ *
12
+ * Performance: Uses Rust-powered RSC scanner when available (~10-100x faster)
13
+ */
14
+ export interface RouteNode {
15
+ segment: string;
16
+ kind: 'static' | 'dynamic' | 'catch-all';
17
+ indexPath?: string;
18
+ layoutPath?: string;
19
+ loadingPath?: string;
20
+ errorPath?: string;
21
+ notFoundPath?: string;
22
+ children: RouteNode[];
23
+ }
24
+ export declare function getRouteTree(appDir: string): RouteNode;
25
+ export interface ClientDirectiveInfo {
26
+ is_client: boolean;
27
+ directive_line: number;
28
+ }
29
+ export interface ScannedFile {
30
+ absolutePath: string;
31
+ relativePath: string;
32
+ isClient: boolean;
33
+ directiveLine: number;
34
+ exports: string[];
35
+ clientHooksUsed: string[];
36
+ hasError: boolean;
37
+ errorMessage?: string;
38
+ }
39
+ export interface ScanResult {
40
+ clientComponents: ScannedFile[];
41
+ serverComponents: ScannedFile[];
42
+ layouts: ScannedFile[];
43
+ pages: ScannedFile[];
44
+ notFound?: ScannedFile;
45
+ error?: ScannedFile;
46
+ loading?: ScannedFile;
47
+ errors: ScanError[];
48
+ }
49
+ export interface ScanError {
50
+ file: string;
51
+ message: string;
52
+ hooks: string[];
53
+ }
54
+ /**
55
+ * Scan the app directory and return categorized files
56
+ * Uses Rust-powered RSC scanner when available for ~10-100x faster performance
57
+ */
58
+ export declare function scanAppDirectory(appDir: string): ScanResult;
59
+ /**
60
+ * Check if Rust native bindings are available
61
+ */
62
+ export declare function isNativeAvailable(): boolean;
63
+ /**
64
+ * Get version info
65
+ */
66
+ export declare function getVersion(): string;