hightjs 0.4.0 → 0.5.0

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 (125) hide show
  1. package/README.md +48 -116
  2. package/dist/bin/hightjs.js +51 -23
  3. package/dist/builder.js +139 -4
  4. package/dist/client/DefaultNotFound.d.ts +1 -1
  5. package/dist/client/DefaultNotFound.js +72 -46
  6. package/dist/client/client.d.ts +3 -0
  7. package/dist/{client.js → client/client.js} +4 -4
  8. package/dist/client/entry.client.js +39 -29
  9. package/dist/global/global.d.ts +117 -0
  10. package/dist/{auth/types.js → global/global.js} +0 -1
  11. package/dist/helpers.js +80 -2
  12. package/dist/hotReload.js +2 -2
  13. package/dist/index.js +16 -16
  14. package/dist/loaders.d.ts +1 -0
  15. package/dist/loaders.js +46 -0
  16. package/dist/renderer.js +158 -4
  17. package/dist/types.d.ts +44 -0
  18. package/package.json +36 -31
  19. package/.idea/HightJS.iml +0 -9
  20. package/.idea/copilot.data.migration.agent.xml +0 -6
  21. package/.idea/copilot.data.migration.ask.xml +0 -6
  22. package/.idea/copilot.data.migration.ask2agent.xml +0 -6
  23. package/.idea/copilot.data.migration.edit.xml +0 -6
  24. package/.idea/copilotDiffState.xml +0 -67
  25. package/.idea/inspectionProfiles/Project_Default.xml +0 -13
  26. package/.idea/libraries/test_package.xml +0 -9
  27. package/.idea/libraries/ts_commonjs_default_export.xml +0 -9
  28. package/.idea/misc.xml +0 -7
  29. package/.idea/modules.xml +0 -8
  30. package/.idea/vcs.xml +0 -6
  31. package/dist/auth/client.d.ts +0 -24
  32. package/dist/auth/client.js +0 -146
  33. package/dist/auth/components.d.ts +0 -29
  34. package/dist/auth/components.js +0 -100
  35. package/dist/auth/core.d.ts +0 -55
  36. package/dist/auth/core.js +0 -189
  37. package/dist/auth/index.d.ts +0 -7
  38. package/dist/auth/index.js +0 -45
  39. package/dist/auth/jwt.d.ts +0 -41
  40. package/dist/auth/jwt.js +0 -185
  41. package/dist/auth/providers/credentials.d.ts +0 -60
  42. package/dist/auth/providers/credentials.js +0 -97
  43. package/dist/auth/providers/discord.d.ts +0 -63
  44. package/dist/auth/providers/discord.js +0 -190
  45. package/dist/auth/providers/google.d.ts +0 -63
  46. package/dist/auth/providers/google.js +0 -186
  47. package/dist/auth/providers/index.d.ts +0 -2
  48. package/dist/auth/providers/index.js +0 -35
  49. package/dist/auth/providers.d.ts +0 -3
  50. package/dist/auth/providers.js +0 -26
  51. package/dist/auth/react/index.d.ts +0 -6
  52. package/dist/auth/react/index.js +0 -48
  53. package/dist/auth/react.d.ts +0 -22
  54. package/dist/auth/react.js +0 -199
  55. package/dist/auth/routes.d.ts +0 -16
  56. package/dist/auth/routes.js +0 -152
  57. package/dist/auth/types.d.ts +0 -76
  58. package/dist/client.d.ts +0 -3
  59. package/docs/README.md +0 -58
  60. package/docs/arquivos-especiais.md +0 -10
  61. package/docs/autenticacao.md +0 -212
  62. package/docs/checklist.md +0 -9
  63. package/docs/cli.md +0 -72
  64. package/docs/config.md +0 -216
  65. package/docs/estrutura.md +0 -20
  66. package/docs/faq.md +0 -10
  67. package/docs/hot-reload.md +0 -5
  68. package/docs/integracoes.md +0 -240
  69. package/docs/middlewares.md +0 -73
  70. package/docs/rotas-backend.md +0 -45
  71. package/docs/rotas-frontend.md +0 -66
  72. package/docs/seguranca.md +0 -8
  73. package/docs/websocket.md +0 -45
  74. package/example/certs/cert.pem +0 -20
  75. package/example/certs/key.pem +0 -27
  76. package/example/hightjs.config.ts +0 -87
  77. package/example/package-lock.json +0 -1174
  78. package/example/package.json +0 -26
  79. package/example/postcss.config.js +0 -8
  80. package/example/src/backend/auth.ts +0 -42
  81. package/example/src/backend/routes/auth.ts +0 -3
  82. package/example/src/backend/routes/version.ts +0 -13
  83. package/example/src/web/components/Home.tsx +0 -140
  84. package/example/src/web/components/LoginPage.tsx +0 -149
  85. package/example/src/web/globals.css +0 -5
  86. package/example/src/web/layout.tsx +0 -100
  87. package/example/src/web/routes/index.tsx +0 -13
  88. package/example/src/web/routes/login.tsx +0 -30
  89. package/example/tailwind.config.js +0 -12
  90. package/example/tsconfig.json +0 -15
  91. package/src/adapters/express.ts +0 -87
  92. package/src/adapters/factory.ts +0 -112
  93. package/src/adapters/fastify.ts +0 -104
  94. package/src/adapters/native.ts +0 -234
  95. package/src/api/console.ts +0 -305
  96. package/src/api/http.ts +0 -535
  97. package/src/auth/client.ts +0 -171
  98. package/src/auth/components.tsx +0 -125
  99. package/src/auth/core.ts +0 -215
  100. package/src/auth/index.ts +0 -25
  101. package/src/auth/jwt.ts +0 -210
  102. package/src/auth/providers/credentials.ts +0 -139
  103. package/src/auth/providers/discord.ts +0 -239
  104. package/src/auth/providers/google.ts +0 -234
  105. package/src/auth/providers/index.ts +0 -20
  106. package/src/auth/providers.ts +0 -20
  107. package/src/auth/react/index.ts +0 -25
  108. package/src/auth/react.tsx +0 -234
  109. package/src/auth/routes.ts +0 -183
  110. package/src/auth/types.ts +0 -108
  111. package/src/bin/hightjs.js +0 -222
  112. package/src/builder.js +0 -472
  113. package/src/client/DefaultNotFound.tsx +0 -84
  114. package/src/client/clientRouter.ts +0 -153
  115. package/src/client/entry.client.tsx +0 -511
  116. package/src/client.ts +0 -24
  117. package/src/components/Link.tsx +0 -38
  118. package/src/helpers.ts +0 -542
  119. package/src/hotReload.ts +0 -569
  120. package/src/index.ts +0 -555
  121. package/src/renderer.tsx +0 -263
  122. package/src/router.ts +0 -730
  123. package/src/types/framework.ts +0 -58
  124. package/src/types.ts +0 -207
  125. package/tsconfig.json +0 -17
