hightjs 0.3.3 → 0.3.5

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 (47) hide show
  1. package/dist/adapters/factory.js +8 -8
  2. package/dist/adapters/native.js +3 -3
  3. package/dist/api/console.js +1 -1
  4. package/dist/auth/client.js +5 -5
  5. package/dist/auth/components.js +2 -2
  6. package/dist/auth/core.js +2 -2
  7. package/dist/auth/react.js +4 -4
  8. package/dist/auth/routes.js +1 -1
  9. package/dist/bin/hightjs.js +32 -331
  10. package/dist/builder.js +7 -19
  11. package/dist/client/DefaultNotFound.js +1 -1
  12. package/dist/client/entry.client.js +98 -8
  13. package/dist/helpers.d.ts +1 -0
  14. package/dist/helpers.js +130 -29
  15. package/dist/hotReload.js +25 -16
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +26 -36
  18. package/dist/renderer.js +137 -18
  19. package/dist/router.js +133 -62
  20. package/dist/types.d.ts +81 -0
  21. package/docs/config.md +216 -0
  22. package/example/hightjs.config.ts +87 -0
  23. package/example/package-lock.json +633 -3054
  24. package/example/package.json +3 -3
  25. package/example/src/web/layout.tsx +57 -3
  26. package/example/src/web/routes/index.tsx +1 -1
  27. package/package.json +1 -1
  28. package/src/adapters/factory.ts +8 -8
  29. package/src/adapters/native.ts +3 -3
  30. package/src/api/console.ts +3 -1
  31. package/src/auth/client.ts +5 -5
  32. package/src/auth/components.tsx +2 -2
  33. package/src/auth/core.ts +2 -2
  34. package/src/auth/react.tsx +4 -4
  35. package/src/auth/routes.ts +1 -1
  36. package/src/bin/hightjs.js +33 -394
  37. package/src/builder.js +7 -20
  38. package/src/client/DefaultNotFound.tsx +1 -1
  39. package/src/client/entry.client.tsx +125 -10
  40. package/src/helpers.ts +144 -30
  41. package/src/hotReload.ts +25 -16
  42. package/src/index.ts +33 -39
  43. package/src/renderer.tsx +142 -18
  44. package/src/router.ts +142 -63
  45. package/src/types.ts +108 -0
  46. package/example/.hweb/entry.client.js +0 -24
  47. 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
