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/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,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
+