sashiko 0.0.0-stage → 0.2.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/LICENSE +15 -0
- package/README.md +398 -2
- package/dist/core/app.d.ts +104 -0
- package/dist/core/app.d.ts.map +1 -0
- package/dist/core/app.js +202 -0
- package/dist/core/app.js.map +1 -0
- package/dist/core/body-parser.d.ts +4 -0
- package/dist/core/body-parser.d.ts.map +1 -0
- package/dist/core/body-parser.js +38 -0
- package/dist/core/body-parser.js.map +1 -0
- package/dist/core/compiler.d.ts +52 -0
- package/dist/core/compiler.d.ts.map +1 -0
- package/dist/core/compiler.js +74 -0
- package/dist/core/compiler.js.map +1 -0
- package/dist/core/compose.d.ts +4 -0
- package/dist/core/compose.d.ts.map +1 -0
- package/dist/core/compose.js +11 -0
- package/dist/core/compose.js.map +1 -0
- package/dist/core/context.d.ts +84 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +121 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/errors.d.ts +24 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +23 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/guard.d.ts +10 -0
- package/dist/core/guard.d.ts.map +1 -0
- package/dist/core/guard.js +12 -0
- package/dist/core/guard.js.map +1 -0
- package/dist/core/index.d.ts +15 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +8 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/infer.d.ts +36 -0
- package/dist/core/infer.d.ts.map +1 -0
- package/dist/core/infer.js +2 -0
- package/dist/core/infer.js.map +1 -0
- package/dist/core/inject.d.ts +27 -0
- package/dist/core/inject.d.ts.map +1 -0
- package/dist/core/inject.js +72 -0
- package/dist/core/inject.js.map +1 -0
- package/dist/core/logger.d.ts +28 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +27 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/metadata.d.ts +59 -0
- package/dist/core/metadata.d.ts.map +1 -0
- package/dist/core/metadata.js +83 -0
- package/dist/core/metadata.js.map +1 -0
- 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/request-validation.d.ts +11 -0
- package/dist/core/request-validation.d.ts.map +1 -0
- package/dist/core/request-validation.js +30 -0
- package/dist/core/request-validation.js.map +1 -0
- package/dist/core/response.d.ts +16 -0
- package/dist/core/response.d.ts.map +1 -0
- package/dist/core/response.js +49 -0
- package/dist/core/response.js.map +1 -0
- package/dist/core/route-table.d.ts +29 -0
- package/dist/core/route-table.d.ts.map +1 -0
- package/dist/core/route-table.js +41 -0
- package/dist/core/route-table.js.map +1 -0
- package/dist/decorators/http.d.ts +16 -0
- package/dist/decorators/http.d.ts.map +1 -0
- package/dist/decorators/http.js +27 -0
- package/dist/decorators/http.js.map +1 -0
- package/dist/decorators/index.d.ts +6 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +6 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/log.d.ts +10 -0
- package/dist/decorators/log.d.ts.map +1 -0
- package/dist/decorators/log.js +32 -0
- package/dist/decorators/log.js.map +1 -0
- 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/decorators/router.d.ts +12 -0
- package/dist/decorators/router.d.ts.map +1 -0
- package/dist/decorators/router.js +19 -0
- package/dist/decorators/router.js.map +1 -0
- package/dist/decorators/schema.d.ts +8 -0
- package/dist/decorators/schema.d.ts.map +1 -0
- package/dist/decorators/schema.js +13 -0
- package/dist/decorators/schema.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/middlewares/cors.d.ts +24 -0
- package/dist/middlewares/cors.d.ts.map +1 -0
- package/dist/middlewares/cors.js +63 -0
- package/dist/middlewares/cors.js.map +1 -0
- package/dist/middlewares/index.d.ts +4 -0
- package/dist/middlewares/index.d.ts.map +1 -0
- package/dist/middlewares/index.js +4 -0
- package/dist/middlewares/index.js.map +1 -0
- package/dist/middlewares/rate-limit.d.ts +35 -0
- package/dist/middlewares/rate-limit.d.ts.map +1 -0
- package/dist/middlewares/rate-limit.js +45 -0
- package/dist/middlewares/rate-limit.js.map +1 -0
- package/dist/middlewares/security-headers.d.ts +26 -0
- package/dist/middlewares/security-headers.d.ts.map +1 -0
- package/dist/middlewares/security-headers.js +34 -0
- package/dist/middlewares/security-headers.js.map +1 -0
- package/dist/schema/serialization.d.ts +2 -0
- package/dist/schema/serialization.d.ts.map +1 -0
- package/dist/schema/serialization.js +11 -0
- package/dist/schema/serialization.js.map +1 -0
- package/dist/schema/validation.d.ts +11 -0
- package/dist/schema/validation.d.ts.map +1 -0
- package/dist/schema/validation.js +48 -0
- package/dist/schema/validation.js.map +1 -0
- package/dist/shims/symbol-metadata.d.ts +2 -0
- package/dist/shims/symbol-metadata.d.ts.map +1 -0
- package/dist/shims/symbol-metadata.js +8 -0
- package/dist/shims/symbol-metadata.js.map +1 -0
- package/dist/utils/content-type.d.ts +5 -0
- package/dist/utils/content-type.d.ts.map +1 -0
- package/dist/utils/content-type.js +10 -0
- package/dist/utils/content-type.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/path.d.ts +3 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +7 -0
- package/dist/utils/path.js.map +1 -0
- package/dist/utils/query.d.ts +13 -0
- package/dist/utils/query.d.ts.map +1 -0
- package/dist/utils/query.js +30 -0
- package/dist/utils/query.js.map +1 -0
- package/package.json +74 -3
package/dist/core/app.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import http from 'node:http';
|
|
3
|
+
import { performance } from 'node:perf_hooks';
|
|
4
|
+
import { compileAutoRoutes, compileManualRoute, createGroup } from './compiler.js';
|
|
5
|
+
import { MountedGroup } from './mounted-group.js';
|
|
6
|
+
import { compose } from './compose.js';
|
|
7
|
+
import { Context } from './context.js';
|
|
8
|
+
import '../shims/symbol-metadata.js';
|
|
9
|
+
import { bodyParser } from './body-parser.js';
|
|
10
|
+
import { assertSchemas, validateRequest } from './request-validation.js';
|
|
11
|
+
import { sendError, sendResult } from './response.js';
|
|
12
|
+
import { RouteTable } from './route-table.js';
|
|
13
|
+
import { inject } from './inject.js';
|
|
14
|
+
import { guardsMiddleware } from './guard.js';
|
|
15
|
+
import { consoleLogger, silentLogger } from './logger.js';
|
|
16
|
+
import { buildSecurityHeaders } from '../middlewares/security-headers.js';
|
|
17
|
+
const SAFE_REQUEST_ID = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
18
|
+
export class SashikoApp {
|
|
19
|
+
middlewares = [];
|
|
20
|
+
router = new RouteTable();
|
|
21
|
+
errorHandlers = [];
|
|
22
|
+
applySecurityHeaders;
|
|
23
|
+
opts;
|
|
24
|
+
server;
|
|
25
|
+
/** Logger do app (F-06). Use para logs fora de uma requisição. */
|
|
26
|
+
log;
|
|
27
|
+
constructor(opts = {}) {
|
|
28
|
+
this.opts = opts;
|
|
29
|
+
this.log = opts.logger === false ? silentLogger : (opts.logger ?? consoleLogger());
|
|
30
|
+
if (opts.securityHeaders !== false)
|
|
31
|
+
this.applySecurityHeaders = buildSecurityHeaders(opts.securityHeaders);
|
|
32
|
+
this.use(bodyParser(opts.bodyLimit ?? 1024 * 1024));
|
|
33
|
+
}
|
|
34
|
+
use(mw) {
|
|
35
|
+
this.middlewares.push(mw);
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
onError(h) {
|
|
39
|
+
this.errorHandlers.push(h);
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
mount(ref, options = {}) {
|
|
43
|
+
const group = createGroup(ref, options);
|
|
44
|
+
for (const route of compileAutoRoutes(group))
|
|
45
|
+
this.addRoute(group.name, route);
|
|
46
|
+
return new MountedGroup(this, group, (g, method, path, select, opts) => this.addRoute(g.name, compileManualRoute(g, method, path, select, opts)));
|
|
47
|
+
}
|
|
48
|
+
addRoute(owner, route) {
|
|
49
|
+
if (this.opts.requireSchemas)
|
|
50
|
+
assertSchemas(owner, route);
|
|
51
|
+
try {
|
|
52
|
+
this.router.on(route.method, route.path, route);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
throw new Error(`[sashiko] app.mount(${owner}): ${route.method} ${route.path} is already registered. ` +
|
|
56
|
+
`Use a different "prefix" to mount the same class twice.`, { cause: err });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async handle(ctx) {
|
|
60
|
+
// Antes de tudo, para valer inclusive em erros, 404 e preflight (S-04).
|
|
61
|
+
this.applySecurityHeaders?.(ctx.res);
|
|
62
|
+
try {
|
|
63
|
+
await compose(ctx, this.middlewares);
|
|
64
|
+
if (ctx.sent)
|
|
65
|
+
return;
|
|
66
|
+
const match = this.router.find(ctx.method, ctx.path);
|
|
67
|
+
if (!match) {
|
|
68
|
+
const allowed = this.router.allowedMethods(ctx.path);
|
|
69
|
+
if (allowed.length > 0) {
|
|
70
|
+
ctx.res.setHeader('Allow', allowed.join(', '));
|
|
71
|
+
// F-08: OPTIONS automático para qualquer path com rotas.
|
|
72
|
+
if (ctx.method === 'OPTIONS')
|
|
73
|
+
return void ctx.status(204).res.end();
|
|
74
|
+
return void ctx.status(405).json({ error: 'Method Not Allowed', allowed });
|
|
75
|
+
}
|
|
76
|
+
return void ctx.status(404).json({ error: 'Not Found' });
|
|
77
|
+
}
|
|
78
|
+
ctx.params = match.params;
|
|
79
|
+
// F-01: middlewares → guards → validação → handler. Guards antes da validação, para que
|
|
80
|
+
// quem não tem acesso receba 401/403 e não um 400 que revele a estrutura esperada.
|
|
81
|
+
const route = match;
|
|
82
|
+
const pipeline = [...route.middlewares];
|
|
83
|
+
if (route.guards.length > 0)
|
|
84
|
+
pipeline.push(guardsMiddleware(route.guards));
|
|
85
|
+
pipeline.push(async () => {
|
|
86
|
+
validateRequest(ctx, route.schemas);
|
|
87
|
+
const result = await route.handler(ctx);
|
|
88
|
+
if (!ctx.sent)
|
|
89
|
+
sendResult(ctx, route.schemas.response, result);
|
|
90
|
+
});
|
|
91
|
+
await compose(ctx, pipeline);
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
await this.runErrorHandlers(err, ctx);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Executa os `onError` do usuário. Se um deles lançar, o erro é logado e seguimos
|
|
99
|
+
* para a resposta padrão com o erro **original** — nunca deixamos a Promise rejeitar (B-08).
|
|
100
|
+
*/
|
|
101
|
+
async runErrorHandlers(err, ctx) {
|
|
102
|
+
for (const h of this.errorHandlers) {
|
|
103
|
+
try {
|
|
104
|
+
await h(err, ctx);
|
|
105
|
+
}
|
|
106
|
+
catch (handlerErr) {
|
|
107
|
+
ctx.log.error({ err: handlerErr, method: ctx.method, path: ctx.path }, 'onError handler failed');
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
if (ctx.res.writableEnded)
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
sendError(ctx, err);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Listener `(req, res)` do app, para usar com qualquer servidor do Node:
|
|
117
|
+
* `https.createServer(opts, app.callback())`, `http2` em modo compat, testes etc. (F-09).
|
|
118
|
+
*/
|
|
119
|
+
callback() {
|
|
120
|
+
const rid = this.opts.requestId ?? {};
|
|
121
|
+
const header = rid.header === false ? undefined : (rid.header ?? 'x-request-id').toLowerCase();
|
|
122
|
+
const trust = rid.trustIncoming ?? true;
|
|
123
|
+
const generate = rid.generate ?? (() => randomUUID());
|
|
124
|
+
return (req, res) => {
|
|
125
|
+
const started = performance.now();
|
|
126
|
+
const incoming = header ? req.headers[header] : undefined;
|
|
127
|
+
const id = trust && typeof incoming === 'string' && SAFE_REQUEST_ID.test(incoming) ? incoming : generate();
|
|
128
|
+
if (header)
|
|
129
|
+
res.setHeader(header, id);
|
|
130
|
+
// Última barreira (B-08): nada que aconteça numa requisição pode virar unhandledRejection.
|
|
131
|
+
const fail = (err) => {
|
|
132
|
+
this.log.error({ err, reqId: id, method: req.method, url: req.url }, 'unhandled error while handling request');
|
|
133
|
+
if (!res.headersSent)
|
|
134
|
+
res.statusCode = 500;
|
|
135
|
+
if (!res.writableEnded)
|
|
136
|
+
res.end();
|
|
137
|
+
};
|
|
138
|
+
try {
|
|
139
|
+
const ctx = new Context(req, res, { queryMaxKeys: this.opts.queryMaxKeys, id, logger: this.log });
|
|
140
|
+
if (this.opts.logRequests) {
|
|
141
|
+
res.once('finish', () => {
|
|
142
|
+
const ms = Math.round((performance.now() - started) * 100) / 100;
|
|
143
|
+
ctx.log.info({ method: ctx.method, path: ctx.path, status: res.statusCode, ms }, 'request completed');
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
this.handle(ctx).catch(fail);
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
fail(err);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/** Sobe o servidor HTTP e resolve quando ele está aceitando conexões (F-09). */
|
|
154
|
+
async listen(options = {}) {
|
|
155
|
+
if (this.server)
|
|
156
|
+
throw new Error('[sashiko] app is already listening; call app.close() first.');
|
|
157
|
+
const { port = 3000, host = '127.0.0.1' } = typeof options === 'number' ? { port: options } : options;
|
|
158
|
+
const server = http.createServer(this.callback());
|
|
159
|
+
const t = this.opts.timeouts ?? {};
|
|
160
|
+
server.requestTimeout = t.requestTimeout ?? 30_000;
|
|
161
|
+
server.headersTimeout = Math.min(t.headersTimeout ?? 10_000, server.requestTimeout || Infinity);
|
|
162
|
+
server.keepAliveTimeout = t.keepAliveTimeout ?? 5_000;
|
|
163
|
+
await new Promise((resolve, reject) => {
|
|
164
|
+
server.once('error', reject);
|
|
165
|
+
server.listen(port, host, () => {
|
|
166
|
+
server.off('error', reject);
|
|
167
|
+
resolve();
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
this.server = server;
|
|
171
|
+
return server;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Para de aceitar conexões, encerra as ociosas e espera as requisições em andamento terminarem.
|
|
175
|
+
* Depois de `graceMs`, força o fechamento das restantes.
|
|
176
|
+
*/
|
|
177
|
+
async close(graceMs = 10_000) {
|
|
178
|
+
const server = this.server;
|
|
179
|
+
if (!server)
|
|
180
|
+
return;
|
|
181
|
+
this.server = undefined;
|
|
182
|
+
const force = setTimeout(() => server.closeAllConnections(), graceMs);
|
|
183
|
+
force.unref();
|
|
184
|
+
try {
|
|
185
|
+
await new Promise((resolve, reject) => {
|
|
186
|
+
server.close((err) => (err ? reject(err) : resolve()));
|
|
187
|
+
server.closeIdleConnections();
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
clearTimeout(force);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/** Executa uma requisição em memória, sem rede. Ideal para testes (F-09). */
|
|
195
|
+
inject(opts) {
|
|
196
|
+
return inject(this.callback(), typeof opts === 'string' ? { url: opts } : opts);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
export function createApp(opts) {
|
|
200
|
+
return new SashikoApp(opts);
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/core/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,WAAW,EAAyD,MAAM,eAAe,CAAC;AAC1I,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAmB,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,6BAA6B,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAA2C,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAA+B,MAAM,oCAAoC,CAAC;AAoDvG,MAAM,eAAe,GAAG,0BAA0B,CAAC;AAEnD,MAAM,OAAO,UAAU;IACb,WAAW,GAAiB,EAAE,CAAC;IAC/B,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;IAC1B,aAAa,GAA6D,EAAE,CAAC;IAC7E,oBAAoB,CAAmD;IAC9D,IAAI,CAAa;IAC1B,MAAM,CAA0B;IACxC,kEAAkE;IACzD,GAAG,CAAS;IAErB,YAAY,IAAI,GAAe,EAAE;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC,CAAC;QACnF,IAAI,IAAI,CAAC,eAAe,KAAK,KAAK;YAAE,IAAI,CAAC,oBAAoB,GAAG,oBAAoB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC3G,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,GAAG,CAAC,EAAc;QAChB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,CAAuD;QAC7D,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAeD,KAAK,CAAC,GAAc,EAAE,OAAO,GAAiB,EAAE;QAC9C,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACxC,KAAK,MAAM,KAAK,IAAI,iBAAiB,CAAC,KAAK,CAAC;YAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/E,OAAO,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CACrE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CACzE,CAAC;IACJ,CAAC;IAEO,QAAQ,CAAC,KAAa,EAAE,KAAoB;QAClD,IAAI,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC1D,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,uBAAuB,KAAK,MAAM,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,0BAA0B;gBACtF,yDAAyD,EACzD,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;QACJ,CAAC;IACH,CAAC;IAID,KAAK,CAAC,MAAM,CAAC,GAAY;QACvB,wEAAwE;QACxE,IAAI,CAAC,oBAAoB,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;YACrC,IAAI,GAAG,CAAC,IAAI;gBAAE,OAAO;YAErB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YACrD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACrD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;oBAC/C,yDAAyD;oBACzD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;wBAAE,OAAO,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;oBACpE,OAAO,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC7E,CAAC;gBACD,OAAO,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;YAC3D,CAAC;YAED,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAE1B,wFAAwF;YACxF,mFAAmF;YACnF,MAAM,KAAK,GAAG,KAAK,CAAC;YACpB,MAAM,QAAQ,GAAiB,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;YACtD,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;YAC3E,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;gBACvB,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;gBACpC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBACxC,IAAI,CAAC,GAAG,CAAC,IAAI;oBAAE,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACjE,CAAC,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,gBAAgB,CAAC,GAAY,EAAE,GAAY;QACvD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACpB,CAAC;YAAC,OAAO,UAAU,EAAE,CAAC;gBACpB,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,wBAAwB,CAAC,CAAC;gBACjG,MAAM;YACR,CAAC;YACD,IAAI,GAAG,CAAC,GAAG,CAAC,aAAa;gBAAE,OAAO;QACpC,CAAC;QACD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACtB,CAAC;IAED;;;OAGG;IACH,QAAQ;QACN,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,cAAc,CAAC,CAAC,WAAW,EAAE,CAAC;QAC/F,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,IAAI,IAAI,CAAC;QACxC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC;QAEtD,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAClB,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC1D,MAAM,EAAE,GAAG,KAAK,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC3G,IAAI,MAAM;gBAAE,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAEtC,2FAA2F;YAC3F,MAAM,IAAI,GAAG,CAAC,GAAY,EAAE,EAAE;gBAC5B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,EAAE,wCAAwC,CAAC,CAAC;gBAC/G,IAAI,CAAC,GAAG,CAAC,WAAW;oBAAE,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;gBAC3C,IAAI,CAAC,GAAG,CAAC,aAAa;oBAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YACpC,CAAC,CAAC;YACF,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;gBAClG,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;oBAC1B,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;wBACtB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;wBACjE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,EAAE,EAAE,EAAE,mBAAmB,CAAC,CAAC;oBACxG,CAAC,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,GAAG,CAAC,CAAC;YACZ,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,MAAM,CAAC,OAAO,GAA2B,EAAE;QAC/C,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QAChG,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,IAAI,GAAG,WAAW,EAAE,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAEtG,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAClD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;QACnC,MAAM,CAAC,cAAc,GAAG,CAAC,CAAC,cAAc,IAAI,MAAM,CAAC;QACnD,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,IAAI,MAAM,EAAE,MAAM,CAAC,cAAc,IAAI,QAAQ,CAAC,CAAC;QAChG,MAAM,CAAC,gBAAgB,GAAG,CAAC,CAAC,gBAAgB,IAAI,KAAK,CAAC;QAEtD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC7B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;gBAC7B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC5B,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,EAAE,EAAE,OAAO,CAAC,CAAC;QACtE,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,IAAI,CAAC;YACH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC1C,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBACvD,MAAM,CAAC,oBAAoB,EAAE,CAAC;YAChC,CAAC,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,MAAM,CAAC,IAA4B;QACjC,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAClF,CAAC;CAEF;AAED,MAAM,UAAU,SAAS,CAAC,IAAiB;IACzC,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body-parser.d.ts","sourceRoot":"","sources":["../../src/core/body-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,4GAA4G;AAC5G,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CA4BpD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { isJsonContentType } from '../utils/content-type.js';
|
|
2
|
+
/** Lê e parseia o body JSON, respeitando `limit` em bytes. Registrado pelo app como primeiro middleware. */
|
|
3
|
+
export function bodyParser(limit) {
|
|
4
|
+
return async (ctx, next) => {
|
|
5
|
+
if (ctx.method === 'GET' || ctx.method === 'HEAD')
|
|
6
|
+
return next();
|
|
7
|
+
if (!isJsonContentType(ctx.req.headers['content-type']))
|
|
8
|
+
return next();
|
|
9
|
+
// B-12: rejeita cedo pelo Content-Length e fecha a conexão ao exceder,
|
|
10
|
+
// para o cliente não continuar enviando um corpo que será descartado.
|
|
11
|
+
const tooLarge = () => {
|
|
12
|
+
ctx.res.setHeader('Connection', 'close');
|
|
13
|
+
return ctx.throw(413, 'Payload too large');
|
|
14
|
+
};
|
|
15
|
+
const declared = Number(ctx.req.headers['content-length']);
|
|
16
|
+
if (Number.isFinite(declared) && declared > limit)
|
|
17
|
+
tooLarge();
|
|
18
|
+
const chunks = [];
|
|
19
|
+
let size = 0;
|
|
20
|
+
for await (const chunk of ctx.req) {
|
|
21
|
+
size += chunk.length;
|
|
22
|
+
if (size > limit)
|
|
23
|
+
tooLarge();
|
|
24
|
+
chunks.push(chunk);
|
|
25
|
+
}
|
|
26
|
+
const raw = Buffer.concat(chunks).toString('utf8');
|
|
27
|
+
if (raw) {
|
|
28
|
+
try {
|
|
29
|
+
ctx.body = JSON.parse(raw);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
ctx.throw(400, 'Invalid JSON');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
await next();
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=body-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body-parser.js","sourceRoot":"","sources":["../../src/core/body-parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,4GAA4G;AAC5G,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO,IAAI,EAAE,CAAC;QACjE,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAAE,OAAO,IAAI,EAAE,CAAC;QAEvE,uEAAuE;QACvE,sEAAsE;QACtE,MAAM,QAAQ,GAAG,GAAU,EAAE;YAC3B,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YACzC,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;QAC7C,CAAC,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAC3D,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,KAAK;YAAE,QAAQ,EAAE,CAAC;QAE9D,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;YAClC,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;YACrB,IAAI,IAAI,GAAG,KAAK;gBAAE,QAAQ,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC;gBAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAAC,CAAC;YACnC,MAAM,CAAC;gBAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YAAC,CAAC;QAC3C,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Guard } from './guard.ts';
|
|
2
|
+
import type { Middleware } from './compose.ts';
|
|
3
|
+
import { type RouterMetadata } from './metadata.ts';
|
|
4
|
+
import type { RouteDefinition } from './route-table.ts';
|
|
5
|
+
export interface CompiledRoute extends RouteDefinition {
|
|
6
|
+
method: string;
|
|
7
|
+
path: string;
|
|
8
|
+
}
|
|
9
|
+
/** Classe com construtor sem argumentos **ou** instância já construída (B-10). */
|
|
10
|
+
export type RouterRef = (new () => object) | object;
|
|
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). */
|
|
17
|
+
export interface MountOptions<T = object> {
|
|
18
|
+
/** Substitui o prefixo definido no `@Router`. */
|
|
19
|
+
prefix?: string;
|
|
20
|
+
/** Registra só estes métodos de rota. Não pode ser usado junto com `except`. */
|
|
21
|
+
only?: MethodsSelector<T>;
|
|
22
|
+
/** Registra todos os métodos de rota, exceto estes. */
|
|
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. */
|
|
27
|
+
middlewares?: readonly Middleware[];
|
|
28
|
+
/** Guards para todas as rotas do grupo; rodam antes dos `@Guards` da classe. */
|
|
29
|
+
guards?: readonly Guard[];
|
|
30
|
+
}
|
|
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 {};
|
|
52
|
+
//# sourceMappingURL=compiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../src/core/compiler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAwC,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD,MAAM,WAAW,aAAc,SAAQ,eAAe;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,kFAAkF;AAClF,MAAM,MAAM,SAAS,GAAG,CAAC,UAAU,MAAM,CAAC,GAAG,MAAM,CAAC;AAEpD,KAAK,SAAS,GAAG,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC;AAE/C,2EAA2E;AAC3E,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,SAAS,CAAC;AACzD,qEAAqE;AACrE,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,SAAS,SAAS,EAAE,CAAC;AAErE,8EAA8E;AAC9E,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,MAAM;IACtC,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,IAAI,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAC1B,uDAAuD;IACvD,MAAM,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAC5B,sGAAsG;IACtG,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0FAA0F;IAC1F,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACpC,gFAAgF;IAChF,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;CAC3B;AAED,iGAAiG;AACjG,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACpC,4CAA4C;IAC5C,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;CAC3B;AAED,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,cAAc,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,CAAC;CACvB;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,GAAE,YAAiB,GAAG,UAAU,CAgBlF;AAED,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,EAAE,CAiBpE;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,EAChC,OAAO,GAAE,kBAAuB,GAC/B,aAAa,CAGf"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { readOwnMetadata } from './metadata.js';
|
|
2
|
+
import { joinPaths } from '../utils/path.js';
|
|
3
|
+
export function createGroup(ref, options = {}) {
|
|
4
|
+
const isClass = typeof ref === 'function';
|
|
5
|
+
const Class = (isClass ? ref : ref.constructor);
|
|
6
|
+
const meta = readOwnMetadata(Class);
|
|
7
|
+
if (!meta?.isRouter) {
|
|
8
|
+
throw new Error(`[sashiko] Class ${Class.name} is not decorated with @Router('/prefix'). ` +
|
|
9
|
+
`Add it to register the class with app.mount().`);
|
|
10
|
+
}
|
|
11
|
+
if (options.only && options.except) {
|
|
12
|
+
throw new Error(`[sashiko] app.mount(${Class.name}): use either "only" or "except", not both.`);
|
|
13
|
+
}
|
|
14
|
+
// Instâncias permitem injetar dependências pelo construtor: app.mount(new UserRoutes(repo))
|
|
15
|
+
const instance = isClass ? new Class() : ref;
|
|
16
|
+
return { name: Class.name, instance, meta, prefix: options.prefix ?? meta.prefix, options };
|
|
17
|
+
}
|
|
18
|
+
/** Rotas declaradas na classe (`@Get`, `@Post`…), filtradas por `only`/`except` e `auto`. */
|
|
19
|
+
export function compileAutoRoutes(group) {
|
|
20
|
+
const { meta, options } = group;
|
|
21
|
+
if (options.auto === false)
|
|
22
|
+
return [];
|
|
23
|
+
const declared = [...meta.methods].filter(([, m]) => m.method && m.path).map(([name]) => name);
|
|
24
|
+
const pick = (selector, label) => new Set(selector(group.instance).map((fn) => resolveMethod(group, fn, label, declared)));
|
|
25
|
+
const excluded = options.except ? pick(options.except, 'except') : new Set();
|
|
26
|
+
const selected = options.only ? pick(options.only, 'only') : new Set(declared.filter((n) => !excluded.has(n)));
|
|
27
|
+
return declared
|
|
28
|
+
.filter((name) => selected.has(name))
|
|
29
|
+
.map((name) => {
|
|
30
|
+
const m = meta.methods.get(name);
|
|
31
|
+
return buildRoute(group, name, m, m.method, m.path);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/** Rota mapeada no app: `.get('/legacy/:id', (r) => r.getUser, opts)` (F-30). */
|
|
35
|
+
export function compileManualRoute(group, httpMethod, path, selector, options = {}) {
|
|
36
|
+
const name = resolveMethod(group, selector(group.instance), `.${httpMethod.toLowerCase()}('${path}')`);
|
|
37
|
+
return buildRoute(group, name, group.meta.methods.get(name), httpMethod, path, options);
|
|
38
|
+
}
|
|
39
|
+
function buildRoute(group, name, methodMeta, httpMethod, path, manual = {}) {
|
|
40
|
+
const fn = group.instance[name];
|
|
41
|
+
const { meta, options, instance } = group;
|
|
42
|
+
return {
|
|
43
|
+
method: httpMethod,
|
|
44
|
+
path: joinPaths(group.prefix, path),
|
|
45
|
+
handler: (ctx) => fn.call(instance, ctx),
|
|
46
|
+
schemas: methodMeta.schemas,
|
|
47
|
+
// Ordem: mount → classe → método → rota manual (F-01, F-28, F-30)
|
|
48
|
+
middlewares: [...(options.middlewares ?? []), ...meta.middlewares, ...methodMeta.middlewares, ...(manual.middlewares ?? [])],
|
|
49
|
+
guards: [...(options.guards ?? []), ...meta.guards, ...methodMeta.guards, ...(manual.guards ?? [])],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Descobre o nome do método a partir da função devolvida pelo seletor.
|
|
54
|
+
* Só aceita métodos com algum decorator do Sashiko (a "permissão" no nível do método).
|
|
55
|
+
*/
|
|
56
|
+
function resolveMethod(group, fn, where, allowed = [...group.meta.methods.keys()]) {
|
|
57
|
+
const target = group.instance;
|
|
58
|
+
const name = typeof fn === 'function' ? allowed.find((n) => target[n] === fn) : undefined;
|
|
59
|
+
if (name !== undefined)
|
|
60
|
+
return name;
|
|
61
|
+
const label = typeof fn === 'function' && fn.name ? `"${fn.name}"` : 'the selected value';
|
|
62
|
+
const available = allowed.map(String).join(', ') || '(none)';
|
|
63
|
+
const decorated = typeof fn === 'function' && [...group.meta.methods.keys()].some((n) => target[n] === fn);
|
|
64
|
+
const isMethod = typeof fn === 'function'
|
|
65
|
+
&& Object.values(Object.getOwnPropertyDescriptors(Object.getPrototypeOf(target))).some((d) => d.value === fn);
|
|
66
|
+
const reason = decorated
|
|
67
|
+
? `${label} has no HTTP verb decorator, so it is not an automatic route; map it manually with .get()/.post()…`
|
|
68
|
+
: isMethod
|
|
69
|
+
? `${label} has no Sashiko decorator (@Get, @Schema, @Middlewares, @Guards…), so it cannot be exposed`
|
|
70
|
+
: `${label} is not a method of ${group.name}`;
|
|
71
|
+
const at = where.startsWith('.') ? where : ` ${where}`;
|
|
72
|
+
throw new Error(`[sashiko] app.mount(${group.name})${at}: ${reason}. Available: ${available}.`);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=compiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../src/core/compiler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/core/compose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE3F,wBAAsB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/core/compose.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAY,EAAE,GAAiB;IAC3D,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM;YAAE,OAAO;QAC5B,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,EAAE,CAAE,CAAC;QACrB,MAAM,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC1B,CAAC,CAAC;IACF,MAAM,QAAQ,EAAE,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { IncomingMessage, OutgoingHttpHeader, ServerResponse } from 'node:http';
|
|
2
|
+
import { Readable } from 'node:stream';
|
|
3
|
+
import { type Logger } from './logger.ts';
|
|
4
|
+
import type { InferBody, InferParams, InferQuery } from './infer.ts';
|
|
5
|
+
import type { RouteSchemas } from './metadata.ts';
|
|
6
|
+
/**
|
|
7
|
+
* Estado por requisição, compartilhado entre middlewares, guards e handlers.
|
|
8
|
+
* Estenda com declaration merging para ter tipos (F-01):
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* declare module 'sashiko' {
|
|
12
|
+
* interface ContextState { user?: { id: string; role: 'admin' | 'user' } }
|
|
13
|
+
* }
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export interface ContextState {
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
}
|
|
19
|
+
export interface ContextOptions {
|
|
20
|
+
queryMaxKeys?: number | undefined;
|
|
21
|
+
/** Id da requisição; o app gera ou reaproveita o header recebido (F-06). */
|
|
22
|
+
id?: string | undefined;
|
|
23
|
+
/** Logger do app; o contexto cria um filho com o `reqId`. */
|
|
24
|
+
logger?: Logger | undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Contexto da requisição. Passe os schemas da rota no genérico para tipar
|
|
28
|
+
* `params`, `query` e `body` a partir do `@Schema` (F-02):
|
|
29
|
+
*
|
|
30
|
+
* ```ts
|
|
31
|
+
* const create = { body: CreateUserSchema, response: { 201: UserSchema } } satisfies RouteSchemas;
|
|
32
|
+
* @Post('/') @Schema(create) createUser(ctx: Context<typeof create>) { ctx.body.name }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class Context<S extends RouteSchemas = RouteSchemas> {
|
|
36
|
+
readonly req: IncomingMessage;
|
|
37
|
+
readonly res: ServerResponse;
|
|
38
|
+
readonly method: string;
|
|
39
|
+
readonly path: string;
|
|
40
|
+
readonly url: URL;
|
|
41
|
+
/** Id da requisição, também enviado no header `X-Request-Id` (F-06). */
|
|
42
|
+
readonly id: string;
|
|
43
|
+
/** Logger da requisição, já com `reqId` (F-06). */
|
|
44
|
+
readonly log: Logger;
|
|
45
|
+
/** Parâmetros de rota; tipados pelo schema `params` quando informado em `Context<S>`. */
|
|
46
|
+
params: InferParams<S>;
|
|
47
|
+
/** Query string; tipada pelo schema `query` (já com coerção e defaults aplicados). */
|
|
48
|
+
query: InferQuery<S>;
|
|
49
|
+
/** Body; tipado pelo schema `body`. */
|
|
50
|
+
body: InferBody<S>;
|
|
51
|
+
state: ContextState;
|
|
52
|
+
/** `true` quando o handler chamou `ctx.status()`. Usado para escolher o schema de resposta (B-05). */
|
|
53
|
+
statusExplicit: boolean;
|
|
54
|
+
private streaming;
|
|
55
|
+
constructor(req: IncomingMessage, res: ServerResponse, opts?: ContextOptions);
|
|
56
|
+
/** IP do cliente conforme o socket. Sem `trustProxy`, `X-Forwarded-For` é ignorado (S-09). */
|
|
57
|
+
get ip(): string;
|
|
58
|
+
status(code: number): this;
|
|
59
|
+
/**
|
|
60
|
+
* `true` quando a resposta já foi enviada (ou está sendo, no caso de streams).
|
|
61
|
+
* Depois disso o framework não escreve mais nada na resposta.
|
|
62
|
+
*/
|
|
63
|
+
get sent(): boolean;
|
|
64
|
+
/** Lê um header da requisição (case-insensitive). Headers repetidos são unidos com `, `. */
|
|
65
|
+
get(name: string): string | undefined;
|
|
66
|
+
/** Define um header da resposta. */
|
|
67
|
+
header(name: string, value: OutgoingHttpHeader): this;
|
|
68
|
+
json(data: unknown): this;
|
|
69
|
+
/** Resposta em texto puro (`text/plain; charset=utf-8`). */
|
|
70
|
+
text(data: string): this;
|
|
71
|
+
/**
|
|
72
|
+
* Envia string, Buffer/Uint8Array ou stream (`Readable`). O `Content-Type` padrão é
|
|
73
|
+
* `application/octet-stream`; passe o tipo correto. Para HTML, faça o escape do conteúdo
|
|
74
|
+
* dinâmico antes: o framework não faz isso por você (S-02).
|
|
75
|
+
*/
|
|
76
|
+
send(body: string | Uint8Array | Readable, contentType?: string): this;
|
|
77
|
+
/**
|
|
78
|
+
* Redireciona (padrão 302). Não use `url` vinda do usuário sem validar: isso abre um
|
|
79
|
+
* open redirect. Prefira caminhos relativos ou uma lista de destinos permitidos.
|
|
80
|
+
*/
|
|
81
|
+
redirect(url: string, status?: 301 | 302 | 303 | 307 | 308): this;
|
|
82
|
+
throw(status: number, message: string, code?: string): never;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACrF,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIvC,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,4EAA4E;IAC5E,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,qBAAa,OAAO,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY;IACxD,QAAQ,CAAC,GAAG,EAAE,eAAe,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,yFAAyF;IACzF,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAwB;IAC9C,sFAAsF;IACtF,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACrB,uCAAuC;IACvC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAA6B;IAC/C,KAAK,EAAE,YAAY,CAAM;IAEzB,sGAAsG;IACtG,cAAc,UAAS;IAEvB,OAAO,CAAC,SAAS,CAAS;IAE1B,YAAY,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,GAAE,cAAmB,EAS/E;IAED,8FAA8F;IAC9F,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIzB;IAED;;;OAGG;IACH,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,4FAA4F;IAC5F,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGpC;IAED,oCAAoC;IACpC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAGpD;IAED,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAKxB;IAED,4DAA4D;IAC5D,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEvB;IAED;;;;OAIG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAerE;IAED;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAS,GAAG,IAAI,CAMrE;IAED,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAE3D;CACF"}
|