sashiko 0.1.0 → 0.3.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.
- package/README.md +132 -27
- package/dist/core/app.d.ts +30 -6
- package/dist/core/app.d.ts.map +1 -1
- package/dist/core/app.js +73 -18
- package/dist/core/app.js.map +1 -1
- package/dist/core/compiler.d.ts +34 -10
- package/dist/core/compiler.d.ts.map +1 -1
- package/dist/core/compiler.js +60 -36
- package/dist/core/compiler.js.map +1 -1
- package/dist/core/context.d.ts +43 -7
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +41 -11
- package/dist/core/context.js.map +1 -1
- package/dist/core/index.d.ts +6 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/infer.d.ts +9 -1
- package/dist/core/infer.d.ts.map +1 -1
- package/dist/core/metadata.d.ts +21 -5
- package/dist/core/metadata.d.ts.map +1 -1
- package/dist/core/metadata.js +6 -0
- package/dist/core/metadata.js.map +1 -1
- package/dist/core/mounted-group.d.ts +41 -0
- package/dist/core/mounted-group.d.ts.map +1 -0
- package/dist/core/mounted-group.js +43 -0
- package/dist/core/mounted-group.js.map +1 -0
- package/dist/core/response.d.ts +22 -8
- package/dist/core/response.d.ts.map +1 -1
- package/dist/core/response.js +93 -15
- package/dist/core/response.js.map +1 -1
- package/dist/core/shutdown.d.ts +36 -0
- package/dist/core/shutdown.d.ts.map +1 -0
- package/dist/core/shutdown.js +53 -0
- package/dist/core/shutdown.js.map +1 -0
- package/dist/decorators/index.d.ts +1 -1
- package/dist/decorators/index.d.ts.map +1 -1
- package/dist/decorators/index.js +1 -1
- package/dist/decorators/index.js.map +1 -1
- package/dist/decorators/middlewares.d.ts +28 -0
- package/dist/decorators/middlewares.d.ts.map +1 -0
- package/dist/decorators/middlewares.js +40 -0
- package/dist/decorators/middlewares.js.map +1 -0
- package/dist/middlewares/index.d.ts +1 -1
- package/dist/middlewares/index.d.ts.map +1 -1
- package/dist/middlewares/index.js.map +1 -1
- package/dist/middlewares/security-headers.d.ts +4 -2
- package/dist/middlewares/security-headers.d.ts.map +1 -1
- package/dist/middlewares/security-headers.js +10 -2
- package/dist/middlewares/security-headers.js.map +1 -1
- package/dist/schema/validation.d.ts +11 -0
- package/dist/schema/validation.d.ts.map +1 -1
- package/dist/schema/validation.js +18 -0
- package/dist/schema/validation.js.map +1 -1
- package/dist/utils/content-type.d.ts +8 -0
- package/dist/utils/content-type.d.ts.map +1 -1
- package/dist/utils/content-type.js +42 -0
- package/dist/utils/content-type.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/decorators/use.d.ts +0 -26
- package/dist/decorators/use.d.ts.map +0 -1
- package/dist/decorators/use.js +0 -38
- package/dist/decorators/use.js.map +0 -1
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ await app.listen({ port: 3000 });
|
|
|
33
33
|
- [Requisitos e instalação](#requisitos-e-instalação)
|
|
34
34
|
- [Rotas](#rotas)
|
|
35
35
|
- [Registro e composição: `app.mount()`](#registro-e-composição-appmount)
|
|
36
|
+
- [Mapeamento manual](#mapeamento-manual)
|
|
36
37
|
- [Schemas: validação, serialização e tipos](#schemas-validação-serialização-e-tipos)
|
|
37
38
|
- [Respostas e o `ctx`](#respostas-e-o-ctx)
|
|
38
39
|
- [Middlewares e guards](#middlewares-e-guards)
|
|
@@ -99,24 +100,50 @@ app
|
|
|
99
100
|
.mount(HealthRoutes)
|
|
100
101
|
.mount(userRoutes) // como declarado
|
|
101
102
|
.mount(userRoutes, { prefix: '/v2/users' }) // a mesma instância em outro prefixo
|
|
102
|
-
.mount(userRoutes, { prefix: '/public/users', only: [
|
|
103
|
+
.mount(userRoutes, { prefix: '/public/users', only: (r) => [r.list, r.get] }) // exposição parcial
|
|
103
104
|
.mount(new AdminRoutes(repo), { middlewares: [authenticate], guards: [isAdmin] }); // regras para o grupo
|
|
104
105
|
```
|
|
105
106
|
|
|
106
107
|
| Opção | Efeito |
|
|
107
108
|
|---|---|
|
|
108
109
|
| `prefix` | Substitui o prefixo do `@Router` |
|
|
109
|
-
| `only` / `except` | Registra só
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
110
|
+
| `only` / `except` | Registra só os métodos selecionados, ou todos menos esses: `(r) => [r.list, r.get]`. O seletor é checado pelo TypeScript; usar os dois juntos gera erro |
|
|
111
|
+
| `auto` | `false` registra só as [rotas manuais](#mapeamento-manual). Padrão: `true` |
|
|
112
|
+
| `middlewares` | Valem para todas as rotas do grupo; rodam antes dos `@Middlewares` da classe |
|
|
113
|
+
| `guards` | Valem para todas as rotas do grupo; rodam antes dos `@Guards` da classe |
|
|
112
114
|
|
|
113
115
|
Erros de registro aparecem na inicialização, com mensagem clara:
|
|
114
116
|
- classe sem `@Router`;
|
|
115
|
-
-
|
|
117
|
+
- seletor em `only`/`except` que não aponta para um método de rota;
|
|
116
118
|
- a mesma classe registrada duas vezes com o mesmo prefixo.
|
|
117
119
|
|
|
118
120
|
> **Por que `mount` e não `register`?** O método monta um grupo de rotas sob um prefixo, quantas vezes for preciso, como o `koa-mount` e os routers do Express. No Fastify, `register` significa plugin encapsulado, e esse nome fica reservado para um futuro sistema de plugins.
|
|
119
121
|
|
|
122
|
+
## Mapeamento manual
|
|
123
|
+
|
|
124
|
+
Depois do `mount`, os verbos `.get()`, `.post()`, `.put()`, `.patch()` e `.delete()` mapeiam um método da classe para um path que ela não declara: um alias, um endpoint legado, um export. O path é relativo ao prefixo do grupo, e o método é escolhido por um **seletor**, checado pelo TypeScript:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
@Router('/users')
|
|
128
|
+
class UserRoutes {
|
|
129
|
+
@Get('/:id', byId) getUser(ctx: Context<typeof byId>) {}
|
|
130
|
+
@Schema(csv) exportCsv(ctx: Context<typeof csv>) {} // sem verbo: só por mapeamento manual
|
|
131
|
+
private findOr404() {} // sem decorator: nunca pode ser exposto
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
app
|
|
135
|
+
.mount(new UserRoutes(repo))
|
|
136
|
+
.get('/legacy/:id', (r) => r.getUser) // GET /users/legacy/:id
|
|
137
|
+
.get('/export.csv', (r) => r.exportCsv, { middlewares: [cache()], guards: [isAuditor] })
|
|
138
|
+
.mount(HealthRoutes); // o encadeamento continua
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
- **Seletor:** funciona com instância (inclusive inline, `mount(new X(repo))`) e com a classe. "Ir para a definição" e renomear no editor funcionam.
|
|
142
|
+
- **Permissão por método:** só podem ser mapeados métodos com algum decorator do Sashiko (verbo, `@Schema`, `@Middlewares` ou `@Guards`). Um método sem decorator gera erro no registro.
|
|
143
|
+
- **Regras herdadas:** a rota manual usa os schemas e os `@Middlewares`/`@Guards` do método, e as regras do grupo.
|
|
144
|
+
- **Opções da rota:** `{ middlewares, guards }` em objeto, e não uma lista de funções, para que middleware, guard e seletor nunca se confundam.
|
|
145
|
+
- **Só mapeamento manual:** `mount(x, { auto: false })` não registra as rotas declaradas na classe.
|
|
146
|
+
|
|
120
147
|
## Schemas: validação, serialização e tipos
|
|
121
148
|
|
|
122
149
|
Os schemas da rota (`params`, `query`, `headers`, `body` e `response`) são escritos em [TypeBox](https://github.com/sinclairzx81/typebox) (JSON Schema) e podem ser declarados de duas formas equivalentes:
|
|
@@ -170,16 +197,80 @@ list(ctx: Context<typeof list>) {
|
|
|
170
197
|
|
|
171
198
|
## Respostas e o `ctx`
|
|
172
199
|
|
|
173
|
-
O valor retornado pelo handler vira a resposta
|
|
200
|
+
O valor retornado pelo handler vira a resposta. Sem schema de resposta, o formato vem do tipo do valor:
|
|
201
|
+
|
|
202
|
+
| Retorno | Resposta |
|
|
203
|
+
|---|---|
|
|
204
|
+
| objeto, array, número, booleano, `null` | `application/json` |
|
|
205
|
+
| `string` | `text/plain; charset=utf-8`, sem aspas |
|
|
206
|
+
| `Buffer` / `Uint8Array` | `application/octet-stream` |
|
|
207
|
+
| `Readable` (stream) | enviado em stream |
|
|
208
|
+
| `undefined` | sem corpo |
|
|
209
|
+
|
|
210
|
+
Um `Content-Type` definido no handler (`ctx.header('Content-Type', ...)`) sempre prevalece.
|
|
211
|
+
|
|
212
|
+
### Outros formatos: `contentType`, serializadores e `Accept`
|
|
213
|
+
|
|
214
|
+
Uma entrada de `response` pode declarar o tipo de conteúdo. Um schema sem `contentType` continua sendo JSON:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
// CSV cru: o `return` de uma string sai como está
|
|
218
|
+
@Get('/export.csv', { response: { 200: { contentType: 'text/csv', schema: Type.String() } } })
|
|
219
|
+
exportCsv() { return 'id,name\n1,Ana\n'; }
|
|
220
|
+
|
|
221
|
+
// Vários formatos: o cliente escolhe pelo Accept (q-values e curingas); sem Accept, vale o primeiro
|
|
222
|
+
@Get('/', { response: { 200: { contentType: ['application/json', 'application/yaml'], schema: Type.Array(User) } } })
|
|
223
|
+
list() { return users; }
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Objetos em formatos que não são JSON passam por um **serializador** registrado no app. A biblioteca é escolha sua:
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
import YAML from 'yaml';
|
|
230
|
+
createApp({ serializers: { 'application/yaml': (data) => YAML.stringify(data) } });
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
- **Campos não declarados nunca saem, em nenhum formato.** Antes do serializador, a saída é validada contra o schema e os campos extras são removidos (sobre uma cópia). Se não bater com o schema, a resposta é 500, com o motivo no log.
|
|
234
|
+
- **Sem formato aceitável:** a resposta é `406 Not Acceptable`, com os tipos disponíveis. Rotas com mais de um tipo enviam `Vary: Accept`.
|
|
235
|
+
- **Sem serializador:** um objeto num tipo sem serializador registrado gera 500, com a instrução no log.
|
|
236
|
+
- **Erros:** continuam em JSON.
|
|
237
|
+
|
|
238
|
+
### Dois estilos, um pipeline
|
|
239
|
+
|
|
240
|
+
Dá para responder com `return` ou com envio imperativo (`ctx.json()`, `ctx.send()`, `ctx.text()`). Os dois passam pelo **mesmo** pipeline: schema do status, remoção de campos não declarados, status padrão, negociação e serializadores. A resposta é idêntica.
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
const job = {
|
|
244
|
+
body: Type.Object({ async: Type.Boolean() }),
|
|
245
|
+
response: { 200: Type.Object({ result: Type.String() }), 202: Type.Object({ jobId: Type.String() }) },
|
|
246
|
+
} satisfies RouteSchemas;
|
|
247
|
+
|
|
248
|
+
@Post('/jobs', job)
|
|
249
|
+
run(ctx: Context<typeof job>) {
|
|
250
|
+
if (ctx.body.async) return ctx.status(202).json({ jobId: enqueue() }); // status decidido em runtime
|
|
251
|
+
return { result: process() }; // status padrão
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**O `status()` tipa o corpo.** Com schemas de resposta, `ctx.status()` só aceita os status declarados, e o `json()`/`send()` seguinte exige o corpo daquele status. `ctx.status(202).json({ result })` e `ctx.status(201)` são erros de compilação no exemplo acima.
|
|
256
|
+
|
|
257
|
+
Estilo recomendado:
|
|
258
|
+
- `return` para o caso comum;
|
|
259
|
+
- `ctx.status(x).json(body)` quando o status é decidido em runtime;
|
|
260
|
+
- `throw` para erros.
|
|
261
|
+
|
|
262
|
+
Os schemas de resposta valem para o que o **handler** envia. Middlewares e guards que respondem antes dele (manutenção, cache, 401), as respostas de erro e os 404/405 do framework não passam pelo schema da rota.
|
|
263
|
+
|
|
264
|
+
### Helpers do `ctx`
|
|
174
265
|
|
|
175
266
|
| Método | Uso |
|
|
176
267
|
|---|---|
|
|
177
268
|
| `ctx.status(code)` | Define o status |
|
|
178
269
|
| `ctx.header(name, value)` | Define um header da resposta |
|
|
179
270
|
| `ctx.get(name)` | Lê um header da requisição |
|
|
180
|
-
| `ctx.json(data)` | JSON
|
|
181
|
-
| `ctx.text(str)` | `text/plain; charset=utf-8
|
|
182
|
-
| `ctx.send(body, contentType?)` |
|
|
271
|
+
| `ctx.json(data)` | Envia JSON pelo pipeline (schema, filtro, status padrão) |
|
|
272
|
+
| `ctx.text(str)` | `text/plain; charset=utf-8`, pelo pipeline |
|
|
273
|
+
| `ctx.send(body, contentType?)` | Qualquer corpo pelo pipeline: string, bytes, stream ou objeto (negociado pelo `Accept`) |
|
|
183
274
|
| `ctx.redirect(url, status?)` | 302 por padrão; aceita 301, 303, 307, 308 |
|
|
184
275
|
| `ctx.throw(status, message)` | Lança um `HttpError` |
|
|
185
276
|
|
|
@@ -199,7 +290,7 @@ app.use(async (ctx, next) => {
|
|
|
199
290
|
});
|
|
200
291
|
```
|
|
201
292
|
|
|
202
|
-
Por classe ou por método, use `@
|
|
293
|
+
Por classe ou por método, use `@Middlewares` e `@Guards`; para um grupo inteiro ou uma rota manual, use as opções `middlewares` e `guards`, com os mesmos nomes em todos os níveis. Um guard retorna `true` para seguir, `false` para responder 403, ou lança um `HttpError` (por exemplo, `unauthorized()` para 401).
|
|
203
294
|
|
|
204
295
|
```ts
|
|
205
296
|
declare module 'sashiko' {
|
|
@@ -212,10 +303,10 @@ const authenticate: Middleware = async (ctx, next) => {
|
|
|
212
303
|
};
|
|
213
304
|
const isAdmin: Guard = (ctx) => ctx.state.user?.role === 'admin';
|
|
214
305
|
|
|
215
|
-
@
|
|
306
|
+
@Middlewares(authenticate)
|
|
216
307
|
@Router('/admin')
|
|
217
308
|
class AdminRoutes {
|
|
218
|
-
@
|
|
309
|
+
@Guards(isAdmin)
|
|
219
310
|
@Delete('/users/:id')
|
|
220
311
|
remove() {}
|
|
221
312
|
}
|
|
@@ -224,13 +315,14 @@ class AdminRoutes {
|
|
|
224
315
|
**Ordem de execução:**
|
|
225
316
|
|
|
226
317
|
```
|
|
227
|
-
globais →
|
|
228
|
-
|
|
318
|
+
globais → mount.middlewares → @Middlewares (classe → método) → rota manual.middlewares
|
|
319
|
+
→ mount.guards → @Guards (classe → método) → rota manual.guards
|
|
320
|
+
→ validação → handler
|
|
229
321
|
```
|
|
230
322
|
|
|
231
|
-
**Ordem dos decorators no código.** `@Router`, `@Get`/`@Post`/…, `@Schema`, `@
|
|
323
|
+
**Ordem dos decorators no código.** `@Router`, `@Get`/`@Post`/…, `@Schema`, `@Middlewares` e `@Guards` só registram metadata, então a posição entre eles não muda o comportamento; a única regra é que vários `@Middlewares` (ou `@Guards`) executam na ordem em que aparecem, de cima para baixo. Já decorators que **envolvem** o método, como `@timer()`, medem tudo o que estiver abaixo deles.
|
|
232
324
|
|
|
233
|
-
Os guards rodam **antes** da validação: quem não tem acesso recebe 401/403, e não um 400 que revelaria o formato esperado.
|
|
325
|
+
Os guards rodam **antes** da validação: quem não tem acesso recebe 401/403, e não um 400 que revelaria o formato esperado.
|
|
234
326
|
|
|
235
327
|
## Erros
|
|
236
328
|
|
|
@@ -252,7 +344,7 @@ Ligado por padrão:
|
|
|
252
344
|
|
|
253
345
|
| Proteção | Detalhe |
|
|
254
346
|
|---|---|
|
|
255
|
-
| Headers de segurança | `X-Content-Type-Options: nosniff`, `Content-Security-Policy: default-src 'none'; frame-ancestors 'none'`, `Referrer-Policy: no-referrer`, `X-Frame-Options: DENY`, `Cross-Origin-Resource-Policy: same-origin`. HSTS é opt-in. |
|
|
347
|
+
| Headers de segurança | `X-Content-Type-Options: nosniff`, `Content-Security-Policy: default-src 'none'; frame-ancestors 'none'`, `Referrer-Policy: no-referrer`, `X-Frame-Options: DENY`, `Cross-Origin-Resource-Policy: same-origin`. HSTS é opt-in. Para servir páginas, use `securityHeaders: 'web'` (CSP `default-src 'self'`, `X-Frame-Options: SAMEORIGIN`). |
|
|
256
348
|
| Limite de body | 1 MiB (`bodyLimit`). Recusado já pelo `Content-Length`, com a conexão fechada. |
|
|
257
349
|
| Timeouts | `requestTimeout` 30s, `headersTimeout` 10s, `keepAliveTimeout` 5s (contra Slowloris). |
|
|
258
350
|
| Query | Até 1000 pares (`queryMaxKeys`); `__proto__`, `constructor` e `prototype` são descartados. |
|
|
@@ -296,17 +388,28 @@ createApp({ logger: pino(), logRequests: true });
|
|
|
296
388
|
```ts
|
|
297
389
|
const app = createApp().mount(UserRoutes);
|
|
298
390
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
process.on('SIGTERM', async () => {
|
|
302
|
-
await app.close(); // para de aceitar conexões e espera as requisições em andamento
|
|
303
|
-
process.exit(0);
|
|
304
|
-
});
|
|
391
|
+
await app.listen({ port: 3000, host: '0.0.0.0' }); // resolve quando está ouvindo; SIGINT/SIGTERM já tratados
|
|
305
392
|
|
|
306
|
-
// Servidor próprio (HTTPS, http2 em modo compat…)
|
|
393
|
+
// Servidor próprio (HTTPS, http2 em modo compat…): aqui o ciclo de vida é seu
|
|
307
394
|
https.createServer(tlsOptions, app.callback()).listen(443);
|
|
308
395
|
```
|
|
309
396
|
|
|
397
|
+
**Encerramento gracioso, sem código.** Com `listen()`, um SIGINT ou SIGTERM faz o app parar de aceitar conexões, esperar as requisições em andamento (com prazo) e sair com código 0:
|
|
398
|
+
|
|
399
|
+
```ts
|
|
400
|
+
createApp({
|
|
401
|
+
shutdown: {
|
|
402
|
+
timeoutMs: 10_000, // prazo para as requisições em andamento (padrão)
|
|
403
|
+
onShutdown: async () => { await db.close(); }, // depois que o servidor fecha
|
|
404
|
+
},
|
|
405
|
+
});
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
- **Segundo sinal:** força a saída com código 1 (o Ctrl+C duplo). Um erro no `onShutdown` também sai com 1.
|
|
409
|
+
- **Vários apps no mesmo processo:** compartilham um único listener por sinal e fecham todos juntos.
|
|
410
|
+
- **Limpeza:** os listeners são removidos no `close()`, então testes com vários `listen(0)` não acumulam listeners. O `inject()` e o `callback()` não registram nada.
|
|
411
|
+
- **Opções:** `signals` muda os sinais tratados, `exit: false` fecha sem chamar `process.exit`, e `shutdown: false` desliga tudo (por exemplo, se outra ferramenta controla o processo).
|
|
412
|
+
|
|
310
413
|
**Testes sem rede.** `app.inject()` executa a requisição em memória:
|
|
311
414
|
|
|
312
415
|
```ts
|
|
@@ -322,13 +425,15 @@ assert.equal(res.json<{ name: string }>().name, 'Ana');
|
|
|
322
425
|
| `bodyLimit` | `1048576` | Tamanho máximo do body JSON, em bytes |
|
|
323
426
|
| `queryMaxKeys` | `1000` | Máximo de pares lidos da query string |
|
|
324
427
|
| `requireSchemas` | `false` | Exige schemas de body e de resposta no registro das rotas |
|
|
325
|
-
| `securityHeaders` |
|
|
428
|
+
| `securityHeaders` | `'api'` | `'api'`, `'web'`, um objeto de opções, ou `false` para desligar |
|
|
429
|
+
| `serializers` | — | Serializadores por content type, para responder em outros formatos |
|
|
430
|
+
| `shutdown` | SIGINT/SIGTERM, 10s | `signals`, `timeoutMs`, `onShutdown`, `exit`; `false` desliga |
|
|
326
431
|
| `timeouts` | 30s / 10s / 5s | `requestTimeout`, `headersTimeout`, `keepAliveTimeout` |
|
|
327
432
|
| `logger` | `consoleLogger()` | Logger compatível com pino; `false` desliga |
|
|
328
433
|
| `logRequests` | `false` | Log de cada requisição concluída |
|
|
329
434
|
| `requestId` | header `x-request-id` | `header`, `trustIncoming`, `generate` |
|
|
330
435
|
|
|
331
|
-
Métodos do app: `use()`, `mount()`, `onError()`, `listen()`, `close()`, `callback()`, `inject()`, `log`.
|
|
436
|
+
Métodos do app: `use()`, `mount()`, `onError()`, `listen()`, `close()`, `callback()`, `inject()`, `log`. O `mount()` devolve um `MountedGroup`, com os verbos do mapeamento manual e os mesmos métodos do app, para continuar o encadeamento.
|
|
332
437
|
|
|
333
438
|
O body só é lido como JSON quando o `Content-Type` é `application/json` ou `application/*+json`.
|
|
334
439
|
|
|
@@ -347,7 +452,7 @@ O body só é lido como JSON quando o `Content-Type` é `application/json` ou `a
|
|
|
347
452
|
|
|
348
453
|
## Exemplo completo
|
|
349
454
|
|
|
350
|
-
[`examples/app-users`](examples/app-users) traz CRUD, composição com `app.mount()`, guards, CORS, rate limit, logger, herança e injeção de dependências, além de um script que percorre todos os cenários:
|
|
455
|
+
[`examples/app-users`](examples/app-users) traz CRUD, composição com `app.mount()`, mapeamento manual, guards, CORS, rate limit, logger, herança e injeção de dependências, além de um script que percorre todos os cenários:
|
|
351
456
|
|
|
352
457
|
```bash
|
|
353
458
|
pnpm dev
|
package/dist/core/app.d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import http from 'node:http';
|
|
2
2
|
import { type MountOptions } from './compiler.ts';
|
|
3
|
+
import { MountedGroup } from './mounted-group.ts';
|
|
3
4
|
import { type Middleware } from './compose.ts';
|
|
4
5
|
import { Context } from './context.ts';
|
|
5
6
|
import '../shims/symbol-metadata.ts';
|
|
7
|
+
import { type Serializer } from './response.ts';
|
|
6
8
|
import { type InjectOptions, type InjectResponse } from './inject.ts';
|
|
9
|
+
import { type ShutdownOptions } from './shutdown.ts';
|
|
7
10
|
import { type Logger } from './logger.ts';
|
|
8
|
-
import { type SecurityHeadersOptions } from '../middlewares/security-headers.ts';
|
|
11
|
+
import { type SecurityHeadersOptions, type SecurityPreset } from '../middlewares/security-headers.ts';
|
|
9
12
|
export interface ListenOptions {
|
|
10
13
|
/** Padrão: 3000. Use 0 para uma porta livre aleatória. */
|
|
11
14
|
port?: number;
|
|
@@ -23,8 +26,16 @@ export interface ServerTimeouts {
|
|
|
23
26
|
export interface AppOptions {
|
|
24
27
|
/** Tamanho máximo do body JSON em bytes. Padrão: 1 MiB. */
|
|
25
28
|
bodyLimit?: number;
|
|
26
|
-
/**
|
|
27
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Headers de segurança aplicados a toda resposta (S-04). Padrão: `'api'`.
|
|
31
|
+
* `'web'` libera recursos do próprio site (CSP `'self'`) para quem serve páginas; `false` desliga.
|
|
32
|
+
*/
|
|
33
|
+
securityHeaders?: SecurityHeadersOptions | SecurityPreset | false;
|
|
34
|
+
/**
|
|
35
|
+
* Serializadores por content type, para responder em outros formatos (F-31):
|
|
36
|
+
* `{ 'application/yaml': (data) => YAML.stringify(data) }`. JSON e valores crus já são nativos.
|
|
37
|
+
*/
|
|
38
|
+
serializers?: Record<string, Serializer>;
|
|
28
39
|
/** Timeouts do servidor HTTP (S-06). */
|
|
29
40
|
timeouts?: ServerTimeouts;
|
|
30
41
|
/**
|
|
@@ -40,6 +51,11 @@ export interface AppOptions {
|
|
|
40
51
|
logRequests?: boolean;
|
|
41
52
|
/** Request id (F-06). */
|
|
42
53
|
requestId?: RequestIdOptions;
|
|
54
|
+
/**
|
|
55
|
+
* Encerramento gracioso nos sinais do processo, ativado pelo `listen()` (F-07).
|
|
56
|
+
* Ligado por padrão (SIGINT/SIGTERM, 10s); `false` desliga.
|
|
57
|
+
*/
|
|
58
|
+
shutdown?: ShutdownOptions | false;
|
|
43
59
|
}
|
|
44
60
|
export interface RequestIdOptions {
|
|
45
61
|
/** Header lido da requisição e devolvido na resposta. Padrão: `x-request-id`. `false` não envia. */
|
|
@@ -58,7 +74,11 @@ export declare class SashikoApp {
|
|
|
58
74
|
private errorHandlers;
|
|
59
75
|
private applySecurityHeaders;
|
|
60
76
|
private readonly opts;
|
|
77
|
+
private readonly serializers;
|
|
61
78
|
private server;
|
|
79
|
+
/** Respostas em andamento, para o encerramento gracioso não travar em conexões keep-alive. */
|
|
80
|
+
private readonly inflight;
|
|
81
|
+
private closing;
|
|
62
82
|
/** Logger do app (F-06). Use para logs fora de uma requisição. */
|
|
63
83
|
readonly log: Logger;
|
|
64
84
|
constructor(opts?: AppOptions);
|
|
@@ -71,11 +91,13 @@ export declare class SashikoApp {
|
|
|
71
91
|
* ```ts
|
|
72
92
|
* app
|
|
73
93
|
* .mount(HealthRoutes)
|
|
74
|
-
* .mount(new UserRoutes(repo), { prefix: '/v2/users', middlewares: [auth], except: [
|
|
94
|
+
* .mount(new UserRoutes(repo), { prefix: '/v2/users', middlewares: [auth], except: (r) => [r.remove] })
|
|
95
|
+
* .get('/legacy/:id', (r) => r.getUser); // mapeamento manual (F-30)
|
|
75
96
|
* ```
|
|
76
97
|
*/
|
|
77
|
-
mount<T extends object>(ref: new () => T, options?: MountOptions<T>):
|
|
78
|
-
mount<T extends object>(ref: T extends abstract new (...args: never) => unknown ? never : T, options?: MountOptions<T>):
|
|
98
|
+
mount<T extends object>(ref: new () => T, options?: MountOptions<T>): MountedGroup<T>;
|
|
99
|
+
mount<T extends object>(ref: T extends abstract new (...args: never) => unknown ? never : T, options?: MountOptions<T>): MountedGroup<T>;
|
|
100
|
+
private addRoute;
|
|
79
101
|
handle(ctx: Context): Promise<void>;
|
|
80
102
|
/**
|
|
81
103
|
* Executa os `onError` do usuário. Se um deles lançar, o erro é logado e seguimos
|
|
@@ -89,6 +111,8 @@ export declare class SashikoApp {
|
|
|
89
111
|
callback(): (req: http.IncomingMessage, res: http.ServerResponse) => void;
|
|
90
112
|
/** Sobe o servidor HTTP e resolve quando ele está aceitando conexões (F-09). */
|
|
91
113
|
listen(options?: number | ListenOptions): Promise<http.Server>;
|
|
114
|
+
/** Ponte entre este app e o coordenador de sinais (F-07). */
|
|
115
|
+
private readonly shutdownTarget;
|
|
92
116
|
/**
|
|
93
117
|
* Para de aceitar conexões, encerra as ociosas e espera as requisições em andamento terminarem.
|
|
94
118
|
* Depois de `graceMs`, força o fechamento das restantes.
|
package/dist/core/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/core/app.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/core/app.ts"],"names":[],"mappings":"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"}
|
package/dist/core/app.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import http from 'node:http';
|
|
3
3
|
import { performance } from 'node:perf_hooks';
|
|
4
|
-
import {
|
|
4
|
+
import { compileAutoRoutes, compileManualRoute, createGroup } from './compiler.js';
|
|
5
|
+
import { MountedGroup } from './mounted-group.js';
|
|
5
6
|
import { compose } from './compose.js';
|
|
6
|
-
import { Context } from './context.js';
|
|
7
|
+
import { Context, kBindResponse, kRawSend } from './context.js';
|
|
7
8
|
import '../shims/symbol-metadata.js';
|
|
8
9
|
import { bodyParser } from './body-parser.js';
|
|
9
10
|
import { assertSchemas, validateRequest } from './request-validation.js';
|
|
10
11
|
import { sendError, sendResult } from './response.js';
|
|
11
12
|
import { RouteTable } from './route-table.js';
|
|
13
|
+
import { mediaType } from '../utils/content-type.js';
|
|
12
14
|
import { inject } from './inject.js';
|
|
13
15
|
import { guardsMiddleware } from './guard.js';
|
|
16
|
+
import { shutdownCoordinator } from './shutdown.js';
|
|
14
17
|
import { consoleLogger, silentLogger } from './logger.js';
|
|
15
18
|
import { buildSecurityHeaders } from '../middlewares/security-headers.js';
|
|
16
19
|
const SAFE_REQUEST_ID = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
@@ -20,12 +23,23 @@ export class SashikoApp {
|
|
|
20
23
|
errorHandlers = [];
|
|
21
24
|
applySecurityHeaders;
|
|
22
25
|
opts;
|
|
26
|
+
serializers;
|
|
23
27
|
server;
|
|
28
|
+
/** Respostas em andamento, para o encerramento gracioso não travar em conexões keep-alive. */
|
|
29
|
+
inflight = new Set();
|
|
30
|
+
closing;
|
|
24
31
|
/** Logger do app (F-06). Use para logs fora de uma requisição. */
|
|
25
32
|
log;
|
|
26
33
|
constructor(opts = {}) {
|
|
27
34
|
this.opts = opts;
|
|
35
|
+
this.serializers = new Map(Object.entries(opts.serializers ?? {}).map(([type, fn]) => [mediaType(type), fn]));
|
|
28
36
|
this.log = opts.logger === false ? silentLogger : (opts.logger ?? consoleLogger());
|
|
37
|
+
const sd = opts.shutdown || {};
|
|
38
|
+
Object.assign(this.shutdownTarget, {
|
|
39
|
+
log: this.log,
|
|
40
|
+
signals: sd.signals ?? ['SIGINT', 'SIGTERM'],
|
|
41
|
+
exitOnShutdown: sd.exit ?? true,
|
|
42
|
+
});
|
|
29
43
|
if (opts.securityHeaders !== false)
|
|
30
44
|
this.applySecurityHeaders = buildSecurityHeaders(opts.securityHeaders);
|
|
31
45
|
this.use(bodyParser(opts.bodyLimit ?? 1024 * 1024));
|
|
@@ -39,19 +53,21 @@ export class SashikoApp {
|
|
|
39
53
|
return this;
|
|
40
54
|
}
|
|
41
55
|
mount(ref, options = {}) {
|
|
42
|
-
const
|
|
43
|
-
for (const route of
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
const group = createGroup(ref, options);
|
|
57
|
+
for (const route of compileAutoRoutes(group))
|
|
58
|
+
this.addRoute(group.name, route);
|
|
59
|
+
return new MountedGroup(this, group, (g, method, path, select, opts) => this.addRoute(g.name, compileManualRoute(g, method, path, select, opts)));
|
|
60
|
+
}
|
|
61
|
+
addRoute(owner, route) {
|
|
62
|
+
if (this.opts.requireSchemas)
|
|
63
|
+
assertSchemas(owner, route);
|
|
64
|
+
try {
|
|
65
|
+
this.router.on(route.method, route.path, route);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
throw new Error(`[sashiko] app.mount(${owner}): ${route.method} ${route.path} is already registered. ` +
|
|
69
|
+
`Use a different "prefix" to mount the same class twice.`, { cause: err });
|
|
53
70
|
}
|
|
54
|
-
return this;
|
|
55
71
|
}
|
|
56
72
|
async handle(ctx) {
|
|
57
73
|
// Antes de tudo, para valer inclusive em erros, 404 e preflight (S-04).
|
|
@@ -68,12 +84,14 @@ export class SashikoApp {
|
|
|
68
84
|
// F-08: OPTIONS automático para qualquer path com rotas.
|
|
69
85
|
if (ctx.method === 'OPTIONS')
|
|
70
86
|
return void ctx.status(204).res.end();
|
|
71
|
-
|
|
87
|
+
ctx.res.statusCode = 405;
|
|
88
|
+
return void ctx[kRawSend](JSON.stringify({ error: 'Method Not Allowed', allowed }), 'application/json; charset=utf-8');
|
|
72
89
|
}
|
|
73
|
-
|
|
90
|
+
ctx.res.statusCode = 404;
|
|
91
|
+
return void ctx[kRawSend](JSON.stringify({ error: 'Not Found' }), 'application/json; charset=utf-8');
|
|
74
92
|
}
|
|
75
93
|
ctx.params = match.params;
|
|
76
|
-
// F-01:
|
|
94
|
+
// F-01: middlewares → guards → validação → handler. Guards antes da validação, para que
|
|
77
95
|
// quem não tem acesso receba 401/403 e não um 400 que revele a estrutura esperada.
|
|
78
96
|
const route = match;
|
|
79
97
|
const pipeline = [...route.middlewares];
|
|
@@ -81,9 +99,11 @@ export class SashikoApp {
|
|
|
81
99
|
pipeline.push(guardsMiddleware(route.guards));
|
|
82
100
|
pipeline.push(async () => {
|
|
83
101
|
validateRequest(ctx, route.schemas);
|
|
102
|
+
// F-32: a partir daqui, ctx.json/send/text passam pelo mesmo pipeline do `return`.
|
|
103
|
+
ctx[kBindResponse](route.schemas.response, this.serializers);
|
|
84
104
|
const result = await route.handler(ctx);
|
|
85
105
|
if (!ctx.sent)
|
|
86
|
-
sendResult(ctx, route.schemas.response, result);
|
|
106
|
+
sendResult(ctx, route.schemas.response, result, this.serializers);
|
|
87
107
|
});
|
|
88
108
|
await compose(ctx, pipeline);
|
|
89
109
|
}
|
|
@@ -120,6 +140,14 @@ export class SashikoApp {
|
|
|
120
140
|
const generate = rid.generate ?? (() => randomUUID());
|
|
121
141
|
return (req, res) => {
|
|
122
142
|
const started = performance.now();
|
|
143
|
+
this.inflight.add(res);
|
|
144
|
+
if (this.closing)
|
|
145
|
+
res.setHeader('Connection', 'close');
|
|
146
|
+
res.once('close', () => {
|
|
147
|
+
this.inflight.delete(res);
|
|
148
|
+
// Durante o close(), cada resposta concluída libera as conexões que ficaram ociosas.
|
|
149
|
+
this.closing?.closeIdleConnections();
|
|
150
|
+
});
|
|
123
151
|
const incoming = header ? req.headers[header] : undefined;
|
|
124
152
|
const id = trust && typeof incoming === 'string' && SAFE_REQUEST_ID.test(incoming) ? incoming : generate();
|
|
125
153
|
if (header)
|
|
@@ -165,8 +193,28 @@ export class SashikoApp {
|
|
|
165
193
|
});
|
|
166
194
|
});
|
|
167
195
|
this.server = server;
|
|
196
|
+
if (this.opts.shutdown !== false)
|
|
197
|
+
shutdownCoordinator.register(this.shutdownTarget);
|
|
168
198
|
return server;
|
|
169
199
|
}
|
|
200
|
+
/** Ponte entre este app e o coordenador de sinais (F-07). */
|
|
201
|
+
shutdownTarget = {
|
|
202
|
+
log: undefined, // definido no construtor
|
|
203
|
+
signals: [],
|
|
204
|
+
exitOnShutdown: true,
|
|
205
|
+
shutdown: async (signal) => {
|
|
206
|
+
const opts = this.opts.shutdown || {};
|
|
207
|
+
try {
|
|
208
|
+
await this.close(opts.timeoutMs ?? 10_000);
|
|
209
|
+
await opts.onShutdown?.(signal);
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
this.log.error({ err, signal }, 'error during graceful shutdown');
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
};
|
|
170
218
|
/**
|
|
171
219
|
* Para de aceitar conexões, encerra as ociosas e espera as requisições em andamento terminarem.
|
|
172
220
|
* Depois de `graceMs`, força o fechamento das restantes.
|
|
@@ -176,6 +224,11 @@ export class SashikoApp {
|
|
|
176
224
|
if (!server)
|
|
177
225
|
return;
|
|
178
226
|
this.server = undefined;
|
|
227
|
+
this.closing = server;
|
|
228
|
+
// Respostas que ainda não enviaram headers avisam o cliente para não reusar a conexão.
|
|
229
|
+
for (const res of this.inflight)
|
|
230
|
+
if (!res.headersSent)
|
|
231
|
+
res.setHeader('Connection', 'close');
|
|
179
232
|
const force = setTimeout(() => server.closeAllConnections(), graceMs);
|
|
180
233
|
force.unref();
|
|
181
234
|
try {
|
|
@@ -186,6 +239,8 @@ export class SashikoApp {
|
|
|
186
239
|
}
|
|
187
240
|
finally {
|
|
188
241
|
clearTimeout(force);
|
|
242
|
+
this.closing = undefined;
|
|
243
|
+
shutdownCoordinator.unregister(this.shutdownTarget);
|
|
189
244
|
}
|
|
190
245
|
}
|
|
191
246
|
/** Executa uma requisição em memória, sem rede. Ideal para testes (F-09). */
|
package/dist/core/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/core/app.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/core/app.ts"],"names":[],"mappings":"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"}
|
package/dist/core/compiler.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Guard } from './guard.ts';
|
|
2
2
|
import type { Middleware } from './compose.ts';
|
|
3
|
+
import { type RouterMetadata } from './metadata.ts';
|
|
3
4
|
import type { RouteDefinition } from './route-table.ts';
|
|
4
5
|
export interface CompiledRoute extends RouteDefinition {
|
|
5
6
|
method: string;
|
|
@@ -7,22 +8,45 @@ export interface CompiledRoute extends RouteDefinition {
|
|
|
7
8
|
}
|
|
8
9
|
/** Classe com construtor sem argumentos **ou** instância já construída (B-10). */
|
|
9
10
|
export type RouterRef = (new () => object) | object;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
type AnyMethod = (...args: never[]) => unknown;
|
|
12
|
+
/** Seleciona um método da instância montada: `(r) => r.getUser` (F-30). */
|
|
13
|
+
export type MethodSelector<T> = (routes: T) => AnyMethod;
|
|
14
|
+
/** Seleciona vários métodos: `(r) => [r.list, r.getUser]` (F-30). */
|
|
15
|
+
export type MethodsSelector<T> = (routes: T) => readonly AnyMethod[];
|
|
16
|
+
/** Opções de `app.mount()`, aplicadas no ponto de composição (F-28, F-30). */
|
|
15
17
|
export interface MountOptions<T = object> {
|
|
16
18
|
/** Substitui o prefixo definido no `@Router`. */
|
|
17
19
|
prefix?: string;
|
|
18
20
|
/** Registra só estes métodos de rota. Não pode ser usado junto com `except`. */
|
|
19
|
-
only?:
|
|
21
|
+
only?: MethodsSelector<T>;
|
|
20
22
|
/** Registra todos os métodos de rota, exceto estes. */
|
|
21
|
-
except?:
|
|
22
|
-
/**
|
|
23
|
+
except?: MethodsSelector<T>;
|
|
24
|
+
/** Registra as rotas declaradas na classe. Padrão: `true`. Use `false` para só mapear manualmente. */
|
|
25
|
+
auto?: boolean;
|
|
26
|
+
/** Middlewares para todas as rotas do grupo; rodam antes dos `@Middlewares` da classe. */
|
|
23
27
|
middlewares?: readonly Middleware[];
|
|
24
|
-
/** Guards para todas as rotas
|
|
28
|
+
/** Guards para todas as rotas do grupo; rodam antes dos `@Guards` da classe. */
|
|
25
29
|
guards?: readonly Guard[];
|
|
26
30
|
}
|
|
27
|
-
|
|
31
|
+
/** Opções de uma rota mapeada manualmente: `.get(path, sel, { middlewares, guards })` (F-30). */
|
|
32
|
+
export interface ManualRouteOptions {
|
|
33
|
+
/** Rodam depois dos `@Middlewares` do método (são as mais específicas). */
|
|
34
|
+
middlewares?: readonly Middleware[];
|
|
35
|
+
/** Rodam depois dos `@Guards` do método. */
|
|
36
|
+
guards?: readonly Guard[];
|
|
37
|
+
}
|
|
38
|
+
/** Um grupo montado: a instância, sua metadata e as opções do `mount`. */
|
|
39
|
+
export interface RouteGroup {
|
|
40
|
+
name: string;
|
|
41
|
+
instance: object;
|
|
42
|
+
meta: RouterMetadata;
|
|
43
|
+
prefix: string;
|
|
44
|
+
options: MountOptions;
|
|
45
|
+
}
|
|
46
|
+
export declare function createGroup(ref: RouterRef, options?: MountOptions): RouteGroup;
|
|
47
|
+
/** Rotas declaradas na classe (`@Get`, `@Post`…), filtradas por `only`/`except` e `auto`. */
|
|
48
|
+
export declare function compileAutoRoutes(group: RouteGroup): CompiledRoute[];
|
|
49
|
+
/** Rota mapeada no app: `.get('/legacy/:id', (r) => r.getUser, opts)` (F-30). */
|
|
50
|
+
export declare function compileManualRoute(group: RouteGroup, httpMethod: string, path: string, selector: MethodSelector<object>, options?: ManualRouteOptions): CompiledRoute;
|
|
51
|
+
export {};
|
|
28
52
|
//# sourceMappingURL=compiler.d.ts.map
|