vatts 1.0.5-alpha.1 → 1.0.5-alpha.3

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 (2) hide show
  1. package/dist/renderer.js +164 -93
  2. package/package.json +1 -1
package/dist/renderer.js CHANGED
@@ -41,6 +41,22 @@ function requireWithoutStyles(modulePath) {
41
41
  });
42
42
  }
43
43
  }
44
+ // --- Gerenciamento de Console (Silenciador) ---
45
+ const originalConsole = {
46
+ log: console.log,
47
+ info: console.info,
48
+ debug: console.debug
49
+ };
50
+ function silenceConsole() {
51
+ console.log = () => { };
52
+ console.info = () => { };
53
+ console.debug = () => { };
54
+ }
55
+ function restoreConsole() {
56
+ console.log = originalConsole.log;
57
+ console.info = originalConsole.info;
58
+ console.debug = originalConsole.debug;
59
+ }
44
60
  // --- Funções de Metadata e Scripts ---
45
61
  function generateMetaTags(metadata) {
46
62
  const tags = [];
@@ -135,46 +151,81 @@ function obfuscateData(data) {
135
151
  const hash = Buffer.from(Date.now().toString()).toString('base64').substring(0, 8);
136
152
  return `${hash}.${base64}`;
137
153
  }
138
- // Retorna as URLs dos scripts para o bootstrapModules do React
139
- // Retorna null se não encontrar scripts (indica que o build ainda não terminou)
140
- function getJavaScriptUrls(req) {
154
+ // Retorna as URLs dos scripts e CSS
155
+ // Procura em .vatts/ e .vatts/assets/
156
+ function getBuildAssets(req) {
141
157
  const projectDir = process.cwd();
142
158
  const distDir = path_1.default.join(projectDir, '.vatts');
159
+ const assetsDir = path_1.default.join(distDir, 'assets');
143
160
  if (!fs_1.default.existsSync(distDir))
144
161
  return null;
162
+ let scripts = [];
163
+ let styles = [];
164
+ // Helper para processar arquivos de um diretório
165
+ const processDirectory = (directory, urlPrefix) => {
166
+ if (!fs_1.default.existsSync(directory))
167
+ return;
168
+ const files = fs_1.default.readdirSync(directory);
169
+ files.forEach(file => {
170
+ if (file.endsWith('.map'))
171
+ return; // Ignora sourcemaps
172
+ const fullPath = path_1.default.join(directory, file);
173
+ const stat = fs_1.default.statSync(fullPath);
174
+ if (stat.isFile()) {
175
+ if (file.endsWith('.js')) {
176
+ scripts.push(`${urlPrefix}/${file}`);
177
+ }
178
+ else if (file.endsWith('.css')) {
179
+ styles.push(`${urlPrefix}/${file}`);
180
+ }
181
+ }
182
+ });
183
+ };
145
184
  try {
185
+ // 1. Verificar Manifesto (se existir)
146
186
  const manifestPath = path_1.default.join(distDir, 'manifest.json');
147
187
  if (fs_1.default.existsSync(manifestPath)) {
148
188
  const manifest = JSON.parse(fs_1.default.readFileSync(manifestPath, 'utf8'));
149
- const files = Object.values(manifest)
150
- .filter((file) => file.endsWith('.js'))
151
- .map((file) => `/_vatts/${file}`);
152
- return files.length > 0 ? files : null;
189
+ const manifestFiles = Object.values(manifest);
190
+ scripts = manifestFiles
191
+ .filter((f) => f.endsWith('.js'))
192
+ .map((f) => `/_vatts/${f}`);
193
+ styles = manifestFiles
194
+ .filter((f) => f.endsWith('.css'))
195
+ .map((f) => `/_vatts/${f}`);
153
196
  }
154
197
  else {
155
- const jsFiles = fs_1.default.readdirSync(distDir)
156
- .filter(file => file.endsWith('.js') && !file.endsWith('.map'))
157
- .sort((a, b) => {
198
+ // 2. Fallback: Scan manual de diretórios
199
+ // Scan na raiz .vatts/ (Geralmente entry points)
200
+ processDirectory(distDir, '/_vatts');
201
+ // Scan em .vatts/assets/ (Assets estáticos, chunks, CSS extraído)
202
+ processDirectory(assetsDir, '/_vatts/assets');
203
+ // Ordenação básica para garantir que o main carregue
204
+ scripts.sort((a, b) => {
158
205
  if (a.includes('main'))
159
206
  return -1;
160
207
  if (b.includes('main'))
161
208
  return 1;
162
209
  return a.localeCompare(b);
163
210
  });
164
- return jsFiles.length > 0 ? jsFiles.map(file => `/_vatts/${file}`) : null;
165
211
  }
212
+ if (scripts.length === 0)
213
+ return null;
214
+ return { scripts, styles };
166
215
  }
167
- catch {
216
+ catch (e) {
217
+ console.error("Error loading assets:", e);
168
218
  return null;
169
219
  }
170
220
  }
171
- function ServerRoot({ lang, title, metaTagsHtml, initialDataScript, hotReloadScript, dataScript, children }) {
221
+ function ServerRoot({ lang, title, metaTagsHtml, stylesHtml, initialDataScript, hotReloadScript, dataScript, children }) {
172
222
  // Concatena tudo que vai no head em uma única string
173
223
  const headContent = `
174
224
  <meta charset="utf-8" />
175
225
  <title>${title}</title>
176
226
  ${initialDataScript ? `<script>${initialDataScript}</script>` : ''}
177
227
  ${metaTagsHtml || ''}
228
+ ${stylesHtml || ''}
178
229
  `;
179
230
  return ((0, jsx_runtime_1.jsxs)("html", { lang: lang, children: [(0, jsx_runtime_1.jsx)("head", { dangerouslySetInnerHTML: { __html: headContent } }), (0, jsx_runtime_1.jsxs)("body", { children: [dataScript, (0, jsx_runtime_1.jsx)("div", { id: "root", children: children }), hotReloadScript && ((0, jsx_runtime_1.jsx)("div", { style: { display: 'none' }, dangerouslySetInnerHTML: { __html: hotReloadScript } }))] })] }));
180
231
  }
@@ -182,91 +233,111 @@ async function renderAsStream({ req, res, route, params, allRoutes }) {
182
233
  const { generateMetadata } = route;
183
234
  const isProduction = !req.hwebDev;
184
235
  const hotReloadManager = req.hotReloadManager;
185
- // 1. Verificar Build - Se não tiver scripts, retorna tela de Loading
186
- const bootstrapScripts = getJavaScriptUrls(req);
187
- if (!bootstrapScripts) {
188
- res.setHeader('Content-Type', 'text/html');
189
- // Usamos .end() diretamente para garantir que a resposta seja enviada sem stream
190
- res.end(getBuildingHTML());
191
- return;
192
- }
193
- // 2. Preparar Layout
194
- const layoutInfo = (0, router_1.getLayout)();
195
- let LayoutComponent = null;
196
- if (layoutInfo) {
197
- try {
198
- // Recarrega o componente de layout para ter acesso à função (o router só guarda metadata)
199
- const layoutModule = requireWithoutStyles(path_1.default.resolve(process.cwd(), layoutInfo.componentPath));
200
- LayoutComponent = layoutModule.default;
236
+ // SILENCIAR CONSOLE: Inicia o silêncio para evitar logs de renderização
237
+ silenceConsole();
238
+ try {
239
+ // 1. Verificar Build - Se não tiver scripts, retorna tela de Loading
240
+ const assets = getBuildAssets(req);
241
+ if (!assets || assets.scripts.length === 0) {
242
+ // Se falhar o build, restauramos o console para o erro aparecer se necessário
243
+ restoreConsole();
244
+ res.setHeader('Content-Type', 'text/html');
245
+ res.end(getBuildingHTML());
246
+ return;
201
247
  }
202
- catch (e) {
203
- console.error("Error loading layout component for SSR:", e);
248
+ // 2. Preparar Layout
249
+ const layoutInfo = (0, router_1.getLayout)();
250
+ let LayoutComponent = null;
251
+ if (layoutInfo) {
252
+ try {
253
+ // Recarrega o componente de layout para ter acesso à função (o router só guarda metadata)
254
+ const layoutModule = requireWithoutStyles(path_1.default.resolve(process.cwd(), layoutInfo.componentPath));
255
+ LayoutComponent = layoutModule.default;
256
+ }
257
+ catch (e) {
258
+ // Usamos console.error original aqui, pois erro de layout é crítico
259
+ restoreConsole();
260
+ console.error("Error loading layout component for SSR:", e);
261
+ silenceConsole(); // Volta a silenciar
262
+ }
204
263
  }
205
- }
206
- // 3. Preparar Metadata
207
- let metadata = { title: 'Vatts App' };
208
- if (layoutInfo && layoutInfo.metadata) {
209
- metadata = { ...metadata, ...layoutInfo.metadata };
210
- }
211
- if (generateMetadata) {
212
- const routeMetadata = await Promise.resolve(generateMetadata(params, req));
213
- metadata = { ...metadata, ...routeMetadata };
214
- }
215
- // 4. Preparar Dados Iniciais
216
- const results = await Promise.all(allRoutes.map(async (r) => {
217
- let routeMeta = {};
218
- if (r.generateMetadata) {
219
- routeMeta = await r.generateMetadata(params, req);
264
+ // 3. Preparar Metadata
265
+ let metadata = { title: 'Vatts App' };
266
+ if (layoutInfo && layoutInfo.metadata) {
267
+ metadata = { ...metadata, ...layoutInfo.metadata };
220
268
  }
221
- return {
222
- pattern: r.pattern,
223
- componentPath: r.componentPath,
224
- metadata: routeMeta,
225
- };
226
- }));
227
- const initialData = {
228
- routes: results,
229
- initialComponentPath: route.componentPath,
230
- initialParams: params,
231
- };
232
- // Scripts
233
- const obfuscatedData = obfuscateData(initialData);
234
- const hotReloadScript = !isProduction && hotReloadManager ? hotReloadManager.getClientScript() : '';
235
- const metaTagsHtml = generateMetaTags(metadata);
236
- const htmlLang = metadata.language || 'pt-BR';
237
- // 5. Componente da Página Atual
238
- const PageComponent = route.component;
239
- // Monta a árvore da aplicação
240
- let AppTree = (0, jsx_runtime_1.jsx)(PageComponent, { params: params });
241
- if (LayoutComponent) {
242
- AppTree = (0, jsx_runtime_1.jsx)(LayoutComponent, { children: AppTree });
243
- }
244
- // 6. Streaming
245
- return new Promise((resolve, reject) => {
246
- let didError = false;
247
- const { pipe } = (0, server_1.renderToPipeableStream)((0, jsx_runtime_1.jsx)(ServerRoot, { lang: htmlLang, title: metadata.title || 'Vatts.js', metaTagsHtml: metaTagsHtml,
248
- // Recriando o script de dados exatamente como o client espera
249
- initialDataScript: `/* Data Injection */`, hotReloadScript: hotReloadScript, dataScript: (0, jsx_runtime_1.jsx)("script", { id: "__vatts_data__", type: "text/plain", "data-h": obfuscatedData }), children: AppTree }), {
250
- // Usar bootstrapModules para scripts tipo módulo (ESM)
251
- bootstrapModules: bootstrapScripts,
252
- onShellReady() {
253
- res.setHeader('Content-Type', 'text/html');
254
- pipe(res);
255
- resolve();
256
- },
257
- onShellError(error) {
258
- console.error('Streaming Shell Error:', error);
259
- res.statusCode = 500;
260
- res.setHeader('Content-Type', 'text/html');
261
- res.end('<h1>Internal Server Error</h1>');
262
- resolve();
263
- },
264
- onError(error) {
265
- didError = true;
266
- console.error('Streaming Error:', error);
269
+ if (generateMetadata) {
270
+ const routeMetadata = await Promise.resolve(generateMetadata(params, req));
271
+ metadata = { ...metadata, ...routeMetadata };
272
+ }
273
+ // 4. Preparar Dados Iniciais
274
+ const results = await Promise.all(allRoutes.map(async (r) => {
275
+ let routeMeta = {};
276
+ if (r.generateMetadata) {
277
+ routeMeta = await r.generateMetadata(params, req);
267
278
  }
279
+ return {
280
+ pattern: r.pattern,
281
+ componentPath: r.componentPath,
282
+ metadata: routeMeta,
283
+ };
284
+ }));
285
+ const initialData = {
286
+ routes: results,
287
+ initialComponentPath: route.componentPath,
288
+ initialParams: params,
289
+ };
290
+ // Scripts e Estilos
291
+ const obfuscatedData = obfuscateData(initialData);
292
+ const hotReloadScript = !isProduction && hotReloadManager ? hotReloadManager.getClientScript() : '';
293
+ const metaTagsHtml = generateMetaTags(metadata);
294
+ const htmlLang = metadata.language || 'pt-BR';
295
+ // Gera tags de estilo para o head
296
+ const stylesHtml = assets.styles.map(styleUrl => `<link rel="stylesheet" href="${styleUrl}">`).join('\n');
297
+ // 5. Componente da Página Atual
298
+ const PageComponent = route.component;
299
+ // Monta a árvore da aplicação
300
+ let AppTree = (0, jsx_runtime_1.jsx)(PageComponent, { params: params });
301
+ if (LayoutComponent) {
302
+ AppTree = (0, jsx_runtime_1.jsx)(LayoutComponent, { children: AppTree });
303
+ }
304
+ // 6. Streaming
305
+ return new Promise((resolve, reject) => {
306
+ let didError = false;
307
+ const { pipe } = (0, server_1.renderToPipeableStream)((0, jsx_runtime_1.jsx)(ServerRoot, { lang: htmlLang, title: metadata.title || 'Vatts.js', metaTagsHtml: metaTagsHtml, stylesHtml: stylesHtml,
308
+ // Recriando o script de dados exatamente como o client espera
309
+ initialDataScript: `/* Data Injection */`, hotReloadScript: hotReloadScript, dataScript: (0, jsx_runtime_1.jsx)("script", { id: "__vatts_data__", type: "text/plain", "data-h": obfuscatedData }), children: AppTree }), {
310
+ // Usar bootstrapModules para scripts tipo módulo (ESM)
311
+ bootstrapModules: assets.scripts,
312
+ onShellReady() {
313
+ // Restaurar console assim que o shell estiver pronto (cabeçalho enviado)
314
+ restoreConsole();
315
+ res.setHeader('Content-Type', 'text/html');
316
+ pipe(res);
317
+ resolve();
318
+ },
319
+ onShellError(error) {
320
+ restoreConsole(); // Restaura para mostrar o erro real
321
+ console.error('Streaming Shell Error:', error);
322
+ res.statusCode = 500;
323
+ res.setHeader('Content-Type', 'text/html');
324
+ res.end('<h1>Internal Server Error</h1>');
325
+ resolve();
326
+ },
327
+ onError(error) {
328
+ didError = true;
329
+ // Log de erro de stream ainda é importante, mas podemos filtrar se quiser
330
+ // Aqui mantemos o log de erro original do React que vai para stderr
331
+ console.error('Streaming Error:', error);
332
+ }
333
+ });
268
334
  });
269
- });
335
+ }
336
+ catch (err) {
337
+ restoreConsole();
338
+ console.error("Critical Render Error:", err);
339
+ throw err;
340
+ }
270
341
  }
271
342
  // Mantemos a função antiga para compatibilidade
272
343
  async function render(options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vatts",
3
- "version": "1.0.5-alpha.1",
3
+ "version": "1.0.5-alpha.3",
4
4
  "description": "Vatts.js is a high-level framework for building web applications with ease and speed. It provides a robust set of tools and features to streamline development and enhance productivity.",
5
5
  "types": "dist/index.d.ts",
6
6
  "author": "itsmuzin",