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
@@ -157,10 +157,49 @@ const DEV_INDICATOR_CORNERS = [
157
157
  function DevIndicator() {
158
158
  const [corner, setCorner] = (0, react_1.useState)(3); // Canto atual (0-3)
159
159
  const [isDragging, setIsDragging] = (0, react_1.useState)(false); // Estado de arrastar
160
+ const [isBuilding, setIsBuilding] = (0, react_1.useState)(false); // Estado de build
160
161
  // Posição visual do indicador durante o arraste
161
162
  const [position, setPosition] = (0, react_1.useState)({ top: 0, left: 0 });
162
163
  const indicatorRef = (0, react_1.useRef)(null);
163
164
  const dragStartRef = (0, react_1.useRef)(null);
165
+ // Escuta eventos de hot reload para mostrar estado de build
166
+ (0, react_1.useEffect)(() => {
167
+ if (typeof window === 'undefined')
168
+ return;
169
+ const handleHotReloadMessage = (event) => {
170
+ try {
171
+ const message = JSON.parse(event.data);
172
+ // Quando detecta mudança em arquivo, ativa loading
173
+ if (message.type === 'frontend-reload' ||
174
+ message.type === 'backend-api-reload' ||
175
+ message.type === 'src-reload') {
176
+ setIsBuilding(true);
177
+ }
178
+ // Quando o build termina ou servidor fica pronto, desativa loading
179
+ if (message.type === 'server-ready' || message.type === 'build-complete') {
180
+ setIsBuilding(false);
181
+ }
182
+ }
183
+ catch (e) {
184
+ // Ignora mensagens que não são JSON
185
+ }
186
+ };
187
+ // Intercepta mensagens WebSocket
188
+ const originalWebSocket = window.WebSocket;
189
+ window.WebSocket = class extends originalWebSocket {
190
+ constructor(url, protocols) {
191
+ super(url, protocols);
192
+ this.addEventListener('message', (event) => {
193
+ if (url.toString().includes('hweb-hotreload')) {
194
+ handleHotReloadMessage(event);
195
+ }
196
+ });
197
+ }
198
+ };
199
+ return () => {
200
+ window.WebSocket = originalWebSocket;
201
+ };
202
+ }, []);
164
203
  // --- Estilos Dinâmicos ---
165
204
  const getIndicatorStyle = () => {
166
205
  const baseStyle = {
@@ -169,17 +208,22 @@ function DevIndicator() {
169
208
  width: DEV_INDICATOR_SIZE,
170
209
  height: DEV_INDICATOR_SIZE,
171
210
  borderRadius: '50%',
172
- background: 'linear-gradient(135deg, #8e2de2, #4a00e0)', // Gradiente Roxo
211
+ background: isBuilding
212
+ ? 'linear-gradient(135deg, #f093fb, #f5576c)' // Gradiente Rosa/Vermelho quando building
213
+ : 'linear-gradient(135deg, #8e2de2, #4a00e0)', // Gradiente Roxo normal
173
214
  color: 'white',
174
215
  fontWeight: 'bold',
175
216
  fontSize: 28,
176
- boxShadow: '0 4px 15px rgba(0,0,0,0.2)',
217
+ boxShadow: isBuilding
218
+ ? '0 4px 25px rgba(245, 87, 108, 0.6)' // Shadow mais forte quando building
219
+ : '0 4px 15px rgba(0,0,0,0.2)',
177
220
  display: 'flex',
178
221
  alignItems: 'center',
179
222
  justifyContent: 'center',
180
223
  cursor: isDragging ? 'grabbing' : 'grab',
181
224
  userSelect: 'none',
182
- transition: isDragging ? 'none' : 'all 0.3s ease-out', // Animação suave ao soltar
225
+ transition: isDragging ? 'none' : 'all 0.3s ease-out',
226
+ animation: isBuilding ? 'hweb-pulse 1.5s ease-in-out infinite' : 'none',
183
227
  };
184
228
  if (isDragging) {
185
229
  return {
@@ -259,13 +303,59 @@ function DevIndicator() {
259
303
  window.removeEventListener('mouseup', handleMouseUp);
260
304
  };
261
305
  }, [isDragging, handleMouseMove, handleMouseUp]);
262
- return ((0, jsx_runtime_1.jsx)("div", { ref: indicatorRef, style: getIndicatorStyle(), onMouseDown: handleMouseDown, title: "Modo Dev HightJS", children: "H" }));
306
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("style", { children: `
307
+ @keyframes hweb-pulse {
308
+ 0%, 100% {
309
+ transform: scale(1);
310
+ opacity: 1;
311
+ }
312
+ 50% {
313
+ transform: scale(1.1);
314
+ opacity: 0.8;
315
+ }
316
+ }
317
+
318
+ @keyframes hweb-spin {
319
+ from {
320
+ transform: rotate(0deg);
321
+ }
322
+ to {
323
+ transform: rotate(360deg);
324
+ }
325
+ }
326
+ ` }), (0, jsx_runtime_1.jsx)("div", { ref: indicatorRef, style: getIndicatorStyle(), onMouseDown: handleMouseDown, title: isBuilding ? "Building..." : "Modo Dev HightJS", children: isBuilding ? ((0, jsx_runtime_1.jsx)("span", { style: { animation: 'hweb-spin 1s linear infinite' }, children: "\u27F3" })) : ('H') })] }));
263
327
  }
