flowingts 0.0.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +74 -3
  3. package/dist/core/abort.d.ts +23 -0
  4. package/dist/core/abort.d.ts.map +1 -0
  5. package/dist/core/abort.js +23 -0
  6. package/dist/core/abort.js.map +1 -0
  7. package/dist/core/app/core.d.ts +35 -0
  8. package/dist/core/app/core.d.ts.map +1 -0
  9. package/dist/core/app/core.js +2 -0
  10. package/dist/core/app/core.js.map +1 -0
  11. package/dist/core/app/options.d.ts +178 -0
  12. package/dist/core/app/options.d.ts.map +1 -0
  13. package/dist/core/app/options.js +2 -0
  14. package/dist/core/app/options.js.map +1 -0
  15. package/dist/core/app.d.ts +143 -0
  16. package/dist/core/app.d.ts.map +1 -0
  17. package/dist/core/app.js +283 -0
  18. package/dist/core/app.js.map +1 -0
  19. package/dist/core/body-parser.d.ts +14 -0
  20. package/dist/core/body-parser.d.ts.map +1 -0
  21. package/dist/core/body-parser.js +76 -0
  22. package/dist/core/body-parser.js.map +1 -0
  23. package/dist/core/compiler.d.ts +104 -0
  24. package/dist/core/compiler.d.ts.map +1 -0
  25. package/dist/core/compiler.js +151 -0
  26. package/dist/core/compiler.js.map +1 -0
  27. package/dist/core/compose.d.ts +16 -0
  28. package/dist/core/compose.d.ts.map +1 -0
  29. package/dist/core/compose.js +41 -0
  30. package/dist/core/compose.js.map +1 -0
  31. package/dist/core/context.d.ts +290 -0
  32. package/dist/core/context.d.ts.map +1 -0
  33. package/dist/core/context.js +460 -0
  34. package/dist/core/context.js.map +1 -0
  35. package/dist/core/contracts.d.ts +76 -0
  36. package/dist/core/contracts.d.ts.map +1 -0
  37. package/dist/core/contracts.js +87 -0
  38. package/dist/core/contracts.js.map +1 -0
  39. package/dist/core/errors.d.ts +50 -0
  40. package/dist/core/errors.d.ts.map +1 -0
  41. package/dist/core/errors.js +25 -0
  42. package/dist/core/errors.js.map +1 -0
  43. package/dist/core/guard.d.ts +10 -0
  44. package/dist/core/guard.d.ts.map +1 -0
  45. package/dist/core/guard.js +14 -0
  46. package/dist/core/guard.js.map +1 -0
  47. package/dist/core/health.d.ts +37 -0
  48. package/dist/core/health.d.ts.map +1 -0
  49. package/dist/core/health.js +68 -0
  50. package/dist/core/health.js.map +1 -0
  51. package/dist/core/hooks.d.ts +34 -0
  52. package/dist/core/hooks.d.ts.map +1 -0
  53. package/dist/core/hooks.js +27 -0
  54. package/dist/core/hooks.js.map +1 -0
  55. package/dist/core/index.d.ts +30 -0
  56. package/dist/core/index.d.ts.map +1 -0
  57. package/dist/core/index.js +11 -0
  58. package/dist/core/index.js.map +1 -0
  59. package/dist/core/infer.d.ts +68 -0
  60. package/dist/core/infer.d.ts.map +1 -0
  61. package/dist/core/infer.js +2 -0
  62. package/dist/core/infer.js.map +1 -0
  63. package/dist/core/inject.d.ts +27 -0
  64. package/dist/core/inject.d.ts.map +1 -0
  65. package/dist/core/inject.js +85 -0
  66. package/dist/core/inject.js.map +1 -0
  67. package/dist/core/logger.d.ts +57 -0
  68. package/dist/core/logger.d.ts.map +1 -0
  69. package/dist/core/logger.js +134 -0
  70. package/dist/core/logger.js.map +1 -0
  71. package/dist/core/metadata.d.ts +83 -0
  72. package/dist/core/metadata.d.ts.map +1 -0
  73. package/dist/core/metadata.js +91 -0
  74. package/dist/core/metadata.js.map +1 -0
  75. package/dist/core/mounted-group.d.ts +77 -0
  76. package/dist/core/mounted-group.d.ts.map +1 -0
  77. package/dist/core/mounted-group.js +131 -0
  78. package/dist/core/mounted-group.js.map +1 -0
  79. package/dist/core/registry/framework-routes.d.ts +28 -0
  80. package/dist/core/registry/framework-routes.d.ts.map +1 -0
  81. package/dist/core/registry/framework-routes.js +83 -0
  82. package/dist/core/registry/framework-routes.js.map +1 -0
  83. package/dist/core/registry/registry.d.ts +58 -0
  84. package/dist/core/registry/registry.d.ts.map +1 -0
  85. package/dist/core/registry/registry.js +208 -0
  86. package/dist/core/registry/registry.js.map +1 -0
  87. package/dist/core/registry/route-program.d.ts +16 -0
  88. package/dist/core/registry/route-program.d.ts.map +1 -0
  89. package/dist/core/registry/route-program.js +62 -0
  90. package/dist/core/registry/route-program.js.map +1 -0
  91. package/dist/core/request-validation.d.ts +15 -0
  92. package/dist/core/request-validation.d.ts.map +1 -0
  93. package/dist/core/request-validation.js +67 -0
  94. package/dist/core/request-validation.js.map +1 -0
  95. package/dist/core/response/pipeline.d.ts +51 -0
  96. package/dist/core/response/pipeline.d.ts.map +1 -0
  97. package/dist/core/response/pipeline.js +169 -0
  98. package/dist/core/response/pipeline.js.map +1 -0
  99. package/dist/core/route-table.d.ts +58 -0
  100. package/dist/core/route-table.d.ts.map +1 -0
  101. package/dist/core/route-table.js +108 -0
  102. package/dist/core/route-table.js.map +1 -0
  103. package/dist/core/runtime/observer.d.ts +47 -0
  104. package/dist/core/runtime/observer.d.ts.map +1 -0
  105. package/dist/core/runtime/observer.js +125 -0
  106. package/dist/core/runtime/observer.js.map +1 -0
  107. package/dist/core/runtime/request-handler.d.ts +62 -0
  108. package/dist/core/runtime/request-handler.d.ts.map +1 -0
  109. package/dist/core/runtime/request-handler.js +256 -0
  110. package/dist/core/runtime/request-handler.js.map +1 -0
  111. package/dist/core/runtime/server.d.ts +59 -0
  112. package/dist/core/runtime/server.d.ts.map +1 -0
  113. package/dist/core/runtime/server.js +180 -0
  114. package/dist/core/runtime/server.js.map +1 -0
  115. package/dist/core/shutdown.d.ts +41 -0
  116. package/dist/core/shutdown.d.ts.map +1 -0
  117. package/dist/core/shutdown.js +53 -0
  118. package/dist/core/shutdown.js.map +1 -0
  119. package/dist/core/streaming/sse.d.ts +35 -0
  120. package/dist/core/streaming/sse.d.ts.map +1 -0
  121. package/dist/core/streaming/sse.js +121 -0
  122. package/dist/core/streaming/sse.js.map +1 -0
  123. package/dist/core/symbols.d.ts +28 -0
  124. package/dist/core/symbols.d.ts.map +1 -0
  125. package/dist/core/symbols.js +28 -0
  126. package/dist/core/symbols.js.map +1 -0
  127. package/dist/core/telemetry.d.ts +83 -0
  128. package/dist/core/telemetry.d.ts.map +1 -0
  129. package/dist/core/telemetry.js +96 -0
  130. package/dist/core/telemetry.js.map +1 -0
  131. package/dist/core/uploads/receive.d.ts +63 -0
  132. package/dist/core/uploads/receive.d.ts.map +1 -0
  133. package/dist/core/uploads/receive.js +342 -0
  134. package/dist/core/uploads/receive.js.map +1 -0
  135. package/dist/core/uploads/types.d.ts +79 -0
  136. package/dist/core/uploads/types.d.ts.map +1 -0
  137. package/dist/core/uploads/types.js +2 -0
  138. package/dist/core/uploads/types.js.map +1 -0
  139. package/dist/decorators/hooks.d.ts +25 -0
  140. package/dist/decorators/hooks.d.ts.map +1 -0
  141. package/dist/decorators/hooks.js +36 -0
  142. package/dist/decorators/hooks.js.map +1 -0
  143. package/dist/decorators/http.d.ts +21 -0
  144. package/dist/decorators/http.d.ts.map +1 -0
  145. package/dist/decorators/http.js +21 -0
  146. package/dist/decorators/http.js.map +1 -0
  147. package/dist/decorators/index.d.ts +7 -0
  148. package/dist/decorators/index.d.ts.map +1 -0
  149. package/dist/decorators/index.js +7 -0
  150. package/dist/decorators/index.js.map +1 -0
  151. package/dist/decorators/log.d.ts +10 -0
  152. package/dist/decorators/log.d.ts.map +1 -0
  153. package/dist/decorators/log.js +32 -0
  154. package/dist/decorators/log.js.map +1 -0
  155. package/dist/decorators/middlewares.d.ts +28 -0
  156. package/dist/decorators/middlewares.d.ts.map +1 -0
  157. package/dist/decorators/middlewares.js +40 -0
  158. package/dist/decorators/middlewares.js.map +1 -0
  159. package/dist/decorators/router.d.ts +12 -0
  160. package/dist/decorators/router.d.ts.map +1 -0
  161. package/dist/decorators/router.js +20 -0
  162. package/dist/decorators/router.js.map +1 -0
  163. package/dist/decorators/schema.d.ts +8 -0
  164. package/dist/decorators/schema.d.ts.map +1 -0
  165. package/dist/decorators/schema.js +14 -0
  166. package/dist/decorators/schema.js.map +1 -0
  167. package/dist/index.d.ts +7 -0
  168. package/dist/index.d.ts.map +1 -0
  169. package/dist/index.js +10 -0
  170. package/dist/index.js.map +1 -0
  171. package/dist/middlewares/auth.d.ts +41 -0
  172. package/dist/middlewares/auth.d.ts.map +1 -0
  173. package/dist/middlewares/auth.js +74 -0
  174. package/dist/middlewares/auth.js.map +1 -0
  175. package/dist/middlewares/cors.d.ts +30 -0
  176. package/dist/middlewares/cors.d.ts.map +1 -0
  177. package/dist/middlewares/cors.js +69 -0
  178. package/dist/middlewares/cors.js.map +1 -0
  179. package/dist/middlewares/csrf.d.ts +42 -0
  180. package/dist/middlewares/csrf.d.ts.map +1 -0
  181. package/dist/middlewares/csrf.js +70 -0
  182. package/dist/middlewares/csrf.js.map +1 -0
  183. package/dist/middlewares/index.d.ts +6 -0
  184. package/dist/middlewares/index.d.ts.map +1 -0
  185. package/dist/middlewares/index.js +6 -0
  186. package/dist/middlewares/index.js.map +1 -0
  187. package/dist/middlewares/rate-limit.d.ts +35 -0
  188. package/dist/middlewares/rate-limit.d.ts.map +1 -0
  189. package/dist/middlewares/rate-limit.js +45 -0
  190. package/dist/middlewares/rate-limit.js.map +1 -0
  191. package/dist/middlewares/security-headers.d.ts +28 -0
  192. package/dist/middlewares/security-headers.d.ts.map +1 -0
  193. package/dist/middlewares/security-headers.js +42 -0
  194. package/dist/middlewares/security-headers.js.map +1 -0
  195. package/dist/openapi/generate.d.ts +51 -0
  196. package/dist/openapi/generate.d.ts.map +1 -0
  197. package/dist/openapi/generate.js +175 -0
  198. package/dist/openapi/generate.js.map +1 -0
  199. package/dist/schema/serialization.d.ts +2 -0
  200. package/dist/schema/serialization.d.ts.map +1 -0
  201. package/dist/schema/serialization.js +11 -0
  202. package/dist/schema/serialization.js.map +1 -0
  203. package/dist/schema/validation.d.ts +22 -0
  204. package/dist/schema/validation.d.ts.map +1 -0
  205. package/dist/schema/validation.js +68 -0
  206. package/dist/schema/validation.js.map +1 -0
  207. package/dist/server/static.d.ts +45 -0
  208. package/dist/server/static.d.ts.map +1 -0
  209. package/dist/server/static.js +204 -0
  210. package/dist/server/static.js.map +1 -0
  211. package/dist/server/tls.d.ts +48 -0
  212. package/dist/server/tls.d.ts.map +1 -0
  213. package/dist/server/tls.js +60 -0
  214. package/dist/server/tls.js.map +1 -0
  215. package/dist/shims/symbol-metadata.d.ts +2 -0
  216. package/dist/shims/symbol-metadata.d.ts.map +1 -0
  217. package/dist/shims/symbol-metadata.js +8 -0
  218. package/dist/shims/symbol-metadata.js.map +1 -0
  219. package/dist/utils/content-type.d.ts +13 -0
  220. package/dist/utils/content-type.d.ts.map +1 -0
  221. package/dist/utils/content-type.js +75 -0
  222. package/dist/utils/content-type.js.map +1 -0
  223. package/dist/utils/cookie.d.ts +34 -0
  224. package/dist/utils/cookie.d.ts.map +1 -0
  225. package/dist/utils/cookie.js +94 -0
  226. package/dist/utils/cookie.js.map +1 -0
  227. package/dist/utils/index.d.ts +7 -0
  228. package/dist/utils/index.d.ts.map +1 -0
  229. package/dist/utils/index.js +7 -0
  230. package/dist/utils/index.js.map +1 -0
  231. package/dist/utils/mime.d.ts +2 -0
  232. package/dist/utils/mime.d.ts.map +1 -0
  233. package/dist/utils/mime.js +52 -0
  234. package/dist/utils/mime.js.map +1 -0
  235. package/dist/utils/origin-match.d.ts +58 -0
  236. package/dist/utils/origin-match.d.ts.map +1 -0
  237. package/dist/utils/origin-match.js +194 -0
  238. package/dist/utils/origin-match.js.map +1 -0
  239. package/dist/utils/path.d.ts +10 -0
  240. package/dist/utils/path.d.ts.map +1 -0
  241. package/dist/utils/path.js +60 -0
  242. package/dist/utils/path.js.map +1 -0
  243. package/dist/utils/query.d.ts +28 -0
  244. package/dist/utils/query.d.ts.map +1 -0
  245. package/dist/utils/query.js +67 -0
  246. package/dist/utils/query.js.map +1 -0
  247. package/dist/utils/request-target.d.ts +31 -0
  248. package/dist/utils/request-target.d.ts.map +1 -0
  249. package/dist/utils/request-target.js +80 -0
  250. package/dist/utils/request-target.js.map +1 -0
  251. package/dist/utils/safe-json.d.ts +24 -0
  252. package/dist/utils/safe-json.d.ts.map +1 -0
  253. package/dist/utils/safe-json.js +83 -0
  254. package/dist/utils/safe-json.js.map +1 -0
  255. package/dist/utils/trace-context.d.ts +17 -0
  256. package/dist/utils/trace-context.d.ts.map +1 -0
  257. package/dist/utils/trace-context.js +30 -0
  258. package/dist/utils/trace-context.js.map +1 -0
  259. package/package.json +85 -6
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 Caio Fernandes
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -1,5 +1,76 @@
1
- # Flowing
1
+ # FlowingTS
2
2
 
