@vistagenic/vista 0.2.4 → 0.2.6

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.
@@ -26,6 +26,8 @@ const constants_1 = require("../constants");
26
26
  const structure_validator_1 = require("../server/structure-validator");
27
27
  const static_generator_1 = require("../server/static-generator");
28
28
  const structure_log_1 = require("../server/structure-log");
29
+ const devtools_indicator_snippet_1 = require("./devtools-indicator-snippet");
30
+ const dev_error_overlay_snippet_1 = require("./dev-error-overlay-snippet");
29
31
  const _debug = !!process.env.VISTA_DEBUG;
30
32
  /**
31
33
  * Run PostCSS for CSS compilation
@@ -101,55 +103,148 @@ function collectFrameworkClientReferences(cwd) {
101
103
  * Generate the RSC-aware client entry file
102
104
  */
103
105
  function generateRSCClientEntry(cwd, vistaDir, isDev) {
104
- const clientEntryContent = `/**
105
- * Vista RSC Client Entry
106
+ const devToolsBootId = `rsc-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
107
+ const clientEntryContent = `/**
108
+ * Vista RSC Client Entry
106
109
  *
107
110
  * This file is auto-generated. Do not edit directly.
108
111
  * It hydrates using React Flight data from /rsc and enables
109
112
  * RSC-aware client-side navigation via RSCRouter.
110
113
  */
111
114
 
112
- import * as React from 'react';
113
- import { hydrateRoot } from 'react-dom/client';
114
- import { createFromFetch } from 'react-server-dom-webpack/client';
115
- import { RSCRouter } from 'vista/client/rsc-router';
116
- import { callServer } from 'vista/client/server-actions';
115
+ import * as React from 'react';
116
+ import { hydrateRoot, createRoot } from 'react-dom/client';
117
+ import { createFromFetch } from 'react-server-dom-webpack/client';
118
+ import { RSCRouter } from 'vista/client/rsc-router';
119
+ import { callServer } from 'vista/client/server-actions';
117
120
 
118
121
  const hydrateDocument = (window as any).${constants_1.HYDRATE_DOCUMENT_FLAG} === true;
119
122
  const rootElement = hydrateDocument ? document : document.getElementById('root');
120
- if (!rootElement) {
121
- throw new Error('Missing #root element for hydration.');
122
- }
123
-
124
- const pathname = window.location.pathname;
125
- const search = window.location.search;
126
- const initialResponse = createFromFetch(
127
- fetch(\`/rsc\${pathname}\${search}\`, { headers: { Accept: 'text/x-component' } }),
128
- { callServer }
129
- ) as Promise<React.ReactNode>;
130
-
131
- hydrateRoot(
132
- rootElement as Document | Element,
133
- React.createElement(RSCRouter, {
134
- initialResponse,
135
- initialPathname: pathname,
136
- })
137
- );
138
-
123
+ if (!rootElement) {
124
+ throw new Error('Missing #root element for hydration.');
125
+ }
126
+
127
+ ${isDev ? (0, devtools_indicator_snippet_1.getDevToolsIndicatorBootstrapSource)(devToolsBootId) : ''}
128
+ ${isDev ? (0, dev_error_overlay_snippet_1.getDevErrorOverlayBootstrapSource)() : ''}
129
+
130
+ function buildRuntimeMessage(title: string, error: unknown): string {
131
+ var value = error as any;
132
+ var text = '';
133
+ if (value && typeof value === 'object') {
134
+ if (typeof value.message === 'string' && value.message.trim().length > 0) {
135
+ text = value.message;
136
+ }
137
+ if (typeof value.stack === 'string' && value.stack.trim().length > 0) {
138
+ text = text ? text + '\\n\\n' + value.stack : value.stack;
139
+ }
140
+ }
141
+ if (!text) {
142
+ text = typeof error === 'string' ? error : String(error || 'Unknown runtime error.');
143
+ }
144
+ return title + '\\n\\n' + text;
145
+ }
146
+
147
+ function reportDevRuntimeError(title: string, error: unknown): void {
148
+ if (typeof window === 'undefined') return;
149
+ var indicator = (window as any).__VISTA_DEVTOOLS_INDICATOR__;
150
+ var overlay = (window as any).__VISTA_DEV_ERROR_OVERLAY__;
151
+ var message = buildRuntimeMessage(title, error);
152
+ if (indicator && typeof indicator.setError === 'function') {
153
+ indicator.setError(title, 1);
154
+ }
155
+ if (overlay && typeof overlay.capture === 'function') {
156
+ overlay.capture([message]);
157
+ return;
158
+ }
159
+ if (overlay && typeof overlay.show === 'function') {
160
+ overlay.show([message]);
161
+ if (typeof overlay.minimize === 'function') {
162
+ overlay.minimize();
163
+ }
164
+ return;
165
+ }
166
+ console.error('[vista] ' + title + ':', error);
167
+ }
168
+
169
+ if (typeof window !== 'undefined') {
170
+ window.addEventListener('error', function (event) {
171
+ var runtimeError = (event as ErrorEvent).error || (event as ErrorEvent).message;
172
+ reportDevRuntimeError('Runtime Error', runtimeError);
173
+ });
174
+ window.addEventListener('unhandledrejection', function (event) {
175
+ reportDevRuntimeError('Unhandled Promise Rejection', (event as PromiseRejectionEvent).reason);
176
+ });
177
+ }
178
+
179
+ const pathname = window.location.pathname;
180
+ const search = window.location.search;
181
+ const initialResponse = createFromFetch(
182
+ fetch(\`/rsc\${pathname}\${search}\`, { headers: { Accept: 'text/x-component' } }),
183
+ { callServer }
184
+ ) as Promise<React.ReactNode>;
185
+
186
+ var appElement = React.createElement(RSCRouter, {
187
+ initialResponse,
188
+ initialPathname: pathname,
189
+ });
190
+
191
+ try {
192
+ hydrateRoot(
193
+ rootElement as Document | Element,
194
+ appElement,
195
+ {
196
+ onRecoverableError(error) {
197
+ var message = String((error as any)?.message || error || '');
198
+ if (/hydration|did not match|server rendered html|text content/i.test(message)) {
199
+ reportDevRuntimeError('Hydration Error', error);
200
+ return;
201
+ }
202
+ reportDevRuntimeError('Recoverable Error', error);
203
+ },
204
+ }
205
+ );
206
+ } catch (error) {
207
+ reportDevRuntimeError('Hydration Error', error);
208
+ if (!hydrateDocument && rootElement instanceof Element) {
209
+ try {
210
+ createRoot(rootElement).render(appElement);
211
+ } catch (fallbackError) {
212
+ reportDevRuntimeError('Client Render Fallback Failed', fallbackError);
213
+ }
214
+ }
215
+ }
216
+
139
217
  ${isDev
140
- ? `// Vista live-reload: listen for server component changes via SSE
141
- (function connectReload() {
142
- const es = new EventSource('${constants_1.SSE_ENDPOINT}');
143
- es.onmessage = (e) => {
144
- if (e.data === 'reload') {
145
- window.location.reload();
146
- } else {
147
- try {
148
- const msg = JSON.parse(e.data);
149
- if (msg.type === 'error') {
150
- console.error('[vista] Build error:', msg.message);
151
- }
152
- } catch {}
218
+ ? `// Vista live-reload: listen for server component changes via SSE
219
+ (function connectReload() {
220
+ const es = new EventSource('${constants_1.SSE_ENDPOINT}');
221
+ es.onmessage = (e) => {
222
+ if (e.data === 'reload') {
223
+ const errorOverlay = window.__VISTA_DEV_ERROR_OVERLAY__;
224
+ if (errorOverlay && typeof errorOverlay.clear === 'function') {
225
+ errorOverlay.clear();
226
+ }
227
+ const indicator = window.__VISTA_DEVTOOLS_INDICATOR__;
228
+ if (indicator && typeof indicator.pulse === 'function') {
229
+ indicator.pulse('hmr', 460);
230
+ }
231
+ setTimeout(() => window.location.reload(), 180);
232
+ } else {
233
+ try {
234
+ const msg = JSON.parse(e.data);
235
+ if (msg.type === 'error' || msg.type === 'structure-error') {
236
+ const errorOverlay = window.__VISTA_DEV_ERROR_OVERLAY__;
237
+ if (errorOverlay && typeof errorOverlay.show === 'function') {
238
+ errorOverlay.show(msg.errors || msg.message);
239
+ }
240
+ console.error('[vista] Build error:', msg.message);
241
+ } else if (msg.type === 'ok' || msg.type === 'structure-ok') {
242
+ const errorOverlay = window.__VISTA_DEV_ERROR_OVERLAY__;
243
+ if (errorOverlay && typeof errorOverlay.clear === 'function') {
244
+ errorOverlay.clear();
245
+ }
246
+ }
247
+ } catch {}
153
248
  }
154
249
  };
155
250
  es.onerror = () => {
package/dist/bin/build.js CHANGED
@@ -15,6 +15,8 @@ const config_1 = require("../config");
15
15
  const constants_1 = require("../constants");
16
16
  const structure_validator_1 = require("../server/structure-validator");
17
17
  const structure_log_1 = require("../server/structure-log");
18
+ const devtools_indicator_snippet_1 = require("./devtools-indicator-snippet");
19
+ const dev_error_overlay_snippet_1 = require("./dev-error-overlay-snippet");
18
20
  const _debug = !!process.env.VISTA_DEBUG;
19
21
  // Helper to run PostCSS
20
22
  function runPostCSS(cwd, vistaDir) {
@@ -71,6 +73,7 @@ function collectRouteArtifactEntries(node, segments = [], entries = []) {
71
73
  // Generate Client Entry File - TRUE RSC
72
74
  // Only imports components with 'use client' directive
73
75
  function generateClientEntry(cwd, vistaDir, clientComponents, isDev = false) {
76
+ const devToolsBootId = `legacy-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
74
77
  const appDir = path_1.default.join(cwd, 'app');
75
78
  // Generate imports ONLY for client components
76
79
  const clientImports = [];
@@ -202,62 +205,43 @@ if ((module as any).hot) {
202
205
 
203
206
  // Server-Side Live Reload (for server component changes)
204
207
  ${isDev
205
- ? `
206
- // Vista Error Overlay Logic
207
- const VISTA_ERROR_ID = 'vista-compile-error';
208
-
209
- function showCompileError(message: string) {
210
- let div = document.getElementById(VISTA_ERROR_ID);
211
- if (!div) {
212
- div = document.createElement('div');
213
- div.id = VISTA_ERROR_ID;
214
- 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);';
215
- document.body.appendChild(div);
216
- }
217
-
218
- div.innerHTML = \`
219
- <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;">
220
- <div style="padding:16px 24px;background:#111;border-bottom:1px solid #333;display:flex;align-items:center;justify-content:space-between;">
221
- <div style="display:flex;align-items:center;gap:12px;">
222
- <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;">
223
- <span style="width:8px;height:8px;background:currentColor;border-radius:50%;"></span>
224
- BUILD ERROR
225
- </span>
226
- <span style="color:#666;font-size:13px;">Vista JS Dev</span>
227
- </div>
228
- </div>
229
- <div style="padding:24px;overflow:auto;background:#0a0a0a;">
230
- <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>
231
- </div>
232
- </div>
233
- \`;
234
- }
235
-
236
- function hideCompileError() {
237
- const div = document.getElementById(VISTA_ERROR_ID);
238
- if (div) div.remove();
239
- }
240
-
241
- const sse = new EventSource('${constants_1.SSE_ENDPOINT}');
242
- sse.onmessage = (event) => {
243
- if (event.data === 'reload') {
244
- hideCompileError();
245
- console.log('[Vista] Server component changed, reloading...');
246
- window.location.reload();
247
- return;
248
- }
208
+ ? `
209
+ ${(0, devtools_indicator_snippet_1.getDevToolsIndicatorBootstrapSource)(devToolsBootId)}
210
+ ${(0, dev_error_overlay_snippet_1.getDevErrorOverlayBootstrapSource)()}
211
+
212
+ const sse = new EventSource('${constants_1.SSE_ENDPOINT}');
213
+ sse.onmessage = (event) => {
214
+ if (event.data === 'reload') {
215
+ const errorOverlay = window.__VISTA_DEV_ERROR_OVERLAY__;
216
+ if (errorOverlay && typeof errorOverlay.clear === 'function') {
217
+ errorOverlay.clear();
218
+ }
219
+ console.log('[Vista] Server component changed, reloading...');
220
+ const indicator = window.__VISTA_DEVTOOLS_INDICATOR__;
221
+ if (indicator && typeof indicator.pulse === 'function') {
222
+ indicator.pulse('hmr', 460);
223
+ }
224
+ setTimeout(() => window.location.reload(), 180);
225
+ return;
226
+ }
249
227
 
250
- try {
251
- const data = JSON.parse(event.data);
252
- if (data.type === 'error') {
253
- showCompileError(data.message);
254
- } else if (data.type === 'ok') {
255
- hideCompileError();
256
- }
257
- } catch (e) {
258
- // Ignore JSON parse errors for non-JSON messages
259
- }
260
- };
228
+ try {
229
+ const data = JSON.parse(event.data);
230
+ if (data.type === 'error' || data.type === 'structure-error') {
231
+ const errorOverlay = window.__VISTA_DEV_ERROR_OVERLAY__;
232
+ if (errorOverlay && typeof errorOverlay.show === 'function') {
233
+ errorOverlay.show(data.errors || data.message);
234
+ }
235
+ } else if (data.type === 'ok' || data.type === 'structure-ok') {
236
+ const errorOverlay = window.__VISTA_DEV_ERROR_OVERLAY__;
237
+ if (errorOverlay && typeof errorOverlay.clear === 'function') {
238
+ errorOverlay.clear();
239
+ }
240
+ }
241
+ } catch (e) {
242
+ // Ignore JSON parse errors for non-JSON messages
243
+ }
244
+ };
261
245
 
262
246
  sse.onerror = (e) => {
263
247
  console.log('[Vista] SSE connection lost');
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Returns a JS snippet that installs the Vista dev error overlay.
3
+ * It supports Next.js-style error pagination and indicator restore.
4
+ */
5
+ export declare function getDevErrorOverlayBootstrapSource(): string;