264
328
  // --- Inicialização do Cliente (CSR - Client-Side Rendering) ---
329
+ function deobfuscateData(obfuscated) {
330
+ try {
331
+ // Remove o hash fake
332
+ const parts = obfuscated.split('.');
333
+ const base64 = parts.length > 1 ? parts[1] : parts[0];
334
+ // Decodifica base64
335
+ const jsonStr = atob(base64);
336
+ // Parse JSON
337
+ return JSON.parse(jsonStr);
338
+ }
339
+ catch (error) {
340
+ console.error('[hweb] Failed to decode data:', error);
341
+ return null;
342
+ }
343
+ }
265
344
  function initializeClient() {
266
- const initialData = window.__HWEB_INITIAL_DATA__;
345
+ // os dados do atributo data-h
346
+ const dataElement = document.getElementById('__hight_data__');
347
+ if (!dataElement) {
348
+ console.error('[hweb] Initial data script not found.');
349
+ return;
350
+ }
351
+ const obfuscated = dataElement.getAttribute('data-h');
352
+ if (!obfuscated) {
353
+ console.error('[hweb] Data attribute not found.');
354
+ return;
355
+ }
356
+ const initialData = deobfuscateData(obfuscated);
267
357
  if (!initialData) {
268
- console.error('[hweb] Dados iniciais não encontrados na página.');
358
+ console.error('[hweb] Failed to parse initial data.');
269
359
  return;
270
360
  }
271
361
  // Cria o mapa de componentes dinamicamente a partir dos módulos carregados
@@ -276,7 +366,7 @@ function initializeClient() {
276
366
  }
277
367
  const container = document.getElementById('root');
278
368
  if (!container) {
279
- console.error('[hweb] Container #root não encontrado.');
369
+ console.error('[hweb] Container #root not found.');
280
370
  return;
281
371
  }
282
372
  try {
@@ -285,7 +375,7 @@ function initializeClient() {
285
375
  root.render((0, jsx_runtime_1.jsx)(App, { componentMap: componentMap, routes: initialData.routes, initialComponentPath: initialData.initialComponentPath, initialParams: initialData.initialParams, layoutComponent: window.__HWEB_LAYOUT__ }));
286
376
  }
287
377
  catch (error) {
288
- console.error('[hweb] Erro ao renderizar aplicação:', error);
378
+ console.error('[hweb] Error rendering application:', error);
289
379
  }
290
380
  }
291
381
  // Executa quando o DOM estiver pronto
package/dist/helpers.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  import http, { Server } from 'http';
2
3
  import type { HightJSOptions } from './types';
3
4
  import https from 'https';
package/dist/helpers.js CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  "use strict";
2
3
  /*
3
4
  * This file is part of the HightJS Project.
@@ -57,6 +58,7 @@ exports.app = app;
57
58
  const http_1 = __importDefault(require("http"));
58
59
  const os_1 = __importDefault(require("os"));
59
60
  const url_1 = require("url"); // API moderna, substitui 'querystring'
61
+ const path_1 = __importDefault(require("path"));
60
62
  // Helpers para integração com diferentes frameworks
61
63
  const index_1 = __importStar(require("./index")); // Importando o tipo
62
64
  const console_1 = __importStar(require("./api/console"));
@@ -81,28 +83,86 @@ function getLocalExternalIp() {
81
83
  return 'localhost'; // Fallback
82
84
  }
83
85
  const sendBox = (options) => {
84
- const isDev = options.dev ? "Rodando em modo de desenvolvimento" : null;
86
+ const isDev = options.dev ? "Running in development mode" : null;
85
87
  // 1. Verifica se o SSL está ativado (baseado na mesma lógica do initNativeServer)
86
88
  const isSSL = options.ssl && options.ssl.key && options.ssl.cert;
87
89
  const protocol = isSSL ? 'https' : 'http';
88
90
  const localIp = getLocalExternalIp(); // Assume que getLocalExternalIp() existe
89
91
  // 2. Monta as mensagens com o protocolo correto
90
92
  const messages = [
91
- ` ${console_1.Colors.FgGray}┃${console_1.Colors.Reset} Local: ${console_1.Colors.FgGreen}${protocol}://localhost:${options.port}${console_1.Colors.Reset}`,
93
+ ` ${console_1.Colors.FgGray}┃${console_1.Colors.Reset} Local: ${console_1.Colors.FgGreen}${protocol}://localhost:${options.port}${console_1.Colors.Reset}`,
92
94
  ];
93
95
  // Só adiciona a rede se o IP local for encontrado
94
96
  if (localIp) {
95
- messages.push(` ${console_1.Colors.FgGray}┃${console_1.Colors.Reset} Rede: ${console_1.Colors.FgGreen}${protocol}://${localIp}:${options.port}${console_1.Colors.Reset}`);
97
+ messages.push(` ${console_1.Colors.FgGray}┃${console_1.Colors.Reset} Network: ${console_1.Colors.FgGreen}${protocol}://${localIp}:${options.port}${console_1.Colors.Reset}`);
96
98
  }
97
99
  if (isDev) {
98
100
  messages.push(` ${console_1.Colors.FgGray}┃${console_1.Colors.Reset} ${isDev}`);
99
101
  }
100
102
  // Adiciona aviso de redirecionamento se estiver em modo SSL
101
103
  if (isSSL && options.ssl?.redirectPort) {
102
- messages.push(` ${console_1.Colors.FgGray}┃${console_1.Colors.Reset} HTTP (porta ${options.ssl?.redirectPort}) está redirecionando para HTTPS.`);
104
+ messages.push(` ${console_1.Colors.FgGray}┃${console_1.Colors.Reset} HTTP (port ${options.ssl?.redirectPort}) is redirecting to HTTPS.`);
103
105
  }
104
- console_1.default.box(messages.join("\n"), { title: "Acesse em:" });
106
+ console_1.default.box(messages.join("\n"), { title: "Access on:" });
105
107
  };
108
+ /**
109
+ * Carrega o arquivo de configuração hightjs.config.ts ou hightjs.config.js do projeto
110
+ * @param projectDir Diretório raiz do projeto
111
+ * @param phase Fase de execução ('development' ou 'production')
112
+ * @returns Configuração mesclada com os valores padrão
113
+ */
114
+ async function loadHightConfig(projectDir, phase) {
115
+ const defaultConfig = {
116
+ maxHeadersCount: 100,
117
+ headersTimeout: 60000,
118
+ requestTimeout: 30000,
119
+ serverTimeout: 35000,
120
+ individualRequestTimeout: 30000,
121
+ maxUrlLength: 2048,
122
+ accessLogging: true,
123
+ };
124
+ try {
125
+ // Tenta primeiro .ts, depois .js
126
+ const possiblePaths = [
127
+ path_1.default.join(projectDir, 'hightjs.config.ts'),
128
+ path_1.default.join(projectDir, 'hightjs.config.js'),
129
+ ];
130
+ let configPath = null;
131
+ for (const p of possiblePaths) {
132
+ if (fs_1.default.existsSync(p)) {
133
+ configPath = p;
134
+ break;
135
+ }
136
+ }
137
+ if (!configPath) {
138
+ return defaultConfig;
139
+ }
140
+ // Remove do cache para permitir hot reload da configuração em dev
141
+ delete require.cache[require.resolve(configPath)];
142
+ const configModule = require(configPath);
143
+ const configExport = configModule.default || configModule;
144
+ let userConfig;
145
+ if (typeof configExport === 'function') {
146
+ // Suporta tanto função síncrona quanto assíncrona
147
+ userConfig = await Promise.resolve(configExport(phase, { defaultConfig }));
148
+ }
149
+ else {
150
+ userConfig = configExport;
151
+ }
152
+ // Mescla a configuração do usuário com a padrão
153
+ const mergedConfig = { ...defaultConfig, ...userConfig };
154
+ const configFileName = path_1.default.basename(configPath);
155
+ console_1.default.info(`${console_1.Colors.FgCyan}[Config]${console_1.Colors.Reset} Loaded ${configFileName}`);
156
+ return mergedConfig;
157
+ }
158
+ catch (error) {
159
+ if (error instanceof Error) {
160
+ console_1.default.warn(`${console_1.Colors.FgYellow}[Config]${console_1.Colors.Reset} Error loading hightjs.config: ${error.message}`);
161
+ console_1.default.warn(`${console_1.Colors.FgYellow}[Config]${console_1.Colors.Reset} Using default configuration`);
162
+ }
163
+ return defaultConfig;
164
+ }
165
+ }
106
166
  /**
107
167
  * Middleware para parsing do body com proteções de segurança (versão melhorada).
108
168
  * Rejeita a promise em caso de erro de parsing ou estouro de limite.
@@ -181,12 +241,19 @@ const parseBody = (req) => {
181
241
  async function initNativeServer(hwebApp, options, port, hostname) {
182
242
  const time = Date.now();
183
243
  await hwebApp.prepare();
244
+ // Carrega a configuração do arquivo hightjs.config.js
245
+ const projectDir = options.dir || process.cwd();
246
+ const phase = options.dev ? 'development' : 'production';
247
+ const hightConfig = await loadHightConfig(projectDir, phase);
184
248
  const handler = hwebApp.getRequestHandler();
185
- const msg = console_1.default.dynamicLine(` ${console_1.Colors.BgYellow} ready ${console_1.Colors.Reset} ${console_1.Colors.Bright}Iniciando HightJS na porta ${options.port}${console_1.Colors.Reset}`);
249
+ const msg = console_1.default.dynamicLine(` ${console_1.Colors.BgYellow} ready ${console_1.Colors.Reset} ${console_1.Colors.Bright}Starting HightJS on port ${options.port}${console_1.Colors.Reset}`);
186
250
  // --- LÓGICA DO LISTENER (REUTILIZÁVEL) ---
187
251
  // Extraímos a lógica principal para uma variável
188
252
  // para que possa ser usada tanto pelo servidor HTTP quanto HTTPS.
189
253
  const requestListener = async (req, res) => {
254
+ const requestStartTime = Date.now();
255
+ const method = req.method || 'GET';
256
+ const url = req.url || '/';
190
257
  // Configurações de segurança básicas
191
258
  res.setHeader('X-Content-Type-Options', 'nosniff');
192
259
  res.setHeader('X-Frame-Options', 'DENY');
@@ -197,15 +264,51 @@ async function initNativeServer(hwebApp, options, port, hostname) {
197
264
  if (options.ssl) {
198
265
  res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
199
266
  }
200
- // Timeout por requisição
201
- req.setTimeout(30000, () => {
267
+ // Timeout por requisição (usa configuração personalizada)
268
+ req.setTimeout(hightConfig.individualRequestTimeout || 30000, () => {
202
269
  res.statusCode = 408; // Request Timeout
203
270
  res.end('Request timeout');
271
+ // Log de timeout
272
+ if (hightConfig.accessLogging) {
273
+ const duration = Date.now() - requestStartTime;
274
+ console_1.default.info(`${console_1.Colors.FgYellow}${method}${console_1.Colors.Reset} ${url} ${console_1.Colors.FgRed}408${console_1.Colors.Reset} ${console_1.Colors.FgGray}${duration}ms${console_1.Colors.Reset}`);
275
+ }
204
276
  });
277
+ // Intercepta o método end() para logar quando a resposta for enviada
278
+ const originalEnd = res.end.bind(res);
279
+ let hasEnded = false;
280
+ res.end = function (...args) {
281
+ if (!hasEnded && hightConfig.accessLogging) {
282
+ hasEnded = true;
283
+ const duration = Date.now() - requestStartTime;
284
+ const statusCode = res.statusCode || 200;
285
+ // Define cor baseada no status code
286
+ let statusColor = console_1.Colors.FgGreen; // 2xx
287
+ if (statusCode >= 500)
288
+ statusColor = console_1.Colors.FgRed; // 5xx
289
+ else if (statusCode >= 400)
290
+ statusColor = console_1.Colors.FgYellow; // 4xx
291
+ else if (statusCode >= 300)
292
+ statusColor = console_1.Colors.FgCyan; // 3xx
293
+ // Formata o método com cor
294
+ let methodColor = console_1.Colors.BgCyan;
295
+ if (method === 'POST')
296
+ methodColor = console_1.Colors.BgGreen;
297
+ else if (method === 'PUT')
298
+ methodColor = console_1.Colors.BgYellow;
299
+ else if (method === 'DELETE')
300
+ methodColor = console_1.Colors.BgRed;
301
+ else if (method === 'PATCH')
302
+ methodColor = console_1.Colors.BgMagenta;
303
+ console_1.default.logCustomLevel(method, true, methodColor, `${url} ${statusColor}${statusCode}${console_1.Colors.Reset} ${console_1.Colors.FgGray}${duration}ms${console_1.Colors.Reset}`);
304
+ }
305
+ // @ts-ignore
306
+ return originalEnd.apply(this, args);
307
+ };
205
308
  try {
206
- // Validação básica de URL
207
- const url = req.url || '/';
208
- if (url.length > 2048) {
309
+ // Validação básica de URL (usa configuração personalizada)
310
+ const maxUrlLength = hightConfig.maxUrlLength || 2048;
311
+ if (url.length > maxUrlLength) {
209
312
  res.statusCode = 414; // URI Too Long
210
313
  res.end('URL too long');
211
314
  return;
@@ -220,10 +323,10 @@ async function initNativeServer(hwebApp, options, port, hostname) {
220
323
  catch (error) {
221
324
  // Log do erro no servidor
222
325
  if (error instanceof Error) {
223
- console_1.default.error(`Erro no servidor nativo: ${error.message}`);
326
+ console_1.default.error(`Native server error: ${error.message}`);
224
327
  }
225
328
  else {
226
- console_1.default.error('Erro desconhecido no servidor nativo:', error);
329
+ console_1.default.error('Unknown native server error:', error);
227
330
  }
228
331
  // Tratamento de erro (idêntico ao seu original)
229
332
  if (!res.headersSent) {
@@ -286,14 +389,14 @@ async function initNativeServer(hwebApp, options, port, hostname) {
286
389
  // Cria o servidor HTTP nativo
287
390
  server = http_1.default.createServer(requestListener); // (any para contornar HWebIncomingMessage)
288
391
  }
289
- // Configurações de segurança do servidor (Comum a ambos)
290
- server.setTimeout(35000); // Timeout geral do servidor
291
- server.maxHeadersCount = 100; // Limita número de headers
292
- server.headersTimeout = 60000; // Timeout para headers
293
- server.requestTimeout = 30000; // Timeout para requisições
392
+ // Configurações de segurança do servidor (usa configuração personalizada)
393
+ server.setTimeout(hightConfig.serverTimeout || 35000); // Timeout geral do servidor
394
+ server.maxHeadersCount = hightConfig.maxHeadersCount || 100; // Limita número de headers
395
+ server.headersTimeout = hightConfig.headersTimeout || 60000; // Timeout para headers
396
+ server.requestTimeout = hightConfig.requestTimeout || 30000; // Timeout para requisições
294
397
  server.listen(port, hostname, () => {
295
398
  sendBox({ ...options, port });
296
- msg.end(` ${console_1.Colors.BgGreen} ready ${console_1.Colors.Reset} ${console_1.Colors.Bright}Pronto na porta ${console_1.Colors.BgGreen} ${options.port} ${console_1.Colors.Reset}${console_1.Colors.Bright} em ${Date.now() - time}ms${console_1.Colors.Reset}\n`);
399
+ msg.end(` ${console_1.Colors.BgGreen} ready ${console_1.Colors.Reset} ${console_1.Colors.Bright}Ready on port ${console_1.Colors.BgGreen} ${options.port} ${console_1.Colors.Reset}${console_1.Colors.Bright} in ${Date.now() - time}ms${console_1.Colors.Reset}\n`);
297
400
  });
298
401
  // Configura WebSocket para hot reload (Comum a ambos)
299
402
  hwebApp.setupWebSocket(server);
@@ -325,7 +428,7 @@ function app(options = {}) {
325
428
  serverApp.use(cookieParser());
326
429
  }
327
430
  catch (e) {
328
- console_1.default.error("Não foi possivel achar cookie-parser");
431
+ console_1.default.error("Could not find cookie-parser");
329
432
  }
330
433
  serverApp.use(express.json());
331
434
  serverApp.use(express.urlencoded({ extended: true }));
@@ -337,13 +440,13 @@ function app(options = {}) {
337
440
  await serverApp.register(require('@fastify/cookie'));
338
441
  }
339
442
  catch (e) {
340
- console_1.default.error("Não foi possivel achar @fastify/cookie");
443
+ console_1.default.error("Could not find @fastify/cookie");
341
444
  }
342
445
  try {
343
446
  await serverApp.register(require('@fastify/formbody'));
344
447
  }
345
448
  catch (e) {
346
- console_1.default.error("Não foi possivel achar @fastify/formbody");
449
+ console_1.default.error("Could not find @fastify/formbody");
347
450
  }
348
451
  await serverApp.register(async (fastify) => {
349
452
  fastify.all('*', handler);
@@ -371,7 +474,7 @@ function app(options = {}) {
371
474
  return data.version;
372
475
  }
373
476
  catch (error) {
374
- console_1.default.error('Não foi possível verificar a versão mais recente do HightJS:', error);
477
+ console_1.default.error('Could not check for the latest HightJS version:', error);
375
478
  return currentVersion; // Retorna a versão atual em caso de erro
376
479
  }
377
480
  }
@@ -379,22 +482,20 @@ function app(options = {}) {
379
482
  const isUpToDate = latestVersion === currentVersion;
380
483
  let message;
381
484
  if (!isUpToDate) {
382
- message = `${console_1.Colors.FgGreen} uma nova versão disponível (v${latestVersion})${console_1.Colors.FgMagenta}`;
485
+ message = `${console_1.Colors.FgGreen} A new version is available (v${latestVersion})${console_1.Colors.FgMagenta}`;
383
486
  }
384
487
  else {
385
- message = `${console_1.Colors.FgGreen} Você está na versão mais recente${console_1.Colors.FgMagenta}`;
488
+ message = `${console_1.Colors.FgGreen} You are on the latest version${console_1.Colors.FgMagenta}`;
386
489
  }
387
490
  console.log(`${console_1.Colors.FgMagenta}
388
491
  __ ___ ${console_1.Colors.FgGreen} __ ${console_1.Colors.FgMagenta}
389
492
  |__| | / _\` |__| | ${console_1.Colors.FgGreen} | /__\` ${console_1.Colors.FgMagenta} ${console_1.Colors.FgMagenta}HightJS ${console_1.Colors.FgGray}(v${require('../package.json').version}) - itsmuzin${console_1.Colors.FgMagenta}
390
- | | | \\__> | | | ${console_1.Colors.FgGreen}\\__/ .__/ ${message}
391
-
392
-
493
+ | | | \\__> | | | ${console_1.Colors.FgGreen}\\__/ .__/ ${message}
393
494
  ${console_1.Colors.Reset}`);
394
495
  const actualPort = options.port || 3000;
395
496
  const actualHostname = options.hostname || "0.0.0.0";
396
497
  if (framework !== 'native') {
397
- console_1.default.warn(`O framework "${framework}" foi selecionado, mas o método init() funciona com o framework "native". Iniciando servidor nativo...`);
498
+ console_1.default.warn(`The "${framework}" framework was selected, but the init() method only works with the "native" framework. Starting native server...`);
398
499
  }
399
500
  return await initNativeServer(hwebApp, options, actualPort, actualHostname);
400
501
  }
package/dist/hotReload.js CHANGED
@@ -202,7 +202,7 @@ class HotReloadManager {
202
202
  this.clearBackendCache(filePath);
203
203
  // Se for arquivo de frontend, aguarda o build terminar antes de recarregar
204
204
  if (isFrontendFile) {
205
- console_1.default.logWithout(console_1.Levels.INFO, console_1.Colors.BgRed, `📄 Aguardando build do frontend...`);
205
+ console_1.default.logWithout(console_1.Levels.INFO, console_1.Colors.BgRed, `📄 Waiting for frontend build...`);
206
206
  // Marca que estamos esperando um build
207
207
  this.isBuilding = true;
208
208
  // Cria uma promise que será resolvida quando o build terminar
@@ -215,12 +215,12 @@ class HotReloadManager {
215
215
  });
216
216
  try {
217
217
  await Promise.race([buildPromise, timeoutPromise]);
218
- console_1.default.logWithout(console_1.Levels.INFO, console_1.Colors.BgRed, `✅ Build concluído, recarregando frontend...`);
218
+ console_1.default.logWithout(console_1.Levels.INFO, console_1.Colors.BgRed, `✅ Build complete, reloading frontend...`);
219
219
  this.frontendChangeCallback?.();
220
220
  this.notifyClients('frontend-reload', { file: filePath, event: 'change' });
221
221
  }
222
222
  catch (error) {
223
- console_1.default.logWithout(console_1.Levels.ERROR, console_1.Colors.BgRed, `⚠️ Timeout no build, recarregando mesmo assim...`);
223
+ console_1.default.logWithout(console_1.Levels.ERROR, console_1.Colors.BgRed, `⚠️ Timeout in build, reloading anyway...`);
224
224
  this.frontendChangeCallback?.();
225
225
  this.notifyClients('frontend-reload', { file: filePath, event: 'change' });
226
226
  }
@@ -231,13 +231,13 @@ class HotReloadManager {
231
231
  }
232
232
  // Se for arquivo de backend, recarrega o módulo e notifica
233
233
  if (isBackendFile) {
234
- console_1.default.logWithout(console_1.Levels.INFO, console_1.Colors.BgRed, `⚙️ Recarregando backend...`);
234
+ console_1.default.logWithout(console_1.Levels.INFO, console_1.Colors.BgRed, `⚙️ Reloading backend...`);
235
235
  this.backendApiChangeCallback?.();
236
236
  this.notifyClients('backend-api-reload', { file: filePath, event: 'change' });
237
237
  }
238
238
  // Fallback: se não for nem frontend nem backend detectado, recarrega tudo
239
239
  if (!isFrontendFile && !isBackendFile) {
240
- console_1.default.logWithout(console_1.Levels.INFO, console_1.Colors.BgRed, `🔄 Recarregando aplicação...`);
240
+ console_1.default.logWithout(console_1.Levels.INFO, console_1.Colors.BgRed, `🔄 Reloading application...`);
241
241
  this.frontendChangeCallback?.();
242
242
  this.backendApiChangeCallback?.();
243
243
  this.notifyClients('src-reload', { file: filePath, event: 'change' });
@@ -249,7 +249,7 @@ class HotReloadManager {
249
249
  }
250
250
  catch (error) {
251
251
  // @ts-ignore
252
- console_1.default.logWithout(console_1.Levels.ERROR, `Erro no listener customizado: ${error.message}`);
252
+ console_1.default.logWithout(console_1.Levels.ERROR, `Error in custom listener: ${error.message}`);
253
253
  }
254
254
  }
255
255
  }
@@ -265,7 +265,7 @@ class HotReloadManager {
265
265
  ws.send(message);
266
266
  }
267
267
  catch (error) {
268
- console_1.default.logWithout(console_1.Levels.ERROR, console_1.Colors.BgRed, `Erro ao enviar mensagem WebSocket: ${error}`);
268
+ console_1.default.logWithout(console_1.Levels.ERROR, console_1.Colors.BgRed, `Error sending WebSocket message: ${error}`);
269
269
  deadClients.push(ws);
270
270
  }
271
271
  }
@@ -312,22 +312,24 @@ class HotReloadManager {
312
312
  if (typeof window !== 'undefined') {
313
313
  let ws;
314
314
  let reconnectAttempts = 0;
315
- let maxReconnectInterval = 30000; // 30 segundos max
316
- let reconnectInterval = 1000; // Começa com 1 segundo
315
+ let maxReconnectInterval = 30000;
316
+ let reconnectInterval = 1000;
317
317
  let reconnectTimer;
318
318
  let isConnected = false;
319
319
 
320
320
  function connect() {
321
- // Evita múltiplas tentativas simultâneas
321
+ const url = window.location; // Objeto com info da URL atual
322
+ const protocol = url.protocol === "https:" ? "wss:" : "ws:"; // Usa wss se for https
323
+ const wsUrl = protocol + '//' + url.host + '/hweb-hotreload/';
322
324
  if (ws && (ws.readyState === WebSocket.CONNECTING || ws.readyState === WebSocket.OPEN)) {
323
325
  return;
324
326
  }
325
327
 
326
328
  try {
327
- ws = new WebSocket('ws://localhost:3000/hweb-hotreload/');
329
+ ws = new WebSocket(wsUrl);
328
330
 
329
331
  ws.onopen = function() {
330
- console.log('🔌 Hot-reload conectado');
332
+ console.log('🔌 Hot-reload connected');
331
333
  isConnected = true;
332
334
  reconnectAttempts = 0;
333
335
  reconnectInterval = 1000;
@@ -347,13 +349,13 @@ class HotReloadManager {
347
349
  window.location.reload();
348
350
  break;
349
351
  case 'server-restart':
350
- console.log('🔄 Servidor reiniciando...');
352
+ console.log('🔄 Server restarting...');
351
353
  break;
352
354
  case 'server-ready':
353
355
  setTimeout(() => window.location.reload(), 500);
354
356
  break;
355
357
  case 'frontend-error':
356
- console.error('❌ Erro no frontend:', message.data);
358
+ console.error('❌ Frontend error:', message.data);
357
359
  break;
358
360
  }
359
361
  } catch (e) {
@@ -378,7 +380,7 @@ class HotReloadManager {
378
380
  };
379
381
 
380
382
  } catch (error) {
381
- console.error('Erro ao criar WebSocket:', error);
383
+ console.error('Error creating WebSocket:', error);
382
384
  scheduleReconnect();
383
385
  }
384
386
  }
@@ -443,7 +445,7 @@ class HotReloadManager {
443
445
  }
444
446
  setHotReloadListener(listener) {
445
447
  this.customHotReloadListener = listener;
446
- console_1.default.info('🔌 Hot reload listener customizado registrado');
448
+ console_1.default.info('🔌 Hot reload custom listener registered');
447
449
  }
448
450
  removeHotReloadListener() {
449
451
  this.customHotReloadListener = null;
@@ -454,6 +456,13 @@ class HotReloadManager {
454
456
  this.buildCompleteResolve = null;
455
457
  }
456
458
  this.isBuilding = false;
459
+ // Notifica os clientes que o build terminou
460
+ if (success) {
461
+ this.notifyClients('build-complete', { success: true });
462
+ }
463
+ else {
464
+ this.notifyClients('build-error', { success: false });
465
+ }
457
466
  }
458
467
  }
459
468
  exports.HotReloadManager = HotReloadManager;
package/dist/index.d.ts CHANGED
@@ -8,11 +8,11 @@ export { FrameworkAdapterFactory } from './adapters/factory';
8
8
  export type { GenericRequest, GenericResponse, CookieOptions } from './types/framework';
9
9
  export { app } from './helpers';
10
10
  export type { WebSocketContext, WebSocketHandler } from './types';
11
+ export type { HightConfig, HightConfigFunction } from './types';
11
12
  export default function hweb(options: HightJSOptions): {
12
13
  prepare: () => Promise<void>;
13
14
  executeInstrumentation: () => void;
14
15
  getRequestHandler: () => RequestHandler;
15
16
  setupWebSocket: (server: any) => void;
16
- build: () => Promise<void>;
17
17
  stop: () => void;
18
18
  };