3
- Framework de APIs em TypeScript com decorators, contratos por rota e o básico de produção pronto.
3
+ Micro-framework HTTP para Node.js com **decorators nativos (TC39)**, **schema-first** e **seguro por padrão**.
4
4
 
5
- Esta versão `0.0.0` só reserva o nome. O projeto se chamava `sashiko`; a primeira versão funcional como `flowingts` sai em breve.
5
+ > **Por que FlowingTS:** num projeto Express que passa por muitas mãos, cada pessoa declara rotas do seu jeito, e quem chega precisa reaprender cada pedaço. O NestJS resolve a padronização, mas traz junto uma estrutura que muitos projetos não precisam. O FlowingTS dá **uma forma só de declarar rotas**, que qualquer pessoa da equipe reconhece, com o contrato de cada rota validado como no Fastify e sem tirar a liberdade do Express. O código flui igual, não importa quem o escreveu.
6
+
7
+ FlowingTS combina a flexibilidade do **Fastify** e do **Express** (middlewares simples, partes plugáveis, pouca cerimônia) com a organização em classes do **NestJS**, mantendo o núcleo pequeno: `node:http` direto e sete dependências de runtime.
8
+
9
+ ```ts
10
+ import { type Context, createApp, Post, Router, type RouteSchemas, Type } from 'flowingts';
11
+
12
+ const User = Type.Object({ id: Type.String(), name: Type.String() });
13
+ const create = {
14
+ body: Type.Object({ name: Type.String({ minLength: 1 }) }, { additionalProperties: false }),
15
+ response: { 201: User },
16
+ } satisfies RouteSchemas;
17
+
18
+ @Router('/users')
19
+ class UserRoutes {
20
+ @Post('/', create)
21
+ create(ctx: Context<typeof create>) {
22
+ return { id: crypto.randomUUID(), name: ctx.body.name }; // ctx.body tipado; responde 201
23
+ }
24
+ }
25
+
26
+ const app = createApp().mount(UserRoutes);
27
+ await app.listen({ port: 3000 });
28
+ ```
29
+
30
+ ## Documentação
31
+
32
+ **[code-cfernandes.github.io/flowing](https://code-cfernandes.github.io/flowing/)**
33
+
34
+ | | |
35
+ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
36
+ | [Introdução](https://code-cfernandes.github.io/flowing/guia/introducao) e [instalação](https://code-cfernandes.github.io/flowing/guia/instalacao) | Princípios, requisitos e o primeiro app |
37
+ | [Rotas e composição](https://code-cfernandes.github.io/flowing/guia/rotas) | `@Router`, `app.mount()`, `app.group()`, virtual hosts e mapeamento manual |
38
+ | [Schemas](https://code-cfernandes.github.io/flowing/guia/schemas) e [respostas](https://code-cfernandes.github.io/flowing/guia/respostas) | Validação, serialização, tipos do `ctx` e outros formatos |
39
+ | [Middlewares e guards](https://code-cfernandes.github.io/flowing/guia/middlewares-e-guards), [hooks](https://code-cfernandes.github.io/flowing/guia/hooks) e [erros](https://code-cfernandes.github.io/flowing/guia/erros) | O pipeline da requisição |
40
+ | [Estáticos e streaming](https://code-cfernandes.github.io/flowing/guia/estaticos-e-streaming) | Arquivos, SSE, NDJSON e `ctx.signal` |
41
+ | [OpenAPI](https://code-cfernandes.github.io/flowing/guia/openapi), [logs](https://code-cfernandes.github.io/flowing/guia/logs) e [observabilidade](https://code-cfernandes.github.io/flowing/guia/observabilidade) | Documentação da API, logs correlacionados e OpenTelemetry |
42
+ | [Segurança](https://code-cfernandes.github.io/flowing/guia/seguranca), [ciclo de vida](https://code-cfernandes.github.io/flowing/guia/ciclo-de-vida) e [deploy](https://code-cfernandes.github.io/flowing/guia/deploy) | Defaults seguros, HTTPS, healthchecks, shutdown e produção |
43
+ | [Referência](https://code-cfernandes.github.io/flowing/referencia/create-app) | `createApp(options)` e a API completa, gerada do código |
44
+
45
+ ## Instalação
46
+
47
+ - **Node.js 22+**
48
+ - **TypeScript 5.2+**, com decorators **padrão**. **Não** use `experimentalDecorators` nem `emitDecoratorMetadata`: se estiverem ligados, o FlowingTS lança um erro dizendo como corrigir. Por isso ele não convive no mesmo projeto com bibliotecas que exigem decorators legados (NestJS, TypeORM…).
49
+ - ESM (`"type": "module"`).
50
+
51
+ ```bash
52
+ pnpm add flowingts
53
+ ```
54
+
55
+ O `tsconfig.json` mínimo e os detalhes estão em [Instalação](https://code-cfernandes.github.io/flowing/guia/instalacao).
56
+
57
+ ## Desenvolvimento
58
+
59
+ ```bash
60
+ pnpm install
61
+ pnpm test # node:test + tsx
62
+ pnpm test:coverage # com limites mínimos de cobertura
63
+ pnpm typecheck
64
+ pnpm check # lint + formatação (Biome); pnpm format corrige a formatação
65
+ pnpm build # dist/
66
+ ```
67
+
68
+ Para o `git blame` ignorar o commit de formatação: `git config blame.ignoreRevsFile .git-blame-ignore-revs`.
69
+
70
+ **Publicação:** um push de tag de versão (`git tag v1.2.3 && git push origin v1.2.3`) dispara o workflow `release.yml`. Ele confere que a tag bate com o `package.json`, que o commit está na `main` e que o CHANGELOG tem a seção da versão. Depois roda as mesmas verificações do CI e envia o pacote ao npm em estágio, por Trusted Publishing, sem token e com provenance, além de criar a GitHub Release com as notas do CHANGELOG. A versão só fica pública depois da aprovação no npmjs.com, com o 2FA da conta.
71
+
72
+ Mudanças notáveis estão no [CHANGELOG](CHANGELOG.md). Para reportar uma vulnerabilidade e conhecer a política de dependências, veja o [SECURITY.md](SECURITY.md).
73
+
74
+ ## Licença
75
+
76
+ [ISC](LICENSE)
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Etapa em que a requisição estava quando um erro chegou ao `onError` (F-38). No modelo onion, um erro
3
+ * lançado depois do `await next()` de um middleware aparece com a etapa mais recente (`handler`, `response`).
4
+ * `validation` inclui a leitura do body (JSON inválido, limite de tamanho).
5
+ */
6
+ export type ErrorPhase = 'middleware' | 'guard' | 'validation' | 'handler' | 'response';
7
+ /** Por que o `ctx.signal` de uma requisição foi cancelado (F-38). */
8
+ export type AbortCode = 'CLIENT_DISCONNECTED' | 'SHUTDOWN' | 'TIMEOUT';
9
+ /**
10
+ * O `ctx.signal.reason` de uma requisição cancelada. Use o `code` para decidir em código:
11
+ *
12
+ * ```ts
13
+ * if (ctx.signal.reason?.code === 'SHUTDOWN') return; // o app está encerrando, não é erro
14
+ * ```
15
+ *
16
+ * `TIMEOUT` está reservado para um futuro timeout por rota.
17
+ */
18
+ export declare class RequestAbortedError extends Error {
19
+ readonly code: AbortCode;
20
+ readonly name = "RequestAbortedError";
21
+ constructor(code: AbortCode);
22
+ }
23
+ //# sourceMappingURL=abort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort.d.ts","sourceRoot":"","sources":["../../src/core/abort.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC;AAExF,qEAAqE;AACrE,MAAM,MAAM,SAAS,GAAG,qBAAqB,GAAG,UAAU,GAAG,SAAS,CAAC;AAQvE;;;;;;;;GAQG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAEhC,QAAQ,CAAC,IAAI,EAAE,SAAS;IADpC,SAAkB,IAAI,yBAAyB;IAC/C,YAAqB,IAAI,EAAE,SAAS,EAEnC;CACF"}
@@ -0,0 +1,23 @@
1
+ const MESSAGES = {
2
+ CLIENT_DISCONNECTED: 'client disconnected',
3
+ SHUTDOWN: 'server shutting down',
4
+ TIMEOUT: 'request timed out',
5
+ };
6
+ /**
7
+ * O `ctx.signal.reason` de uma requisição cancelada. Use o `code` para decidir em código:
8
+ *
9
+ * ```ts
10
+ * if (ctx.signal.reason?.code === 'SHUTDOWN') return; // o app está encerrando, não é erro
11
+ * ```
12
+ *
13
+ * `TIMEOUT` está reservado para um futuro timeout por rota.
14
+ */
15
+ export class RequestAbortedError extends Error {
16
+ code;
17
+ name = 'RequestAbortedError';
18
+ constructor(code) {
19
+ super(MESSAGES[code]);
20
+ this.code = code;
21
+ }
22
+ }
23
+ //# sourceMappingURL=abort.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort.js","sourceRoot":"","sources":["../../src/core/abort.ts"],"names":[],"mappings":"AAUA,MAAM,QAAQ,GAA8B;IAC1C,mBAAmB,EAAE,qBAAqB;IAC1C,QAAQ,EAAE,sBAAsB;IAChC,OAAO,EAAE,mBAAmB;CAC7B,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAEvB,IAAI;IADP,IAAI,GAAG,qBAAqB,CAAC;IAC/C,YAAqB,IAAe;QAClC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;oBADH,IAAI;IAEzB,CAAC;CACF"}
@@ -0,0 +1,35 @@
1
+ import type { UploadSettings } from '../uploads/receive.ts';
2
+ import type http from 'node:http';
3
+ import type { Middleware } from '../compose.ts';
4
+ import type { OnSendHook } from '../context.ts';
5
+ import type { Logger } from '../logger.ts';
6
+ import type { Telemetry } from '../telemetry.ts';
7
+ import type { Serializer } from '../response/pipeline.ts';
8
+ import type { AppOptions, OnCloseHook, OnErrorHook, OnRequestHook, OnResponseHook } from './options.ts';
9
+ import type { Contracts } from '../contracts.ts';
10
+ /**
11
+ * Estado compartilhado do app entre a fachada (`FlowingApp`) e os componentes internos (registro,
12
+ * servidor, pipeline da requisição). Só configuração e listas de hooks; nada por requisição.
13
+ */
14
+ export interface AppCore {
15
+ readonly opts: AppOptions;
16
+ readonly log: Logger;
17
+ readonly middlewares: Middleware[];
18
+ readonly errorHandlers: OnErrorHook[];
19
+ readonly onSendHooks: OnSendHook[];
20
+ readonly onRequestHooks: OnRequestHook[];
21
+ /** O motor dos contratos (F-27): o do app, ou o nativo. */
22
+ readonly contracts: Contracts;
23
+ /** OpenTelemetry, quando `createApp({ telemetry })` (F-38). */
24
+ readonly telemetry: Telemetry | undefined;
25
+ readonly onResponseHooks: OnResponseHook[];
26
+ /** Rotas com `onResponse` de escopo (F-43): basta uma para o observer acompanhar o fim das requisições. */
27
+ scopedOnResponse: number;
28
+ readonly onCloseHooks: OnCloseHook[];
29
+ readonly serializers: ReadonlyMap<string, Serializer>;
30
+ /** Configuração de upload (F-46), resolvida na criação do app. */
31
+ readonly uploads: UploadSettings;
32
+ readonly allowedHosts: ((hostname: string, host: string) => boolean) | undefined;
33
+ readonly applySecurityHeaders: ((res: http.ServerResponse) => void) | undefined;
34
+ }
35
+ //# sourceMappingURL=core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/core/app/core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACxG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,WAAW,EAAE,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,aAAa,EAAE,CAAC;IACzC,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,eAAe,EAAE,cAAc,EAAE,CAAC;IAC3C,2GAA2G;IAC3G,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,WAAW,EAAE,CAAC;IACrC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACtD,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;IACjF,QAAQ,CAAC,oBAAoB,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACjF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/core/app/core.ts"],"names":[],"mappings":""}
@@ -0,0 +1,178 @@
1
+ import type { UploadsOptions } from '../uploads/types.ts';
2
+ import type { AbortCode, ErrorPhase } from '../abort.ts';
3
+ import type { TelemetryApi } from '../telemetry.ts';
4
+ import type { Context } from '../context.ts';
5
+ import type { RouteInfo } from '../route-table.ts';
6
+ import type { ErrorFormatter } from '../errors.ts';
7
+ import type { Logger } from '../logger.ts';
8
+ import type { Serializer } from '../response/pipeline.ts';
9
+ import type { ShutdownOptions } from '../shutdown.ts';
10
+ import type { TlsOptions } from '../../server/tls.ts';
11
+ import type { ProtoPoisoning } from '../../utils/safe-json.ts';
12
+ import type { SecurityHeadersOptions, SecurityPreset } from '../../middlewares/security-headers.ts';
13
+ import type { QueryParser } from '../../utils/query.ts';
14
+ import type { BodyParser } from '../body-parser.ts';
15
+ import type { Contracts } from '../contracts.ts';
16
+ /**
17
+ * Tratamento de erros (F-04). `phase` diz em que etapa a requisição estava: `middleware`, `guard`,
18
+ * `validation` (inclui a leitura do body), `handler` ou `response`.
19
+ */
20
+ export type OnErrorHook = (err: unknown, ctx: Context, phase: ErrorPhase) => void | Promise<void>;
21
+ /** Como a requisição terminou, no `onResponse` (F-04, F-38). */
22
+ export interface ResponseInfo {
23
+ /** Status enviado (num cancelamento, o que estava definido quando a conexão caiu). */
24
+ status: number;
25
+ /** Duração total em milissegundos, até o fim da resposta ou o cancelamento. */
26
+ ms: number;
27
+ /** `completed`, `aborted` (cancelada antes do fim) ou `error` (respondida com 5xx). */
28
+ outcome: 'completed' | 'aborted' | 'error';
29
+ /** Por que foi cancelada, quando `outcome` é `aborted`. */
30
+ abortReason?: AbortCode;
31
+ /**
32
+ * Milissegundos até os headers saírem. Em SSE e NDJSON, é a latência real; `ms` mede a conexão inteira.
33
+ * Medido nos servidores do `listen()` e no `inject()`; ausente num servidor próprio (`callback()`).
34
+ */
35
+ ttfbMs?: number;
36
+ /** Resposta em stream: SSE, NDJSON, `Readable` ou arquivo. */
37
+ streaming: boolean;
38
+ /** A rota que atendeu; ausente em 404, 405, healthcheck e OpenAPI. */
39
+ route?: RouteInfo;
40
+ /** O erro lançado, quando a resposta veio do tratamento de erros. */
41
+ error?: unknown;
42
+ /** A etapa em que o erro chegou (a mesma do 3º argumento do `onError`). */
43
+ errorPhase?: ErrorPhase;
44
+ }
45
+ /**
46
+ * Depois que a requisição termina (F-04). Roda **exatamente uma vez** por requisição, em todos os caminhos:
47
+ * sucesso, erro, 404/405, `Host` inválido, cancelamento pelo cliente, shutdown, streams e `inject()`.
48
+ */
49
+ export type OnResponseHook = (ctx: Context, info: ResponseInfo) => void | Promise<void>;
50
+ /**
51
+ * No início de cada requisição, antes da validação do `Host` e de qualquer middleware (F-38). É síncrono:
52
+ * uma Promise devolvida não é esperada. Erros são logados e não interrompem a requisição.
53
+ */
54
+ export type OnRequestHook = (ctx: Context) => void;
55
+ /** No `close()` do app (F-04). */
56
+ export type OnCloseHook = () => void | Promise<void>;
57
+ export interface ListenOptions {
58
+ /** Padrão: 3000. Use 0 para uma porta livre aleatória. */
59
+ port?: number;
60
+ /** Padrão: `127.0.0.1`. Use `0.0.0.0` para aceitar conexões externas (ex.: em containers). */
61
+ host?: string;
62
+ /**
63
+ * Sobe em HTTPS, com os mesmos timeouts, encerramento gracioso e `close()` do HTTP. Atrás de um
64
+ * proxy que termina o TLS (Caddy, Nginx, load balancer), não use: fique em HTTP com `trustProxy`.
65
+ */
66
+ tls?: TlsOptions;
67
+ }
68
+ export interface ServerTimeouts {
69
+ /** Tempo máximo para receber a requisição inteira. Padrão: 30s. */
70
+ requestTimeout?: number;
71
+ /** Tempo máximo para receber os headers (mitiga Slowloris). Padrão: 10s. */
72
+ headersTimeout?: number;
73
+ /** Tempo de conexão keep-alive ociosa. Padrão: 5s. */
74
+ keepAliveTimeout?: number;
75
+ }
76
+ export interface AppOptions {
77
+ /**
78
+ * OpenTelemetry nativo (F-38): passe o `@opentelemetry/api` que a aplicação usa (`import * as otel`).
79
+ * Enriquece o span da auto-instrumentação HTTP (ou cria o span SERVER, se não houver), com o template da
80
+ * rota e os erros com a fase, e gera as métricas HTTP. Sem esta opção, nada é carregado.
81
+ */
82
+ telemetry?: TelemetryApi;
83
+ /** Tamanho máximo do body JSON em bytes. Padrão: 1 MiB. */
84
+ bodyLimit?: number;
85
+ /**
86
+ * Headers de segurança aplicados a toda resposta (S-04). Padrão: `'api'`.
87
+ * `'web'` libera recursos do próprio site (CSP `'self'`) para quem serve páginas; `false` desliga.
88
+ */
89
+ securityHeaders?: SecurityHeadersOptions | SecurityPreset | false;
90
+ /**
91
+ * Serializadores por content type, para responder em outros formatos (F-31):
92
+ * `{ 'application/yaml': (data) => YAML.stringify(data) }`. JSON e valores crus já são nativos.
93
+ */
94
+ serializers?: Record<string, Serializer>;
95
+ /** Upload de arquivos (F-46): limites globais, pasta dos temporários e detector de conteúdo. */
96
+ uploads?: UploadsOptions;
97
+ /** Timeouts do servidor HTTP (S-06). */
98
+ timeouts?: ServerTimeouts;
99
+ /**
100
+ * Modo estrito (S-07): exige schema de `body` em POST/PUT/PATCH e schema de `response`
101
+ * em toda rota, falhando no `app.mount()`. Padrão: `false`.
102
+ */
103
+ requireSchemas?: boolean;
104
+ /**
105
+ * Body JSON com `__proto__` ou `constructor.prototype` (S-08): `'error'` responde 400
106
+ * (`PROTO_POISONING`); `'remove'` descarta as chaves e segue. Padrão: `'error'`.
107
+ */
108
+ protoPoisoning?: ProtoPoisoning;
109
+ /** Máximo de pares chave/valor lidos da query string. Padrão: 1000 (S-06). */
110
+ queryMaxKeys?: number;
111
+ /**
112
+ * Parser de query próprio (F-26), para sintaxes aninhadas como `?filter[status]=ativo`:
113
+ * `createApp({ queryParser: (raw) => qs.parse(raw, { depth: 3, arrayLimit: 50, parameterLimit: 1000 }) })`.
114
+ * O retorno passa pelo filtro de chaves perigosas; se o parser lançar, a resposta é 400. Os limites ficam com o
115
+ * parser: o `queryMaxKeys` vale só para o padrão.
116
+ */
117
+ queryParser?: QueryParser;
118
+ /**
119
+ * O motor dos contratos das rotas (F-27), um para o app inteiro. Sem a opção, `contracts.native()` (schemas
120
+ * TypeBox). Para Zod, Valibot ou ArkType: `contracts.standard()`. Um schema de outro motor é recusado no registro.
121
+ */
122
+ contracts?: Contracts;
123
+ /**
124
+ * Parsers de body por tipo de mídia (F-12), além do JSON nativo:
125
+ * `createApp({ parsers: { 'application/yaml': (raw) => YAML.parse(raw.toString('utf8')) } })`.
126
+ * O `bodyLimit` e a proteção contra prototype pollution valem para todos, e o contrato da rota valida o resultado.
127
+ * Atenção: tipos que o navegador envia sem preflight (`application/x-www-form-urlencoded`, `text/plain`) abrem
128
+ * espaço para CSRF; use o `csrf()` em rotas com sessão por cookie.
129
+ */
130
+ parsers?: Readonly<Record<string, BodyParser>>;
131
+ /** Logger compatível com pino. Padrão: `consoleLogger()`; `false` desliga (F-06). */
132
+ logger?: Logger | false;
133
+ /** Loga cada requisição concluída (método, path, status, duração) em nível `info`. Padrão: `false`. */
134
+ logRequests?: boolean;
135
+ /** Request id (F-06). */
136
+ requestId?: RequestIdOptions;
137
+ /**
138
+ * Encerramento gracioso nos sinais do processo, ativado pelo `listen()` (F-07).
139
+ * Ligado por padrão (SIGINT/SIGTERM, 10s); `false` desliga.
140
+ */
141
+ shutdown?: ShutdownOptions | false;
142
+ /**
143
+ * Confia nos headers `X-Forwarded-For`, `-Host` e `-Proto` para `ctx.ip`, `ctx.host` e `ctx.protocol`
144
+ * (S-09). Padrão: `false`. Use `true` para confiar em toda a cadeia, ou o número de proxies à frente
145
+ * do app (ex.: `1` para um load balancer). Só ligue atrás de um proxy que reescreve esses headers.
146
+ */
147
+ trustProxy?: boolean | number;
148
+ /**
149
+ * Hosts aceitos (S-09). Requisições com outro `Host` (ou `X-Forwarded-Host` confiável) recebem 400.
150
+ * Protege contra host header injection e DNS rebinding. Padrão: qualquer host válido.
151
+ * - `'api.exemplo.com'` casa com o hostname (qualquer porta); `'api.exemplo.com:8443'` exige a porta;
152
+ * - `'*.exemplo.dev'` aceita só subdomínios;
153
+ * - uma RegExp precisa casar o hostname **inteiro** (como se tivesse `^…$`).
154
+ */
155
+ allowedHosts?: readonly (string | RegExp)[];
156
+ /**
157
+ * Rotas com `host` (virtual hosts) fora do `allowedHosts` nunca são alcançadas (F-35). `'error'` (padrão)
158
+ * falha no registro; `'warn'` só registra um aviso no log; `'off'` não confere.
159
+ */
160
+ unreachableHosts?: 'error' | 'warn' | 'off';
161
+ /**
162
+ * Personaliza o corpo de todos os erros do framework e dos `HttpError` (F-15). Padrão: Problem
163
+ * Details (RFC 9457) em `application/problem+json`. O retorno é enviado como `application/json`.
164
+ */
165
+ formatError?: ErrorFormatter;
166
+ }
167
+ export interface RequestIdOptions {
168
+ /** Header lido da requisição e devolvido na resposta. Padrão: `x-request-id`. `false` não envia. */
169
+ header?: string | false;
170
+ /**
171
+ * Reaproveita o id recebido no header (útil atrás de um gateway). Padrão: `true`.
172
+ * O valor só é aceito se tiver até 128 caracteres de `[A-Za-z0-9._:-]`, para evitar log injection.
173
+ */
174
+ trustIncoming?: boolean;
175
+ /** Gerador de ids. Padrão: `crypto.randomUUID()`. */
176
+ generate?: () => string;
177
+ }
178
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/core/app/options.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../../../src/core/app/options.ts"],"names":[],"mappings":""}
@@ -0,0 +1,143 @@
1
+ import type http from 'node:http';
2
+ import type https from 'node:https';
3
+ import '../shims/symbol-metadata.ts';
4
+ import type { TlsOptions } from '../server/tls.ts';
5
+ import { type GroupOptions, type MountOptions, type RouteScope, type RouterRef } from './compiler.ts';
6
+ import { MountedGroup, RouteGroupScope } from './mounted-group.ts';
7
+ import type { Middleware } from './compose.ts';
8
+ import type { Context, OnSendHook } from './context.ts';
9
+ import { type StaticOptions } from '../server/static.ts';
10
+ import { type OpenAPIOptions } from '../openapi/generate.ts';
11
+ import { type HealthOptions } from './health.ts';
12
+ import { type InjectOptions, type InjectResponse } from './inject.ts';
13
+ import { type Logger } from './logger.ts';
14
+ import type { AppOptions, ListenOptions, OnCloseHook, OnErrorHook, OnRequestHook, OnResponseHook } from './app/options.ts';
15
+ export type { AppOptions, ListenOptions, OnCloseHook, OnErrorHook, OnRequestHook, OnResponseHook, RequestIdOptions, ResponseInfo, ServerTimeouts, } from './app/options.ts';
16
+ /**
17
+ * O app. É uma fachada (Facade) sobre o registro de rotas, as rotas do próprio framework (health, OpenAPI),
18
+ * o servidor e o pipeline da requisição: a API pública fica aqui, e o trabalho fica nesses componentes.
19
+ */
20
+ export declare class FlowingApp {
21
+ readonly log: Logger;
22
+ private readonly core;
23
+ private readonly registry;
24
+ private readonly framework;
25
+ private readonly runtime;
26
+ private readonly requests;
27
+ constructor(opts?: AppOptions);
28
+ use(mw: Middleware): this;
29
+ onError(h: OnErrorHook): this;
30
+ /**
31
+ * Roda imediatamente antes de escrever uma resposta com corpo (exceto streams), inclusive em erros
32
+ * e 404. É síncrono: pode alterar headers (ETag, assinatura) ou devolver `{ body, contentType }`
33
+ * novos. Se lançar, o erro é logado e a resposta original é enviada (F-04).
34
+ */
35
+ onSend(hook: OnSendHook): this;
36
+ /**
37
+ * Roda no início de cada requisição, antes da validação do `Host` e dos middlewares: abrir um span, contar
38
+ * requisições ativas. Toda requisição que passa por aqui também passa pelo `onResponse`. É síncrono; erros
39
+ * são só logados (F-38).
40
+ */
41
+ onRequest(hook: OnRequestHook): this;
42
+ /**
43
+ * Roda exatamente uma vez quando a requisição termina, com status, duração, `outcome` (`completed`,
44
+ * `aborted`, `error`), motivo do cancelamento, tempo até os headers, rota e se foi stream: métricas,
45
+ * tracing, auditoria. Pode ser assíncrono; erros são só logados (F-04, F-38).
46
+ */
47
+ onResponse(hook: OnResponseHook): this;
48
+ /**
49
+ * Roda no `close()`, depois que o servidor fecha, qualquer que seja a origem (sinal, teste, código),
50
+ * e antes do `shutdown.onShutdown`. Erros são logados e fazem o `close()` rejeitar ao final (F-04).
51
+ */
52
+ onClose(hook: OnCloseHook): this;
53
+ /**
54
+ * Registra uma classe com `@Router` (F-28). Aceita a classe (construtor sem argumentos) ou uma
55
+ * instância pronta (B-10), e opções aplicadas no ponto de composição:
56
+ *
57
+ * ```ts
58
+ * app
59
+ * .mount(HealthRoutes)
60
+ * .mount(new UserRoutes(repo), { prefix: '/v2/users', middlewares: [auth], except: (r) => [r.remove] })
61
+ * .get('/legacy/:id', (r) => r.getUser); // mapeamento manual (F-30)
62
+ * ```
63
+ */
64
+ mount<T extends object>(ref: new () => T, options?: MountOptions<T>): MountedGroup<T>;
65
+ mount<T extends object>(ref: T extends abstract new (...args: never) => unknown ? never : T, options?: MountOptions<T>): MountedGroup<T>;
66
+ /**
67
+ * Agrupa `mount()`s sob um prefixo, middlewares e guards comuns. Não é um container: é só composição,
68
+ * com a mesma semântica do `mount()`. Grupos podem ser aninhados.
69
+ *
70
+ * ```ts
71
+ * app.group({ prefix: '/v2', middlewares: [authenticate], guards: [isAdmin] }, (g) =>
72
+ * g.mount(UserRoutes).mount(new OrderRoutes(db)),
73
+ * );
74
+ * ```
75
+ * Ordem de execução: middlewares dos grupos (de fora para dentro) → do `mount()` → da classe → do método.
76
+ */
77
+ group(options: GroupOptions, define: (group: RouteGroupScope) => unknown): this;
78
+ /** @internal */
79
+ groupIn(parent: RouteScope, options: GroupOptions, define: (group: RouteGroupScope) => unknown): void;
80
+ /**
81
+ * Serve os arquivos de `root` em `GET prefix/*` (F-13). É uma rota como as outras: vale `group()`
82
+ * (host, guards, middlewares), 404/405 e a checagem de conflitos. Não entra no OpenAPI.
83
+ *
84
+ * ```ts
85
+ * app.static('/assets', './public', { maxAge: '7d', immutable: true });
86
+ * app.static('/', './dist', { fallback: 'index.html' }); // SPA
87
+ * ```
88
+ * Caminhos que saem da raiz (`..`, symlinks), arquivos ocultos e diretórios sem índice respondem 404.
89
+ */
90
+ static(prefix: string, root: string, opts?: StaticOptions): this;
91
+ /** @internal */
92
+ staticIn(scope: RouteScope, prefix: string, root: string, opts: StaticOptions): void;
93
+ /** @internal */
94
+ mountIn(scope: RouteScope, ref: RouterRef, options?: MountOptions): MountedGroup<object>;
95
+ /**
96
+ * Serve o documento OpenAPI 3.1 gerado das rotas (`/openapi.json`) e, com `docs`, o Swagger UI (F-16).
97
+ * As duas rotas passam pelos middlewares globais e pelos `middlewares`/`guards` informados aqui:
98
+ * `app.openapi({ guards: [isAdmin] })`. O documento é gerado na primeira requisição, depois dos `mount()`.
99
+ */
100
+ openapi(opts?: OpenAPIOptions): this;
101
+ /**
102
+ * Healthchecks para load balancers e orquestradores (Kubernetes, ECS…).
103
+ * - `GET /livez`: o processo está de pé (200 sempre).
104
+ * - `GET /readyz`: pronto para receber tráfego. Roda os `checks` (banco, fila…) e responde 503 se algum
105
+ * falhar ou estourar o tempo, e também durante o encerramento.
106
+ *
107
+ * As rotas são servidas **antes** dos middlewares globais (sondas não têm credenciais nem devem
108
+ * consumir rate limit); use `guards`/`middlewares` aqui para restringir.
109
+ */
110
+ health(opts?: HealthOptions): this;
111
+ /**
112
+ * Documento OpenAPI 3.1 das rotas registradas até agora, para gravar em arquivo ou testar (F-16).
113
+ * Com virtual hosts, é por host (F-35): `{ host: 'api.exemplo.com' }` traz as rotas desse host e as sem
114
+ * host; sem `host`, só as sem host. Domínios diferentes nunca se misturam num mesmo documento.
115
+ */
116
+ openapiDocument(opts?: OpenAPIOptions): Record<string, unknown>;
117
+ /** Executa o pipeline completo para um contexto já criado. */
118
+ handle(ctx: Context): Promise<void>;
119
+ /**
120
+ * Listener `(req, res)` do app, para usar com qualquer servidor do Node:
121
+ * `https.createServer(opts, app.callback())`, `http2` em modo compat, testes etc. (F-09).
122
+ */
123
+ callback(): (req: http.IncomingMessage, res: http.ServerResponse) => void;
124
+ /** Sobe o servidor HTTP (ou HTTPS, com `tls`) e resolve quando ele está aceitando conexões (F-09, F-33). */
125
+ listen(options: ListenOptions & {
126
+ tls: TlsOptions;
127
+ }): Promise<https.Server>;
128
+ listen(options?: number | ListenOptions): Promise<http.Server>;
129
+ /**
130
+ * Troca os certificados sem reiniciar nem derrubar conexões (renovação, ACME externo). Conexões novas
131
+ * usam os novos; as abertas seguem com os antigos. Um certificado inválido lança erro e mantém os atuais.
132
+ */
133
+ reloadTLS(tls: TlsOptions): void;
134
+ /**
135
+ * Para de aceitar conexões, encerra as ociosas e espera as requisições em andamento terminarem.
136
+ * Depois de `graceMs`, força o fechamento das restantes.
137
+ */
138
+ close(graceMs?: number): Promise<void>;
139
+ /** Executa uma requisição em memória, sem rede. Ideal para testes (F-09). */
140
+ inject(opts: InjectOptions | string): Promise<InjectResponse>;
141
+ }
142
+ export declare function createApp(opts?: AppOptions): FlowingApp;
143
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/core/app.ts"],"names":[],"mappings":"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"}