@ismael1361/router 1.0.1 → 1.0.6

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/README.md CHANGED
@@ -1,988 +1,743 @@
1
1
  # @ismael1361/router
2
2
 
3
- Esse módulo foi criado para preparar e centralizar rotas em um Express.js com tipagem encadeada, útil para tipar conteúdo de escobo e propriedades de requisição como `body`, `params` e `query`. Também oferece a geração de documentação OpenAPI/Swagger integrada.
4
-
5
- ## Instalação
3
+ [![npm version](https://img.shields.io/npm/v/@ismael1361/router.svg)](https://www.npmjs.com/package/@ismael1361/router)
4
+ [![License](https://img.shields.io/npm/l/@ismael1361/router.svg)](https://github.com/ismael1361/router/blob/main/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
6
+
7
+ Um módulo moderno e robusto para criar e gerenciar rotas em Express.js com tipagem encadeada forte, útil para tipar conteúdo de escopo e propriedades de requisição como `body`, `params` e `query`. Oferece geração automática de documentação OpenAPI/Swagger integrada.
8
+
9
+ ## 📋 Índice
10
+
11
+ - [Características](#-características)
12
+ - [Instalação](#-instalação)
13
+ - [Início Rápido](#-início-rápido)
14
+ - [API Completa](#-api-completa)
15
+ - [create](#create)
16
+ - [middleware](#middleware)
17
+ - [route](#route)
18
+ - [Classe Router](#classe-router)
19
+ - [Exemplos Avançados](#-exemplos-avançados)
20
+ - [Documentação OpenAPI/Swagger](#-documentação-openapiswagger)
21
+ - [TypeScript](#-typescript)
22
+ - [Contribuindo](#-contribuindo)
23
+ - [Licença](#-licença)
24
+
25
+ ## ✨ Características
26
+
27
+ - 🔒 **Tipagem Forte**: Suporte completo a TypeScript com tipos encadeados
28
+ - 📚 **Documentação Automática**: Geração de documentação OpenAPI/Swagger integrada
29
+ - 🔗 **API Fluente**: Interface encadeável e intuitiva para definição de rotas
30
+ - 🛡️ **Middlewares Documentados**: Middlewares com documentação automática
31
+ - 🎯 **Organização Modular**: Suporte a sub-roteadores e rotas agrupadas
32
+ - ⚡ **Performance**: Construído sobre Express.js, mantendo sua eficiência
33
+ - 🧩 **Extensível**: Fácil de estender com tipos personalizados
34
+
35
+ ## 📦 Instalação
6
36
 
7
37
  ```bash
8
38
  npm install @ismael1361/router
9
- # ou
10
- yarn add @ismael1361/router
11
39
  ```
12
40
 
13
- ---
14
-
15
- ## Indice
16
-
17
- - [@ismael1361/router](#ismael1361router)
18
- - [Instalação](#instalação)
19
- - [Indice](#indice)
20
- - [`create`](#create)
21
- - [Parâmetros](#parâmetros)
22
- - [Retorno](#retorno)
23
- - [Exemplo de Uso](#exemplo-de-uso)
24
- - [`middleware`](#middleware)
25
- - [Parâmetros](#parâmetros-1)
26
- - [Retorno](#retorno-1)
27
- - [Exemplo de Uso](#exemplo-de-uso-1)
28
- - [`route`](#route)
29
- - [Parâmetros](#parâmetros-2)
30
- - [Retorno](#retorno-2)
31
- - [Exemplo de Uso](#exemplo-de-uso-2)
32
- - [`Router`](#router)
33
- - [Propriedades da Instância](#propriedades-da-instância)
34
- - [`router`](#router-1)
35
- - [`routes`](#routes)
36
- - [Métodos da Instância](#métodos-da-instância)
37
- - [`get`](#get)
38
- - [`post`](#post)
39
- - [`put`](#put)
40
- - [`delete`](#delete)
41
- - [`patch`](#patch)
42
- - [`options`](#options)
43
- - [`head`](#head)
44
- - [`all`](#all)
45
- - [`use`](#use)
46
- - [`route`](#route-1)
47
- - [`middleware`](#middleware-1)
48
- - [`handler`](#handler)
49
- - [`by`](#by)
50
- - [`getSwagger`](#getswagger)
51
-
52
- ---
53
-
54
- ## `create`
41
+ ou
55
42
 
56
- ```typescript
57
- create<Req extends Request, Res extends Response>(app?: express.Express | express.Router): Router<Req, Res>;
43
+ ```bash
44
+ yarn add @ismael1361/router
58
45
  ```
59
46
 
60
- A função `create` é o ponto de partida para a criação de rotas. Ela inicializa uma instância de um roteador aprimorado que pode ser anexado a uma aplicação Express existente ou usado de forma independente.
61
-
62
- Este roteador oferece uma API fluente e fortemente tipada para definir rotas, ao mesmo tempo que integra a geração de documentação OpenAPI (Swagger).
63
-
64
- ### Parâmetros
65
-
66
- - `app` (opcional): Uma instância de uma aplicação `Express` ou `Router` do Express. Se fornecido, o novo roteador será montado diretamente nesta instância.
67
-
68
- ### Retorno
69
-
70
- Retorna uma nova instância do `Router`, que possui métodos encadeáveis (`.get()`, `.post()`, etc.) para a definição de rotas com metadados para a documentação.
71
-
72
- ### Exemplo de Uso
47
+ ## 🚀 Início Rápido
73
48
 
74
49
  ```typescript
75
- import express from 'express';
76
- import { create, Request, Response } from '@ismael1361/router';
50
+ import { create, Middlewares } from '@ismael1361/router';
77
51
 
78
- // 1. (Opcional) Estenda os tipos de Request e Response se precisar de propriedades customizadas
79
- interface CustomRequest extends Request {
80
- user?: { id: string; name: string };
81
- }
52
+ const app = create();
82
53
 
83
- interface CustomResponse extends Response {
84
- // ... propriedades customizadas para a resposta
85
- }
86
-
87
- const app = express();
54
+ app.middleware(Middlewares.json());
88
55
 
89
- // 2. Crie a instância do roteador, passando a aplicação Express
90
- const router = create<CustomRequest, CustomResponse>(app).middleware(express.json());
56
+ // Crie o roteador com middleware JSON
57
+ const router = app.route();
91
58
 
92
- // 3. Defina as rotas usando a API fluente
59
+ // Defina rotas com documentação
93
60
  router
94
61
  .get('/users/:id')
95
62
  .handle((req, res) => {
96
- // req.params.id é totalmente tipado aqui
97
- res.json({ id: req.params.id, name: 'John Doe' });
98
- }).doc({
99
- summary: 'Obter um usuário pelo ID',
100
- description: 'Retorna os detalhes de um usuário específico.',
63
+ res.json({
64
+ id: req.params.id,
65
+ name: 'John Doe'
66
+ });
67
+ })
68
+ .doc({
69
+ summary: 'Obter usuário por ID',
70
+ description: 'Retorna os detalhes de um usuário específico',
101
71
  tags: ['Users'],
102
72
  params: {
103
73
  id: {
104
74
  description: 'ID do usuário',
105
75
  type: 'string',
106
- required: true,
107
- },
76
+ required: true
77
+ }
108
78
  },
109
79
  responses: {
110
80
  200: { description: 'Usuário encontrado' },
111
- 404: { description: 'Usuário não encontrado' },
112
- },
81
+ 404: { description: 'Usuário não encontrado' }
82
+ }
113
83
  });
114
84
 
115
- // O roteador já está montado na 'app' e as rotas estão ativas.
116
85
  app.listen(3000, () => {
117
- console.log('Servidor rodando na porta 3000');
86
+ console.log('🚀 Servidor rodando na porta 3000');
118
87
  });
119
88
  ```
120
89
 
121
- ---
90
+ ## 📖 API Completa
122
91
 
123
- ## `middleware`
92
+ ### create
124
93
 
125
- ```ts
126
- middleware<Req extends Request, Res extends Response>(
127
- callback: MiddlewareFC<Req, Res>,
128
- doc?: MiddlewareFCDoc
129
- ): MiddlewareFC<Req, Res>;
94
+ Cria uma nova instância do roteador aprimorado.
95
+
96
+ ```typescript
97
+ create<Req extends Request, Res extends Response>(): Router<Req, Res>
130
98
  ```
131
99
 
132
- A função `middleware` é um wrapper que permite criar middlewares reutilizáveis para o Express, enriquecendo-os com metadados para a documentação OpenAPI (Swagger).
100
+ **Retorno:** Nova instância do Router com métodos encadeáveis
101
+
102
+ **Exemplo:**
103
+
104
+ ```typescript
105
+ import { create, Request, Response } from '@ismael1361/router';
133
106
 
134
- Ao envolver sua lógica de middleware com esta função, você pode definir como ele deve ser documentado (ex: quais cabeçalhos ele espera, quais respostas de erro ele pode retornar). Quando este middleware é aplicado a uma rota, sua documentação é automaticamente mesclada com a documentação da rota.
107
+ interface CustomRequest extends Request {
108
+ user?: { id: string; name: string };
109
+ }
135
110
 
136
- ### Parâmetros
111
+ const router = create<CustomRequest>()
112
+ .middleware(express.json());
113
+ ```
137
114
 
138
- - `callback`: A função de middleware padrão do Express, com a assinatura `(req, res, next)`. É aqui que a lógica do seu middleware (autenticação, logging, etc.) reside.
139
- - `doc` (opcional): Um objeto que descreve o middleware para a documentação OpenAPI. É útil para documentar requisitos globais como autenticação.
115
+ ### middleware
140
116
 
141
- ### Retorno
117
+ Cria middlewares reutilizáveis com documentação integrada.
118
+
119
+ ```typescript
120
+ middleware<Req extends Request, Res extends Response>(
121
+ callback: MiddlewareFC<Req, Res>,
122
+ doc?: MiddlewareFCDoc
123
+ ): MiddlewareFC<Req, Res>
124
+ ```
142
125
 
143
- Retorna a própria função de `callback` do middleware, mas com os metadados da documentação anexados a ela. Isso permite que o roteador a utilize tanto como um middleware funcional quanto como uma fonte de documentação.
126
+ **Parâmetros:**
127
+ - `callback`: Função de middleware padrão do Express `(req, res, next)`
128
+ - `doc` (opcional): Objeto com metadados para documentação OpenAPI
144
129
 
145
- ### Exemplo de Uso
130
+ **Retorno:** Função de middleware com metadados de documentação anexados
146
131
 
147
- Vamos criar e usar um middleware de autenticação que verifica um token no cabeçalho `Authorization`.
132
+ **Exemplo:**
148
133
 
149
134
  ```typescript
150
- import express from 'express';
151
- import { create, middleware, Request, Response } from '@ismael1361/router';
135
+ import { middleware, Request } from '@ismael1361/router';
152
136
 
153
- interface AuthRequest extends Request {
137
+ interface AuthRequest extends Request<
138
+ "api_key" | "token",
139
+ {
140
+ api_key?: string;
141
+ token?: string
142
+ }
143
+ > {
154
144
  user: { id: string; roles: string[] };
155
145
  }
156
146
 
157
- // 1. Crie o middleware de autenticação com sua documentação
158
147
  const isAuthenticated = middleware<AuthRequest>(
159
148
  (req, res, next) => {
160
149
  const token = req.headers.authorization;
150
+
161
151
  if (token === 'Bearer meu-token-secreto') {
162
152
  req.user = { id: '123', roles: ['admin', 'user'] };
163
- return next(); // Token válido, continue
153
+ return next();
164
154
  }
155
+
165
156
  res.status(401).json({ message: 'Não autorizado' });
166
157
  },
167
158
  {
168
- // 2. Documente os requisitos e possíveis respostas do middleware
169
- security: [{ bearerAuth: [] }], // Indica que a rota requer autenticação Bearer
159
+ security: [{ bearerAuth: [] }],
170
160
  responses: {
171
- 401: { description: 'Token de autenticação inválido ou não fornecido' },
172
- },
161
+ 401: {
162
+ description: 'Token de autenticação inválido ou não fornecido'
163
+ }
164
+ }
173
165
  }
174
166
  );
175
167
 
176
- const app = express();
177
- const router = create(app);
178
-
179
- // 3. Aplique o middleware a uma rota específica
168
+ // Usar o middleware
180
169
  router
181
170
  .get('/profile')
182
- .middleware(isAuthenticated) // O middleware é aplicado aqui
171
+ .middleware(isAuthenticated)
183
172
  .handle((req, res) => {
184
173
  res.json({ user: req.user });
185
- }).doc({
186
- summary: 'Obter perfil do usuário',
187
- description: 'Acessa informações do usuário autenticado. Requer um token válido.',
188
- tags: ['Users'],
189
- responses: {
190
- 200: { description: 'Perfil do usuário' },
191
- },
192
174
  });
193
-
194
- // A documentação OpenAPI gerada para a rota GET /profile agora incluirá
195
- // automaticamente as seções 'security' e a resposta '401' definidas no middleware.
196
-
197
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
198
175
  ```
199
176
 
200
- ---
177
+ ### route
201
178
 
202
- ## `route`
179
+ Cria uma instância de rota para agrupar múltiplos métodos HTTP sob o mesmo caminho.
203
180
 
204
- ```ts
205
- route<Req extends Request, Res extends Response>(path: string): Router<Req, Res>;
181
+ ```typescript
182
+ route<Req extends Request, Res extends Response>(
183
+ path?: string
184
+ ): Router<Req, Res>
206
185
  ```
207
186
 
208
- A função `route` cria uma instância de rota encadeável para um caminho (path) específico. Isso permite agrupar múltiplos métodos HTTP (como GET, POST, PUT, etc.) para o mesmo endpoint de URL, o que é uma prática comum para organizar APIs RESTful.
187
+ **Parâmetros:**
188
+ - `path`: Caminho da URL para a rota
209
189
 
210
- Ao invés de definir `router.get('/tasks', ...)` e `router.post('/tasks', ...)` separadamente, você pode agrupar ambos sob `router.route('/tasks')`.
190
+ **Retorno:** Nova instância do Router "travada" no path especificado
211
191
 
212
- ### Parâmetros
213
-
214
- - `path`: A string do caminho da URL para a qual a rota será criada.
215
-
216
- ### Retorno
217
-
218
- Retorna uma nova instância do `Router` que está "travada" no `path` especificado. Você pode então encadear os métodos HTTP (`.get()`, `.post()`, etc.) diretamente a esta instância.
219
-
220
- ### Exemplo de Uso
221
-
222
- Vamos criar um endpoint `/tasks` que lida com a listagem (GET) e a criação (POST) de tarefas.
192
+ **Exemplo:**
223
193
 
224
194
  ```typescript
225
- import express from 'express';
226
- import { route, Request, Response } from '@ismael1361/router';
227
-
228
- const app = express();
229
- const main = create(app).middleware(express.json());
195
+ import { route } from '@ismael1361/router';
230
196
 
231
- // 1. Crie uma rota para o caminho '/tasks'
232
- const router = route('/tasks');
197
+ const tasksRouter = route('/tasks');
233
198
 
234
- // 2. Defina o handler para o método GET nesta rota
235
- router
236
- .get("/items")
199
+ // GET /tasks/items
200
+ tasksRouter
201
+ .get('/items')
237
202
  .handle((req, res) => {
238
- res.json([{ id: 1, title: 'Aprender a usar o @ismael1361/router' }]);
239
- }).doc({
203
+ res.json([{ id: 1, title: 'Aprender @ismael1361/router' }]);
204
+ })
205
+ .doc({
240
206
  summary: 'Listar todas as tarefas',
241
207
  tags: ['Tasks'],
242
- responses: { 200: { description: 'Lista de tarefas' } },
208
+ responses: { 200: { description: 'Lista de tarefas' } }
243
209
  });
244
210
 
245
- // 3. Defina o handler para o método POST na mesma rota
246
- router
247
- .post("item")
211
+ // POST /tasks/item
212
+ tasksRouter
213
+ .post('/item')
248
214
  .handle((req, res) => {
249
215
  const newTask = req.body;
250
216
  res.status(201).json({ id: 2, ...newTask });
251
- }).doc({
252
- summary: 'Criar uma nova tarefa',
217
+ })
218
+ .doc({
219
+ summary: 'Criar nova tarefa',
253
220
  tags: ['Tasks'],
254
221
  body: { description: 'Dados da nova tarefa' },
255
- responses: { 201: { description: 'Tarefa criada com sucesso' } },
222
+ responses: { 201: { description: 'Tarefa criada' } }
256
223
  });
257
224
 
258
- // 4. Adicione a rota ao roteador principal
259
- main.by(router);
260
- // ou diretamente ao app
261
- // app.use(router.router);
262
-
263
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
225
+ // Adicionar ao roteador principal
226
+ mainRouter.by(tasksRouter);
264
227
  ```
265
228
 
266
- ---
267
-
268
- ## `Router`
229
+ ### Classe Router
269
230
 
270
- ```ts
271
- Router<Rq extends Request, Rs extends Response>;
272
- ```
231
+ A classe principal que encapsula o roteador do Express com API fluente e tipada.
273
232
 
274
- A classe `Router` é o principal objeto com o qual você irá interagir. Ela encapsula o roteador do Express, fornecendo uma API encadeável e fortemente tipada para definir rotas, aplicar middlewares e gerar documentação OpenAPI.
275
-
276
- Uma instância do `Router` é retornada pela função `create` ou pelo método `.route()`.
277
-
278
- ---
233
+ #### Propriedades
279
234
 
280
- ### Propriedades da Instância
281
-
282
- #### `router`
283
-
284
- ```ts
285
- .router: express.Router;
286
- ```
287
-
288
- A instância do roteador do Express. Usada internamente para definir rotas e middlewares.
289
-
290
- ---
291
-
292
- #### `routes`
293
-
294
- ```ts
295
- .routes: Array<{
296
- path: string;
297
- methods: string[];
298
- type: "ROUTE" | "MIDDLEWARE";
299
- swagger?: Pick<swaggerJSDoc.OAS3Definition, "paths" | "components">;
300
- }>;
235
+ ##### `.app`
236
+ ```typescript
237
+ router: express.Express
301
238
  ```
239
+ Instância do Express subjacente.
302
240
 
303
- Um array que armazena as rotas e middlewares definidos na instância. Essas rotas e middlewares serão usadas para gerar a documentação OpenAPI.
304
-
305
- ---
306
-
307
- ### Métodos da Instância
308
-
309
- #### `get`
310
-
311
- ```ts
312
- .get(path: string): RequestHandler<Rq, Rs>;
241
+ ##### `.routes`
242
+ ```typescript
243
+ routes: Array<{
244
+ path: string;
245
+ methods: string[];
246
+ type: "ROUTE" | "MIDDLEWARE";
247
+ swagger?: Pick<swaggerJSDoc.OAS3Definition, "paths" | "components">;
248
+ }>
313
249
  ```
250
+ Array de rotas e middlewares registrados para geração de documentação.
314
251
 
315
- Registra uma rota que responde a requisições HTTP do método GET. Este método é o ponto de partida para definir um endpoint que recupera dados.
252
+ #### Métodos HTTP
316
253
 
317
- Após chamar `.get()`, você deve encadear o método `.handle()` para fornecer a lógica do controlador e, opcionalmente, o método `.doc()` para adicionar a documentação OpenAPI.
254
+ ##### `.get(path: string, doc?: MiddlewareFCDoc)`
255
+ Registra uma rota GET.
318
256
 
319
- * **Parâmetros**
320
- - `path` (string): A string do caminho da URL para a rota. O caminho é relativo ao prefixo do roteador. Pode conter parâmetros de rota, como `/users/:id`.
321
-
322
- * **Retorno**
323
- Retorna uma instância de `RequestHandler`, que é um objeto intermediário com os seguintes métodos encadeáveis:
324
- - `.middleware()`: Para aplicar middlewares específicos a esta rota.
325
- - `.handle()`: Para definir a função controladora que processará a requisição.
326
- - `.doc()`: Para fornecer metadados de documentação OpenAPI para a rota.
327
-
328
- * **Exemplo de Uso**
329
257
  ```typescript
330
- import express from 'express';
331
- import { create, Request, Response } from '@ismael1361/router';
332
-
333
- const app = express();
334
- const router = create(app);
335
-
336
- // Exemplo 1: Rota GET simples
337
258
  router
338
259
  .get('/status')
339
260
  .handle((req, res) => {
340
261
  res.json({ status: 'ok' });
341
262
  })
342
263
  .doc({
343
- summary: 'Verificar o status da API',
264
+ summary: 'Verificar status da API',
344
265
  tags: ['Health'],
345
- responses: {
346
- 200: { description: 'A API está funcionando corretamente' },
347
- },
348
- });
349
-
350
- // Exemplo 2: Rota GET com parâmetros
351
- router
352
- .get('/users/:id')
353
- .handle((req, res) => {
354
- // 'req.params.id' é totalmente tipado como string
355
- const userId = req.params.id;
356
- // Lógica para buscar o usuário...
357
- res.json({ id: userId, name: 'Usuário Exemplo' });
358
- })
359
- .doc({
360
- summary: 'Obter um usuário pelo ID',
361
- tags: ['Users'],
362
- params: { id: { description: 'ID do usuário', type: 'string', required: true } },
363
- responses: { 200: { description: 'Dados do usuário' }, 404: { description: 'Usuário não encontrado' } },
266
+ responses: { 200: { description: 'API funcionando' } }
364
267
  });
365
-
366
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
367
268
  ```
368
269
 
369
- ---
370
-
371
- #### `post`
372
-
373
- ```ts
374
- .post(path: string): RequestHandler<Rq, Rs>;
375
- ```
376
-
377
- Registra uma rota que responde a requisições HTTP do método POST. Este método é comumente utilizado para **criar novos recursos** no servidor.
378
-
379
- Após chamar `.post()`, você deve encadear o método `.handle()` para fornecer a lógica do controlador (que geralmente acessa `req.body`) e, opcionalmente, o método `.doc()` para documentar o corpo da requisição e as possíveis respostas.
270
+ ##### `.post(path: string, doc?: MiddlewareFCDoc)`
271
+ Registra uma rota POST.
380
272
 
381
- * **Parâmetros**
382
- - `path` (string): A string do caminho da URL para a rota.
383
-
384
- * **Retorno**
385
- Retorna uma instância de `RequestHandler` para encadeamento dos métodos `.middleware()`, `.handle()` e `.doc()`.
386
-
387
- * **Exemplo de Uso**
388
273
  ```typescript
389
- import express from 'express';
390
- import { create, Request, Response } from '@ismael1361/router';
391
-
392
- const app = express();
393
- // É essencial usar um middleware para parsear o corpo da requisição JSON
394
- const router = create(app).middleware(express.json());
395
-
396
274
  router
397
275
  .post('/users')
398
276
  .handle((req, res) => {
399
- // req.body contém os dados enviados pelo cliente
400
277
  const newUser = req.body;
401
- // Lógica para salvar o novo usuário no banco de dados...
402
- const createdUser = { id: Date.now().toString(), ...newUser };
403
- res.status(201).json(createdUser);
278
+ res.status(201).json({ id: Date.now(), ...newUser });
404
279
  })
405
280
  .doc({
406
- summary: 'Criar um novo usuário',
281
+ summary: 'Criar novo usuário',
407
282
  tags: ['Users'],
408
283
  body: {
409
- description: 'Dados do novo usuário a ser criado.',
410
- required: true,
411
- // Você pode fornecer um schema para o corpo da requisição
284
+ description: 'Dados do usuário',
412
285
  schema: {
413
286
  type: 'object',
414
287
  properties: {
415
- name: { type: 'string', example: 'Jane Doe' },
416
- email: { type: 'string', example: 'jane.doe@example.com' },
417
- },
418
- required: ['name', 'email'],
419
- },
420
- },
421
- responses: {
422
- 201: { description: 'Usuário criado com sucesso' },
423
- 400: { description: 'Dados inválidos fornecidos' },
288
+ name: { type: 'string' },
289
+ email: { type: 'string' }
290
+ }
291
+ }
424
292
  },
293
+ responses: { 201: { description: 'Usuário criado' } }
425
294
  });
426
-
427
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
428
295
  ```
429
296
 
430
- ---
297
+ ##### `.put(path: string, doc?: MiddlewareFCDoc)`
298
+ Registra uma rota PUT para substituição completa de recursos.
431
299
 
432
- #### `put`
300
+ ##### `.patch(path: string, doc?: MiddlewareFCDoc)`
301
+ Registra uma rota PATCH para atualizações parciais.
433
302
 
434
- ```ts
435
- .put(path: string): RequestHandler<Rq, Rs>;
436
- ```
303
+ ##### `.delete(path: string, doc?: MiddlewareFCDoc)`
304
+ Registra uma rota DELETE para remoção de recursos.
437
305
 
438
- Registra uma rota que responde a requisições HTTP do método PUT. Este método é usado para **substituir completamente um recurso existente** com os novos dados fornecidos no corpo da requisição.
306
+ ##### `.options(path: string, doc?: MiddlewareFCDoc)`
307
+ Registra uma rota OPTIONS para requisições de pré-voo CORS.
439
308
 
440
- * **Parâmetros**
441
- - `path` (string): O caminho da URL, geralmente contendo um parâmetro para identificar o recurso a ser atualizado (ex: `/users/:id`).
309
+ ##### `.head(path: string, doc?: MiddlewareFCDoc)`
310
+ Registra uma rota HEAD para obter metadados sem corpo de resposta.
442
311
 
443
- * **Retorno**
444
- Retorna uma instância de `RequestHandler` para encadeamento.
312
+ ##### `.all(path: string, doc?: MiddlewareFCDoc)`
313
+ Registra uma rota que responde a todos os métodos HTTP.
445
314
 
446
- * **Exemplo de Uso**
447
- ```typescript
448
- import express from 'express';
449
- import { create, Request, Response } from '@ismael1361/router';
315
+ #### Métodos de Configuração
450
316
 
451
- const app = express();
452
- const router = create(app).middleware(express.json());
317
+ ##### `.use(path?: string, doc?: MiddlewareFCDoc)`
318
+ Monta middlewares em um caminho específico.
453
319
 
454
- router
455
- .put('/users/:id')
456
- .handle((req, res) => {
457
- const { id } = req.params;
458
- const updatedData = req.body;
459
- // Lógica para substituir o usuário com o ID fornecido...
460
- res.json({ id, ...updatedData });
461
- })
462
- .doc({
463
- summary: 'Atualizar um usuário (substituição completa)',
464
- tags: ['Users'],
465
- params: { id: { description: 'ID do usuário a ser atualizado', type: 'string', required: true } },
466
- body: { description: 'Dados completos do usuário para substituição.' },
467
- responses: {
468
- 200: { description: 'Usuário atualizado com sucesso' },
469
- 404: { description: 'Usuário não encontrado' },
470
- },
471
- });
472
-
473
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
474
- ```
475
-
476
- ---
477
-
478
- #### `delete`
479
-
480
- ```ts
481
- .delete(path: string): RequestHandler<Rq, Rs>;
320
+ ```typescript
321
+ router.use('/api').handle((req, res, next) => {
322
+ console.log(`[${new Date().toISOString()}] ${req.method} ${req.originalUrl}`);
323
+ next();
324
+ });
482
325
  ```
483
326
 
484
- Registra uma rota que responde a requisições HTTP do método DELETE. Este método é utilizado para **remover um recurso específico**.
485
-
486
- * **Parâmetros**
487
- - `path` (string): O caminho da URL, que deve conter um parâmetro para identificar o recurso a ser removido (ex: `/items/:id`).
327
+ ##### `.route(path?: string)`
328
+ Cria um sub-roteador com prefixo.
488
329
 
489
- * **Retorno**
490
- Retorna uma instância de `RequestHandler` para encadeamento.
491
-
492
- * **Exemplo de Uso**
493
330
  ```typescript
494
- import express from 'express';
495
- import { create, Request, Response } from '@ismael1361/router';
496
-
497
- const app = express();
498
- const router = create(app);
331
+ const usersRouter = mainRouter.route('/users');
499
332
 
500
- router
501
- .delete('/items/:id')
333
+ usersRouter
334
+ .get('/')
502
335
  .handle((req, res) => {
503
- const { id } = req.params;
504
- // Lógica para deletar o item do banco de dados...
505
- console.log(`Item ${id} deletado.`);
506
- // Uma boa prática é retornar 204 (No Content) em caso de sucesso.
507
- res.status(204).send();
508
- })
509
- .doc({
510
- summary: 'Deletar um item',
511
- tags: ['Items'],
512
- params: { id: { description: 'ID do item a ser deletado', type: 'string', required: true } },
513
- responses: {
514
- 204: { description: 'Item deletado com sucesso' },
515
- 404: { description: 'Item não encontrado' },
516
- },
336
+ res.json([{ id: '1', name: 'Alice' }]);
517
337
  });
518
-
519
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
520
338
  ```
521
339
 
522
- ---
523
-
524
- #### `patch`
340
+ ##### `.middleware(callback: MiddlewareFC, doc?: MiddlewareFCDoc)`
341
+ Aplica middleware a todas as rotas subsequentes.
525
342
 
526
- ```ts
527
- .patch(path: string): RequestHandler<Rq, Rs>;
343
+ ```typescript
344
+ const router = create(app)
345
+ .middleware(express.json())
346
+ .middleware(authMiddleware);
528
347
  ```
529
348
 
530
- Registra uma rota que responde a requisições HTTP do método PATCH. É usado para aplicar **atualizações parciais** a um recurso, modificando apenas os campos enviados no corpo da requisição.
531
-
532
- * **Parâmetros**
533
- - `path` (string): O caminho da URL, geralmente com um parâmetro para identificar o recurso (ex: `/tasks/:id`).
534
-
535
- * **Retorno**
536
- Retorna uma instância de `RequestHandler` para encadeamento.
349
+ ##### `.handler(callback: HandlerFC, doc?: MiddlewareFCDoc)`
350
+ Define a função controladora para processar requisições.
537
351
 
538
- * **Exemplo de Uso**
539
352
  ```typescript
540
- import express from 'express';
541
- import { create, Request, Response } from '@ismael1361/router';
542
-
543
- const app = express();
544
- const router = create(app).middleware(express.json());
545
-
546
353
  router
547
- .patch('/tasks/:id')
548
- .handle((req, res) => {
549
- const { id } = req.params;
550
- const partialUpdates = req.body; // ex: { "completed": true }
551
- // Lógica para aplicar a atualização parcial na tarefa...
552
- res.json({ id, message: 'Tarefa atualizada parcialmente.', changes: partialUpdates });
553
- })
554
- .doc({
555
- summary: 'Atualizar uma tarefa (parcialmente)',
556
- tags: ['Tasks'],
557
- params: { id: { description: 'ID da tarefa', type: 'string', required: true } },
558
- body: { description: 'Campos da tarefa a serem atualizados.' },
559
- responses: {
560
- 200: { description: 'Tarefa atualizada' },
561
- 404: { description: 'Tarefa não encontrada' },
562
- },
354
+ .get('/status')
355
+ .handler((req, res) => {
356
+ res.json({ status: 'ok' });
563
357
  });
564
-
565
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
566
358
  ```
567
359
 
568
- ---
360
+ ##### `.by(router: ExpressRouter | Router)`
361
+ Anexa um roteador existente ao atual.
569
362
 
570
- #### `options`
363
+ ```typescript
364
+ const productsRouter = route('/products');
365
+ // ... definir rotas
571
366
 
572
- ```ts
573
- .options(path: string): RequestHandler<Rq, Rs>;
367
+ mainRouter.by(productsRouter);
574
368
  ```
575
369
 
576
- Registra uma rota que responde a requisições HTTP do método OPTIONS. Este método é usado pelo navegador para determinar as opções de comunicação para um recurso de destino, principalmente em requisições de **pré-voo (pre-flight) do CORS**.
577
-
578
- * **Parâmetros**
579
- - `path` (string): O caminho da URL do recurso.
370
+ ##### `.defineSwagger(options: SwaggerOptions)`
371
+ Gera as rotas de documentação para a especificação OpenAPI completa.
580
372
 
581
- * **Retorno**
582
- Retorna uma instância de `RequestHandler` para encadeamento.
583
-
584
- * **Exemplo de Uso**
585
373
  ```typescript
586
- import express from 'express';
587
- import { create, Request, Response } from '@ismael1361/router';
374
+ import { create } from '@ismael1361/router';
588
375
 
589
- const app = express();
590
- const router = create(app);
376
+ const router = create();
591
377
 
592
- // Para um recurso específico, informa quais métodos são permitidos
593
- router
594
- .options('/articles/:id')
595
- .handle((req, res) => {
596
- res.header('Access-Control-Allow-Methods', 'GET, PUT, DELETE');
597
- res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
598
- res.status(204).send();
599
- })
600
- .doc({
601
- summary: 'Verificar opções de comunicação para um artigo',
602
- tags: ['Articles'],
603
- responses: {
604
- 204: { description: 'Sucesso. Os métodos permitidos estão nos cabeçalhos de resposta.' },
378
+ const swaggerDefinition = {
379
+ openapi: '3.0.0',
380
+ info: {
381
+ title: 'Minha API',
382
+ version: '1.0.0',
383
+ description: 'API com documentação automática'
384
+ },
385
+ servers: [{ url: 'http://localhost:3000' }],
386
+ components: {
387
+ securitySchemes: {
388
+ bearerAuth: {
389
+ type: 'http',
390
+ scheme: 'bearer',
391
+ bearerFormat: 'JWT'
392
+ }
393
+ }
394
+ },
395
+ defaultResponses: {
396
+ 400: { description: "Dados inválidos" },
397
+ 401: {
398
+ description: "Falha na autenticação",
605
399
  },
606
- });
607
-
608
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
609
- ```
610
-
611
- ---
612
-
613
- #### `head`
400
+ 403: { description: "Acesso negado" },
401
+ 500: { description: "Erro interno do servidor" },
402
+ },
403
+ };
614
404
 
615
- ```ts
616
- .head(path: string): RequestHandler<Rq, Rs>;
405
+ router.defineSwagger(swaggerDefinition);
406
+ // By swagger json -> /doc/swagger/definition.json
407
+ // By swagger -> /doc/swagger
408
+ // By redoc -> /doc/redoc
617
409
  ```
618
410
 
619
- Registra uma rota que responde a requisições HTTP do método HEAD. É idêntico ao GET, mas o servidor **não envia o corpo da resposta**. É útil para verificar metadados de um recurso, como `Content-Length` ou `Last-Modified`, sem precisar baixar o conteúdo completo.
620
-
621
- * **Parâmetros**
622
- - `path` (string): O caminho da URL do recurso.
411
+ ## 🎯 Exemplos Avançados
623
412
 
624
- * **Retorno**
625
- Retorna uma instância de `RequestHandler` para encadeamento.
413
+ ### Autenticação e Autorização
626
414
 
627
- * **Exemplo de Uso**
628
415
  ```typescript
629
- import express from 'express';
630
- import { create, Request, Response } from '@ismael1361/router';
416
+ import { create, middleware, Middlewares, Request } from '@ismael1361/router';
631
417
 
632
- const app = express();
633
- const router = create(app);
418
+ interface AuthRequest extends Request {
419
+ user: { id: string; roles: string[] };
420
+ }
634
421
 
635
- // O Express lida com HEAD automaticamente se você tiver uma rota GET correspondente.
636
- // No entanto, você pode definir um handler específico se precisar de lógica customizada.
637
- router
638
- .head('/large-file.zip')
639
- .handle((req, res) => {
640
- // Lógica para obter o tamanho do arquivo sem lê-lo
641
- const fileSize = 104857600; // 100 MB
642
- res.header('Content-Length', fileSize.toString());
643
- res.status(200).send(); // O corpo é omitido pelo Express
644
- })
645
- .doc({
646
- summary: 'Obter metadados de um arquivo',
647
- tags: ['Files'],
422
+ // Middleware de autenticação
423
+ const authenticate = middleware<AuthRequest>(
424
+ (req, res, next) => {
425
+ const token = req.headers.authorization?.replace('Bearer ', '');
426
+
427
+ if (!token) {
428
+ return res.status(401).json({ message: 'Token não fornecido' });
429
+ }
430
+
431
+ // Validar token (exemplo simplificado)
432
+ req.user = { id: '123', roles: ['user'] };
433
+ next();
434
+ },
435
+ {
436
+ security: [{ bearerAuth: [] }],
648
437
  responses: {
649
- 200: { description: 'Metadados do arquivo nos cabeçalhos.' },
650
- 404: { description: 'Arquivo não encontrado.' },
651
- },
652
- });
653
-
654
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
655
- ```
656
-
657
- ---
658
-
659
- #### `all`
660
-
661
- ```ts
662
- .all(path: string): RequestHandler<Rq, Rs>;
663
- ```
664
-
665
- Registra uma rota que responde a **todos os métodos HTTP** (GET, POST, PUT, etc.) para um caminho específico. É útil para aplicar lógica genérica a um endpoint, como logging ou validações que independem do método.
666
-
667
- * **Parâmetros**
668
- - `path` (string): O caminho da URL.
669
-
670
- * **Retorno**
671
- Retorna uma instância de `RequestHandler` para encadeamento.
438
+ 401: { description: 'Não autorizado' }
439
+ }
440
+ }
441
+ );
672
442
 
673
- * **Exemplo de Uso**
674
- ```typescript
675
- import express from 'express';
676
- import { create, Request, Response } from '@ismael1361/router';
443
+ // Middleware de autorização
444
+ const authorize = (...roles: string[]) =>
445
+ middleware<AuthRequest>(
446
+ (req, res, next) => {
447
+ if (!req.user.roles.some(role => roles.includes(role))) {
448
+ return res.status(403).json({ message: 'Acesso negado' });
449
+ }
450
+ next();
451
+ },
452
+ {
453
+ responses: {
454
+ 403: { description: 'Acesso negado' }
455
+ }
456
+ }
457
+ );
677
458
 
678
- const app = express();
679
- const router = create(app);
459
+ const app = create<AuthRequest>()
460
+ .middleware(Middlewares.json());
680
461
 
681
- router
682
- .all('/secret-data')
462
+ // Rota protegida
463
+ app
464
+ .get('/admin/users')
465
+ .middleware(authenticate)
466
+ .middleware(authorize('admin'))
683
467
  .handle((req, res) => {
684
- // Este handler será executado para GET, POST, DELETE, etc. em '/secret-data'
685
- console.log(`Requisição ${req.method} recebida em /secret-data`);
686
- res.status(403).send('Acesso negado a este endpoint.');
468
+ res.json({ users: [] });
687
469
  })
688
470
  .doc({
689
- summary: 'Endpoint genérico de captura',
690
- tags: ['Utils'],
691
- description: 'Este endpoint responde a todos os métodos HTTP com uma mensagem padrão.',
692
- responses: {
693
- 403: { description: 'Acesso sempre negado.' },
694
- },
471
+ summary: 'Listar usuários (Admin)',
472
+ tags: ['Admin'],
473
+ responses: { 200: { description: 'Lista de usuários' } }
695
474
  });
696
-
697
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
698
475
  ```
699
476
 
700
- ---
701
-
702
- #### `use`
703
-
704
- ```ts
705
- .use(path: string): Router<Rq, Rs>;
706
- ```
707
-
708
- Monta uma função de middleware ou uma série de middlewares em um caminho específico. Diferente dos métodos de rota (GET, POST, etc.), `use` é projetado para interceptar requisições e executar código **antes** que elas cheguem ao handler final da rota.
709
-
710
- É ideal para tarefas como logging, parsing de corpo de requisição, autenticação e tratamento de erros. Se nenhum caminho for especificado, o middleware será aplicado a todas as rotas definidas no roteador.
711
-
712
- * **Parâmetros**
713
- - `path` (opcional): O caminho no qual o middleware será aplicado. Suporta wildcards (ex: `/api/*`).
477
+ ### Validação de Dados
714
478
 
715
- * **Retorno**
716
- Retorna a própria instância do `Router`, permitindo o encadeamento de mais definições.
717
-
718
- * **Exemplo de Uso**
719
479
  ```typescript
720
- import express from 'express';
721
- import { create, Request, Response, NextFunction } from '@ismael1361/router';
722
-
723
- const app = express();
724
- const router = create(app);
480
+ import { middleware, Request } from '@ismael1361/router';
481
+
482
+ interface ValidatedRequest extends Request {
483
+ validated: {
484
+ body?: any;
485
+ params?: any;
486
+ query?: any;
487
+ };
488
+ }
725
489
 
726
- // Aplica o middleware no caminho /api
727
- router.use('/api').handle((req, res, next) => {
728
- console.log(`[${new Date().toISOString()}] ${req.method} ${req.originalUrl}`);
729
- next(); // Passa o controle para o próximo middleware ou handler
730
- });
490
+ const validate = (schema: any) =>
491
+ middleware<ValidatedRequest>(
492
+ (req, res, next) => {
493
+ // Implementar validação (ex: usando Zod, Joi, etc)
494
+ const result = schema.safeParse(req.body);
495
+
496
+ if (!result.success) {
497
+ return res.status(400).json({
498
+ message: 'Dados inválidos',
499
+ errors: result.error.errors
500
+ });
501
+ }
502
+
503
+ req.validated = { body: result.data };
504
+ next();
505
+ },
506
+ {
507
+ responses: {
508
+ 400: { description: 'Dados de entrada inválidos' }
509
+ }
510
+ }
511
+ );
731
512
 
732
- // Define uma rota dentro do escopo do middleware
733
513
  router
734
- .get('/api/status')
514
+ .post('/users')
515
+ .middleware(validate(userSchema))
735
516
  .handle((req, res) => {
736
- res.json({ status: 'ok' });
517
+ const validatedData = req.validated.body;
518
+ res.status(201).json(validatedData);
737
519
  });
738
-
739
- // Uma requisição para GET /api/status irá primeiro executar o loggerMiddleware.
740
-
741
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
742
520
  ```
743
521
 
744
- ---
745
-
746
- #### `route`
747
-
748
- ```ts
749
- .route(path: string): Router<Rq, Rs>;
750
- ```
751
-
752
- Cria e retorna uma nova instância de `Router` que é montada sob um caminho (prefixo) específico. É uma maneira poderosa de agrupar um conjunto de rotas relacionadas sob um namespace comum, promovendo a organização e a modularidade do código.
753
-
754
- Todas as rotas definidas no roteador retornado serão relativas ao `path` fornecido.
755
-
756
- * **Parâmetros**
757
- - `path` (string): O caminho do prefixo para o novo roteador. Por exemplo, `/api/v1`.
522
+ ### Organização Modular
758
523
 
759
- * **Retorno**
760
- Retorna uma nova instância de `Router` que pode ser usada para definir um grupo de rotas.
761
-
762
- * **Exemplo de Uso**
763
524
  ```typescript
764
- import express from 'express';
765
- import { create, Request, Response } from '@ismael1361/router';
766
-
767
- const app = express();
768
- const mainRouter = create(app);
525
+ // routes/users.routes.ts
526
+ import { route } from '@ismael1361/router';
769
527
 
770
- // 1. Crie um sub-roteador para os endpoints de usuários
771
- const usersRouter = mainRouter.route('/users');
528
+ export const usersRouter = route('/users');
772
529
 
773
- // 2. Defina as rotas neste sub-roteador. Os caminhos são relativos a '/users'.
774
530
  usersRouter
775
531
  .get('/')
776
532
  .handle((req, res) => {
777
- // Este handler responde a GET /users
778
- res.json([{ id: '1', name: 'Alice' }]);
533
+ res.json([]);
779
534
  })
780
- .doc({ summary: 'Listar todos os usuários', tags: ['Users'] });
535
+ .doc({
536
+ summary: 'Listar usuários',
537
+ tags: ['Users']
538
+ });
781
539
 
782
540
  usersRouter
783
- .get('/:id')
541
+ .post('/')
784
542
  .handle((req, res) => {
785
- // Este handler responde a GET /users/:id
786
- res.json({ id: req.params.id, name: 'Alice' });
543
+ res.status(201).json(req.body);
787
544
  })
788
- .doc({ summary: 'Obter um usuário pelo ID', tags: ['Users'] });
789
-
790
- // O mainRouter já está conectado ao 'app', então as rotas estão ativas.
791
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
792
- ```
793
-
794
- ---
795
-
796
- #### `middleware`
797
-
798
- ```ts
799
- .middleware<Req extends Request, Res extends Response>(callback: MiddlewareFC<Req, Res>): Router<Rq & Req, Rs & Res>;
800
- ```
801
-
802
- Aplica uma função de middleware a **todas as rotas subsequentes** definidas nesta instância do roteador. É o método ideal para aplicar middlewares que devem ser executados para um grupo de endpoints, como parsing de corpo de requisição (`express.json()`) ou autenticação.
803
-
804
- A tipagem do `Request` e `Response` é inteligentemente mesclada, garantindo que as propriedades adicionadas por um middleware (ex: `req.user`) estejam disponíveis e corretamente tipadas nos handlers das rotas.
805
-
806
- * **Parâmetros**
807
- - `callbacks`: Uma função de middleware do Express.
545
+ .doc({
546
+ summary: 'Criar usuário',
547
+ tags: ['Users']
548
+ });
808
549
 
809
- * **Retorno**
810
- Retorna a própria instância do `Router`, com os tipos de `Request` e `Response` atualizados, permitindo o encadeamento contínuo.
550
+ // routes/products.routes.ts
551
+ export const productsRouter = route('/products');
552
+ // ... definir rotas
811
553
 
812
- * **Exemplo de Uso**
813
- ```typescript
814
- import express from 'express';
815
- import { create, middleware, Request, Response, NextFunction } from '@ismael1361/router';
816
-
817
- interface AuthRequest extends Request {
818
- user?: { id: string };
819
- }
554
+ // app.ts
555
+ import { create } from '@ismael1361/router';
556
+ import { usersRouter } from './routes/users.routes';
557
+ import { productsRouter } from './routes/products.routes';
820
558
 
821
559
  const app = express();
822
-
823
- // Middleware de autenticação simples
824
- const authMiddleware = middleware<AuthRequest>((req, res, next) => {
825
- req.user = { id: 'user-123' };
826
- next();
827
- });
828
-
829
- // 1. Crie o roteador e aplique middlewares globais a ele
830
- const router = create<AuthRequest>(app)
560
+ const router = create(app)
831
561
  .middleware(express.json());
832
562
 
833
- // 2. Todas as rotas definidas a partir daqui terão acesso a `req.body` e `req.user`
834
563
  router
835
- .get('/profile')
836
- .middleware(authMiddleware)
837
- .handle((req, res) => {
838
- // req.user é totalmente tipado como { id: string }
839
- res.json({ profile: req.user });
840
- });
841
-
842
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
564
+ .by(usersRouter)
565
+ .by(productsRouter);
843
566
  ```
844
567
 
845
- ---
846
-
847
- #### `handler`
848
-
849
- ```ts
850
- .handler<Req extends Request, Res extends Response>(callback: HandlerFC<Req, Res>): PreparedHandler<Rq & Req, Rs & Res>;
851
- ```
852
-
853
- Define a função controladora (handler) que processará a requisição para uma rota ou middleware específico. Este método é o coração da sua rota, onde a lógica de negócios é executada.
854
-
855
- Ele deve ser encadeado após a definição de um método HTTP (como `.get()`, `.post()`) ou de um middleware (`.use()`). A função de `callback` recebe os objetos `req` e `res`, que são fortemente tipados com base nos middlewares aplicados anteriormente.
568
+ ## 📚 Documentação OpenAPI/Swagger
856
569
 
857
- * **Parâmetros**
858
- - `callback`: A função controladora que processará a requisição, com a assinatura `(req, res, next)`.
570
+ O módulo gera automaticamente documentação OpenAPI 3.0 compatível com Swagger UI.
859
571
 
860
- * **Retorno**
861
- Retorna uma instância de `PreparedHandler`, que permite encadear o método `.doc()` para adicionar a documentação OpenAPI.
572
+ ### Configuração Completa
862
573
 
863
- * **Exemplo de Uso**
864
574
  ```typescript
865
- import express from 'express';
866
- import { create, Request, Response, NextFunction } from '@ismael1361/router';
575
+ import { create, Middlewares } from '@ismael1361/router';
867
576
 
868
- const app = express();
869
- const router = create(app);
577
+ const app = create().middleware(Middlewares.json());
870
578
 
871
- // Exemplo 1: Handler para uma rota GET
872
- router
873
- .get('/status')
874
- .handler((req, res) => {
875
- res.json({ status: 'ok' });
579
+ // Definir rotas com documentação
580
+ app
581
+ .get('/users/:id')
582
+ .handle((req, res) => {
583
+ res.json({ id: req.params.id, name: 'John Doe' });
584
+ })
585
+ .doc({
586
+ summary: 'Obter usuário',
587
+ description: 'Retorna um usuário pelo ID',
588
+ tags: ['Users'],
589
+ params: {
590
+ id: {
591
+ description: 'ID do usuário',
592
+ type: 'string',
593
+ required: true,
594
+ example: '123'
595
+ }
596
+ },
597
+ responses: {
598
+ 200: {
599
+ description: 'Usuário encontrado',
600
+ content: {
601
+ 'application/json': {
602
+ schema: {
603
+ type: 'object',
604
+ properties: {
605
+ id: { type: 'string' },
606
+ name: { type: 'string' }
607
+ }
608
+ }
609
+ }
610
+ }
611
+ },
612
+ 404: { description: 'Usuário não encontrado' }
613
+ }
876
614
  });
877
615
 
878
- // Exemplo 2: Handler para um middleware
879
- router.use('/api').handler((req, res, next) => {
880
- console.log('Requisição recebida na API');
881
- next(); // Passa para o próximo handler
616
+ // Configurar Swagger
617
+ app.defineSwagger({
618
+ openapi: '3.0.0',
619
+ info: {
620
+ title: 'API de Exemplo',
621
+ version: '1.0.0',
622
+ description: 'Documentação automática gerada com @ismael1361/router',
623
+ contact: {
624
+ name: 'Suporte',
625
+ email: 'suporte@exemplo.com'
626
+ }
627
+ },
628
+ servers: [
629
+ {
630
+ url: 'http://localhost:3000',
631
+ description: 'Servidor de desenvolvimento'
632
+ },
633
+ {
634
+ url: 'https://api.exemplo.com',
635
+ description: 'Servidor de produção'
636
+ }
637
+ ],
638
+ components: {
639
+ securitySchemes: {
640
+ bearerAuth: {
641
+ type: 'http',
642
+ scheme: 'bearer',
643
+ bearerFormat: 'JWT',
644
+ description: 'Token JWT no formato Bearer'
645
+ },
646
+ apiKey: {
647
+ type: 'apiKey',
648
+ in: 'header',
649
+ name: 'X-API-Key'
650
+ }
651
+ }
652
+ },
653
+ defaultResponses: {
654
+ 500: { description: 'Erro interno do servidor' },
655
+ 429: { description: 'Muitas requisições' }
656
+ }
882
657
  });
883
658
 
884
659
  app.listen(3000, () => {
885
- console.log('Servidor rodando na porta 3000');
886
- console.log('Acesse /status ou /health-check');
660
+ console.log('🚀 Servidor: http://localhost:3000');
661
+ console.log('📚 Docs-swagger: http://localhost:3000/docs/swagger');
662
+ console.log('📚 Docs-redoc: http://localhost:3000/docs/redoc');
887
663
  });
888
664
  ```
889
665
 
890
- ---
666
+ ## 🔷 TypeScript
891
667
 
892
- #### `by`
668
+ O módulo é totalmente tipado e oferece excelente suporte ao TypeScript.
893
669
 
894
- ```ts
895
- .by(router: ExpressRouter | Router<Request, Response>): this;
896
- ```
897
-
898
- Anexa um roteador existente (seja uma instância do `Router` desta biblioteca ou um `express.Router` padrão) ao roteador atual. Este método é uma forma conveniente de compor e modularizar sua aplicação, permitindo que você defina grupos de rotas em arquivos separados e depois os integre ao roteador principal.
899
-
900
- * **Parâmetros**
901
- - `router`: A instância do roteador a ser anexada.
670
+ ### Tipos Personalizados
902
671
 
903
- * **Retorno**
904
- - Retorna a própria instância do `Router` (`this`), permitindo o encadeamento de mais chamadas.
905
-
906
- * **Exemplo de Uso**
907
672
  ```typescript
908
- import express from 'express';
909
- import { create, route, Request, Response } from '@ismael1361/router';
910
-
911
- const app = express();
912
- const mainRouter = create(app);
673
+ import { Request, Response } from '@ismael1361/router';
913
674
 
914
- // 1. Crie um roteador separado para as rotas de produtos
915
- const productsRouter = route('/products');
675
+ // Estender Request
676
+ interface CustomRequest extends Request {
677
+ user?: {
678
+ id: string;
679
+ email: string;
680
+ roles: string[];
681
+ };
682
+ requestId: string;
683
+ startTime: number;
684
+ }
916
685
 
917
- productsRouter
918
- .get('/')
919
- .handle((req, res) => {
920
- res.json([{ id: 'p1', name: 'Laptop' }]);
921
- })
922
- .doc({ summary: 'Listar produtos', tags: ['Products'] });
686
+ // Estender Response
687
+ interface CustomResponse extends Response {
688
+ sendSuccess: (data: any) => void;
689
+ sendError: (message: string, code?: number) => void;
690
+ }
923
691
 
924
- // 2. Use o método .by() para anexar o roteador de produtos ao roteador principal
925
- mainRouter.by(productsRouter);
692
+ // Usar tipos personalizados
693
+ const router = create<CustomRequest, CustomResponse>(app);
926
694
 
927
- // A rota GET /products está agora ativa na aplicação.
928
- app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
695
+ router
696
+ .get('/profile')
697
+ .handle((req, res) => {
698
+ // req.user está totalmente tipado
699
+ // res.sendSuccess está disponível
700
+ res.sendSuccess({ user: req.user });
701
+ });
929
702
  ```
930
703
 
931
- ---
704
+ ### Inferência de Tipos
932
705
 
933
- #### `getSwagger`
706
+ ```typescript
707
+ import { Request } from '@ismael1361/router';
934
708
 
935
- ```ts
936
- .getSwagger(options?: swaggerJSDoc.OAS3Definition, defaultResponses?: swaggerJSDoc.Responses): swaggerJSDoc.Options;
709
+ // Os tipos são inferidos automaticamente
710
+ router
711
+ .get('/users/:id')
712
+ .handle<Request<any, any, "id">>((req, res) => {
713
+ // req.params é Record<"id", any>
714
+ // req.params.id é any
715
+ // req.query é Record<string, any>
716
+ // req.body é any (pode ser tipado com middleware)
717
+ const userId: string = req.params.id;
718
+ });
937
719
  ```
938
720
 
939
- Coleta todas as informações de documentação fornecidas através dos métodos `.doc()` em todas as rotas e as compila em um objeto de opções compatível com a biblioteca `swagger-jsdoc`. Este objeto pode ser usado para gerar a especificação OpenAPI completa (geralmente um arquivo `swagger.json`).
721
+ ## 🤝 Contribuindo
940
722
 
941
- * **Parâmetros**
942
- - `options` (opcional): Um objeto de definição base do OpenAPI 3.0. Aqui você define informações globais da sua API, como `info` (título, versão), `servers`, `components` (schemas, securitySchemes), etc.
943
- - `defaultResponses` (opcional): Um objeto para definir respostas padrão que serão mescladas em todas as rotas, como `500: { description: 'Erro interno do servidor' }`.
723
+ Contribuições são bem-vindas! Por favor, siga estas etapas:
944
724
 
945
- * **Retorno**
946
- - Retorna um objeto de opções (`swaggerJSDoc.Options`) que pode ser passado diretamente para a função `swaggerJSDoc()` para gerar a documentação.
725
+ 1. Faça um fork do projeto
726
+ 2. Crie uma branch para sua feature (`git checkout -b feature/MinhaFeature`)
727
+ 3. Commit suas mudanças (`git commit -m 'Adiciona MinhaFeature'`)
728
+ 4. Push para a branch (`git push origin feature/MinhaFeature`)
729
+ 5. Abra um Pull Request
947
730
 
948
- * **Exemplo de Uso**
949
- ```typescript
950
- import swaggerJSDoc from 'swagger-jsdoc';
951
- import swaggerUi from 'swagger-ui-express';
731
+ ## 📄 Licença
952
732
 
953
- // ... (definição do seu app e rotas com .doc())
733
+ Este projeto está sob a licença MIT. Veja o arquivo [LICENSE](MIT) para mais detalhes.
954
734
 
955
- // 1. Defina as opções base para a sua documentação OpenAPI
956
- const swaggerDefinition: swaggerJSDoc.OAS3Definition = {
957
- openapi: '3.0.0',
958
- info: {
959
- title: 'Minha API Incrível',
960
- version: '1.0.0',
961
- description: 'Documentação da API criada com @ismael1361/router',
962
- },
963
- servers: [{ url: 'http://localhost:3000' }],
964
- components: {
965
- securitySchemes: {
966
- bearerAuth: {
967
- type: 'http',
968
- scheme: 'bearer',
969
- bearerFormat: 'JWT',
970
- },
971
- },
972
- },
973
- };
974
-
975
- // 2. Gere as opções completas usando o método .getSwagger() do seu roteador
976
- const swaggerOptions = router.getSwagger(swaggerDefinition);
735
+ ## 🙏 Agradecimentos
977
736
 
978
- // 3. Gere a especificação final com swagger-jsdoc
979
- const swaggerSpec = swaggerJSDoc(swaggerOptions);
737
+ - Express.js pela base sólida
738
+ - Swagger/OpenAPI pela especificação de documentação
739
+ - A comunidade TypeScript
980
740
 
981
- // 4. Sirva a documentação usando swagger-ui-express
982
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
741
+ ---
983
742
 
984
- app.listen(3000, () => {
985
- console.log('Servidor rodando na porta 3000');
986
- console.log('Documentação disponível em http://localhost:3000/api-docs');
987
- });
988
- ```
743
+ Desenvolvido com ❤️ por [Ismael Souza Silva](https://github.com/ismael1361)