package/src/index.ts DELETED
@@ -1,555 +0,0 @@
1
- /*
2
- * This file is part of the HightJS Project.
3
- * Copyright (c) 2025 itsmuzin
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
- import path from 'path';
18
- import fs from 'fs';
19
- import {ExpressAdapter} from './adapters/express';
20
- import {build, buildWithChunks, watch, watchWithChunks} from './builder';
21
- import {
22
- BackendHandler,
23
- BackendRouteConfig,
24
- HightJSOptions,
25
- HightMiddleware,
26
- RequestHandler,
27
- RouteConfig
28
- } from './types';
29
- import {
30
- findMatchingBackendRoute,
31
- findMatchingRoute,
32
- getLayout,
33
- getNotFound,
34
- loadBackendRoutes,
35
- loadLayout,
36
- loadNotFound,
37
- loadRoutes,
38
- processWebSocketRoutes,
39
- setupWebSocketUpgrade
40
- } from './router';
41
- import {render} from './renderer';
42
- import {HightJSRequest, HightJSResponse} from './api/http';
43
- import {HotReloadManager} from './hotReload';
44
- import {FrameworkAdapterFactory} from './adapters/factory';
45
- import {GenericRequest, GenericResponse} from './types/framework';
46
- import Console, {Colors} from "./api/console"
47
-
48
- // Exporta apenas os tipos e classes para o backend
49
- export { HightJSRequest, HightJSResponse };
50
- export type { BackendRouteConfig, BackendHandler };
51
-
52
- // Exporta os adapters para uso manual se necessário
53
- export { ExpressAdapter } from './adapters/express';
54
- export { FastifyAdapter } from './adapters/fastify';
55
- export { FrameworkAdapterFactory } from './adapters/factory';
56
- export type { GenericRequest, GenericResponse, CookieOptions } from './types/framework';
57
-
58
- // Exporta os helpers para facilitar integração
59
- export { app } from './helpers';
60
-
61
- // Exporta o sistema de WebSocket
62
- export type { WebSocketContext, WebSocketHandler } from './types';
63
-
64
- // Exporta os tipos de configuração
65
- export type { HightConfig, HightConfigFunction } from './types';
66
-
67
- // Função para verificar se o projeto é grande o suficiente para se beneficiar de chunks
68
- function isLargeProject(projectDir: string): boolean {
69
- try {
70
- const srcDir = path.join(projectDir, 'src');
71
- if (!fs.existsSync(srcDir)) return false;
72
-
73
- let totalFiles = 0;
74
- let totalSize = 0;
75
-
76
- function scanDirectory(dir: string) {
77
- const items = fs.readdirSync(dir, { withFileTypes: true });
78
-
79
- for (const item of items) {
80
- const fullPath = path.join(dir, item.name);
81
-
82
- if (item.isDirectory() && item.name !== 'node_modules' && item.name !== '.git') {
83
- scanDirectory(fullPath);
84
- } else if (item.isFile() && /\.(tsx?|jsx?|css|scss|less)$/i.test(item.name)) {
85
- totalFiles++;
86
- totalSize += fs.statSync(fullPath).size;
87
- }
88
- }
89
- }
90
-
91
- scanDirectory(srcDir);
92
-
93
- // Considera projeto grande se:
94
- // - Mais de 20 arquivos de frontend/style
95
- // - Ou tamanho total > 500KB
96
- return totalFiles > 20 || totalSize > 500 * 1024;
97
- } catch (error) {
98
- // Em caso de erro, assume que não é um projeto grande
99
- return false;
100
- }
101
- }
102
-
103
- // Função para gerar o arquivo de entrada para o esbuild
104
- function createEntryFile(projectDir: string, routes: (RouteConfig & { componentPath: string })[]): string {
105
- try {
106
- const tempDir = path.join(projectDir, '.hight', 'temp');
107
-
108
- fs.mkdirSync(tempDir, { recursive: true });
109
-
110
- const entryFilePath = path.join(tempDir, 'entry.client.js');
111
- // Verifica se há layout
112
- const layout = getLayout();
113
-
114
- // Verifica se há notFound personalizado
115
- const notFound = getNotFound();
116
-
117
- // Gera imports dinâmicos para cada componente
118
- const imports = routes
119
- .map((route, index) => {
120
- const relativePath = path.relative(tempDir, route.componentPath).replace(/\\/g, '/');
121
- return `import route${index} from '${relativePath}';`;
122
- })
123
- .join('\n');
124
-
125
- // Import do layout se existir
126
- const layoutImport = layout
127
- ? `import LayoutComponent from '${path.relative(tempDir, layout.componentPath).replace(/\\/g, '/')}';`
128
- : '';
129
-
130
- // Import do notFound se existir
131
- const notFoundImport = notFound
132
- ? `import NotFoundComponent from '${path.relative(tempDir, notFound.componentPath).replace(/\\/g, '/')}';`
133
- : '';
134
-
135
- // Registra os componentes no window para o cliente acessar
136
- const componentRegistration = routes
137
- .map((route, index) => ` '${route.componentPath}': route${index}.component || route${index}.default?.component,`)
138
- .join('\n');
139
-
140
- // Registra o layout se existir
141
- const layoutRegistration = layout
142
- ? `window.__HWEB_LAYOUT__ = LayoutComponent.default || LayoutComponent;`
143
- : `window.__HWEB_LAYOUT__ = null;`;
144
-
145
- // Registra o notFound se existir
146
- const notFoundRegistration = notFound
147
- ? `window.__HWEB_NOT_FOUND__ = NotFoundComponent.default || NotFoundComponent;`
148
- : `window.__HWEB_NOT_FOUND__ = null;`;
149
-
150
- // Caminho correto para o entry.client.tsx
151
- const sdkDir = path.dirname(__dirname); // Vai para a pasta pai de src (onde está o hweb-sdk)
152
- const entryClientPath = path.join(sdkDir, 'src', 'client', 'entry.client.tsx');
153
- const relativeEntryPath = path.relative(tempDir, entryClientPath).replace(/\\/g, '/');
154
-
155
- // Import do DefaultNotFound do SDK
156
- const defaultNotFoundPath = path.join(sdkDir, 'src', 'client', 'DefaultNotFound.tsx');
157
- const relativeDefaultNotFoundPath = path.relative(tempDir, defaultNotFoundPath).replace(/\\/g, '/');
158
-
159
- const entryContent = `// Arquivo gerado automaticamente pelo hweb
160
- ${imports}
161
- ${layoutImport}
162
- ${notFoundImport}
163
- import DefaultNotFound from '${relativeDefaultNotFoundPath}';
164
-
165
- // Registra os componentes para o cliente
166
- window.__HWEB_COMPONENTS__ = {
167
- ${componentRegistration}
168
- };
169
-
170
- // Registra o layout se existir
171
- ${layoutRegistration}
172
-
173
- // Registra o notFound se existir
174
- ${notFoundRegistration}
175
-
176
- // Registra o DefaultNotFound do hweb
177
- window.__HWEB_DEFAULT_NOT_FOUND__ = DefaultNotFound;
178
-
179
- // Importa e executa o entry.client.tsx
180
- import '${relativeEntryPath}';
181
- `;
182
-
183
- try {
184
- fs.writeFileSync(entryFilePath, entryContent);
185
- } catch (e) {
186
- console.error("sdfijnsdfnijfsdijnfsdnijsdfnijfsdnijfsdnijfsdn", e)
187
- }
188
-
189
- return entryFilePath;
190
- }catch (e){
191
- Console.error("Error creating entry file:", e);
192
- throw e;
193
- }
194
- }
195
-
196
- export default function hweb(options: HightJSOptions) {
197
- const { dev = true, dir = process.cwd(), port = 3000 } = options;
198
- // @ts-ignore
199
- process.hight = options;
200
- const userWebDir = path.join(dir, 'src', 'web');
201
- const userWebRoutesDir = path.join(userWebDir, 'routes');
202
- const userBackendRoutesDir = path.join(dir, 'src', 'backend', 'routes');
203
-
204
- /**
205
- * Executa middlewares sequencialmente e depois o handler final
206
- * @param middlewares Array de middlewares para executar
207
- * @param finalHandler Handler final da rota
208
- * @param request Requisição do HightJS
209
- * @param params Parâmetros da rota
210
- * @returns Resposta do middleware ou handler final
211
- */
212
- async function executeMiddlewareChain(
213
- middlewares: HightMiddleware[] | undefined,
214
- finalHandler: BackendHandler,
215
- request: HightJSRequest,
216
- params: { [key: string]: string }
217
- ): Promise<HightJSResponse> {
218
- if (!middlewares || middlewares.length === 0) {
219
- // Não há middlewares, executa diretamente o handler final
220
- return await finalHandler(request, params);
221
- }
222
-
223
- let currentIndex = 0;
224
-
225
- // Função next que será chamada pelos middlewares
226
- const next = async (): Promise<HightJSResponse> => {
227
- if (currentIndex < middlewares.length) {
228
- // Ainda há middlewares para executar
229
- const currentMiddleware = middlewares[currentIndex];
230
- currentIndex++;
231
- return await currentMiddleware(request, params, next);
232
- } else {
233
- // Todos os middlewares foram executados, chama o handler final
234
- return await finalHandler(request, params);
235
- }
236
- };
237
-
238
- // Inicia a cadeia de execução
239
- return await next();
240
- }
241
-
242
- let frontendRoutes: (RouteConfig & { componentPath: string })[] = [];
243
- let hotReloadManager: HotReloadManager | null = null;
244
- let entryPoint: string;
245
- let outfile: string;
246
-
247
- // Função para regenerar o entry file
248
- const regenerateEntryFile = () => {
249
- // Recarrega todas as rotas e componentes
250
- frontendRoutes = loadRoutes(userWebRoutesDir);
251
- loadLayout(userWebDir);
252
- loadNotFound(userWebDir);
253
-
254
- // Regenera o entry file
255
- entryPoint = createEntryFile(dir, frontendRoutes);
256
- };
257
-
258
- return {
259
- prepare: async () => {
260
- const isProduction = !dev;
261
-
262
- if (!isProduction) {
263
- // Inicia hot reload apenas em desenvolvimento (com suporte ao main)
264
- hotReloadManager = new HotReloadManager(dir);
265
- await hotReloadManager.start();
266
-
267
- // Adiciona callback para recarregar TUDO quando qualquer arquivo mudar
268
- hotReloadManager.onBackendApiChange(() => {
269
-
270
-
271
- loadBackendRoutes(userBackendRoutesDir);
272
- processWebSocketRoutes(); // Processa rotas WS após recarregar backend
273
- });
274
-
275
- // Adiciona callback para regenerar entry file quando frontend mudar
276
- hotReloadManager.onFrontendChange(() => {
277
- regenerateEntryFile();
278
- });
279
- }
280
- const now = Date.now();
281
- const timee = Console.dynamicLine(` ${Colors.BgYellow} router ${Colors.Reset} Loading routes and components`);
282
- const spinnerFrames1 = ['|', '/', '-', '\\'];
283
- let frameIndex1 = 0;
284
-
285
- const spinner1 = setInterval(() => {
286
- timee.update(` ${Colors.FgYellow}${spinnerFrames1[frameIndex1]}${Colors.Reset} Loading routes and components...`);
287
- frameIndex1 = (frameIndex1 + 1) % spinnerFrames1.length;
288
- }, 100); // muda a cada 100ms
289
- // ORDEM IMPORTANTE: Carrega TUDO antes de criar o arquivo de entrada
290
- frontendRoutes = loadRoutes(userWebRoutesDir);
291
- loadBackendRoutes(userBackendRoutesDir);
292
-
293
- // Processa rotas WebSocket após carregar backend
294
- processWebSocketRoutes();
295
-
296
- // Carrega layout.tsx ANTES de criar o entry file
297
- const layout = loadLayout(userWebDir);
298
-
299
- const notFound = loadNotFound(userWebDir);
300
-
301
- const outDir = path.join(dir, '.hight');
302
- fs.mkdirSync(outDir, {recursive: true});
303
-
304
- entryPoint = createEntryFile(dir, frontendRoutes);
305
- clearInterval(spinner1)
306
- timee.end(` ${Colors.BgGreen} router ${Colors.Reset} Routes and components loaded in ${Date.now() - now}ms`);
307
-
308
-
309
- if (isProduction) {
310
- const time = Console.dynamicLine(` ${Colors.BgYellow} build ${Colors.Reset} Starting client build`);
311
-
312
- // Spinner
313
- const spinnerFrames = ['|', '/', '-', '\\'];
314
- let frameIndex = 0;
315
-
316
- const spinner = setInterval(() => {
317
- time.update(` ${Colors.FgYellow}${spinnerFrames[frameIndex]}${Colors.Reset} Building...`);
318
- frameIndex = (frameIndex + 1) % spinnerFrames.length;
319
- }, 100); // muda a cada 100ms
320
-
321
- const now = Date.now();
322
- await buildWithChunks(entryPoint, outDir, isProduction);
323
- const elapsed = Date.now() - now;
324
-
325
- clearInterval(spinner); // para o spinner
326
- time.update(""); // limpa a linha
327
- time.end(` ${Colors.BgGreen} build ${Colors.Reset} Client build completed in ${elapsed}ms`);
328
-
329
- // Notifica o hot reload manager que o build foi concluído
330
- if (hotReloadManager) {
331
- hotReloadManager.onBuildComplete(true);
332
- }
333
-
334
- } else {
335
- const time = Console.dynamicLine(` ${Colors.BgYellow} watcher ${Colors.Reset} Starting client watch`);
336
- watchWithChunks(entryPoint, outDir, hotReloadManager!).catch(err => {
337
- Console.error(`Error starting watch`, err);
338
- });
339
- time.end(` ${Colors.BgGreen} watcher ${Colors.Reset} Client Watch started`);
340
- }
341
-
342
- },
343
-
344
- executeInstrumentation: () => {
345
-
346
- // verificar se dir/src/instrumentation.(tsx/jsx/js/ts) existe com regex
347
- const instrumentationFile = fs.readdirSync(path.join(dir, 'src')).find(file => /^hightweb\.(tsx|jsx|js|ts)$/.test(file));
348
- if (instrumentationFile) {
349
- const instrumentationPath = path.join(dir, 'src', instrumentationFile);
350
- // dar require, e executar a função principal do arquivo
351
- const instrumentation = require(instrumentationPath);
352
-
353
- // Registra o listener de hot reload se existir
354
- if (instrumentation.hotReloadListener && typeof instrumentation.hotReloadListener === 'function') {
355
- if (hotReloadManager) {
356
- hotReloadManager.setHotReloadListener(instrumentation.hotReloadListener);
357
- }
358
- }
359
-
360
- if (typeof instrumentation === 'function') {
361
- instrumentation();
362
- } else if (typeof instrumentation.default === 'function') {
363
- instrumentation.default();
364
- } else {
365
- Console.warn(`The instrumentation file ${instrumentationFile} does not export a default function.`);
366
- }
367
- }
368
- },
369
- getRequestHandler: (): RequestHandler => {
370
- return async (req: any, res: any) => {
371
- // Detecta automaticamente o framework e cria o adapter apropriado
372
- const adapter = FrameworkAdapterFactory.detectFramework(req, res);
373
- const genericReq = adapter.parseRequest(req);
374
- const genericRes = adapter.createResponse(res);
375
-
376
- // Adiciona informações do hweb na requisição genérica
377
- (genericReq as any).hwebDev = dev;
378
- (genericReq as any).hotReloadManager = hotReloadManager;
379
-
380
- const {pathname} = new URL(genericReq.url, `http://${genericReq.headers.host || 'localhost'}`);
381
- const method = genericReq.method.toUpperCase();
382
-
383
- // 1. Verifica se é WebSocket upgrade para hot reload
384
- if (pathname === '/hweb-hotreload/' && genericReq.headers.upgrade === 'websocket' && hotReloadManager) {
385
- // Framework vai chamar o evento 'upgrade' do servidor HTTP
386
- return;
387
- }
388
-
389
- // 2. Primeiro verifica se é um arquivo estático da pasta public
390
- if (pathname !== '/' && !pathname.startsWith('/api/') && !pathname.startsWith('/.hight')) {
391
- const publicDir = path.join(dir, 'public');
392
- const filePath = path.join(publicDir, pathname);
393
-
394
- if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
395
- const ext = path.extname(filePath).toLowerCase();
396
- const contentTypes: Record<string, string> = {
397
- '.html': 'text/html',
398
- '.css': 'text/css',
399
- '.js': 'application/javascript',
400
- '.json': 'application/json',
401
- '.png': 'image/png',
402
- '.jpg': 'image/jpeg',
403
- '.jpeg': 'image/jpeg',
404
- '.gif': 'image/gif',
405
- '.svg': 'image/svg+xml',
406
- '.ico': 'image/x-icon',
407
- '.webp': 'image/webp',
408
- '.mp4': 'video/mp4',
409
- '.webm': 'video/webm',
410
- '.mp3': 'audio/mpeg',
411
- '.wav': 'audio/wav',
412
- '.pdf': 'application/pdf',
413
- '.txt': 'text/plain',
414
- '.xml': 'application/xml',
415
- '.zip': 'application/zip'
416
- };
417
-
418
- genericRes.header('Content-Type', contentTypes[ext] || 'application/octet-stream');
419
-
420
- // Para arquivos estáticos, usamos o método nativo do framework
421
- if (adapter.type === 'express') {
422
- (res as any).sendFile(filePath);
423
- } else if (adapter.type === 'fastify') {
424
- const fileContent = fs.readFileSync(filePath);
425
- genericRes.send(fileContent);
426
- } else if (adapter.type === 'native') {
427
- const fileContent = fs.readFileSync(filePath);
428
- genericRes.send(fileContent);
429
- }
430
- return;
431
- }
432
- }
433
-
434
- // 3. Verifica se é um arquivo estático do .hight
435
- if (pathname.startsWith('/_hight/')) {
436
-
437
- const staticPath = path.join(dir, '.hight');
438
- const filePath = path.join(staticPath, pathname.replace('/_hight/', ''));
439
-
440
- if (fs.existsSync(filePath)) {
441
-
442
- const ext = path.extname(filePath).toLowerCase();
443
- const contentTypes: Record<string, string> = {
444
- '.js': 'application/javascript',
445
- '.css': 'text/css',
446
- '.map': 'application/json'
447
- };
448
-
449
- genericRes.header('Content-Type', contentTypes[ext] || 'text/plain');
450
-
451
- // Para arquivos estáticos, usamos o método nativo do framework
452
- if (adapter.type === 'express') {
453
- (res as any).sendFile(filePath);
454
- } else if (adapter.type === 'fastify') {
455
- const fileContent = fs.readFileSync(filePath);
456
- genericRes.send(fileContent);
457
- } else if (adapter.type === 'native') {
458
- const fileContent = fs.readFileSync(filePath);
459
- genericRes.send(fileContent);
460
- }
461
- return;
462
- }
463
- }
464
-
465
- // 4. REMOVIDO: Verificação de arquivos React UMD - não precisamos mais
466
- // O React agora será bundlado diretamente no main.js
467
-
468
- // 5. Verifica se é uma rota de API (backend)
469
- const backendMatch = findMatchingBackendRoute(pathname, method);
470
- if (backendMatch) {
471
- try {
472
- const handler = backendMatch.route[method as keyof BackendRouteConfig] as BackendHandler;
473
- if (handler) {
474
- const hwebReq = new HightJSRequest(genericReq);
475
-
476
- // Executa middlewares e depois o handler final
477
- const hwebRes = await executeMiddlewareChain(
478
- backendMatch.route.middleware,
479
- handler,
480
- hwebReq,
481
- backendMatch.params
482
- );
483
-
484
- // Aplica a resposta usando o adapter correto
485
- hwebRes._applyTo(genericRes);
486
- return;
487
- }
488
- } catch (error) {
489
- Console.error(`API route error ${pathname}:`, error);
490
- genericRes.status(500).text('Internal server error in API');
491
- return;
492
- }
493
- }
494
-
495
- // 6. Por último, tenta renderizar uma página (frontend) ou 404
496
- const pageMatch = findMatchingRoute(pathname);
497
-
498
- if (!pageMatch) {
499
- // Em vez de enviar texto simples, renderiza a página 404 React
500
- try {
501
- // Cria uma "rota falsa" para a página 404
502
- const notFoundRoute = {
503
- pattern: '/__404__',
504
- component: () => null, // Componente vazio, será tratado no cliente
505
- componentPath: '__404__'
506
- };
507
-
508
- const html = await render({
509
- req: genericReq,
510
- route: notFoundRoute,
511
- params: {},
512
- allRoutes: frontendRoutes
513
- });
514
- genericRes.status(404).header('Content-Type', 'text/html').send(html);
515
- return;
516
- } catch (error) {
517
- Console.error(`Error rendering page 404:`, error);
518
- genericRes.status(404).text('Page not found');
519
- return;
520
- }
521
- }
522
-
523
- try {
524
- const html = await render({
525
- req: genericReq,
526
- route: pageMatch.route,
527
- params: pageMatch.params,
528
- allRoutes: frontendRoutes
529
- });
530
- genericRes.status(200).header('Content-Type', 'text/html').send(html);
531
- } catch (error) {
532
- Console.error(`Error rendering page ${pathname}:`, error);
533
- genericRes.status(500).text('Internal server error');
534
- }
535
- };
536
- },
537
-
538
- // Método para configurar WebSocket upgrade nos servidores Express e Fastify
539
- setupWebSocket: (server: any) => {
540
- // Detecta se é um servidor Express ou Fastify
541
- const isExpressServer = FrameworkAdapterFactory.getCurrentAdapter() instanceof ExpressAdapter;
542
- const actualServer = isExpressServer ? server : (server.server || server);
543
-
544
- // Usa o sistema coordenado de WebSocket upgrade que integra hot-reload e rotas de usuário
545
- setupWebSocketUpgrade(actualServer, hotReloadManager);
546
- },
547
-
548
-
549
- stop: () => {
550
- if (hotReloadManager) {
551
- hotReloadManager.stop();
552
- }
553
- }
554
- };
555
- }