hightjs 0.2.42 → 0.2.45

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 (76) hide show
  1. package/.idea/copilotDiffState.xml +67 -0
  2. package/README.md +26 -514
  3. package/dist/auth/core.js +3 -3
  4. package/dist/auth/index.d.ts +1 -1
  5. package/dist/auth/index.js +2 -1
  6. package/dist/auth/providers/google.d.ts +63 -0
  7. package/dist/auth/providers/google.js +186 -0
  8. package/dist/auth/providers.d.ts +1 -0
  9. package/dist/auth/providers.js +3 -1
  10. package/dist/auth/types.d.ts +6 -7
  11. package/dist/bin/hightjs.js +393 -0
  12. package/dist/client/entry.client.js +11 -1
  13. package/dist/hotReload.d.ts +8 -1
  14. package/dist/hotReload.js +304 -144
  15. package/dist/index.d.ts +2 -1
  16. package/dist/index.js +20 -33
  17. package/dist/renderer.js +1 -1
  18. package/dist/router.d.ts +24 -1
  19. package/dist/router.js +201 -2
  20. package/dist/types.d.ts +19 -1
  21. package/docs/README.md +59 -0
  22. package/docs/adapters.md +7 -0
  23. package/docs/arquivos-especiais.md +10 -0
  24. package/docs/autenticacao.md +212 -0
  25. package/docs/checklist.md +9 -0
  26. package/docs/cli.md +21 -0
  27. package/docs/estrutura.md +20 -0
  28. package/docs/faq.md +10 -0
  29. package/docs/hot-reload.md +5 -0
  30. package/docs/middlewares.md +73 -0
  31. package/docs/rotas-backend.md +45 -0
  32. package/docs/rotas-frontend.md +66 -0
  33. package/docs/seguranca.md +8 -0
  34. package/docs/websocket.md +45 -0
  35. package/package.json +1 -1
  36. package/src/auth/core.ts +3 -3
  37. package/src/auth/index.ts +2 -3
  38. package/src/auth/providers/google.ts +218 -0
  39. package/src/auth/providers.ts +1 -1
  40. package/src/auth/types.ts +3 -8
  41. package/src/bin/hightjs.js +475 -0
  42. package/src/client/entry.client.tsx +12 -1
  43. package/src/hotReload.ts +333 -147
  44. package/src/index.ts +58 -51
  45. package/src/renderer.tsx +1 -1
  46. package/src/router.ts +230 -3
  47. package/src/types.ts +24 -1
  48. package/dist/adapters/starters/express.d.ts +0 -0
  49. package/dist/adapters/starters/express.js +0 -1
  50. package/dist/adapters/starters/factory.d.ts +0 -0
  51. package/dist/adapters/starters/factory.js +0 -1
  52. package/dist/adapters/starters/fastify.d.ts +0 -0
  53. package/dist/adapters/starters/fastify.js +0 -1
  54. package/dist/adapters/starters/index.d.ts +0 -0
  55. package/dist/adapters/starters/index.js +0 -1
  56. package/dist/adapters/starters/native.d.ts +0 -0
  57. package/dist/adapters/starters/native.js +0 -1
  58. package/dist/auth/example.d.ts +0 -40
  59. package/dist/auth/example.js +0 -104
  60. package/dist/client/ErrorBoundary.d.ts +0 -16
  61. package/dist/client/ErrorBoundary.js +0 -181
  62. package/dist/client/routerContext.d.ts +0 -26
  63. package/dist/client/routerContext.js +0 -62
  64. package/dist/eslint/index.d.ts +0 -32
  65. package/dist/eslint/index.js +0 -15
  66. package/dist/eslint/use-client-rule.d.ts +0 -19
  67. package/dist/eslint/use-client-rule.js +0 -99
  68. package/dist/eslintSetup.d.ts +0 -0
  69. package/dist/eslintSetup.js +0 -1
  70. package/dist/example/src/web/routes/index.d.ts +0 -3
  71. package/dist/example/src/web/routes/index.js +0 -15
  72. package/dist/typescript/use-client-plugin.d.ts +0 -5
  73. package/dist/typescript/use-client-plugin.js +0 -113
  74. package/dist/validation.d.ts +0 -0
  75. package/dist/validation.js +0 -1
  76. package/src/auth/example.ts +0 -115
