vatts 1.0.2-alpha.2 → 1.0.2-alpha.4
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/dist/bin/vatts.js +91 -100
- package/dist/builder.js +111 -123
- package/dist/client/clientRouter.d.ts +11 -54
- package/dist/client/clientRouter.js +39 -94
- package/dist/client/rpc.d.ts +1 -1
- package/dist/client/rpc.js +19 -2
- package/dist/env/env.d.ts +5 -0
- package/dist/env/env.js +69 -0
- package/dist/helpers.js +4 -1
- package/dist/index.js +44 -86
- package/dist/renderer.d.ts +3 -1
- package/dist/renderer.js +151 -170
- package/dist/types.d.ts +5 -0
- package/package.json +1 -1
package/dist/builder.js
CHANGED
|
@@ -58,14 +58,14 @@ const markdownPlugin = () => {
|
|
|
58
58
|
if (id.endsWith('.md')) {
|
|
59
59
|
return {
|
|
60
60
|
code: `export default ${JSON.stringify(code)};`,
|
|
61
|
-
map: null
|
|
61
|
+
map: null // Null map economiza memória se não precisa debugar markdown
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
};
|
|
66
66
|
};
|
|
67
67
|
/**
|
|
68
|
-
* Plugin para CSS/PostCSS Manual (
|
|
68
|
+
* Plugin para CSS/PostCSS Manual (Otimizado para RAM)
|
|
69
69
|
*/
|
|
70
70
|
const customPostCssPlugin = (isProduction) => {
|
|
71
71
|
let cachedProcessor = null;
|
|
@@ -95,7 +95,9 @@ const customPostCssPlugin = (isProduction) => {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
if (postcss) {
|
|
98
|
-
delete require.cache
|
|
98
|
+
// OTIMIZAÇÃO DE RAM: Removido 'delete require.cache'.
|
|
99
|
+
// Limpar o cache constantemente fragmenta a memória heap do V8 em processos longos (watch).
|
|
100
|
+
// Se o usuário alterar o config, ele deve reiniciar o processo.
|
|
99
101
|
const config = require(configPath);
|
|
100
102
|
const postcssConfig = config.default || config;
|
|
101
103
|
const plugins = [];
|
|
@@ -174,36 +176,24 @@ const customPostCssPlugin = (isProduction) => {
|
|
|
174
176
|
Console.warn(`PostCSS process error:`, e.message);
|
|
175
177
|
}
|
|
176
178
|
}
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
// Isso mantém compatibilidade (não quebra o app) mas usa arquivo externo
|
|
187
|
-
return `
|
|
188
|
-
const cssUrl = import.meta.ROLLUP_FILE_URL_${referenceId};
|
|
189
|
-
if (typeof document !== 'undefined') {
|
|
190
|
-
const link = document.createElement('link');
|
|
191
|
-
link.rel = 'stylesheet';
|
|
192
|
-
link.href = cssUrl;
|
|
193
|
-
document.head.appendChild(link);
|
|
194
|
-
}
|
|
195
|
-
export default cssUrl;
|
|
196
|
-
`;
|
|
197
|
-
}
|
|
198
|
-
// Modo DEV (Inline para Hot Reload mais rápido)
|
|
179
|
+
// OTIMIZAÇÃO: Emite arquivo físico sempre que possível.
|
|
180
|
+
// Strings gigantes de CSS inline consomem muita RAM no bundle JS.
|
|
181
|
+
const referenceId = this.emitFile({
|
|
182
|
+
type: 'asset',
|
|
183
|
+
name: path.basename(filePath),
|
|
184
|
+
source: processedCss
|
|
185
|
+
});
|
|
186
|
+
// Lógica unificada: Usa arquivo externo tanto em Dev quanto Prod.
|
|
187
|
+
// Isso libera a memória que seria usada para stringificar o CSS dentro do JS.
|
|
199
188
|
return `
|
|
200
|
-
const
|
|
189
|
+
const cssUrl = import.meta.ROLLUP_FILE_URL_${referenceId};
|
|
201
190
|
if (typeof document !== 'undefined') {
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
191
|
+
const link = document.createElement('link');
|
|
192
|
+
link.rel = 'stylesheet';
|
|
193
|
+
link.href = cssUrl;
|
|
194
|
+
document.head.appendChild(link);
|
|
205
195
|
}
|
|
206
|
-
export default
|
|
196
|
+
export default cssUrl;
|
|
207
197
|
`;
|
|
208
198
|
}
|
|
209
199
|
return null;
|
|
@@ -211,12 +201,13 @@ const customPostCssPlugin = (isProduction) => {
|
|
|
211
201
|
};
|
|
212
202
|
};
|
|
213
203
|
/**
|
|
214
|
-
* Plugin Inteligente para Assets (
|
|
215
|
-
* -
|
|
216
|
-
* - Prod: Arquivos > 4KB viram URL (Melhora LCP), < 4KB Base64 (Menos requests)
|
|
204
|
+
* Plugin Inteligente para Assets (Otimizado para RAM)
|
|
205
|
+
* - Agora utiliza emissão de arquivos também em DEV para arquivos grandes.
|
|
217
206
|
*/
|
|
218
207
|
const smartAssetPlugin = (isProduction) => {
|
|
219
|
-
|
|
208
|
+
// 4KB - Arquivos maiores que isso viram referência externa.
|
|
209
|
+
// Manter isso baixo economiza MUITA RAM, pois evita strings Base64 gigantes no JS.
|
|
210
|
+
const INLINE_LIMIT = 4096;
|
|
220
211
|
return {
|
|
221
212
|
name: 'smart-asset-loader',
|
|
222
213
|
async load(id) {
|
|
@@ -238,42 +229,23 @@ const smartAssetPlugin = (isProduction) => {
|
|
|
238
229
|
const type = mimeTypes[ext];
|
|
239
230
|
if (!type)
|
|
240
231
|
return null;
|
|
241
|
-
// Text files always strings
|
|
232
|
+
// Text files always strings (geralmente pequenos)
|
|
242
233
|
if (type === 'txt') {
|
|
243
234
|
const content = await fs.promises.readFile(cleanId, 'utf8');
|
|
244
235
|
return `export default ${JSON.stringify(content)};`;
|
|
245
236
|
}
|
|
246
|
-
|
|
237
|
+
let buffer = await fs.promises.readFile(cleanId);
|
|
247
238
|
const size = buffer.length;
|
|
248
|
-
//
|
|
249
|
-
if (
|
|
250
|
-
// SVG: Se for pequeno inlina, se grande emite arquivo
|
|
251
|
-
if (type === 'svg') {
|
|
252
|
-
if (size < INLINE_LIMIT) {
|
|
253
|
-
const content = buffer.toString('utf8');
|
|
254
|
-
const base64 = buffer.toString('base64');
|
|
255
|
-
return `
|
|
256
|
-
export default "data:image/svg+xml;base64,${base64}";
|
|
257
|
-
export const svgContent = ${JSON.stringify(content)};
|
|
258
|
-
`;
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
// Emite arquivo físico
|
|
262
|
-
const referenceId = this.emitFile({
|
|
263
|
-
type: 'asset',
|
|
264
|
-
name: path.basename(cleanId),
|
|
265
|
-
source: buffer
|
|
266
|
-
});
|
|
267
|
-
const content = buffer.toString('utf8');
|
|
268
|
-
return `
|
|
269
|
-
export default import.meta.ROLLUP_FILE_URL_${referenceId};
|
|
270
|
-
export const svgContent = ${JSON.stringify(content)};
|
|
271
|
-
`;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
// Outros assets
|
|
239
|
+
// Tratamento especial para SVG (inline SVG vs URL)
|
|
240
|
+
if (type === 'svg') {
|
|
275
241
|
if (size < INLINE_LIMIT) {
|
|
276
|
-
|
|
242
|
+
const content = buffer.toString('utf8');
|
|
243
|
+
const base64 = buffer.toString('base64');
|
|
244
|
+
buffer = null; // GC Hint
|
|
245
|
+
return `
|
|
246
|
+
export default "data:image/svg+xml;base64,${base64}";
|
|
247
|
+
export const svgContent = ${JSON.stringify(content)};
|
|
248
|
+
`;
|
|
277
249
|
}
|
|
278
250
|
else {
|
|
279
251
|
const referenceId = this.emitFile({
|
|
@@ -281,19 +253,32 @@ const smartAssetPlugin = (isProduction) => {
|
|
|
281
253
|
name: path.basename(cleanId),
|
|
282
254
|
source: buffer
|
|
283
255
|
});
|
|
284
|
-
|
|
256
|
+
const content = buffer.toString('utf8');
|
|
257
|
+
buffer = null; // GC Hint
|
|
258
|
+
return `
|
|
259
|
+
export default import.meta.ROLLUP_FILE_URL_${referenceId};
|
|
260
|
+
export const svgContent = ${JSON.stringify(content)};
|
|
261
|
+
`;
|
|
285
262
|
}
|
|
286
263
|
}
|
|
287
|
-
//
|
|
288
|
-
|
|
289
|
-
|
|
264
|
+
// Para outros assets:
|
|
265
|
+
// Se for pequeno, Base64 (reduz requests HTTP)
|
|
266
|
+
// Se for grande, Arquivo (reduz uso de RAM e tamanho do bundle JS)
|
|
267
|
+
// Essa lógica agora aplica para DEV e PROD. Base64 em Dev para arquivos grandes era o vilão da RAM.
|
|
268
|
+
if (size < INLINE_LIMIT) {
|
|
290
269
|
const base64 = buffer.toString('base64');
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
270
|
+
buffer = null; // Libera memória do buffer bruto imediatamente
|
|
271
|
+
return `export default "data:${type};base64,${base64}";`;
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
const referenceId = this.emitFile({
|
|
275
|
+
type: 'asset',
|
|
276
|
+
name: path.basename(cleanId),
|
|
277
|
+
source: buffer
|
|
278
|
+
});
|
|
279
|
+
buffer = null; // Libera memória
|
|
280
|
+
return `export default import.meta.ROLLUP_FILE_URL_${referenceId};`;
|
|
295
281
|
}
|
|
296
|
-
return `export default "data:${type};base64,${buffer.toString('base64')}";`;
|
|
297
282
|
}
|
|
298
283
|
};
|
|
299
284
|
};
|
|
@@ -303,25 +288,26 @@ const smartAssetPlugin = (isProduction) => {
|
|
|
303
288
|
function createRollupConfig(entryPoint, outdir, isProduction) {
|
|
304
289
|
return {
|
|
305
290
|
input: entryPoint,
|
|
306
|
-
// Para evitar bare imports no browser (sem import map), em DEV também bundle React/ReactDOM.
|
|
307
|
-
// O HMR evita "Invalid hook call" removendo o script antigo e recarregando main.js.
|
|
308
291
|
external: nodeBuiltIns,
|
|
309
|
-
// Otimização:
|
|
310
|
-
treeshake:
|
|
311
|
-
|
|
312
|
-
|
|
292
|
+
// Otimização: Treeshake limpa memória removendo nós da AST não usados
|
|
293
|
+
treeshake: {
|
|
294
|
+
moduleSideEffects: 'no-external', // Mais agressivo, economiza memória
|
|
295
|
+
preset: isProduction ? 'recommended' : 'smallest'
|
|
296
|
+
},
|
|
297
|
+
// Cache desativado em DEV conforme solicitado anteriormente,
|
|
298
|
+
// o que ajuda na RAM pois não mantém a AST antiga em memória.
|
|
313
299
|
cache: isProduction ? true : false,
|
|
314
300
|
perf: false,
|
|
301
|
+
// Limita execuções paralelas de leitura de arquivo internas do Rollup
|
|
302
|
+
maxParallelFileOps: 20,
|
|
315
303
|
plugins: [
|
|
316
|
-
// CRÍTICO: 'replace' deve vir PRIMEIRO para injetar NODE_ENV antes que
|
|
317
|
-
// libs como React decidam qual bundle importar.
|
|
318
304
|
replace({
|
|
319
305
|
preventAssignment: true,
|
|
320
306
|
values: {
|
|
321
|
-
'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development')
|
|
307
|
+
'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development'),
|
|
308
|
+
'proccess.env.PORT': JSON.stringify(process.vatts.port || 3000)
|
|
322
309
|
}
|
|
323
310
|
}),
|
|
324
|
-
// Precisa vir antes do nodeResolve
|
|
325
311
|
tsconfigPathsPlugin(process.cwd()),
|
|
326
312
|
nodeResolve({
|
|
327
313
|
extensions: ['.mjs', '.js', '.json', '.node', '.jsx', '.tsx', '.ts'],
|
|
@@ -331,20 +317,21 @@ function createRollupConfig(entryPoint, outdir, isProduction) {
|
|
|
331
317
|
}),
|
|
332
318
|
commonjs({
|
|
333
319
|
sourceMap: !isProduction,
|
|
334
|
-
requireReturnsDefault: 'auto'
|
|
320
|
+
requireReturnsDefault: 'auto',
|
|
321
|
+
// Ignora try-catch dinâmicos para economizar análise
|
|
322
|
+
ignoreTryCatch: true
|
|
335
323
|
}),
|
|
336
324
|
markdownPlugin(),
|
|
337
|
-
//
|
|
325
|
+
// PostCSS Otimizado
|
|
338
326
|
customPostCssPlugin(isProduction),
|
|
339
|
-
//
|
|
327
|
+
// Assets Otimizados (menos Base64)
|
|
340
328
|
smartAssetPlugin(isProduction),
|
|
341
329
|
esbuild({
|
|
342
330
|
include: /\.[jt]sx?$/,
|
|
343
331
|
exclude: /node_modules/,
|
|
344
332
|
sourceMap: !isProduction,
|
|
345
333
|
minify: isProduction,
|
|
346
|
-
//
|
|
347
|
-
legalComments: isProduction ? 'none' : 'eof',
|
|
334
|
+
legalComments: 'none', // Remove comentários para limpar buffer
|
|
348
335
|
treeShaking: isProduction,
|
|
349
336
|
target: isProduction ? 'es2020' : 'esnext',
|
|
350
337
|
jsx: 'automatic',
|
|
@@ -357,6 +344,9 @@ function createRollupConfig(entryPoint, outdir, isProduction) {
|
|
|
357
344
|
return;
|
|
358
345
|
if (warning.code === 'THIS_IS_UNDEFINED')
|
|
359
346
|
return;
|
|
347
|
+
// Ignora avisos circulares comuns que enchem o log/buffer
|
|
348
|
+
if (warning.code === 'CIRCULAR_DEPENDENCY' && warning.message.includes('node_modules'))
|
|
349
|
+
return;
|
|
360
350
|
warn(warning);
|
|
361
351
|
}
|
|
362
352
|
};
|
|
@@ -371,39 +361,31 @@ async function buildWithChunks(entryPoint, outdir, isProduction = false) {
|
|
|
371
361
|
const outputOptions = {
|
|
372
362
|
dir: outdir,
|
|
373
363
|
format: 'es',
|
|
374
|
-
// Padrão de nomes mantido, mas com estrutura para vários arquivos
|
|
375
364
|
entryFileNames: isProduction ? 'main-[hash].js' : 'main.js',
|
|
376
365
|
chunkFileNames: 'chunks/[name]-[hash].js',
|
|
377
366
|
assetFileNames: 'assets/[name]-[hash][extname]',
|
|
378
367
|
sourcemap: !isProduction,
|
|
379
|
-
//
|
|
368
|
+
// Compacta output para economizar memória de escrita
|
|
369
|
+
compact: isProduction,
|
|
380
370
|
manualChunks(id) {
|
|
381
371
|
if (id.includes('node_modules')) {
|
|
382
|
-
// Normaliza separadores para garantir funcionamento em Windows/Linux
|
|
383
372
|
const normalizedId = id.replace(/\\/g, '/');
|
|
384
|
-
// React Core isolado
|
|
385
|
-
// IMPORTANTE: Uso de Regex para garantir que pegamos APENAS os pacotes do core
|
|
386
|
-
// e não pacotes que tenham 'react' no nome (ex: react-router, react-icons),
|
|
387
|
-
// pois isso causa dependências circulares com o chunk 'vendor'.
|
|
388
373
|
if (/\/node_modules\/(react|react-dom|scheduler|prop-types|loose-envify|object-assign)\//.test(normalizedId)) {
|
|
389
374
|
return 'vendor-react';
|
|
390
375
|
}
|
|
391
|
-
// UI Libs comuns (opcional, pode ajustar conforme necessidade)
|
|
392
376
|
if (id.includes('framer-motion') || id.includes('@radix-ui')) {
|
|
393
377
|
return 'vendor-ui';
|
|
394
378
|
}
|
|
395
|
-
// Utils comuns
|
|
396
379
|
if (id.includes('lodash') || id.includes('date-fns') || id.includes('axios')) {
|
|
397
380
|
return 'vendor-utils';
|
|
398
381
|
}
|
|
399
|
-
// Resto das dependências
|
|
400
382
|
return 'vendor';
|
|
401
383
|
}
|
|
402
384
|
}
|
|
403
385
|
};
|
|
404
386
|
const bundle = await rollup(inputOptions);
|
|
405
387
|
await bundle.write(outputOptions);
|
|
406
|
-
await bundle.close();
|
|
388
|
+
await bundle.close(); // Importante fechar para liberar memória
|
|
407
389
|
}
|
|
408
390
|
catch (error) {
|
|
409
391
|
Console.error('An error occurred while building with chunks:', error);
|
|
@@ -423,7 +405,8 @@ async function build(entryPoint, outfile, isProduction = false) {
|
|
|
423
405
|
format: 'iife',
|
|
424
406
|
name: 'Vattsjs',
|
|
425
407
|
sourcemap: !isProduction,
|
|
426
|
-
inlineDynamicImports: true
|
|
408
|
+
inlineDynamicImports: true,
|
|
409
|
+
compact: true // Ajuda na RAM
|
|
427
410
|
};
|
|
428
411
|
const bundle = await rollup(inputOptions);
|
|
429
412
|
await bundle.write(outputOptions);
|
|
@@ -438,20 +421,22 @@ async function build(entryPoint, outfile, isProduction = false) {
|
|
|
438
421
|
* Helper para lidar com notificações do Watcher
|
|
439
422
|
*/
|
|
440
423
|
function handleWatcherEvents(watcher, hotReloadManager, resolveFirstBuild) {
|
|
441
|
-
// Controla o estado do build por "geração" para evitar END atrasado
|
|
442
|
-
// (ou múltiplos ciclos) emitirem sucesso após um erro.
|
|
443
424
|
let currentBuildId = 0;
|
|
444
425
|
let lastStartedBuildId = 0;
|
|
445
426
|
const erroredBuildIds = new Set();
|
|
446
|
-
// DEBUG: stack trace rate-limited
|
|
447
|
-
let lastTraceAt = 0;
|
|
448
427
|
watcher.on('event', event => {
|
|
449
428
|
if (event.code === 'START') {
|
|
450
429
|
currentBuildId += 1;
|
|
451
430
|
lastStartedBuildId = currentBuildId;
|
|
431
|
+
// Dica pro V8 limpar lixo antes de começar um build pesado
|
|
432
|
+
if (global.gc) {
|
|
433
|
+
try {
|
|
434
|
+
global.gc();
|
|
435
|
+
}
|
|
436
|
+
catch (e) { }
|
|
437
|
+
}
|
|
452
438
|
}
|
|
453
439
|
if (event.code === 'ERROR') {
|
|
454
|
-
// Marca erro para o build atualmente em andamento.
|
|
455
440
|
erroredBuildIds.add(currentBuildId);
|
|
456
441
|
const errDetails = {
|
|
457
442
|
message: event.error?.message || 'Unknown build error',
|
|
@@ -461,7 +446,6 @@ function handleWatcherEvents(watcher, hotReloadManager, resolveFirstBuild) {
|
|
|
461
446
|
loc: event.error?.loc,
|
|
462
447
|
buildId: currentBuildId
|
|
463
448
|
};
|
|
464
|
-
// Notifica erro imediatamente
|
|
465
449
|
if (hotReloadManager) {
|
|
466
450
|
hotReloadManager.onBuildComplete(false, errDetails);
|
|
467
451
|
}
|
|
@@ -470,21 +454,18 @@ function handleWatcherEvents(watcher, hotReloadManager, resolveFirstBuild) {
|
|
|
470
454
|
if (resolveFirstBuild)
|
|
471
455
|
resolveFirstBuild();
|
|
472
456
|
}
|
|
473
|
-
if (event.code === 'BUNDLE_END')
|
|
457
|
+
if (event.code === 'BUNDLE_END') {
|
|
458
|
+
// CRÍTICO: Fechar o bundle libera a memória dos módulos
|
|
474
459
|
event.result.close();
|
|
460
|
+
}
|
|
475
461
|
if (event.code === 'END') {
|
|
476
462
|
const endBuildId = currentBuildId;
|
|
477
463
|
const hadError = erroredBuildIds.has(endBuildId);
|
|
478
|
-
// Só emite sucesso se:
|
|
479
|
-
// 1) esse END é do build mais recentemente iniciado (evita END atrasado)
|
|
480
|
-
// 2) esse build não teve ERROR
|
|
481
464
|
if (endBuildId === lastStartedBuildId && !hadError) {
|
|
482
465
|
if (hotReloadManager) {
|
|
483
466
|
hotReloadManager.onBuildComplete(true, { buildId: endBuildId });
|
|
484
467
|
}
|
|
485
468
|
}
|
|
486
|
-
// Limpa estados antigos pra não crescer sem limite.
|
|
487
|
-
// (qualquer build mais antigo que o último START não faz mais sentido manter)
|
|
488
469
|
for (const id of erroredBuildIds) {
|
|
489
470
|
if (id < lastStartedBuildId)
|
|
490
471
|
erroredBuildIds.delete(id);
|
|
@@ -502,11 +483,9 @@ function handleWatcherEvents(watcher, hotReloadManager, resolveFirstBuild) {
|
|
|
502
483
|
async function watchWithChunks(entryPoint, outdir, hotReloadManager = null) {
|
|
503
484
|
await cleanDirectoryExcept(outdir, 'temp');
|
|
504
485
|
try {
|
|
505
|
-
// DEV MODE: isProduction = false
|
|
506
486
|
const inputOptions = createRollupConfig(entryPoint, outdir, false);
|
|
507
487
|
const outputOptions = {
|
|
508
488
|
dir: outdir,
|
|
509
|
-
// Em DEV usamos ESM para suportar externals como react/react-dom sem output.globals
|
|
510
489
|
format: 'es',
|
|
511
490
|
entryFileNames: 'main.js',
|
|
512
491
|
sourcemap: true
|
|
@@ -517,7 +496,9 @@ async function watchWithChunks(entryPoint, outdir, hotReloadManager = null) {
|
|
|
517
496
|
watch: {
|
|
518
497
|
exclude: 'node_modules/**',
|
|
519
498
|
clearScreen: false,
|
|
520
|
-
skipWrite: false
|
|
499
|
+
skipWrite: false,
|
|
500
|
+
// Atraso curto para evitar múltiplos rebuilds rápidos que comem CPU/RAM
|
|
501
|
+
buildDelay: 100
|
|
521
502
|
}
|
|
522
503
|
};
|
|
523
504
|
const watcher = rollupWatch(watchOptions);
|
|
@@ -540,7 +521,6 @@ async function watch(entryPoint, outfile, hotReloadManager = null) {
|
|
|
540
521
|
const inputOptions = createRollupConfig(entryPoint, outdir, false);
|
|
541
522
|
const outputOptions = {
|
|
542
523
|
file: outfile,
|
|
543
|
-
// Em DEV usamos ESM para suportar externals como react/react-dom sem output.globals
|
|
544
524
|
format: 'es',
|
|
545
525
|
sourcemap: true
|
|
546
526
|
};
|
|
@@ -549,7 +529,8 @@ async function watch(entryPoint, outfile, hotReloadManager = null) {
|
|
|
549
529
|
output: outputOptions,
|
|
550
530
|
watch: {
|
|
551
531
|
exclude: 'node_modules/**',
|
|
552
|
-
clearScreen: false
|
|
532
|
+
clearScreen: false,
|
|
533
|
+
buildDelay: 100
|
|
553
534
|
}
|
|
554
535
|
};
|
|
555
536
|
const watcher = rollupWatch(watchOptions);
|
|
@@ -569,14 +550,21 @@ async function cleanDirectoryExcept(dirPath, excludeFolder) {
|
|
|
569
550
|
return;
|
|
570
551
|
const excludes = Array.isArray(excludeFolder) ? excludeFolder : [excludeFolder];
|
|
571
552
|
const items = await readdir(dirPath);
|
|
572
|
-
//
|
|
573
|
-
|
|
553
|
+
// OTIMIZAÇÃO: Loop sequencial ao invés de Promise.all.
|
|
554
|
+
// Promise.all é mais rápido, mas cria dezenas/centenas de Promises simultâneas na RAM.
|
|
555
|
+
// O loop sequencial é mais gentil com o Garbage Collector.
|
|
556
|
+
for (const item of items) {
|
|
574
557
|
if (excludes.includes(item))
|
|
575
|
-
|
|
558
|
+
continue;
|
|
576
559
|
const itemPath = path.join(dirPath, item);
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
560
|
+
try {
|
|
561
|
+
const info = await stat(itemPath);
|
|
562
|
+
await rm(itemPath, { recursive: info.isDirectory(), force: true });
|
|
563
|
+
}
|
|
564
|
+
catch (e) {
|
|
565
|
+
// Ignora erro se arquivo sumir durante o loop
|
|
566
|
+
}
|
|
567
|
+
}
|
|
580
568
|
}
|
|
581
569
|
catch (e) {
|
|
582
570
|
Console.warn(`Warning cleaning directory: ${e.message}`);
|
|
@@ -1,58 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
afterNavigate?: (url: string) => void;
|
|
4
|
-
}
|
|
5
|
-
declare class Router {
|
|
6
|
-
private events;
|
|
1
|
+
type RouteListener = () => void;
|
|
2
|
+
export declare class Router {
|
|
7
3
|
private listeners;
|
|
8
|
-
|
|
9
|
-
* Navega para uma nova rota
|
|
10
|
-
*/
|
|
11
|
-
push(url: string): Promise<void>;
|
|
12
|
-
/**
|
|
13
|
-
* Substitui a entrada atual do histórico
|
|
14
|
-
*/
|
|
15
|
-
replace(url: string): Promise<void>;
|
|
16
|
-
/**
|
|
17
|
-
* Volta uma página no histórico
|
|
18
|
-
*/
|
|
19
|
-
back(): void;
|
|
20
|
-
/**
|
|
21
|
-
* Avança uma página no histórico
|
|
22
|
-
*/
|
|
23
|
-
forward(): void;
|
|
24
|
-
/**
|
|
25
|
-
* Recarrega a página atual (re-renderiza o componente)
|
|
26
|
-
*/
|
|
27
|
-
refresh(): void;
|
|
28
|
-
/**
|
|
29
|
-
* Obtém a URL atual
|
|
30
|
-
*/
|
|
4
|
+
constructor();
|
|
31
5
|
get pathname(): string;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
get url(): string;
|
|
40
|
-
/**
|
|
41
|
-
* Adiciona event listeners para eventos de roteamento
|
|
42
|
-
*/
|
|
43
|
-
on(events: RouterEvents): void;
|
|
44
|
-
/**
|
|
45
|
-
* Remove event listeners
|
|
46
|
-
*/
|
|
47
|
-
off(): void;
|
|
48
|
-
/**
|
|
49
|
-
* Adiciona um listener para mudanças de rota
|
|
50
|
-
*/
|
|
51
|
-
subscribe(listener: () => void): () => void;
|
|
52
|
-
/**
|
|
53
|
-
* Dispara evento de navegação para todos os listeners
|
|
54
|
-
*/
|
|
55
|
-
private triggerNavigation;
|
|
6
|
+
get search(): string;
|
|
7
|
+
get hash(): string;
|
|
8
|
+
push(path: string): void;
|
|
9
|
+
replace(path: string): void;
|
|
10
|
+
back(): void;
|
|
11
|
+
subscribe(listener: RouteListener): () => void;
|
|
12
|
+
private notify;
|
|
56
13
|
}
|
|
57
14
|
export declare const router: Router;
|
|
58
|
-
export
|
|
15
|
+
export {};
|
|
@@ -16,116 +16,61 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.router = void 0;
|
|
19
|
+
exports.router = exports.Router = void 0;
|
|
20
20
|
class Router {
|
|
21
21
|
constructor() {
|
|
22
|
-
this.events = {};
|
|
23
22
|
this.listeners = new Set();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// Callback antes de navegar
|
|
30
|
-
if (this.events.beforeNavigate) {
|
|
31
|
-
const shouldProceed = await this.events.beforeNavigate(url);
|
|
32
|
-
if (shouldProceed === false)
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
// Atualiza a URL na barra de endereço
|
|
36
|
-
window.history.pushState({ path: url }, '', url);
|
|
37
|
-
// Dispara evento para o roteador capturar de forma assíncrona
|
|
38
|
-
setTimeout(() => this.triggerNavigation(), 0);
|
|
39
|
-
// Callback após navegar
|
|
40
|
-
if (this.events.afterNavigate) {
|
|
41
|
-
this.events.afterNavigate(url);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Substitui a entrada atual do histórico
|
|
46
|
-
*/
|
|
47
|
-
async replace(url) {
|
|
48
|
-
// Callback antes de navegar
|
|
49
|
-
if (this.events.beforeNavigate) {
|
|
50
|
-
const shouldProceed = await this.events.beforeNavigate(url);
|
|
51
|
-
if (shouldProceed === false)
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
// Substitui a URL atual no histórico
|
|
55
|
-
window.history.replaceState({ path: url }, '', url);
|
|
56
|
-
// Dispara evento para o roteador capturar de forma assíncrona
|
|
57
|
-
setTimeout(() => this.triggerNavigation(), 0);
|
|
58
|
-
// Callback após navegar
|
|
59
|
-
if (this.events.afterNavigate) {
|
|
60
|
-
this.events.afterNavigate(url);
|
|
23
|
+
// Só adiciona listener no lado do cliente
|
|
24
|
+
if (typeof window !== 'undefined') {
|
|
25
|
+
window.addEventListener('popstate', () => {
|
|
26
|
+
this.notify();
|
|
27
|
+
});
|
|
61
28
|
}
|
|
62
29
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Volta uma página no histórico
|
|
65
|
-
*/
|
|
66
|
-
back() {
|
|
67
|
-
window.history.back();
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Avança uma página no histórico
|
|
71
|
-
*/
|
|
72
|
-
forward() {
|
|
73
|
-
window.history.forward();
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Recarrega a página atual (re-renderiza o componente)
|
|
77
|
-
*/
|
|
78
|
-
refresh() {
|
|
79
|
-
setTimeout(() => this.triggerNavigation(), 0);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Obtém a URL atual
|
|
83
|
-
*/
|
|
84
30
|
get pathname() {
|
|
31
|
+
if (typeof window === 'undefined') {
|
|
32
|
+
return '/'; // Retorno seguro para SSR
|
|
33
|
+
}
|
|
85
34
|
return window.location.pathname;
|
|
86
35
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return
|
|
36
|
+
get search() {
|
|
37
|
+
if (typeof window === 'undefined') {
|
|
38
|
+
return '';
|
|
39
|
+
}
|
|
40
|
+
return window.location.search;
|
|
41
|
+
}
|
|
42
|
+
get hash() {
|
|
43
|
+
if (typeof window === 'undefined') {
|
|
44
|
+
return '';
|
|
45
|
+
}
|
|
46
|
+
return window.location.hash;
|
|
92
47
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
48
|
+
push(path) {
|
|
49
|
+
if (typeof window !== 'undefined') {
|
|
50
|
+
window.history.pushState({}, '', path);
|
|
51
|
+
this.notify();
|
|
52
|
+
}
|
|
98
53
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
54
|
+
replace(path) {
|
|
55
|
+
if (typeof window !== 'undefined') {
|
|
56
|
+
window.history.replaceState({}, '', path);
|
|
57
|
+
this.notify();
|
|
58
|
+
}
|
|
104
59
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
this.events = {};
|
|
60
|
+
back() {
|
|
61
|
+
if (typeof window !== 'undefined') {
|
|
62
|
+
window.history.back();
|
|
63
|
+
}
|
|
110
64
|
}
|
|
111
|
-
/**
|
|
112
|
-
* Adiciona um listener para mudanças de rota
|
|
113
|
-
*/
|
|
114
65
|
subscribe(listener) {
|
|
115
66
|
this.listeners.add(listener);
|
|
116
|
-
return () =>
|
|
67
|
+
return () => {
|
|
68
|
+
this.listeners.delete(listener);
|
|
69
|
+
};
|
|
117
70
|
}
|
|
118
|
-
|
|
119
|
-
* Dispara evento de navegação para todos os listeners
|
|
120
|
-
*/
|
|
121
|
-
triggerNavigation() {
|
|
122
|
-
// Dispara o evento nativo para o roteador do hweb capturar
|
|
123
|
-
window.dispatchEvent(new PopStateEvent('popstate'));
|
|
124
|
-
// Notifica todos os listeners customizados
|
|
71
|
+
notify() {
|
|
125
72
|
this.listeners.forEach(listener => listener());
|
|
126
73
|
}
|
|
127
74
|
}
|
|
128
|
-
|
|
75
|
+
exports.Router = Router;
|
|
129
76
|
exports.router = new Router();
|
|
130
|
-
// Para compatibilidade, também exporta como default
|
|
131
|
-
exports.default = exports.router;
|