- try {
65
- const tempResolvedPath = require.resolve(tempFile);
66
- delete require.cache[tempResolvedPath];
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 (error) {
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
- // Carrega o arquivo temporário sem CSS
134
- delete require.cache[require.resolve(tempFile)];
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(`Erro ao carregar layout ${layoutFile}:`, 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(`Diretório de rotas de frontend não encontrado em ${routesDir}. Nenhuma página será carregada.`);
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
- const files = fs_1.default.readdirSync(routesDir, { recursive: true, encoding: 'utf-8' });
171
- // Corrigindo o filtro para excluir corretamente o diretório backend
172
- const routeFiles = files.filter(file => {
173
- const isTypeScriptFile = file.endsWith('.ts') || file.endsWith('.tsx');
174
- const isNotBackend = !file.includes('backend' + path_1.default.sep) && !file.includes('backend/');
175
- return isTypeScriptFile && isNotBackend;
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
- // Limpa o cache antes de recarregar para pegar alterações nos metadados
185
- clearRequireCache(absolutePath);
199
+ // Otimização: limpa cache apenas se 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 && routeModule.default.pattern && routeModule.default.component) {
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(`Erro ao carregar a rota de página ${filePath}:`, 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(`Erro ao carregar middleware ${middlewareFile}:`, 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
- const files = fs_1.default.readdirSync(backendRoutesDir, { recursive: true, encoding: 'utf-8' });
305
- const routeFiles = files.filter(file => {
306
- const isTypeScript = file.endsWith('.ts') || file.endsWith('.tsx');
307
- const isNotMiddleware = !path_1.default.basename(file).startsWith('middleware');
308
- return isTypeScript && isNotMiddleware;
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 && routeModule.default.pattern) {
391
+ if (routeModule.default?.pattern) {
316
392
  const routeConfig = { ...routeModule.default };
317
- // Se a rota NÃO tem a propriedade middleware definida, carrega os da pasta
393
+ // Se a rota NÃO tem middleware definido, usa os da pasta
318
394
  if (!routeConfig.hasOwnProperty('middleware')) {
319
- const folderMiddlewares = collectMiddlewaresForRoute(filePath, backendRoutesDir);
320
- if (folderMiddlewares.length > 0) {
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(`Erro ao carregar a rota de API ${filePath}:`, 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
- // Limpa o cache antes de recarregar
380
- clearRequireCache(absolutePath);
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(`Erro ao carregar notFound ${notFoundFile}:`, 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, 'Rota não encontrada');
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('Erro no handler WebSocket:', error);
492
- ws.close(1011, 'Erro interno do servidor');
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 não detectado. Não é possível processar upgrade WebSocket.');
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,10 +27,91 @@ 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
+ * Habilita o log de acesso HTTP (ex: GET /api/users 200 15ms).
67
+ * Padrão: false
68
+ */
69
+ accessLogging?: boolean;
70
+ }
71
+ /**
72
+ * Tipo da função de configuração que pode ser exportada no hightjs.config.js
73
+ */
74
+ export type HightConfigFunction = (phase: string, context: {
75
+ defaultConfig: HightConfig;
76
+ }) => HightConfig | Promise<HightConfig>;
30
77
  export interface Metadata {
31
78
  title?: string;
32
79
  description?: string;
80
+ keywords?: string | string[];
81
+ author?: string;
33
82
  favicon?: string;
83
+ viewport?: string;
84
+ themeColor?: string;
85
+ canonical?: string;
86
+ robots?: string;
87
+ openGraph?: {
88
+ title?: string;
89
+ description?: string;
90
+ type?: string;
91
+ url?: string;
92
+ image?: string | {
93
+ url: string;
94
+ width?: number;
95
+ height?: number;
96
+ alt?: string;
97
+ };
98
+ siteName?: string;
99
+ locale?: string;
100
+ };
101
+ twitter?: {
102
+ card?: 'summary' | 'summary_large_image' | 'app' | 'player';
103
+ site?: string;
104
+ creator?: string;
105
+ title?: string;
106
+ description?: string;
107
+ image?: string;
108
+ imageAlt?: string;
109
+ };
110
+ language?: string;
111
+ charset?: string;
112
+ appleTouchIcon?: string;
113
+ manifest?: string;
114
+ other?: Record<string, string>;
34
115
  }
35
116
  export interface RouteConfig {
36
117
  pattern: string;
package/docs/config.md ADDED
@@ -0,0 +1,216 @@
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
+ | `accessLogging` | `boolean` | `false` | Habilita logs de acesso HTTP (ex: `GET /api/users 200 15ms`) |
67
+
68
+ ## 🎯 Casos de Uso
69
+
70
+ ### Habilitar Logs de Acesso
71
+
72
+ ```typescript
73
+ const config: HightConfig = {
74
+ accessLogging: true, // Mostra: GET /api/users 200 15ms
75
+ };
76
+ ```
77
+
78
+ ### Aumentar Timeouts para Debugging
79
+
80
+ ```typescript
81
+ const config: HightConfig = {
82
+ requestTimeout: 120000, // 2 minutos
83
+ individualRequestTimeout: 120000,
84
+ };
85
+ ```
86
+
87
+ ### Aumentar Limites para APIs com Muitos Headers
88
+
89
+ ```typescript
90
+ const config: HightConfig = {
91
+ maxHeadersCount: 200, // Dobro do padrão
92
+ };
93
+ ```
94
+
95
+ ### Configuração Rigorosa para Produção
96
+
97
+ ```typescript
98
+ const hightConfig: HightConfigFunction = (phase) => {
99
+ if (phase === 'production') {
100
+ return {
101
+ maxHeadersCount: 50,
102
+ maxUrlLength: 1024,
103
+ requestTimeout: 15000, // Mais restritivo
104
+ individualRequestTimeout: 15000,
105
+ };
106
+ }
107
+
108
+ // Valores padrão para desenvolvimento
109
+ return {};
110
+ };
111
+ ```
112
+
113
+ ### Suporte a URLs Muito Longas
114
+
115
+ ```typescript
116
+ const config: HightConfig = {
117
+ maxUrlLength: 4096, // Dobro do padrão
118
+ };
119
+ ```
120
+
121
+ ## 🔄 Hot Reload
122
+
123
+ Em modo de desenvolvimento (`dev: true`), o arquivo de configuração é recarregado automaticamente quando modificado, permitindo ajustes sem reiniciar o servidor.
124
+
125
+ ## 📦 TypeScript vs JavaScript
126
+
127
+ ### TypeScript (Recomendado)
128
+ - Arquivo: `hightjs.config.ts`
129
+ - Benefícios: Autocomplete, validação de tipos, detecção de erros
130
+
131
+ ### JavaScript
132
+ - Arquivo: `hightjs.config.js`
133
+ - Use JSDoc para ter intellisense:
134
+
135
+ ```javascript
136
+ /**
137
+ * @type {import('hightjs').HightConfigFunction}
138
+ */
139
+ const hightConfig = (phase, { defaultConfig }) => {
140
+ /** @type {import('hightjs').HightConfig} */
141
+ const config = {
142
+ maxHeadersCount: 100,
143
+ };
144
+
145
+ return config;
146
+ };
147
+
148
+ module.exports = hightConfig;
149
+ ```
150
+
151
+ ## 🚀 Exemplo Completo
152
+
153
+ ```typescript
154
+ import type { HightConfig, HightConfigFunction } from 'hightjs';
155
+
156
+ const hightConfig: HightConfigFunction = (phase, { defaultConfig }) => {
157
+ // Começa com valores padrão
158
+ const config: HightConfig = { ...defaultConfig };
159
+
160
+ // Configurações comuns
161
+ config.maxHeadersCount = 150;
162
+
163
+ // Ajustes por ambiente
164
+ if (phase === 'development') {
165
+ // Habilita logs de acesso em dev
166
+ config.accessLogging = true;
167
+
168
+ // Timeouts maiores para debugging
169
+ config.requestTimeout = 120000;
170
+ config.individualRequestTimeout = 120000;
171
+
172
+ // URLs longas para testes
173
+ config.maxUrlLength = 4096;
174
+ } else if (phase === 'production') {
175
+ // Logs de acesso também podem ser úteis em produção
176
+ config.accessLogging = true;
177
+
178
+ // Mais restritivo em produção
179
+ config.maxHeadersCount = 50;
180
+ config.maxUrlLength = 1024;
181
+ config.requestTimeout = 20000;
182
+ config.individualRequestTimeout = 20000;
183
+
184
+ // Timeouts mais curtos para headers
185
+ config.headersTimeout = 30000;
186
+ config.serverTimeout = 25000;
187
+ }
188
+
189
+ return config;
190
+ };
191
+
192
+ export default hightConfig;
193
+ ```
194
+
195
+ ## 📍 Localização do Arquivo
196
+
197
+ O arquivo `hightjs.config.ts` (ou `.js`) deve estar na **raiz do seu projeto**, no mesmo nível do `package.json`.
198
+
199
+ ```
200
+ seu-projeto/
201
+ ├── hightjs.config.ts ← Aqui
202
+ ├── package.json
203
+ ├── tsconfig.json
204
+ └── src/
205
+ └── web/
206
+ └── ...
207
+ ```
208
+
209
+ ## ⚠️ Notas Importantes
210
+
211
+ 1. **Prioridade**: `.ts` tem prioridade sobre `.js` se ambos existirem
212
+ 2. **Fallback**: Se o arquivo não existir, valores padrão serão usados
213
+ 3. **Validação**: Valores inválidos serão ignorados e substituídos pelos padrões
214
+ 4. **Performance**: Use valores apropriados para evitar timeouts desnecessários ou aberturas de segurança
215
+ 5. **Segurança**: Não exponha valores muito altos em produção (ex: `maxUrlLength` muito grande pode facilitar ataques DoS)
216
+