hightjs 0.3.3 → 0.3.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/adapters/factory.js +8 -8
- package/dist/adapters/native.js +3 -3
- package/dist/auth/client.js +5 -5
- package/dist/auth/components.js +2 -2
- package/dist/auth/core.js +2 -2
- package/dist/auth/react.js +4 -4
- package/dist/auth/routes.js +1 -1
- package/dist/bin/hightjs.js +29 -328
- package/dist/builder.js +7 -19
- package/dist/client/DefaultNotFound.js +1 -1
- package/dist/client/entry.client.js +3 -3
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +90 -28
- package/dist/hotReload.js +12 -12
- package/dist/index.d.ts +1 -1
- package/dist/index.js +16 -30
- package/dist/router.js +133 -62
- package/dist/types.d.ts +42 -0
- package/docs/config.md +201 -0
- package/example/hightjs.config.ts +81 -0
- package/example/package-lock.json +633 -3054
- package/example/package.json +1 -1
- package/package.json +1 -1
- package/src/adapters/factory.ts +8 -8
- package/src/adapters/native.ts +3 -3
- package/src/auth/client.ts +5 -5
- package/src/auth/components.tsx +2 -2
- package/src/auth/core.ts +2 -2
- package/src/auth/react.tsx +4 -4
- package/src/auth/routes.ts +1 -1
- package/src/bin/hightjs.js +30 -391
- package/src/builder.js +7 -20
- package/src/client/DefaultNotFound.tsx +1 -1
- package/src/client/entry.client.tsx +3 -3
- package/src/helpers.ts +105 -29
- package/src/hotReload.ts +12 -12
- package/src/index.ts +20 -33
- package/src/router.ts +140 -63
- package/src/types.ts +52 -0
- package/example/.hweb/entry.client.js +0 -24
- package/example/hweb-dist/main-5KKAYNUU.js +0 -1137
package/dist/router.js
CHANGED
|
@@ -59,18 +59,15 @@ function clearRequireCache(filePath) {
|
|
|
59
59
|
try {
|
|
60
60
|
const resolvedPath = require.resolve(filePath);
|
|
61
61
|
delete require.cache[resolvedPath];
|
|
62
|
-
// Também limpa arquivos temporários relacionados
|
|
62
|
+
// Também limpa arquivos temporários relacionados (apenas se existir no cache)
|
|
63
63
|
const tempFile = filePath.replace(/\.(tsx|ts)$/, '.temp.$1');
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
delete require.cache[
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
// Arquivo temporário pode não existir
|
|
64
|
+
const tempResolvedPath = require.cache[require.resolve(tempFile)];
|
|
65
|
+
if (tempResolvedPath) {
|
|
66
|
+
delete require.cache[require.resolve(tempFile)];
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
|
-
catch
|
|
73
|
-
// Arquivo pode não estar no cache
|
|
69
|
+
catch {
|
|
70
|
+
// Arquivo pode não estar no cache ou não ser resolvível
|
|
74
71
|
}
|
|
75
72
|
}
|
|
76
73
|
/**
|
|
@@ -117,11 +114,9 @@ function loadLayout(webDir) {
|
|
|
117
114
|
const layoutFile = fs_1.default.existsSync(layoutPath) ? layoutPath :
|
|
118
115
|
fs_1.default.existsSync(layoutPathJs) ? layoutPathJs : null;
|
|
119
116
|
if (layoutFile) {
|
|
120
|
-
const componentPath = path_1.default.relative(process.cwd(), layoutFile).replace(/\\/g, '/');
|
|
121
117
|
const absolutePath = path_1.default.resolve(layoutFile);
|
|
118
|
+
const componentPath = path_1.default.relative(process.cwd(), layoutFile).replace(/\\/g, '/');
|
|
122
119
|
try {
|
|
123
|
-
// Limpa o cache antes de recarregar
|
|
124
|
-
clearRequireCache(absolutePath);
|
|
125
120
|
// HACK: Cria uma versão temporária do layout SEM imports de CSS para carregar no servidor
|
|
126
121
|
const layoutContent = fs_1.default.readFileSync(layoutFile, 'utf8');
|
|
127
122
|
const tempContent = layoutContent
|
|
@@ -130,8 +125,14 @@ function loadLayout(webDir) {
|
|
|
130
125
|
.replace(/import\s+['"][^'"]*\.sass['"];?/g, '// SASS import removido para servidor');
|
|
131
126
|
const tempFile = layoutFile.replace(/\.(tsx|ts)$/, '.temp.$1');
|
|
132
127
|
fs_1.default.writeFileSync(tempFile, tempContent);
|
|
133
|
-
//
|
|
134
|
-
|
|
128
|
+
// Otimização: limpa cache apenas se existir
|
|
129
|
+
try {
|
|
130
|
+
const resolvedPath = require.resolve(tempFile);
|
|
131
|
+
if (require.cache[resolvedPath]) {
|
|
132
|
+
delete require.cache[resolvedPath];
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch { }
|
|
135
136
|
const layoutModule = require(tempFile);
|
|
136
137
|
// Remove o arquivo temporário
|
|
137
138
|
fs_1.default.unlinkSync(tempFile);
|
|
@@ -142,7 +143,7 @@ function loadLayout(webDir) {
|
|
|
142
143
|
return layoutComponent;
|
|
143
144
|
}
|
|
144
145
|
catch (error) {
|
|
145
|
-
console_1.default.error(`
|
|
146
|
+
console_1.default.error(`Error loading layout ${layoutFile}:`, error);
|
|
146
147
|
layoutComponent = { componentPath };
|
|
147
148
|
return layoutComponent;
|
|
148
149
|
}
|
|
@@ -163,35 +164,53 @@ function getLayout() {
|
|
|
163
164
|
*/
|
|
164
165
|
function loadRoutes(routesDir) {
|
|
165
166
|
if (!fs_1.default.existsSync(routesDir)) {
|
|
166
|
-
console_1.default.warn(`
|
|
167
|
+
console_1.default.warn(`Frontend routes directory not found at ${routesDir}. No page will be loaded.`);
|
|
167
168
|
allRoutes = [];
|
|
168
169
|
return allRoutes;
|
|
169
170
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
const
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
171
|
+
// Otimização: usa função recursiva manual para evitar overhead do recursive: true
|
|
172
|
+
const routeFiles = [];
|
|
173
|
+
const scanDirectory = (dir, baseDir = '') => {
|
|
174
|
+
const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
|
|
175
|
+
for (const entry of entries) {
|
|
176
|
+
const relativePath = baseDir ? path_1.default.join(baseDir, entry.name) : entry.name;
|
|
177
|
+
if (entry.isDirectory()) {
|
|
178
|
+
// Pula diretório backend inteiro
|
|
179
|
+
if (entry.name === 'backend')
|
|
180
|
+
continue;
|
|
181
|
+
scanDirectory(path_1.default.join(dir, entry.name), relativePath);
|
|
182
|
+
}
|
|
183
|
+
else if (entry.isFile()) {
|
|
184
|
+
// Filtra apenas arquivos .ts/.tsx
|
|
185
|
+
if (entry.name.endsWith('.ts') || entry.name.endsWith('.tsx')) {
|
|
186
|
+
routeFiles.push(relativePath);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
scanDirectory(routesDir);
|
|
177
192
|
const loaded = [];
|
|
193
|
+
const cwdPath = process.cwd();
|
|
194
|
+
// Otimização: processa arquivos em lote
|
|
178
195
|
for (const file of routeFiles) {
|
|
179
196
|
const filePath = path_1.default.join(routesDir, file);
|
|
180
197
|
const absolutePath = path_1.default.resolve(filePath);
|
|
181
|
-
// Usamos um caminho relativo ao CWD como um ID estável para o componente.
|
|
182
|
-
const componentPath = path_1.default.relative(process.cwd(), filePath).replace(/\\/g, '/');
|
|
183
198
|
try {
|
|
184
|
-
//
|
|
185
|
-
|
|
199
|
+
// Otimização: limpa cache apenas se já existir
|
|
200
|
+
const resolvedPath = require.resolve(filePath);
|
|
201
|
+
if (require.cache[resolvedPath]) {
|
|
202
|
+
delete require.cache[resolvedPath];
|
|
203
|
+
}
|
|
186
204
|
const routeModule = require(filePath);
|
|
187
|
-
if (routeModule.default
|
|
205
|
+
if (routeModule.default?.pattern && routeModule.default?.component) {
|
|
206
|
+
// Otimização: calcula componentPath apenas uma vez
|
|
207
|
+
const componentPath = path_1.default.relative(cwdPath, filePath).replace(/\\/g, '/');
|
|
188
208
|
loaded.push({ ...routeModule.default, componentPath });
|
|
189
|
-
// Registra o arquivo como carregado
|
|
190
209
|
loadedRouteFiles.add(absolutePath);
|
|
191
210
|
}
|
|
192
211
|
}
|
|
193
212
|
catch (error) {
|
|
194
|
-
console_1.default.error(`
|
|
213
|
+
console_1.default.error(`Error loading page route ${filePath}:`, error);
|
|
195
214
|
}
|
|
196
215
|
}
|
|
197
216
|
allRoutes = loaded;
|
|
@@ -268,7 +287,7 @@ function loadMiddlewareFromDirectory(dir) {
|
|
|
268
287
|
}
|
|
269
288
|
}
|
|
270
289
|
catch (error) {
|
|
271
|
-
console_1.default.error(`
|
|
290
|
+
console_1.default.error(`Error loading middleware ${middlewareFile}:`, error);
|
|
272
291
|
}
|
|
273
292
|
}
|
|
274
293
|
return middlewares;
|
|
@@ -301,32 +320,89 @@ function loadBackendRoutes(backendRoutesDir) {
|
|
|
301
320
|
}
|
|
302
321
|
// Limpa cache de middlewares para recarregar
|
|
303
322
|
loadedMiddlewares.clear();
|
|
304
|
-
|
|
305
|
-
const routeFiles =
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
323
|
+
// Otimização: usa função recursiva manual e coleta middlewares durante o scan
|
|
324
|
+
const routeFiles = [];
|
|
325
|
+
const middlewareFiles = new Map(); // dir -> filepath
|
|
326
|
+
const scanDirectory = (dir, baseDir = '') => {
|
|
327
|
+
const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
|
|
328
|
+
for (const entry of entries) {
|
|
329
|
+
const relativePath = baseDir ? path_1.default.join(baseDir, entry.name) : entry.name;
|
|
330
|
+
if (entry.isDirectory()) {
|
|
331
|
+
scanDirectory(path_1.default.join(dir, entry.name), relativePath);
|
|
332
|
+
}
|
|
333
|
+
else if (entry.isFile()) {
|
|
334
|
+
const isTypeScript = entry.name.endsWith('.ts') || entry.name.endsWith('.tsx');
|
|
335
|
+
if (!isTypeScript)
|
|
336
|
+
continue;
|
|
337
|
+
// Identifica middlewares durante o scan
|
|
338
|
+
if (entry.name.startsWith('middleware')) {
|
|
339
|
+
const dirPath = path_1.default.dirname(path_1.default.join(backendRoutesDir, relativePath));
|
|
340
|
+
middlewareFiles.set(dirPath, path_1.default.join(backendRoutesDir, relativePath));
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
routeFiles.push(relativePath);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
scanDirectory(backendRoutesDir);
|
|
349
|
+
// Otimização: pré-carrega todos os middlewares em um único passe
|
|
350
|
+
for (const [dirPath, middlewarePath] of middlewareFiles) {
|
|
351
|
+
try {
|
|
352
|
+
const resolvedPath = require.resolve(middlewarePath);
|
|
353
|
+
if (require.cache[resolvedPath]) {
|
|
354
|
+
delete require.cache[resolvedPath];
|
|
355
|
+
}
|
|
356
|
+
const middlewareModule = require(middlewarePath);
|
|
357
|
+
const middlewares = [];
|
|
358
|
+
if (typeof middlewareModule.default === 'function') {
|
|
359
|
+
middlewares.push(middlewareModule.default);
|
|
360
|
+
}
|
|
361
|
+
else if (Array.isArray(middlewareModule.default)) {
|
|
362
|
+
middlewares.push(...middlewareModule.default);
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
// Exports nomeados
|
|
366
|
+
for (const key in middlewareModule) {
|
|
367
|
+
if (key !== 'default' && typeof middlewareModule[key] === 'function') {
|
|
368
|
+
middlewares.push(middlewareModule[key]);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (middlewares.length > 0) {
|
|
373
|
+
loadedMiddlewares.set(dirPath, middlewares);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
catch (error) {
|
|
377
|
+
console_1.default.error(`Error loading middleware ${middlewarePath}:`, error);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
// Otimização: processa rotas com cache já limpo
|
|
310
381
|
const loaded = [];
|
|
311
382
|
for (const file of routeFiles) {
|
|
312
383
|
const filePath = path_1.default.join(backendRoutesDir, file);
|
|
313
384
|
try {
|
|
385
|
+
// Otimização: limpa cache apenas se existir
|
|
386
|
+
const resolvedPath = require.resolve(filePath);
|
|
387
|
+
if (require.cache[resolvedPath]) {
|
|
388
|
+
delete require.cache[resolvedPath];
|
|
389
|
+
}
|
|
314
390
|
const routeModule = require(filePath);
|
|
315
|
-
if (routeModule.default
|
|
391
|
+
if (routeModule.default?.pattern) {
|
|
316
392
|
const routeConfig = { ...routeModule.default };
|
|
317
|
-
// Se a rota NÃO tem
|
|
393
|
+
// Se a rota NÃO tem middleware definido, usa os da pasta
|
|
318
394
|
if (!routeConfig.hasOwnProperty('middleware')) {
|
|
319
|
-
const
|
|
320
|
-
|
|
395
|
+
const routeDir = path_1.default.dirname(path_1.default.resolve(filePath));
|
|
396
|
+
const folderMiddlewares = loadedMiddlewares.get(routeDir);
|
|
397
|
+
if (folderMiddlewares && folderMiddlewares.length > 0) {
|
|
321
398
|
routeConfig.middleware = folderMiddlewares;
|
|
322
399
|
}
|
|
323
400
|
}
|
|
324
|
-
// Se tem middleware definido (mesmo que seja []), usa só esses (não adiciona os da pasta)
|
|
325
401
|
loaded.push(routeConfig);
|
|
326
402
|
}
|
|
327
403
|
}
|
|
328
404
|
catch (error) {
|
|
329
|
-
console_1.default.error(`
|
|
405
|
+
console_1.default.error(`Error loading API route ${filePath}:`, error);
|
|
330
406
|
}
|
|
331
407
|
}
|
|
332
408
|
allBackendRoutes = loaded;
|
|
@@ -373,18 +449,24 @@ function loadNotFound(webDir) {
|
|
|
373
449
|
const notFoundFile = fs_1.default.existsSync(notFoundPath) ? notFoundPath :
|
|
374
450
|
fs_1.default.existsSync(notFoundPathJs) ? notFoundPathJs : null;
|
|
375
451
|
if (notFoundFile) {
|
|
376
|
-
const componentPath = path_1.default.relative(process.cwd(), notFoundFile).replace(/\\/g, '/');
|
|
377
452
|
const absolutePath = path_1.default.resolve(notFoundFile);
|
|
453
|
+
const componentPath = path_1.default.relative(process.cwd(), notFoundFile).replace(/\\/g, '/');
|
|
378
454
|
try {
|
|
379
|
-
//
|
|
380
|
-
|
|
455
|
+
// Otimização: limpa cache apenas se existir
|
|
456
|
+
try {
|
|
457
|
+
const resolvedPath = require.resolve(notFoundFile);
|
|
458
|
+
if (require.cache[resolvedPath]) {
|
|
459
|
+
delete require.cache[resolvedPath];
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
catch { }
|
|
381
463
|
// Registra o arquivo como carregado
|
|
382
464
|
loadedNotFoundFiles.add(absolutePath);
|
|
383
465
|
notFoundComponent = { componentPath };
|
|
384
466
|
return notFoundComponent;
|
|
385
467
|
}
|
|
386
468
|
catch (error) {
|
|
387
|
-
console_1.default.error(`
|
|
469
|
+
console_1.default.error(`Error loading notFound ${notFoundFile}:`, error);
|
|
388
470
|
notFoundComponent = { componentPath };
|
|
389
471
|
return notFoundComponent;
|
|
390
472
|
}
|
|
@@ -416,7 +498,6 @@ function processWebSocketRoutes() {
|
|
|
416
498
|
middleware: route.middleware
|
|
417
499
|
};
|
|
418
500
|
allWebSocketRoutes.push(wsRoute);
|
|
419
|
-
console_1.default.info(`WebSocket route registered: ${route.pattern}`);
|
|
420
501
|
}
|
|
421
502
|
}
|
|
422
503
|
}
|
|
@@ -453,7 +534,7 @@ function handleWebSocketConnection(ws, req, hwebReq) {
|
|
|
453
534
|
const pathname = url.pathname;
|
|
454
535
|
const matchedRoute = findMatchingWebSocketRoute(pathname);
|
|
455
536
|
if (!matchedRoute) {
|
|
456
|
-
ws.close(1000, '
|
|
537
|
+
ws.close(1000, 'Route not found');
|
|
457
538
|
return;
|
|
458
539
|
}
|
|
459
540
|
const params = extractWebSocketParams(pathname, matchedRoute.route.pattern);
|
|
@@ -488,8 +569,8 @@ function handleWebSocketConnection(ws, req, hwebReq) {
|
|
|
488
569
|
matchedRoute.route.handler(context);
|
|
489
570
|
}
|
|
490
571
|
catch (error) {
|
|
491
|
-
console.error('
|
|
492
|
-
ws.close(1011, '
|
|
572
|
+
console.error('Error in WebSocket handler:', error);
|
|
573
|
+
ws.close(1011, 'Internal server error');
|
|
493
574
|
}
|
|
494
575
|
}
|
|
495
576
|
/**
|
|
@@ -525,16 +606,11 @@ function setupWebSocketUpgrade(server, hotReloadManager) {
|
|
|
525
606
|
handleWebSocketUpgrade(request, socket, head, hotReloadManager);
|
|
526
607
|
});
|
|
527
608
|
}
|
|
528
|
-
else {
|
|
529
|
-
// Se já existe um listener (provavelmente do hot-reload),
|
|
530
|
-
// vamos interceptar e coordenar
|
|
531
|
-
console.log('🔧 Coordenando WebSocket upgrade com sistema existente');
|
|
532
|
-
}
|
|
533
609
|
}
|
|
534
610
|
function handleWebSocketUpgrade(request, socket, head, hotReloadManager) {
|
|
535
611
|
const adapter = factory_1.FrameworkAdapterFactory.getCurrentAdapter();
|
|
536
612
|
if (!adapter) {
|
|
537
|
-
console.error('❌ Framework adapter
|
|
613
|
+
console.error('❌ Framework adapter not detected. Unable to process WebSocket upgrade.');
|
|
538
614
|
socket.destroy();
|
|
539
615
|
return;
|
|
540
616
|
}
|
|
@@ -562,13 +638,10 @@ function handleWebSocketUpgrade(request, socket, head, hotReloadManager) {
|
|
|
562
638
|
});
|
|
563
639
|
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
564
640
|
wsConnections.add(ws);
|
|
565
|
-
console.log(`✅ WebSocket conectado em ${pathname}`);
|
|
566
641
|
ws.on('close', () => {
|
|
567
642
|
wsConnections.delete(ws);
|
|
568
|
-
console.log(`❌ WebSocket desconectado de ${pathname}`);
|
|
569
643
|
});
|
|
570
644
|
ws.on('error', (error) => {
|
|
571
|
-
console.error(`💥 Erro WebSocket em ${pathname}:`, error);
|
|
572
645
|
wsConnections.delete(ws);
|
|
573
646
|
});
|
|
574
647
|
// Processa a conexão
|
|
@@ -576,7 +649,5 @@ function handleWebSocketUpgrade(request, socket, head, hotReloadManager) {
|
|
|
576
649
|
});
|
|
577
650
|
return;
|
|
578
651
|
}
|
|
579
|
-
// Nenhuma rota encontrada - rejeita conexão
|
|
580
|
-
console.log(`🚫 Nenhuma rota WebSocket encontrada para: ${pathname}`);
|
|
581
652
|
socket.destroy();
|
|
582
653
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -27,6 +27,48 @@ export interface HightJSOptions {
|
|
|
27
27
|
ca?: string;
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Interface para as configurações avançadas do servidor HightJS.
|
|
32
|
+
* Essas configurações podem ser definidas no arquivo hightjs.config.js
|
|
33
|
+
*/
|
|
34
|
+
export interface HightConfig {
|
|
35
|
+
/**
|
|
36
|
+
* Limita o número máximo de headers HTTP permitidos por requisição.
|
|
37
|
+
* Padrão: 100
|
|
38
|
+
*/
|
|
39
|
+
maxHeadersCount?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Timeout em milissegundos para receber os headers HTTP.
|
|
42
|
+
* Padrão: 60000 (60 segundos)
|
|
43
|
+
*/
|
|
44
|
+
headersTimeout?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Timeout em milissegundos para uma requisição completa.
|
|
47
|
+
* Padrão: 30000 (30 segundos)
|
|
48
|
+
*/
|
|
49
|
+
requestTimeout?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Timeout geral do servidor em milissegundos.
|
|
52
|
+
* Padrão: 35000 (35 segundos)
|
|
53
|
+
*/
|
|
54
|
+
serverTimeout?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Timeout por requisição individual em milissegundos.
|
|
57
|
+
* Padrão: 30000 (30 segundos)
|
|
58
|
+
*/
|
|
59
|
+
individualRequestTimeout?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Tamanho máximo permitido para a URL em caracteres.
|
|
62
|
+
* Padrão: 2048
|
|
63
|
+
*/
|
|
64
|
+
maxUrlLength?: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Tipo da função de configuração que pode ser exportada no hightjs.config.js
|
|
68
|
+
*/
|
|
69
|
+
export type HightConfigFunction = (phase: string, context: {
|
|
70
|
+
defaultConfig: HightConfig;
|
|
71
|
+
}) => HightConfig | Promise<HightConfig>;
|
|
30
72
|
export interface Metadata {
|
|
31
73
|
title?: string;
|
|
32
74
|
description?: string;
|
package/docs/config.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# HightJS Configuration (hightjs.config.ts)
|
|
2
|
+
|
|
3
|
+
O HightJS permite que você personalize as configurações do servidor através de um arquivo `hightjs.config.ts` (ou `.js`) na raiz do seu projeto.
|
|
4
|
+
|
|
5
|
+
## 📝 Estrutura Básica
|
|
6
|
+
|
|
7
|
+
### Opção 1: Função de Configuração (Recomendado)
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import type { HightConfig, HightConfigFunction } from 'hightjs';
|
|
11
|
+
|
|
12
|
+
const hightConfig: HightConfigFunction = (phase, { defaultConfig }) => {
|
|
13
|
+
const config: HightConfig = {
|
|
14
|
+
maxHeadersCount: 100,
|
|
15
|
+
headersTimeout: 60000,
|
|
16
|
+
requestTimeout: 30000,
|
|
17
|
+
serverTimeout: 35000,
|
|
18
|
+
individualRequestTimeout: 30000,
|
|
19
|
+
maxUrlLength: 2048,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// Personalize baseado no ambiente
|
|
23
|
+
if (phase === 'development') {
|
|
24
|
+
config.requestTimeout = 60000;
|
|
25
|
+
config.individualRequestTimeout = 60000;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (phase === 'production') {
|
|
29
|
+
config.maxHeadersCount = 50;
|
|
30
|
+
config.maxUrlLength = 1024;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return config;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default hightConfig;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Opção 2: Objeto Estático
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import type { HightConfig } from 'hightjs';
|
|
43
|
+
|
|
44
|
+
const config: HightConfig = {
|
|
45
|
+
maxHeadersCount: 100,
|
|
46
|
+
headersTimeout: 60000,
|
|
47
|
+
requestTimeout: 30000,
|
|
48
|
+
serverTimeout: 35000,
|
|
49
|
+
individualRequestTimeout: 30000,
|
|
50
|
+
maxUrlLength: 2048,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default config;
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## ⚙️ Configurações Disponíveis
|
|
57
|
+
|
|
58
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
59
|
+
|------------|------|--------|-----------|
|
|
60
|
+
| `maxHeadersCount` | `number` | `100` | Número máximo de headers HTTP permitidos por requisição |
|
|
61
|
+
| `headersTimeout` | `number` | `60000` | Timeout em ms para receber os headers HTTP |
|
|
62
|
+
| `requestTimeout` | `number` | `30000` | Timeout em ms para uma requisição completa |
|
|
63
|
+
| `serverTimeout` | `number` | `35000` | Timeout geral do servidor em ms |
|
|
64
|
+
| `individualRequestTimeout` | `number` | `30000` | Timeout por requisição individual em ms |
|
|
65
|
+
| `maxUrlLength` | `number` | `2048` | Tamanho máximo da URL em caracteres |
|
|
66
|
+
|
|
67
|
+
## 🎯 Casos de Uso
|
|
68
|
+
|
|
69
|
+
### Aumentar Timeouts para Debugging
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
const config: HightConfig = {
|
|
73
|
+
requestTimeout: 120000, // 2 minutos
|
|
74
|
+
individualRequestTimeout: 120000,
|
|
75
|
+
};
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Aumentar Limites para APIs com Muitos Headers
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
const config: HightConfig = {
|
|
82
|
+
maxHeadersCount: 200, // Dobro do padrão
|
|
83
|
+
};
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Configuração Rigorosa para Produção
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const hightConfig: HightConfigFunction = (phase) => {
|
|
90
|
+
if (phase === 'production') {
|
|
91
|
+
return {
|
|
92
|
+
maxHeadersCount: 50,
|
|
93
|
+
maxUrlLength: 1024,
|
|
94
|
+
requestTimeout: 15000, // Mais restritivo
|
|
95
|
+
individualRequestTimeout: 15000,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Valores padrão para desenvolvimento
|
|
100
|
+
return {};
|
|
101
|
+
};
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Suporte a URLs Muito Longas
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
const config: HightConfig = {
|
|
108
|
+
maxUrlLength: 4096, // Dobro do padrão
|
|
109
|
+
};
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## 🔄 Hot Reload
|
|
113
|
+
|
|
114
|
+
Em modo de desenvolvimento (`dev: true`), o arquivo de configuração é recarregado automaticamente quando modificado, permitindo ajustes sem reiniciar o servidor.
|
|
115
|
+
|
|
116
|
+
## 📦 TypeScript vs JavaScript
|
|
117
|
+
|
|
118
|
+
### TypeScript (Recomendado)
|
|
119
|
+
- Arquivo: `hightjs.config.ts`
|
|
120
|
+
- Benefícios: Autocomplete, validação de tipos, detecção de erros
|
|
121
|
+
|
|
122
|
+
### JavaScript
|
|
123
|
+
- Arquivo: `hightjs.config.js`
|
|
124
|
+
- Use JSDoc para ter intellisense:
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
/**
|
|
128
|
+
* @type {import('hightjs').HightConfigFunction}
|
|
129
|
+
*/
|
|
130
|
+
const hightConfig = (phase, { defaultConfig }) => {
|
|
131
|
+
/** @type {import('hightjs').HightConfig} */
|
|
132
|
+
const config = {
|
|
133
|
+
maxHeadersCount: 100,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
return config;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
module.exports = hightConfig;
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## 🚀 Exemplo Completo
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import type { HightConfig, HightConfigFunction } from 'hightjs';
|
|
146
|
+
|
|
147
|
+
const hightConfig: HightConfigFunction = (phase, { defaultConfig }) => {
|
|
148
|
+
// Começa com valores padrão
|
|
149
|
+
const config: HightConfig = { ...defaultConfig };
|
|
150
|
+
|
|
151
|
+
// Configurações comuns
|
|
152
|
+
config.maxHeadersCount = 150;
|
|
153
|
+
|
|
154
|
+
// Ajustes por ambiente
|
|
155
|
+
if (phase === 'development') {
|
|
156
|
+
// Timeouts maiores para debugging
|
|
157
|
+
config.requestTimeout = 120000;
|
|
158
|
+
config.individualRequestTimeout = 120000;
|
|
159
|
+
|
|
160
|
+
// URLs longas para testes
|
|
161
|
+
config.maxUrlLength = 4096;
|
|
162
|
+
} else if (phase === 'production') {
|
|
163
|
+
// Mais restritivo em produção
|
|
164
|
+
config.maxHeadersCount = 50;
|
|
165
|
+
config.maxUrlLength = 1024;
|
|
166
|
+
config.requestTimeout = 20000;
|
|
167
|
+
config.individualRequestTimeout = 20000;
|
|
168
|
+
|
|
169
|
+
// Timeouts mais curtos para headers
|
|
170
|
+
config.headersTimeout = 30000;
|
|
171
|
+
config.serverTimeout = 25000;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return config;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export default hightConfig;
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## 📍 Localização do Arquivo
|
|
181
|
+
|
|
182
|
+
O arquivo `hightjs.config.ts` (ou `.js`) deve estar na **raiz do seu projeto**, no mesmo nível do `package.json`.
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
seu-projeto/
|
|
186
|
+
├── hightjs.config.ts ← Aqui
|
|
187
|
+
├── package.json
|
|
188
|
+
├── tsconfig.json
|
|
189
|
+
└── src/
|
|
190
|
+
└── web/
|
|
191
|
+
└── ...
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## ⚠️ Notas Importantes
|
|
195
|
+
|
|
196
|
+
1. **Prioridade**: `.ts` tem prioridade sobre `.js` se ambos existirem
|
|
197
|
+
2. **Fallback**: Se o arquivo não existir, valores padrão serão usados
|
|
198
|
+
3. **Validação**: Valores inválidos serão ignorados e substituídos pelos padrões
|
|
199
|
+
4. **Performance**: Use valores apropriados para evitar timeouts desnecessários ou aberturas de segurança
|
|
200
|
+
5. **Segurança**: Não exponha valores muito altos em produção (ex: `maxUrlLength` muito grande pode facilitar ataques DoS)
|
|
201
|
+
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { HightConfig, HightConfigFunction } from 'hightjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* HightJS Configuration File
|
|
5
|
+
*
|
|
6
|
+
* This file allows you to customize server settings for your HightJS application.
|
|
7
|
+
* You can export either a static configuration object or a function that returns the configuration.
|
|
8
|
+
*
|
|
9
|
+
* In a real project, you would import from 'hightjs' instead:
|
|
10
|
+
* import type { HightConfig, HightConfigFunction } from 'hightjs';
|
|
11
|
+
*/
|
|
12
|
+
const hightConfig: HightConfigFunction = (phase, { defaultConfig }) => {
|
|
13
|
+
const config: HightConfig = {
|
|
14
|
+
/**
|
|
15
|
+
* Maximum number of HTTP headers allowed per request
|
|
16
|
+
* Default: 100
|
|
17
|
+
* Increase this if you need to support requests with many headers
|
|
18
|
+
*/
|
|
19
|
+
maxHeadersCount: 100,
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Timeout in milliseconds for receiving HTTP headers
|
|
23
|
+
* Default: 60000 (60 seconds)
|
|
24
|
+
*/
|
|
25
|
+
headersTimeout: 60000,
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Timeout in milliseconds for a complete request
|
|
29
|
+
* Default: 30000 (30 seconds)
|
|
30
|
+
*/
|
|
31
|
+
requestTimeout: 30000,
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* General server timeout in milliseconds
|
|
35
|
+
* Default: 35000 (35 seconds)
|
|
36
|
+
*/
|
|
37
|
+
serverTimeout: 35000,
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Timeout per individual request in milliseconds
|
|
41
|
+
* Default: 30000 (30 seconds)
|
|
42
|
+
*/
|
|
43
|
+
individualRequestTimeout: 30000,
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Maximum URL length in characters
|
|
47
|
+
* Default: 2048
|
|
48
|
+
*/
|
|
49
|
+
maxUrlLength: 2048,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// You can customize settings based on the phase
|
|
53
|
+
if (phase === 'development') {
|
|
54
|
+
// In development, you might want longer timeouts for debugging
|
|
55
|
+
config.requestTimeout = 60000;
|
|
56
|
+
config.individualRequestTimeout = 60000;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (phase === 'production') {
|
|
60
|
+
// In production, you might want stricter limits
|
|
61
|
+
config.maxHeadersCount = 50;
|
|
62
|
+
config.maxUrlLength = 1024;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return config;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default hightConfig;
|
|
69
|
+
|
|
70
|
+
// You can also export a static object instead of a function:
|
|
71
|
+
// const staticConfig: HightConfig = {
|
|
72
|
+
// maxHeadersCount: 100,
|
|
73
|
+
// headersTimeout: 60000,
|
|
74
|
+
// requestTimeout: 30000,
|
|
75
|
+
// serverTimeout: 35000,
|
|
76
|
+
// individualRequestTimeout: 30000,
|
|
77
|
+
// maxUrlLength: 2048,
|
|
78
|
+
// };
|
|
79
|
+
//
|
|
80
|
+
// export default staticConfig;
|
|
81
|
+
|