package/src/index.ts CHANGED
@@ -1,15 +1,32 @@
1
- import express from 'express';
2
1
  import path from 'path';
3
2
  import fs from 'fs';
4
- import { ExpressAdapter } from './adapters/express';
5
- import { build, watch, buildWithChunks, watchWithChunks } from './builder';
6
- import { HightJSOptions, RequestHandler, RouteConfig, BackendRouteConfig, BackendHandler, HightMiddleware } from './types';
7
- import { loadRoutes, findMatchingRoute, loadBackendRoutes, findMatchingBackendRoute, loadLayout, getLayout, loadNotFound, getNotFound } from './router';
8
- import { render } from './renderer';
9
- import { HightJSRequest, HightJSResponse } from './api/http';
10
- import { HotReloadManager } from './hotReload';
11
- import { FrameworkAdapterFactory } from './adapters/factory';
12
- import { GenericRequest, GenericResponse } from './types/framework';
3
+ import {ExpressAdapter} from './adapters/express';
4
+ import {build, buildWithChunks, watch, watchWithChunks} from './builder';
5
+ import {
6
+ BackendHandler,
7
+ BackendRouteConfig,
8
+ HightJSOptions,
9
+ HightMiddleware,
10
+ RequestHandler,
11
+ RouteConfig
12
+ } from './types';
13
+ import {
14
+ findMatchingBackendRoute,
15
+ findMatchingRoute,
16
+ getLayout,
17
+ getNotFound,
18
+ loadBackendRoutes,
19
+ loadLayout,
20
+ loadNotFound,
21
+ loadRoutes,
22
+ processWebSocketRoutes,
23
+ setupWebSocketUpgrade
24
+ } from './router';
25
+ import {render} from './renderer';
26
+ import {HightJSRequest, HightJSResponse} from './api/http';
27
+ import {HotReloadManager} from './hotReload';
28
+ import {FrameworkAdapterFactory} from './adapters/factory';
29
+ import {GenericRequest, GenericResponse} from './types/framework';
13
30
  import Console, {Colors} from "./api/console"
14
31
 
15
32
  // Exporta apenas os tipos e classes para o backend
@@ -25,7 +42,8 @@ export type { GenericRequest, GenericResponse, CookieOptions } from './types/fra
25
42
  // Exporta os helpers para facilitar integração
26
43
  export { app } from './helpers';
27
44
 
28
- // Exporta o sistema de autenticação
45
+ // Exporta o sistema de WebSocket
46
+ export type { WebSocketContext, WebSocketHandler } from './types';
29
47
 
30
48
  // Função para verificar se o projeto é grande o suficiente para se beneficiar de chunks
