@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.
- package/bin/vista.js +98 -0
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/index.js +16 -0
- package/dist/bin/build-rsc.d.ts +17 -0
- package/dist/bin/build-rsc.js +320 -0
- package/dist/bin/build.d.ts +4 -0
- package/dist/bin/build.js +336 -0
- package/dist/bin/file-scanner.d.ts +66 -0
- package/dist/bin/file-scanner.js +399 -0
- package/dist/bin/server-component-plugin.d.ts +17 -0
- package/dist/bin/server-component-plugin.js +133 -0
- package/dist/bin/webpack.config.d.ts +6 -0
- package/dist/bin/webpack.config.js +138 -0
- package/dist/build/manifest.d.ts +95 -0
- package/dist/build/manifest.js +168 -0
- package/dist/build/rsc/client-manifest.d.ts +48 -0
- package/dist/build/rsc/client-manifest.js +191 -0
- package/dist/build/rsc/client-reference-plugin.d.ts +37 -0
- package/dist/build/rsc/client-reference-plugin.js +185 -0
- package/dist/build/rsc/compiler.d.ts +36 -0
- package/dist/build/rsc/compiler.js +311 -0
- package/dist/build/rsc/index.d.ts +16 -0
- package/dist/build/rsc/index.js +32 -0
- package/dist/build/rsc/native-scanner.d.ts +123 -0
- package/dist/build/rsc/native-scanner.js +165 -0
- package/dist/build/rsc/rsc-renderer.d.ts +99 -0
- package/dist/build/rsc/rsc-renderer.js +269 -0
- package/dist/build/rsc/server-component-loader.d.ts +19 -0
- package/dist/build/rsc/server-component-loader.js +147 -0
- package/dist/build/rsc/server-manifest.d.ts +63 -0
- package/dist/build/rsc/server-manifest.js +268 -0
- package/dist/build/webpack/loaders/vista-flight-loader.d.ts +17 -0
- package/dist/build/webpack/loaders/vista-flight-loader.js +93 -0
- package/dist/build/webpack/plugins/vista-flight-plugin.d.ts +36 -0
- package/dist/build/webpack/plugins/vista-flight-plugin.js +133 -0
- package/dist/client/dynamic.d.ts +25 -0
- package/dist/client/dynamic.js +68 -0
- package/dist/client/font.d.ts +98 -0
- package/dist/client/font.js +109 -0
- package/dist/client/head.d.ts +79 -0
- package/dist/client/head.js +261 -0
- package/dist/client/hydration.d.ts +45 -0
- package/dist/client/hydration.js +291 -0
- package/dist/client/link.d.ts +30 -0
- package/dist/client/link.js +188 -0
- package/dist/client/navigation.d.ts +28 -0
- package/dist/client/navigation.js +116 -0
- package/dist/client/router.d.ts +41 -0
- package/dist/client/router.js +190 -0
- package/dist/client/script.d.ts +51 -0
- package/dist/client/script.js +118 -0
- package/dist/components/client-island.d.ts +34 -0
- package/dist/components/client-island.js +75 -0
- package/dist/components/client.d.ts +29 -0
- package/dist/components/client.js +102 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +8 -0
- package/dist/components/link.d.ts +6 -0
- package/dist/components/link.js +13 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.js +31 -0
- package/dist/dev-error.d.ts +35 -0
- package/dist/dev-error.js +310 -0
- package/dist/image/get-img-props.d.ts +28 -0
- package/dist/image/get-img-props.js +49 -0
- package/dist/image/image-config.d.ts +20 -0
- package/dist/image/image-config.js +20 -0
- package/dist/image/image-loader.d.ts +7 -0
- package/dist/image/image-loader.js +14 -0
- package/dist/image/index.d.ts +6 -0
- package/dist/image/index.js +110 -0
- package/dist/image.d.ts +10 -0
- package/dist/image.js +7 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +53 -0
- package/dist/metadata/generate.d.ts +22 -0
- package/dist/metadata/generate.js +324 -0
- package/dist/metadata/index.d.ts +7 -0
- package/dist/metadata/index.js +26 -0
- package/dist/metadata/types.d.ts +325 -0
- package/dist/metadata/types.js +15 -0
- package/dist/router/context.d.ts +8 -0
- package/dist/router/context.js +13 -0
- package/dist/router/index.d.ts +2 -0
- package/dist/router/index.js +18 -0
- package/dist/router/provider.d.ts +5 -0
- package/dist/router/provider.js +31 -0
- package/dist/server/client-boundary.d.ts +48 -0
- package/dist/server/client-boundary.js +133 -0
- package/dist/server/engine.d.ts +4 -0
- package/dist/server/engine.js +651 -0
- package/dist/server/index.d.ts +95 -0
- package/dist/server/index.js +177 -0
- package/dist/server/rsc-engine.d.ts +20 -0
- package/dist/server/rsc-engine.js +588 -0
- package/dist/server/rsc-module-system.d.ts +33 -0
- package/dist/server/rsc-module-system.js +119 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.js +2 -0
- 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, '<').replace(/>/g, '>')}</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;
|