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.
- package/dist/adapters/factory.js +8 -8
- package/dist/adapters/native.js +3 -3
- package/dist/api/console.js +1 -1
- 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 +32 -331
- package/dist/builder.js +7 -19
- package/dist/client/DefaultNotFound.js +1 -1
- package/dist/client/entry.client.js +98 -8
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +130 -29
- package/dist/hotReload.js +25 -16
- package/dist/index.d.ts +1 -1
- package/dist/index.js +26 -36
- package/dist/renderer.js +137 -18
- package/dist/router.js +133 -62
- package/dist/types.d.ts +81 -0
- package/docs/config.md +216 -0
- package/example/hightjs.config.ts +87 -0
- package/example/package-lock.json +633 -3054
- package/example/package.json +3 -3
- package/example/src/web/layout.tsx +57 -3
- package/example/src/web/routes/index.tsx +1 -1
- package/package.json +1 -1
- package/src/adapters/factory.ts +8 -8
- package/src/adapters/native.ts +3 -3
- package/src/api/console.ts +3 -1
- 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 +33 -394
- package/src/builder.js +7 -20
- package/src/client/DefaultNotFound.tsx +1 -1
- package/src/client/entry.client.tsx +125 -10
- package/src/helpers.ts +144 -30
- package/src/hotReload.ts +25 -16
- package/src/index.ts +33 -39
- package/src/renderer.tsx +142 -18
- package/src/router.ts +142 -63
- package/src/types.ts +108 -0
- package/example/.hweb/entry.client.js +0 -24
- 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:
|
|
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:
|
|
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',
|
|
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.
|
|
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
|
-
|
|
345
|
+
// Lê 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]
|
|
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
|
|
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]
|
|
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
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 ? "
|
|
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:
|
|
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}
|
|
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 (
|
|
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: "
|
|
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}
|
|
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
|
|
208
|
-
if (url.length >
|
|
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(`
|
|
326
|
+
console_1.default.error(`Native server error: ${error.message}`);
|
|
224
327
|
}
|
|
225
328
|
else {
|
|
226
|
-
console_1.default.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 (
|
|
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}
|
|
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("
|
|
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("
|
|
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("
|
|
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('
|
|
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}
|
|
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}
|
|
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(`
|
|
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, `📄
|
|
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
|
|
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
|
|
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, `⚙️
|
|
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, `🔄
|
|
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, `
|
|
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, `
|
|
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;
|
|
316
|
-
let reconnectInterval = 1000;
|
|
315
|
+
let maxReconnectInterval = 30000;
|
|
316
|
+
let reconnectInterval = 1000;
|
|
317
317
|
let reconnectTimer;
|
|
318
318
|
let isConnected = false;
|
|
319
319
|
|
|
320
320
|
function connect() {
|
|
321
|
-
//
|
|
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(
|
|
329
|
+
ws = new WebSocket(wsUrl);
|
|
328
330
|
|
|
329
331
|
ws.onopen = function() {
|
|
330
|
-
console.log('🔌 Hot-reload
|
|
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('🔄
|
|
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('❌
|
|
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('
|
|
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
|
|
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
|
};
|