31
49
  function isLargeProject(projectDir: string): boolean {
@@ -207,22 +225,26 @@ export default function hweb(options: HightJSOptions) {
207
225
  entryPoint = createEntryFile(dir, frontendRoutes);
208
226
  };
209
227
 
210
- const app = {
228
+ return {
211
229
  prepare: async () => {
212
230
  const isProduction = !dev;
213
231
 
214
232
  if (!isProduction) {
215
- // Inicia hot reload apenas em desenvolvimento (sem logs)
233
+ // Inicia hot reload apenas em desenvolvimento (com suporte ao main)
216
234
  hotReloadManager = new HotReloadManager(dir);
217
235
  await hotReloadManager.start();
218
236
 
219
- // Adiciona callback para recarregar rotas de backend quando mudarem
237
+ // Adiciona callback para recarregar TUDO quando qualquer arquivo mudar
220
238
  hotReloadManager.onBackendApiChange(() => {
239
+ Console.info('🔄 Recarregando backend e dependências...');
240
+
221
241
  loadBackendRoutes(userBackendRoutesDir);
242
+ processWebSocketRoutes(); // Processa rotas WS após recarregar backend
222
243
  });
223
244
 
224
245
  // Adiciona callback para regenerar entry file quando frontend mudar
225
246
  hotReloadManager.onFrontendChange(() => {
247
+ Console.info('🔄 Regenerando frontend...');
226
248
  regenerateEntryFile();
227
249
  });
228
250
  }
@@ -231,13 +253,16 @@ export default function hweb(options: HightJSOptions) {
231
253
  frontendRoutes = loadRoutes(userWebRoutesDir);
232
254
  loadBackendRoutes(userBackendRoutesDir);
233
255
 
234
- // Carrega layout.tsx ANTES de criar o entry file
256
+ // Processa rotas WebSocket após carregar backend
257
+ processWebSocketRoutes();
258
+
259
+ // Carrega layout.tsx ANTES de criar o entry file
235
260
  const layout = loadLayout(userWebDir);
236
261
 
237
- const notFound = loadNotFound(userWebDir);
262
+ const notFound = loadNotFound(userWebDir);
238
263
 
239
264
  const outDir = path.join(dir, 'hweb-dist');
240
- fs.mkdirSync(outDir, { recursive: true });
265
+ fs.mkdirSync(outDir, {recursive: true});
241
266
 
242
267
  entryPoint = createEntryFile(dir, frontendRoutes);
243
268
 
@@ -278,6 +303,15 @@ export default function hweb(options: HightJSOptions) {
278
303
  const instrumentationPath = path.join(dir, 'src', instrumentationFile);
279
304
  // dar require, e executar a função principal do arquivo
280
305
  const instrumentation = require(instrumentationPath);
306
+
307
+ // Registra o listener de hot reload se existir
308
+ if (instrumentation.hotReloadListener && typeof instrumentation.hotReloadListener === 'function') {
309
+ if (hotReloadManager) {
310
+ hotReloadManager.setHotReloadListener(instrumentation.hotReloadListener);
311
+ Console.info('✅ Hot reload listener registrado');
312
+ }
313
+ }
314
+
281
315
  if (typeof instrumentation === 'function') {
282
316
  instrumentation();
283
317
  } else if (typeof instrumentation.default === 'function') {
@@ -298,7 +332,7 @@ export default function hweb(options: HightJSOptions) {
298
332
  (genericReq as any).hwebDev = dev;
299
333
  (genericReq as any).hotReloadManager = hotReloadManager;
300
334
 
301
- const { pathname } = new URL(genericReq.url, `http://${genericReq.headers.host || 'localhost'}`);
335
+ const {pathname} = new URL(genericReq.url, `http://${genericReq.headers.host || 'localhost'}`);
302
336
  const method = genericReq.method.toUpperCase();
303
337
 
304
338
  // 1. Verifica se é WebSocket upgrade para hot reload
@@ -456,43 +490,18 @@ export default function hweb(options: HightJSOptions) {
456
490
 
457
491
  // Método para configurar WebSocket upgrade nos servidores Express e Fastify
458
492
  setupWebSocket: (server: any) => {
459
- if (hotReloadManager) {
460
- // Detecta se é um servidor Express ou Fastify
461
- const isExpressServer = FrameworkAdapterFactory.getCurrentAdapter() instanceof ExpressAdapter;
462
-
463
-
464
- if (isExpressServer) {
465
-
466
- server.on('upgrade', (request: any, socket: any, head: Buffer) => {
467
- const { pathname } = new URL(request.url, `http://${request.headers.host}`);
493
+ // Detecta se é um servidor Express ou Fastify
494
+ const isExpressServer = FrameworkAdapterFactory.getCurrentAdapter() instanceof ExpressAdapter;
495
+ const actualServer = isExpressServer ? server : (server.server || server);
468
496
 
469
- if (pathname === '/hweb-hotreload/') {
470
- hotReloadManager!.handleUpgrade(request, socket, head);
471
- } else {
472
- socket.destroy();
473
- }
474
- });
475
- } else {
476
-
477
- // Fastify usa um approach diferente para WebSockets
478
- const actualServer = server.server || server;
479
- actualServer.on('upgrade', (request: any, socket: any, head: Buffer) => {
480
- const { pathname } = new URL(request.url, `http://${request.headers.host}`);
481
-
482
- if (pathname === '/hweb-hotreload/') {
483
- hotReloadManager!.handleUpgrade(request, socket, head);
484
- } else {
485
- socket.destroy();
486
- }
487
- });
488
- }
489
- }
497
+ // Usa o sistema coordenado de WebSocket upgrade que integra hot-reload e rotas de usuário
498
+ setupWebSocketUpgrade(actualServer, hotReloadManager);
490
499
  },
491
500
 
492
501
  build: async () => {
493
502
  const msg = Console.dynamicLine(` ${Colors.FgYellow}● ${Colors.Reset}Iniciando build do cliente para produção`);
494
503
  const outDir = path.join(dir, 'hweb-dist');
495
- fs.mkdirSync(outDir, { recursive: true });
504
+ fs.mkdirSync(outDir, {recursive: true});
496
505
 
497
506
  const routes = loadRoutes(userWebRoutesDir);
498
507
  const entryPoint = createEntryFile(dir, routes);
@@ -509,6 +518,4 @@ export default function hweb(options: HightJSOptions) {
509
518
  }
510
519
  }
511
520
  };
512
-
513
- return app;
514
521
  }
package/src/renderer.tsx CHANGED
@@ -15,7 +15,7 @@ function encodeInitialData(data: any): string {
15
15
 
16
16
  function createDecodeScript(): string {
17
17
  return `
18
- const process = { env: { NODE_ENV: '${process.env.NODE_ENV || 'development'}' } };
18
+
19
19
  window.__HWEB_DECODE__ = function(encoded) { const base64 = encoded.replace('hweb_', '').replace('_config', ''); const jsonStr = atob(base64); return JSON.parse(jsonStr); };
20
20
  `;
21
21
  }
package/src/router.ts CHANGED
@@ -1,7 +1,12 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { RouteConfig, BackendRouteConfig, HightMiddleware } from './types';
3
+ import { RouteConfig, BackendRouteConfig, HightMiddleware, WebSocketHandler, WebSocketContext } from './types';
4
+ import { WebSocketServer as WSServer, WebSocket } from 'ws';
5
+ import { IncomingMessage } from 'http';
6
+ import { URL } from 'url';
4
7
  import Console from "./api/console"
8
+ import {FrameworkAdapterFactory} from "./adapters/factory";
9
+ import {HightJSRequest} from "./api/http";
5
10
 
6
11
  // --- Roteamento do Frontend ---
7
12
 
@@ -198,8 +203,19 @@ export function findMatchingRoute(pathname: string) {
198
203
  for (const route of allRoutes) {
199
204
  if (!route.pattern) continue;
200
205
 
201
- // Converte o padrão da rota (ex: /users/[id]) em uma RegExp
202
- const regexPattern = route.pattern.replace(/\[(\w+)\]/g, '(?<$1>[^/]+)');
206
+ const regexPattern = route.pattern
207
+ // [[...param]] → opcional catch-all
208
+ .replace(/\[\[\.\.\.(\w+)\]\]/g, '(?<$1>.+)?')
209
+ // [...param] → obrigatório catch-all
210
+ .replace(/\[\.\.\.(\w+)\]/g, '(?<$1>.+)')
211
+ // /[[param]] → opcional com barra também opcional
212
+ .replace(/\/\[\[(\w+)\]\]/g, '(?:/(?<$1>[^/]+))?')
213
+ // [[param]] → segmento opcional (sem barra anterior)
214
+ .replace(/\[\[(\w+)\]\]/g, '(?<$1>[^/]+)?')
215
+ // [param] → segmento obrigatório
216
+ .replace(/\[(\w+)\]/g, '(?<$1>[^/]+)');
217
+
218
+ // permite / opcional no final
203
219
  const regex = new RegExp(`^${regexPattern}/?$`);
204
220
  const match = pathname.match(regex);
205
221
 
@@ -210,9 +226,11 @@ export function findMatchingRoute(pathname: string) {
210
226
  };
211
227
  }
212
228
  }
229
+
213
230
  return null;
214
231
  }
215
232
 
233
+
216
234
  // --- Roteamento do Backend ---
217
235
 
218
236
  // Guarda todas as rotas de API encontradas
@@ -406,3 +424,212 @@ export function loadNotFound(webDir: string): { componentPath: string } | null {
406
424
  export function getNotFound(): { componentPath: string } | null {
407
425
  return notFoundComponent;
408
426
  }
427
+
428
+ // --- WebSocket Functions ---
429
+
430
+ // Guarda todas as rotas WebSocket encontradas
431
+ let allWebSocketRoutes: { pattern: string; handler: WebSocketHandler; middleware?: HightMiddleware[] }[] = [];
432
+
433
+ // Conexões WebSocket ativas
434
+ let wsConnections: Set<WebSocket> = new Set();
435
+
436
+ /**
437
+ * Processa e registra rotas WebSocket encontradas nas rotas backend
438
+ */
439
+ export function processWebSocketRoutes() {
440
+ allWebSocketRoutes = [];
441
+
442
+ for (const route of allBackendRoutes) {
443
+ if (route.WS) {
444
+ const wsRoute = {
445
+ pattern: route.pattern,
446
+ handler: route.WS,
447
+ middleware: route.middleware
448
+ };
449
+
450
+ allWebSocketRoutes.push(wsRoute);
451
+ Console.info(`WebSocket route registered: ${route.pattern}`);
452
+ }
453
+ }
454
+ }
455
+
456
+ /**
457
+ * Encontra a rota WebSocket correspondente para uma URL
458
+ */
459
+ export function findMatchingWebSocketRoute(pathname: string) {
460
+ for (const route of allWebSocketRoutes) {
461
+ if (!route.pattern) continue;
462
+
463
+ const regexPattern = route.pattern
464
+ .replace(/\[\[\.\.\.(\w+)\]\]/g, '(?<$1>.+)?')
465
+ .replace(/\[\.\.\.(\w+)\]/g, '(?<$1>.+)')
466
+ .replace(/\[\[(\w+)\]\]/g, '(?<$1>[^/]+)?')
467
+ .replace(/\[(\w+)\]/g, '(?<$1>[^/]+)');
468
+
469
+ const regex = new RegExp(`^${regexPattern}/?$`);
470
+ const match = pathname.match(regex);
471
+
472
+ if (match) {
473
+ return {
474
+ route,
475
+ params: match.groups || {}
476
+ };
477
+ }
478
+ }
479
+ return null;
480
+ }
481
+
482
+ /**
483
+ * Trata uma nova conexão WebSocket
484
+ */
485
+ function handleWebSocketConnection(ws: WebSocket, req: IncomingMessage, hwebReq: HightJSRequest) {
486
+ if (!req.url) return;
487
+
488
+ const url = new URL(req.url, `http://${req.headers.host}`);
489
+ const pathname = url.pathname;
490
+
491
+ const matchedRoute = findMatchingWebSocketRoute(pathname);
492
+ if (!matchedRoute) {
493
+ ws.close(1000, 'Rota não encontrada');
494
+ return;
495
+ }
496
+
497
+ const params = extractWebSocketParams(pathname, matchedRoute.route.pattern);
498
+ const query = Object.fromEntries(url.searchParams.entries());
499
+
500
+ const context: WebSocketContext = {
501
+ hightReq: hwebReq,
502
+ ws,
503
+ req,
504
+ url,
505
+ params,
506
+ query,
507
+ send: (data: any) => {
508
+ if (ws.readyState === WebSocket.OPEN) {
509
+ const message = typeof data === 'string' ? data : JSON.stringify(data);
510
+ ws.send(message);
511
+ }
512
+ },
513
+ close: (code?: number, reason?: string) => {
514
+ ws.close(code || 1000, reason);
515
+ },
516
+ broadcast: (data: any, exclude?: WebSocket[]) => {
517
+ const message = typeof data === 'string' ? data : JSON.stringify(data);
518
+ const excludeSet = new Set(exclude || []);
519
+ wsConnections.forEach(connection => {
520
+ if (connection.readyState === WebSocket.OPEN && !excludeSet.has(connection)) {
521
+ connection.send(message);
522
+ }
523
+ });
524
+ }
525
+ };
526
+
527
+ try {
528
+ matchedRoute.route.handler(context);
529
+ } catch (error) {
530
+ console.error('Erro no handler WebSocket:', error);
531
+ ws.close(1011, 'Erro interno do servidor');
532
+ }
533
+ }
534
+
535
+ /**
536
+ * Extrai parâmetros da URL para WebSocket
537
+ */
538
+ function extractWebSocketParams(pathname: string, pattern: string): Record<string, string> {
539
+ const params: Record<string, string> = {};
540
+
541
+ const regexPattern = pattern
542
+ .replace(/\[\[\.\.\.(\w+)\]\]/g, '(?<$1>.+)?')
543
+ .replace(/\[\.\.\.(\w+)\]/g, '(?<$1>.+)')
544
+ .replace(/\[\[(\w+)\]\]/g, '(?<$1>[^/]+)?')
545
+ .replace(/\[(\w+)\]/g, '(?<$1>[^/]+)');
546
+
547
+ const regex = new RegExp(`^${regexPattern}/?$`);
548
+ const match = pathname.match(regex);
549
+
550
+ if (match && match.groups) {
551
+ Object.assign(params, match.groups);
552
+ }
553
+
554
+ return params;
555
+ }
556
+
557
+ /**
558
+ * Configura WebSocket upgrade no servidor HTTP existente
559
+ * @param server Servidor HTTP (Express, Fastify ou Native)
560
+ * @param hotReloadManager Instância do gerenciador de hot-reload para coordenação
561
+ */
562
+ export function setupWebSocketUpgrade(server: any, hotReloadManager?: any) {
563
+ // NÃO remove listeners existentes para preservar hot-reload
564
+ // Em vez disso, coordena com o sistema existente
565
+
566
+ // Verifica se já existe um listener de upgrade
567
+ const existingListeners = server.listeners('upgrade');
568
+
569
+ // Se não há listeners, ou se o hot-reload ainda não foi configurado, adiciona o nosso
570
+ if (existingListeners.length === 0) {
571
+ server.on('upgrade', (request: any, socket: any, head: Buffer) => {
572
+ handleWebSocketUpgrade(request, socket, head, hotReloadManager);
573
+ });
574
+ } else {
575
+ // Se já existe um listener (provavelmente do hot-reload),
576
+ // vamos interceptar e coordenar
577
+ console.log('🔧 Coordenando WebSocket upgrade com sistema existente');
578
+ }
579
+ }
580
+
581
+ function handleWebSocketUpgrade(request: any, socket: any, head: Buffer, hotReloadManager?: any) {
582
+ const adapter = FrameworkAdapterFactory.getCurrentAdapter()
583
+ if (!adapter) {
584
+ console.error('❌ Framework adapter não detectado. Não é possível processar upgrade WebSocket.');
585
+ socket.destroy();
586
+ return;
587
+ }
588
+ const genericReq = adapter.parseRequest(request);
589
+ const hwebReq = new HightJSRequest(genericReq);
590
+ const { pathname } = new URL(request.url, `http://${request.headers.host}`);
591
+
592
+ // Prioridade 1: Hot reload (sistema interno)
593
+ if (pathname === '/hweb-hotreload/') {
594
+ if (hotReloadManager) {
595
+ hotReloadManager.handleUpgrade(request, socket, head);
596
+ } else {
597
+ socket.destroy();
598
+ }
599
+ return;
600
+ }
601
+
602
+ // Prioridade 2: Rotas WebSocket do usuário
603
+ const matchedRoute = findMatchingWebSocketRoute(pathname);
604
+ if (matchedRoute) {
605
+ // Faz upgrade para WebSocket usando noServer
606
+ const wss = new WSServer({
607
+ noServer: true,
608
+ perMessageDeflate: false, // Melhor performance
609
+ maxPayload: 1024 * 1024 // Limite de 1MB
610
+ });
611
+
612
+ wss.handleUpgrade(request, socket, head, (ws) => {
613
+ wsConnections.add(ws);
614
+ console.log(`✅ WebSocket conectado em ${pathname}`);
615
+
616
+ ws.on('close', () => {
617
+ wsConnections.delete(ws);
618
+ console.log(`❌ WebSocket desconectado de ${pathname}`);
619
+ });
620
+
621
+ ws.on('error', (error) => {
622
+ console.error(`💥 Erro WebSocket em ${pathname}:`, error);
623
+ wsConnections.delete(ws);
624
+ });
625
+
626
+ // Processa a conexão
627
+ handleWebSocketConnection(ws, request, hwebReq);
628
+ });
629
+ return;
630
+ }
631
+
632
+ // Nenhuma rota encontrada - rejeita conexão
633
+ console.log(`🚫 Nenhuma rota WebSocket encontrada para: ${pathname}`);
634
+ socket.destroy();
635
+ }
package/src/types.ts CHANGED
@@ -1,6 +1,21 @@
1
1
  import type { ComponentType } from 'react';
2
2
  import type { GenericRequest } from './types/framework';
3
3
  import {HightJSRequest, HightJSResponse} from "./api/http";
4
+ import { WebSocket } from 'ws';
5
+ import { IncomingMessage } from 'http';
6
+
7
+ // Interface do contexto WebSocket simplificada
8
+ export interface WebSocketContext {
9
+ ws: WebSocket;
10
+ req: IncomingMessage;
11
+ hightReq: HightJSRequest;
12
+ url: URL;
13
+ params: Record<string, string>;
14
+ query: Record<string, string>;
15
+ send: (data: any) => void;
16
+ close: (code?: number, reason?: string) => void;
17
+ broadcast: (data: any, exclude?: WebSocket[]) => void;
18
+ }
4
19
 
5
20
  // --- Tipos do Frontend (sem alteração) ---
6
21
  export interface HightJSOptions {
@@ -42,7 +57,14 @@ export type HightMiddleware = (
42
57
 
43
58
 
44
59
  /**
45
- * Define a estrutura de cada rota da API, com suporte para métodos HTTP.
60
+ * Define o formato de uma função que manipula uma rota WebSocket.
61
+ */
62
+ export type WebSocketHandler = (
63
+ context: WebSocketContext
64
+ ) => Promise<void> | void;
65
+
66
+ /**
67
+ * Define a estrutura de cada rota da API, com suporte para métodos HTTP e WebSocket.
46
68
  */
47
69
  export interface BackendRouteConfig {
48
70
  pattern: string;
@@ -50,5 +72,6 @@ export interface BackendRouteConfig {
50
72
  POST?: BackendHandler;
51
73
  PUT?: BackendHandler;
52
74
  DELETE?: BackendHandler;
75
+ WS?: WebSocketHandler; // Suporte para WebSocket
53
76
  middleware?: HightMiddleware[]; // Permite adicionar middlewares específicos à rota
54
77
  }
File without changes
@@ -1 +0,0 @@
1
- "use strict";
File without changes
@@ -1 +0,0 @@
1
- "use strict";
File without changes
@@ -1 +0,0 @@
1
- "use strict";
File without changes
@@ -1 +0,0 @@
1
- "use strict";
File without changes
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,40 +0,0 @@
1
- /**
2
- * Exemplo de como usar os novos providers baseados em classes
3
- */
4
- export declare const authRoutes: {
5
- pattern: string;
6
- GET(req: import("..").HightJSRequest, params: {
7
- [key: string]: string;
8
- }): Promise<any>;
9
- POST(req: import("..").HightJSRequest, params: {
10
- [key: string]: string;
11
- }): Promise<any>;
12
- auth: import("./core").HWebAuth;
13
- };
14
- /**
15
- * Como usar em suas rotas API:
16
- *
17
- * // arquivo: /api/auth/[...value].ts
18
- * import { authRoutes } from '../../../src/auth/example';
19
- *
20
- * export const GET = authRoutes.GET;
21
- * export const POST = authRoutes.POST;
22
- */
23
- /**
24
- * Rotas disponíveis automaticamente:
25
- *
26
- * Core routes:
27
- * - GET /api/auth/session - Obter sessão atual
28
- * - GET /api/auth/providers - Listar providers
29
- * - GET /api/auth/csrf - Obter token CSRF
30
- * - POST /api/auth/signin - Login
31
- * - POST /api/auth/signout - Logout
32
- *
33
- * Provider específico (CredentialsProvider):
34
- * - GET /api/auth/credentials/config - Config do provider
35
- *
36
- * Provider específico (DiscordProvider):
37
- * - GET /api/auth/signin/discord - Iniciar OAuth Discord
38
- * - GET /api/auth/callback/discord - Callback OAuth Discord
39
- * - GET /api/auth/discord/config - Config do provider Discord
40
- */
@@ -1,104 +0,0 @@
1
- "use strict";
2
- /**
3
- * Exemplo de como usar os novos providers baseados em classes
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.authRoutes = void 0;
7
- const routes_1 = require("./routes");
8
- const providers_1 = require("./providers");
9
- // Exemplo de configuração com os novos providers
10
- const authConfig = {
11
- providers: [
12
- // Provider de credenciais customizado
13
- new providers_1.CredentialsProvider({
14
- name: "Login com Email",
15
- credentials: {
16
- email: {
17
- label: "Email",
18
- type: "email",
19
- placeholder: "seu@email.com"
20
- },
21
- password: {
22
- label: "Senha",
23
- type: "password"
24
- }
25
- },
26
- async authorize(credentials) {
27
- // Aqui você faz a validação com seu banco de dados
28
- const { email, password } = credentials;
29
- // Exemplo de validação (substitua pela sua lógica)
30
- if (email === "admin@example.com" && password === "123456") {
31
- return {
32
- id: "1",
33
- name: "Admin User",
34
- email: email,
35
- role: "admin"
36
- };
37
- }
38
- // Retorna null se credenciais inválidas
39
- return null;
40
- }
41
- }),
42
- // Provider do Discord
43
- new providers_1.DiscordProvider({
44
- clientId: process.env.DISCORD_CLIENT_ID,
45
- clientSecret: process.env.DISCORD_CLIENT_SECRET,
46
- callbackUrl: "http://localhost:3000/api/auth/callback/discord"
47
- })
48
- ],
49
- secret: process.env.HWEB_AUTH_SECRET || "seu-super-secret-aqui-32-chars-min",
50
- session: {
51
- strategy: 'jwt',
52
- maxAge: 86400 // 24 horas
53
- },
54
- pages: {
55
- signIn: '/auth/signin',
56
- signOut: '/auth/signout'
57
- },
58
- callbacks: {
59
- async signIn(user, account, profile) {
60
- // Lógica customizada antes do login
61
- console.log(`Usuário ${user.email} fazendo login via ${account.provider}`);
62
- return true; // permitir login
63
- },
64
- async session(session, user) {
65
- // Adicionar dados customizados à sessão
66
- return {
67
- ...session,
68
- user: {
69
- ...session.user,
70
- customData: "dados extras"
71
- }
72
- };
73
- }
74
- }
75
- };
76
- // Criar as rotas de autenticação
77
- exports.authRoutes = (0, routes_1.createAuthRoutes)(authConfig);
78
- /**
79
- * Como usar em suas rotas API:
80
- *
81
- * // arquivo: /api/auth/[...value].ts
82
- * import { authRoutes } from '../../../src/auth/example';
83
- *
84
- * export const GET = authRoutes.GET;
85
- * export const POST = authRoutes.POST;
86
- */
87
- /**
88
- * Rotas disponíveis automaticamente:
89
- *
90
- * Core routes:
91
- * - GET /api/auth/session - Obter sessão atual
92
- * - GET /api/auth/providers - Listar providers
93
- * - GET /api/auth/csrf - Obter token CSRF
94
- * - POST /api/auth/signin - Login
95
- * - POST /api/auth/signout - Logout
96
- *
97
- * Provider específico (CredentialsProvider):
98
- * - GET /api/auth/credentials/config - Config do provider
99
- *
100
- * Provider específico (DiscordProvider):
101
- * - GET /api/auth/signin/discord - Iniciar OAuth Discord
102
- * - GET /api/auth/callback/discord - Callback OAuth Discord
103
- * - GET /api/auth/discord/config - Config do provider Discord
104
- */