sashiko 0.2.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 +90 -13
- package/dist/core/app.d.ts +24 -3
- package/dist/core/app.d.ts.map +1 -1
- package/dist/core/app.js +56 -4
- package/dist/core/app.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 +4 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -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 +17 -1
- 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/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/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/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,6BAA6B,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAClI,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACjE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAClH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC/G,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,oBAAoB,EAAE,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjH,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,6BAA6B,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAClI,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACjE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAClH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC/G,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,oBAAoB,EAAE,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjH,OAAO,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACtI,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACrI,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3L,YAAY,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/core/index.js
CHANGED
|
@@ -4,5 +4,5 @@ export { MountedGroup } from './mounted-group.js';
|
|
|
4
4
|
export { consoleLogger, silentLogger } from './logger.js';
|
|
5
5
|
export { Context } from './context.js';
|
|
6
6
|
export { badRequest, forbidden, HttpError, internal, isHttpError, notFound, unauthorized } from './errors.js';
|
|
7
|
-
export { ROUTER_METADATA, readOwnMetadata } from './metadata.js';
|
|
7
|
+
export { isResponseContent, ROUTER_METADATA, readOwnMetadata } from './metadata.js';
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,6BAA6B,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAmF,MAAM,UAAU,CAAC;AAGlI,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,6BAA6B,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAmF,MAAM,UAAU,CAAC;AAGlI,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMlD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAyD,MAAM,aAAa,CAAC;AACjH,OAAO,EAAE,OAAO,EAAiG,MAAM,cAAc,CAAC;AACtI,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAyB,MAAM,aAAa,CAAC;AACrI,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAyG,MAAM,eAAe,CAAC"}
|
package/dist/core/infer.d.ts
CHANGED
|
@@ -31,6 +31,14 @@ export type InferHeaders<S extends RouteSchemas> = InferSchema<S['headers'], Rec
|
|
|
31
31
|
* Útil para anotar o retorno do handler: `create(ctx): InferResponse<typeof create, 201>`.
|
|
32
32
|
*/
|
|
33
33
|
export type InferResponse<S extends RouteSchemas, Status extends number = number> = S['response'] extends Record<number, unknown> ? {
|
|
34
|
-
[K in keyof S['response'] & Status]: InferSchema<S['response'][K]
|
|
34
|
+
[K in keyof S['response'] & Status]: InferSchema<UnwrapResponse<S['response'][K]>>;
|
|
35
35
|
}[keyof S['response'] & Status] : unknown;
|
|
36
|
+
/** `{ contentType, schema }` → `schema`; um schema JSON direto continua como está (F-31). */
|
|
37
|
+
type UnwrapResponse<E> = E extends {
|
|
38
|
+
contentType: unknown;
|
|
39
|
+
schema: infer S;
|
|
40
|
+
} ? S : E extends {
|
|
41
|
+
contentType: unknown;
|
|
42
|
+
} ? undefined : E;
|
|
43
|
+
export {};
|
|
36
44
|
//# sourceMappingURL=infer.d.ts.map
|
package/dist/core/infer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"infer.d.ts","sourceRoot":"","sources":["../../src/core/infer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;GAKG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,IAC3C;IAAC,WAAW,CAAC,CAAC,CAAC;CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,QAAQ,GACzC,WAAW,CAAC,CAAC,CAAC,SAAS;IAAE,WAAW,EAAE;QAAE,KAAK,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC,CAAA;SAAE,GAAG,SAAS,CAAA;KAAE,CAAA;CAAE,GAAG,CAAC,GACvF,WAAW,CAAC,CAAC,CAAC,SAAS;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG;IAAE,MAAM,EAAE,EAAE,CAAA;CAAE,CAAC,CAAC,QAAQ,CAAC,GACxF,QAAQ,CAAC;AAEb,gDAAgD;AAChD,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AACnG,+CAA+C;AAC/C,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC;AAC5G,8CAA8C;AAC9C,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;AAChF,sDAAsD;AACtD,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;AAE5H;;;GAGG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,SAAS,MAAM,GAAG,MAAM,IAC9E,CAAC,CAAC,UAAU,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACzC;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"infer.d.ts","sourceRoot":"","sources":["../../src/core/infer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;GAKG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,IAC3C;IAAC,WAAW,CAAC,CAAC,CAAC;CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,QAAQ,GACzC,WAAW,CAAC,CAAC,CAAC,SAAS;IAAE,WAAW,EAAE;QAAE,KAAK,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC,CAAA;SAAE,GAAG,SAAS,CAAA;KAAE,CAAA;CAAE,GAAG,CAAC,GACvF,WAAW,CAAC,CAAC,CAAC,SAAS;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG;IAAE,MAAM,EAAE,EAAE,CAAA;CAAE,CAAC,CAAC,QAAQ,CAAC,GACxF,QAAQ,CAAC;AAEb,gDAAgD;AAChD,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AACnG,+CAA+C;AAC/C,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC;AAC5G,8CAA8C;AAC9C,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;AAChF,sDAAsD;AACtD,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;AAE5H;;;GAGG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,SAAS,MAAM,GAAG,MAAM,IAC9E,CAAC,CAAC,UAAU,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACzC;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,GACpH,OAAO,CAAC;AAEd,6FAA6F;AAC7F,KAAK,cAAc,CAAC,CAAC,IACnB,CAAC,SAAS;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GACrD,CAAC,SAAS;IAAE,WAAW,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,GAC9C,CAAC,CAAC"}
|
package/dist/core/metadata.d.ts
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
import type { Middleware } from './compose.ts';
|
|
2
2
|
import type { Guard } from './guard.ts';
|
|
3
3
|
export declare const ROUTER_METADATA: unique symbol;
|
|
4
|
+
/**
|
|
5
|
+
* Resposta com tipo de conteúdo declarado (F-31). Sem `contentType`, a entrada é um schema JSON.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* response: { 200: { contentType: ['application/json', 'text/csv'], schema: Users } }
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export interface ResponseContent {
|
|
12
|
+
/** Um tipo ou a lista de tipos oferecidos; com vários, o cliente escolhe pelo `Accept`. */
|
|
13
|
+
contentType: string | readonly string[];
|
|
14
|
+
/** Schema dos dados. Em formatos não JSON, valida e remove campos antes do serializador. */
|
|
15
|
+
schema?: object;
|
|
16
|
+
}
|
|
17
|
+
/** Schema JSON (como sempre) ou `{ contentType, schema? }`. */
|
|
18
|
+
export type ResponseEntry = object | ResponseContent;
|
|
4
19
|
export interface RouteSchemas {
|
|
5
20
|
params?: object;
|
|
6
21
|
body?: object;
|
|
7
22
|
query?: object;
|
|
8
23
|
headers?: object;
|
|
9
|
-
response?: Record<number,
|
|
24
|
+
response?: Record<number, ResponseEntry>;
|
|
10
25
|
}
|
|
26
|
+
export declare function isResponseContent(entry: unknown): entry is ResponseContent;
|
|
11
27
|
export interface MethodMetadata {
|
|
12
28
|
method?: string;
|
|
13
29
|
path?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/core/metadata.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,eAAO,MAAM,eAAe,eAA+B,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/core/metadata.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,eAAO,MAAM,eAAe,eAA+B,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,2FAA2F;IAC3F,WAAW,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IACxC,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,eAAe,CAAC;AAErD,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CAC1C;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAI1E;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,uCAAuC;IACvC,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,kCAAkC;IAClC,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;IAC9C,4EAA4E;IAC5E,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,kCAAkC;IAClC,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,uBAAuB,GAAG,cAAc,CAoBjF;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAKzE;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAe/E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAW/F;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,CAO7F"}
|
package/dist/core/metadata.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
export const ROUTER_METADATA = Symbol.for('sashiko:router');
|
|
2
|
+
export function isResponseContent(entry) {
|
|
3
|
+
if (typeof entry !== 'object' || entry === null || !('contentType' in entry))
|
|
4
|
+
return false;
|
|
5
|
+
const ct = entry.contentType;
|
|
6
|
+
return typeof ct === 'string' || Array.isArray(ct);
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
* Retorna a metadata **própria** da classe.
|
|
4
10
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/core/metadata.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/core/metadata.ts"],"names":[],"mappings":"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"}
|
package/dist/core/response.d.ts
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type
|
|
1
|
+
import { type Context } from './context.ts';
|
|
2
|
+
import { type RouteSchemas } from './metadata.ts';
|
|
3
|
+
/** Converte dados num corpo de resposta para um content type (F-31). */
|
|
4
|
+
export type Serializer = (data: unknown) => string | Uint8Array;
|
|
3
5
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* - Com schemas de resposta declarados, um status sem schema correspondente **não** cai no
|
|
7
|
-
* `JSON.stringify`, que mandaria o objeto inteiro (S-07): vira 500 e o motivo vai para o log.
|
|
8
|
-
* - Respostas sem corpo (`undefined`) dispensam schema.
|
|
6
|
+
* Como o corpo chegou ao pipeline (F-32): `auto` (`return` e `ctx.send()`), `json` (`ctx.json()`,
|
|
7
|
+
* sempre JSON) ou `text` (`ctx.text()`, sempre texto).
|
|
9
8
|
*/
|
|
10
|
-
export
|
|
9
|
+
export type SendMode = 'auto' | 'json' | 'text';
|
|
10
|
+
/**
|
|
11
|
+
* Envia o retorno do handler.
|
|
12
|
+
*
|
|
13
|
+
* Status (B-05): sem `ctx.status()` e com um único 2xx declarado, esse 2xx vira o padrão. Com schemas
|
|
14
|
+
* de resposta declarados, um status sem schema correspondente vira 500 em vez de enviar o objeto
|
|
15
|
+
* sem filtro (S-07). Respostas sem corpo (`undefined`) dispensam schema.
|
|
16
|
+
*
|
|
17
|
+
* Content type (F-31), em ordem de prioridade:
|
|
18
|
+
* 1. o `Content-Type` definido pelo handler;
|
|
19
|
+
* 2. o `contentType` declarado no schema de resposta (com negociação pelo `Accept` se houver vários);
|
|
20
|
+
* 3. schema de resposta sem `contentType` → JSON;
|
|
21
|
+
* 4. sem schema, o tipo do valor: string → `text/plain`, Buffer/Uint8Array/stream → `application/octet-stream`,
|
|
22
|
+
* o resto → JSON.
|
|
23
|
+
*/
|
|
24
|
+
export declare function sendResult(ctx: Context, response: RouteSchemas['response'], result: unknown, serializers?: ReadonlyMap<string, Serializer>, mode?: SendMode): void;
|
|
11
25
|
/**
|
|
12
26
|
* Resposta de erro padrão. Só mensagens marcadas como `expose` chegam ao cliente;
|
|
13
27
|
* o resto vira 500 genérico e o erro original é logado no servidor (S-05).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../src/core/response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../src/core/response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAY,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAQrE,wEAAwE;AACxE,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,GAAG,UAAU,CAAC;AAEhE;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAIhD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,YAAY,CAAC,UAAU,CAAC,EAClC,MAAM,EAAE,OAAO,EACf,WAAW,GAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAa,EACxD,IAAI,GAAE,QAAiB,GACtB,IAAI,CAwCN;AAyDD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,IAAI,CAc1D"}
|
package/dist/core/response.js
CHANGED
|
@@ -1,31 +1,107 @@
|
|
|
1
|
+
import { kRawSend } from './context.js';
|
|
1
2
|
import { HttpError } from './errors.js';
|
|
3
|
+
import { isResponseContent } from './metadata.js';
|
|
4
|
+
import { Readable } from 'node:stream';
|
|
2
5
|
import { serialize } from '../schema/serialization.js';
|
|
6
|
+
import { stripToSchema } from '../schema/validation.js';
|
|
7
|
+
import { isJsonContentType, mediaType, negotiate, withCharset } from '../utils/content-type.js';
|
|
3
8
|
const GENERIC_500 = 'Internal Server Error';
|
|
9
|
+
const JSON_TYPE = 'application/json';
|
|
4
10
|
/**
|
|
5
|
-
* Envia o retorno do handler
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
9
|
-
* - Respostas sem corpo (`undefined`) dispensam schema.
|
|
11
|
+
* Envia o retorno do handler.
|
|
12
|
+
*
|
|
13
|
+
* Status (B-05): sem `ctx.status()` e com um único 2xx declarado, esse 2xx vira o padrão. Com schemas
|
|
14
|
+
* de resposta declarados, um status sem schema correspondente vira 500 em vez de enviar o objeto
|
|
15
|
+
* sem filtro (S-07). Respostas sem corpo (`undefined`) dispensam schema.
|
|
16
|
+
*
|
|
17
|
+
* Content type (F-31), em ordem de prioridade:
|
|
18
|
+
* 1. o `Content-Type` definido pelo handler;
|
|
19
|
+
* 2. o `contentType` declarado no schema de resposta (com negociação pelo `Accept` se houver vários);
|
|
20
|
+
* 3. schema de resposta sem `contentType` → JSON;
|
|
21
|
+
* 4. sem schema, o tipo do valor: string → `text/plain`, Buffer/Uint8Array/stream → `application/octet-stream`,
|
|
22
|
+
* o resto → JSON.
|
|
10
23
|
*/
|
|
11
|
-
export function sendResult(ctx, response, result) {
|
|
24
|
+
export function sendResult(ctx, response, result, serializers = new Map(), mode = 'auto') {
|
|
12
25
|
if (response && !ctx.statusExplicit) {
|
|
13
|
-
const success = Object.keys(response).map(Number).filter((
|
|
26
|
+
const success = Object.keys(response).map(Number).filter((st) => st >= 200 && st < 300);
|
|
14
27
|
if (success.length === 1 && response[200] === undefined)
|
|
15
28
|
ctx.res.statusCode = success[0];
|
|
16
29
|
}
|
|
17
30
|
if (result === undefined)
|
|
18
31
|
return void ctx.res.end();
|
|
19
32
|
const status = ctx.res.statusCode;
|
|
20
|
-
const
|
|
21
|
-
if (
|
|
22
|
-
ctx.res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
23
|
-
return void ctx.res.end(serialize(schema, result));
|
|
24
|
-
}
|
|
25
|
-
if (response && Object.keys(response).length > 0) {
|
|
33
|
+
const entry = response?.[status];
|
|
34
|
+
if (!entry && response && Object.keys(response).length > 0) {
|
|
26
35
|
throw new Error(`[sashiko] ${ctx.method} ${ctx.path}: no response schema for status ${status}`);
|
|
27
36
|
}
|
|
28
|
-
ctx.
|
|
37
|
+
const headerType = ctx.res.getHeader('Content-Type');
|
|
38
|
+
const explicit = mode === 'json' ? JSON_TYPE
|
|
39
|
+
: mode === 'text' ? 'text/plain'
|
|
40
|
+
: typeof headerType === 'string' ? headerType : undefined;
|
|
41
|
+
let type;
|
|
42
|
+
let schema;
|
|
43
|
+
let jsonSchemaDeclared = false;
|
|
44
|
+
if (entry && isResponseContent(entry)) {
|
|
45
|
+
schema = entry.schema;
|
|
46
|
+
const offered = typeof entry.contentType === 'string' ? [entry.contentType] : [...entry.contentType];
|
|
47
|
+
if (offered.length > 1)
|
|
48
|
+
ctx.res.appendHeader('Vary', 'Accept');
|
|
49
|
+
const chosen = explicit ?? negotiate(ctx.get('accept'), offered);
|
|
50
|
+
if (!chosen) {
|
|
51
|
+
throw new HttpError(406, 'Not Acceptable', 'NOT_ACCEPTABLE', { details: { available: offered } });
|
|
52
|
+
}
|
|
53
|
+
type = chosen;
|
|
54
|
+
}
|
|
55
|
+
else if (entry) {
|
|
56
|
+
schema = entry;
|
|
57
|
+
jsonSchemaDeclared = true;
|
|
58
|
+
type = explicit ?? JSON_TYPE;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
type = explicit ?? inferType(result);
|
|
62
|
+
}
|
|
63
|
+
write(ctx, type, result, schema, mode === 'json' || (jsonSchemaDeclared && !explicit), serializers);
|
|
64
|
+
}
|
|
65
|
+
function inferType(value) {
|
|
66
|
+
if (typeof value === 'string')
|
|
67
|
+
return 'text/plain';
|
|
68
|
+
if (value instanceof Uint8Array || value instanceof Readable)
|
|
69
|
+
return 'application/octet-stream';
|
|
70
|
+
return JSON_TYPE;
|
|
71
|
+
}
|
|
72
|
+
function write(ctx, type, value, schema, forceJson, serializers) {
|
|
73
|
+
const header = withCharset(type);
|
|
74
|
+
const base = mediaType(type);
|
|
75
|
+
const json = isJsonContentType(base);
|
|
76
|
+
if (value instanceof Readable)
|
|
77
|
+
return void ctx[kRawSend](value, header);
|
|
78
|
+
// Valores crus (string/Buffer) vão como estão, exceto quando a rota declarou um schema JSON:
|
|
79
|
+
// nesse caso `"olá"` continua sendo serializado como JSON, como sempre.
|
|
80
|
+
if ((typeof value === 'string' || value instanceof Uint8Array) && !forceJson) {
|
|
81
|
+
if (schema && typeof value === 'string')
|
|
82
|
+
ensureValid(ctx, schema, value);
|
|
83
|
+
return void ctx[kRawSend](value, header);
|
|
84
|
+
}
|
|
85
|
+
if (json) {
|
|
86
|
+
ctx.res.setHeader('Content-Type', header);
|
|
87
|
+
return void ctx.res.end(schema ? serialize(schema, value) : JSON.stringify(value));
|
|
88
|
+
}
|
|
89
|
+
const serializer = serializers.get(base);
|
|
90
|
+
if (!serializer) {
|
|
91
|
+
throw new Error(`[sashiko] ${ctx.method} ${ctx.path}: no serializer registered for "${base}". ` +
|
|
92
|
+
`Add it to createApp({ serializers: { '${base}': (data) => ... } }).`);
|
|
93
|
+
}
|
|
94
|
+
const data = schema ? ensureValid(ctx, schema, value) : value;
|
|
95
|
+
ctx[kRawSend](Buffer.from(serializer(data)), header);
|
|
96
|
+
}
|
|
97
|
+
/** Valida a saída e devolve uma cópia sem campos não declarados (S-07 em qualquer formato). */
|
|
98
|
+
function ensureValid(ctx, schema, value) {
|
|
99
|
+
const checked = stripToSchema(schema, value);
|
|
100
|
+
if (!checked.ok) {
|
|
101
|
+
throw new Error(`[sashiko] ${ctx.method} ${ctx.path}: response does not match its schema: ` +
|
|
102
|
+
checked.issues.map((i) => `${i.path} ${i.message}`).join('; '));
|
|
103
|
+
}
|
|
104
|
+
return checked.value;
|
|
29
105
|
}
|
|
30
106
|
/**
|
|
31
107
|
* Resposta de erro padrão. Só mensagens marcadas como `expose` chegam ao cliente;
|
|
@@ -44,6 +120,8 @@ export function sendError(ctx, err) {
|
|
|
44
120
|
const body = { error: exposed ? httpErr.message : GENERIC_500 };
|
|
45
121
|
if (exposed && httpErr.details !== undefined)
|
|
46
122
|
body.details = httpErr.details;
|
|
47
|
-
|
|
123
|
+
// Erros nunca passam pelo schema da rota (F-32): envio cru.
|
|
124
|
+
ctx.res.statusCode = status;
|
|
125
|
+
ctx[kRawSend](JSON.stringify(body), 'application/json; charset=utf-8');
|
|
48
126
|
}
|
|
49
127
|
//# sourceMappingURL=response.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/core/response.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/core/response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,QAAQ,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAqB,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEhG,MAAM,WAAW,GAAG,uBAAuB,CAAC;AAW5C,MAAM,SAAS,GAAG,kBAAkB,CAAC;AAErC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,UAAU,CACxB,GAAY,EACZ,QAAkC,EAClC,MAAe,EACf,WAAW,GAAoC,IAAI,GAAG,EAAE,EACxD,IAAI,GAAa,MAAM;IAEvB,IAAI,QAAQ,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC,CAAC;QACxF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,SAAS;YAAE,GAAG,CAAC,GAAG,CAAC,UAAU,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;IAC5F,CAAC;IAED,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,KAAK,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;IAEpD,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC;IAClC,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK,IAAI,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,mCAAmC,MAAM,EAAE,CAAC,CAAC;IAClG,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS;QAC1C,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY;YAChC,CAAC,CAAC,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,IAAI,IAAY,CAAC;IACjB,IAAI,MAA0B,CAAC;IAC/B,IAAI,kBAAkB,GAAG,KAAK,CAAC;IAE/B,IAAI,KAAK,IAAI,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QACtB,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;QACrG,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,QAAQ,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QACjE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,SAAS,CAAC,GAAG,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QACpG,CAAC;QACD,IAAI,GAAG,MAAM,CAAC;IAChB,CAAC;SAAM,IAAI,KAAK,EAAE,CAAC;QACjB,MAAM,GAAG,KAAK,CAAC;QACf,kBAAkB,GAAG,IAAI,CAAC;QAC1B,IAAI,GAAG,QAAQ,IAAI,SAAS,CAAC;IAC/B,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,QAAQ,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,KAAK,MAAM,IAAI,CAAC,kBAAkB,IAAI,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC,CAAC;AACtG,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,YAAY,CAAC;IACnD,IAAI,KAAK,YAAY,UAAU,IAAI,KAAK,YAAY,QAAQ;QAAE,OAAO,0BAA0B,CAAC;IAChG,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,KAAK,CACZ,GAAY,EACZ,IAAY,EACZ,KAAc,EACd,MAA0B,EAC1B,SAAkB,EAClB,WAA4C;IAE5C,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAErC,IAAI,KAAK,YAAY,QAAQ;QAAE,OAAO,KAAK,GAAG,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAExE,6FAA6F;IAC7F,wEAAwE;IACxE,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,YAAY,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QAC7E,IAAI,MAAM,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACzE,OAAO,KAAK,GAAG,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,IAAI,EAAE,CAAC;QACT,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QAC1C,OAAO,KAAK,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACrF,CAAC;IAED,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,aAAa,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,mCAAmC,IAAI,KAAK;YAC/E,yCAAyC,IAAI,wBAAwB,CACtE,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC9D,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACvD,CAAC;AAED,+FAA+F;AAC/F,SAAS,WAAW,CAAC,GAAY,EAAE,MAAc,EAAE,KAAc;IAC/D,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7C,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,aAAa,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,wCAAwC;YAC3E,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAC/D,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,GAAY,EAAE,GAAY;IAClD,MAAM,OAAO,GAAG,GAAG,YAAY,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,GAAG,CAAC;IACtC,MAAM,OAAO,GAAG,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAEzC,IAAI,CAAC,OAAO;QAAE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC;IACnG,IAAI,GAAG,CAAC,GAAG,CAAC,aAAa;QAAE,OAAO;IAClC,IAAI,GAAG,CAAC,GAAG,CAAC,WAAW;QAAE,OAAO,KAAK,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;IAEnD,MAAM,IAAI,GAAyC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,OAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACvG,IAAI,OAAO,IAAI,OAAQ,CAAC,OAAO,KAAK,SAAS;QAAE,IAAI,CAAC,OAAO,GAAG,OAAQ,CAAC,OAAO,CAAC;IAC/E,4DAA4D;IAC5D,GAAG,CAAC,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC;IAC5B,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,iCAAiC,CAAC,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Logger } from './logger.ts';
|
|
2
|
+
export interface ShutdownOptions {
|
|
3
|
+
/** Sinais tratados. Padrão: `['SIGINT', 'SIGTERM']`. */
|
|
4
|
+
signals?: readonly NodeJS.Signals[];
|
|
5
|
+
/** Prazo para as requisições em andamento terminarem. Padrão: 10s. */
|
|
6
|
+
timeoutMs?: number;
|
|
7
|
+
/** Executado depois que o servidor fecha (banco, filas…). Se lançar, o processo sai com código 1. */
|
|
8
|
+
onShutdown?: (signal: NodeJS.Signals) => void | Promise<void>;
|
|
9
|
+
/** Chama `process.exit` ao final. Padrão: `true`. Use `false` se outro código controla o processo. */
|
|
10
|
+
exit?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** O que o coordenador precisa de cada app que está ouvindo. */
|
|
13
|
+
export interface ShutdownTarget {
|
|
14
|
+
readonly log: Logger;
|
|
15
|
+
/** Fecha o app e roda o `onShutdown`; resolve com `false` se algo falhou. */
|
|
16
|
+
shutdown(signal: NodeJS.Signals): Promise<boolean>;
|
|
17
|
+
/** Se este app quer `process.exit` ao final. */
|
|
18
|
+
readonly exitOnShutdown: boolean;
|
|
19
|
+
readonly signals: readonly NodeJS.Signals[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Coordena o encerramento de todos os apps ouvindo no processo (F-07):
|
|
23
|
+
* um único listener por sinal, compartilhado, removido quando o último app fecha.
|
|
24
|
+
*/
|
|
25
|
+
declare class ShutdownCoordinator {
|
|
26
|
+
private readonly targets;
|
|
27
|
+
private readonly listeners;
|
|
28
|
+
private shuttingDown;
|
|
29
|
+
register(target: ShutdownTarget): void;
|
|
30
|
+
unregister(target: ShutdownTarget): void;
|
|
31
|
+
private prune;
|
|
32
|
+
private onSignal;
|
|
33
|
+
}
|
|
34
|
+
export declare const shutdownCoordinator: ShutdownCoordinator;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=shutdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../../src/core/shutdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,OAAO,CAAC,EAAE,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC;IACpC,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qGAAqG;IACrG,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,sGAAsG;IACtG,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,gDAAgD;IAChD,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC;CAC7C;AAED;;;GAGG;AACH,cAAM,mBAAmB;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyC;IACnE,OAAO,CAAC,YAAY,CAAS;IAE7B,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAQrC;IAED,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAKvC;IAED,OAAO,CAAC,KAAK;YASC,QAAQ;CAgBvB;AAED,eAAO,MAAM,mBAAmB,qBAA4B,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordena o encerramento de todos os apps ouvindo no processo (F-07):
|
|
3
|
+
* um único listener por sinal, compartilhado, removido quando o último app fecha.
|
|
4
|
+
*/
|
|
5
|
+
class ShutdownCoordinator {
|
|
6
|
+
targets = new Set();
|
|
7
|
+
listeners = new Map();
|
|
8
|
+
shuttingDown = false;
|
|
9
|
+
register(target) {
|
|
10
|
+
this.targets.add(target);
|
|
11
|
+
for (const signal of target.signals) {
|
|
12
|
+
if (this.listeners.has(signal))
|
|
13
|
+
continue;
|
|
14
|
+
const listener = () => void this.onSignal(signal);
|
|
15
|
+
this.listeners.set(signal, listener);
|
|
16
|
+
process.on(signal, listener);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
unregister(target) {
|
|
20
|
+
this.targets.delete(target);
|
|
21
|
+
// Durante um encerramento, os listeners ficam até o fim: o segundo sinal precisa ser ouvido
|
|
22
|
+
// enquanto o onShutdown ainda roda (ex.: fechando o banco).
|
|
23
|
+
if (!this.shuttingDown)
|
|
24
|
+
this.prune();
|
|
25
|
+
}
|
|
26
|
+
prune() {
|
|
27
|
+
const stillUsed = new Set([...this.targets].flatMap((t) => t.signals));
|
|
28
|
+
for (const [signal, listener] of this.listeners) {
|
|
29
|
+
if (stillUsed.has(signal))
|
|
30
|
+
continue;
|
|
31
|
+
process.off(signal, listener);
|
|
32
|
+
this.listeners.delete(signal);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async onSignal(signal) {
|
|
36
|
+
const targets = [...this.targets].filter((t) => t.signals.includes(signal));
|
|
37
|
+
if (this.shuttingDown) {
|
|
38
|
+
// Segundo sinal durante o encerramento: o usuário quer sair já (Ctrl+C duplo).
|
|
39
|
+
targets[0]?.log.warn({ signal }, 'second signal received, forcing exit');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
this.shuttingDown = true;
|
|
43
|
+
targets[0]?.log.info({ signal }, 'shutting down gracefully');
|
|
44
|
+
const results = await Promise.all(targets.map((t) => t.shutdown(signal)));
|
|
45
|
+
const ok = results.every(Boolean);
|
|
46
|
+
this.shuttingDown = false;
|
|
47
|
+
this.prune();
|
|
48
|
+
if (targets.some((t) => t.exitOnShutdown))
|
|
49
|
+
process.exit(ok ? 0 : 1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export const shutdownCoordinator = new ShutdownCoordinator();
|
|
53
|
+
//# sourceMappingURL=shutdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../src/core/shutdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { cors, type CorsOptions, type CorsOrigin } from './cors.ts';
|
|
2
2
|
export { MemoryRateLimitStore, rateLimit, type RateLimitOptions, type RateLimitStore } from './rate-limit.ts';
|
|
3
|
-
export { buildSecurityHeaders, type SecurityHeadersOptions } from './security-headers.ts';
|
|
3
|
+
export { buildSecurityHeaders, type SecurityHeadersOptions, type SecurityPreset } from './security-headers.ts';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middlewares/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC9G,OAAO,EAAE,oBAAoB,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middlewares/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC9G,OAAO,EAAE,oBAAoB,EAAE,KAAK,sBAAsB,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middlewares/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAqC,MAAM,WAAW,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAA8C,MAAM,iBAAiB,CAAC;AAC9G,OAAO,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middlewares/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAqC,MAAM,WAAW,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAA8C,MAAM,iBAAiB,CAAC;AAC9G,OAAO,EAAE,oBAAoB,EAAoD,MAAM,uBAAuB,CAAC"}
|
|
@@ -18,9 +18,11 @@ export interface SecurityHeadersOptions {
|
|
|
18
18
|
preload?: boolean;
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
+
/** `'api'`: restritivo, para APIs (padrão). `'web'`: permite recursos do próprio site (F-31). */
|
|
22
|
+
export type SecurityPreset = 'api' | 'web';
|
|
21
23
|
/**
|
|
22
|
-
* Headers de segurança padrão (S-04) e proteções contra XSS
|
|
24
|
+
* Headers de segurança padrão (S-04) e proteções contra XSS (S-02).
|
|
23
25
|
* Retorna uma função que aplica os headers pré-calculados na resposta.
|
|
24
26
|
*/
|
|
25
|
-
export declare function buildSecurityHeaders(
|
|
27
|
+
export declare function buildSecurityHeaders(input?: SecurityHeadersOptions | SecurityPreset): (res: ServerResponse) => void;
|
|
26
28
|
//# sourceMappingURL=security-headers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-headers.d.ts","sourceRoot":"","sources":["../../src/middlewares/security-headers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,WAAW,sBAAsB;IACrC,uGAAuG;IACvG,qBAAqB,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACvC,6BAA6B;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAChC,sBAAsB;IACtB,YAAY,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,KAAK,CAAC;IAC7C,6BAA6B;IAC7B,yBAAyB,CAAC,EAAE,aAAa,GAAG,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC;IACjF;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACxG;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,
|
|
1
|
+
{"version":3,"file":"security-headers.d.ts","sourceRoot":"","sources":["../../src/middlewares/security-headers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,WAAW,sBAAsB;IACrC,uGAAuG;IACvG,qBAAqB,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACvC,6BAA6B;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAChC,sBAAsB;IACtB,YAAY,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,KAAK,CAAC;IAC7C,6BAA6B;IAC7B,yBAAyB,CAAC,EAAE,aAAa,GAAG,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC;IACjF;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACxG;AAED,iGAAiG;AACjG,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,CAAC;AAU3C;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,GAAE,sBAAsB,GAAG,cAAmB,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CA4BvH"}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
const PRESETS = {
|
|
2
|
+
api: {},
|
|
3
|
+
web: {
|
|
4
|
+
contentSecurityPolicy: "default-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'",
|
|
5
|
+
frameOptions: 'SAMEORIGIN',
|
|
6
|
+
},
|
|
7
|
+
};
|
|
1
8
|
/**
|
|
2
|
-
* Headers de segurança padrão (S-04) e proteções contra XSS
|
|
9
|
+
* Headers de segurança padrão (S-04) e proteções contra XSS (S-02).
|
|
3
10
|
* Retorna uma função que aplica os headers pré-calculados na resposta.
|
|
4
11
|
*/
|
|
5
|
-
export function buildSecurityHeaders(
|
|
12
|
+
export function buildSecurityHeaders(input = {}) {
|
|
13
|
+
const opts = typeof input === 'string' ? PRESETS[input] : input;
|
|
6
14
|
const headers = [['X-Content-Type-Options', 'nosniff']];
|
|
7
15
|
const csp = opts.contentSecurityPolicy ?? "default-src 'none'; frame-ancestors 'none'";
|
|
8
16
|
if (csp)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-headers.js","sourceRoot":"","sources":["../../src/middlewares/security-headers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"security-headers.js","sourceRoot":"","sources":["../../src/middlewares/security-headers.ts"],"names":[],"mappings":"AAqBA,MAAM,OAAO,GAAmD;IAC9D,GAAG,EAAE,EAAE;IACP,GAAG,EAAE;QACH,qBAAqB,EAAE,iFAAiF;QACxG,YAAY,EAAE,YAAY;KAC3B;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAK,GAA4C,EAAE;IACtF,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAChE,MAAM,OAAO,GAAuB,CAAC,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAC,CAAC;IAE5E,MAAM,GAAG,GAAG,IAAI,CAAC,qBAAqB,IAAI,4CAA4C,CAAC;IACvF,IAAI,GAAG;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC,CAAC;IAExD,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,IAAI,aAAa,CAAC;IACtD,IAAI,QAAQ;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE1D,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC;IAC1C,IAAI,KAAK;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAC;IAEpD,MAAM,IAAI,GAAG,IAAI,CAAC,yBAAyB,IAAI,aAAa,CAAC;IAC7D,IAAI,IAAI;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,8BAA8B,EAAE,IAAI,CAAC,CAAC,CAAC;IAE/D,MAAM,IAAI,GAAG,IAAI,CAAC,uBAAuB,CAAC;IAC1C,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,GAAG,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACjF,IAAI,KAAK,GAAG,WAAW,GAAG,CAAC,MAAM,EAAE,CAAC;QACpC,IAAI,GAAG,CAAC,iBAAiB;YAAE,KAAK,IAAI,qBAAqB,CAAC;QAC1D,IAAI,SAAS,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO;YAAE,KAAK,IAAI,WAAW,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,EAAE;QACb,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO;YAAE,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAClE,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -5,6 +5,17 @@ export interface ValidationIssue {
|
|
|
5
5
|
path: string;
|
|
6
6
|
message: string;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Valida `data` contra `schema` sobre uma cópia, removendo campos não declarados.
|
|
10
|
+
* Retorna a cópia filtrada, ou os problemas encontrados.
|
|
11
|
+
*/
|
|
12
|
+
export declare function stripToSchema(schema: object, data: unknown): {
|
|
13
|
+
ok: true;
|
|
14
|
+
value: unknown;
|
|
15
|
+
} | {
|
|
16
|
+
ok: false;
|
|
17
|
+
issues: ValidationIssue[];
|
|
18
|
+
};
|
|
8
19
|
/** Valida `data` contra `schema`. Retorna `null` se válido, ou a lista de problemas (B-02). */
|
|
9
20
|
export declare function validate(schema: object, data: unknown, target: ValidationTarget): ValidationIssue[] | null;
|
|
10
21
|
export declare function formatErrors(errors: ErrorObject[]): ValidationIssue[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/schema/validation.ts"],"names":[],"mappings":"AAAA,OAAkB,EAAE,KAAK,WAAW,EAAyB,MAAM,KAAK,CAAC;AAYzE,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/schema/validation.ts"],"names":[],"mappings":"AAAA,OAAkB,EAAE,KAAK,WAAW,EAAyB,MAAM,KAAK,CAAC;AAYzE,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAyBD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAQpI;AAkBD,+FAA+F;AAC/F,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,eAAe,EAAE,GAAG,IAAI,CAG1G;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,eAAe,EAAE,CAKrE"}
|
|
@@ -20,6 +20,24 @@ function createAjv(coerceTypes) {
|
|
|
20
20
|
// 'array' também converte valor único em array quando o schema pede array (`?tag=a` → `['a']`, B-07)
|
|
21
21
|
const coercing = createAjv('array');
|
|
22
22
|
const strict = createAjv(false);
|
|
23
|
+
// F-31: para respostas em formatos não JSON, remove TODOS os campos não declarados (como o
|
|
24
|
+
// fast-json-stringify faz no JSON) antes do serializador, sem alterar o objeto do handler.
|
|
25
|
+
const stripper = new Ajv({ allErrors: true, coerceTypes: false, useDefaults: false, removeAdditional: 'all' });
|
|
26
|
+
addFormats(stripper);
|
|
27
|
+
const stripCache = new WeakMap();
|
|
28
|
+
/**
|
|
29
|
+
* Valida `data` contra `schema` sobre uma cópia, removendo campos não declarados.
|
|
30
|
+
* Retorna a cópia filtrada, ou os problemas encontrados.
|
|
31
|
+
*/
|
|
32
|
+
export function stripToSchema(schema, data) {
|
|
33
|
+
let fn = stripCache.get(schema);
|
|
34
|
+
if (!fn) {
|
|
35
|
+
fn = stripper.compile(schema);
|
|
36
|
+
stripCache.set(schema, fn);
|
|
37
|
+
}
|
|
38
|
+
const copy = data === undefined ? undefined : JSON.parse(JSON.stringify(data));
|
|
39
|
+
return fn(copy) ? { ok: true, value: copy } : { ok: false, issues: formatErrors(fn.errors ?? []) };
|
|
40
|
+
}
|
|
23
41
|
const caches = new Map([
|
|
24
42
|
[coercing, new WeakMap()],
|
|
25
43
|
[strict, new WeakMap()],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/schema/validation.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,EAAE,EAA2C,MAAM,KAAK,CAAC;AACzE,OAAO,gBAAgB,MAAM,aAAa,CAAC;AAE3C,0EAA0E;AAC1E,0EAA0E;AAC1E,qEAAqE;AACrE,MAAM,GAAG,GAAG,CAAE,SAAiB,CAAC,OAAO,IAAI,SAAS,CAAiC,CAAC;AACtF,MAAM,UAAU,GAAG,CAAE,gBAAwB,CAAC,OAAO,IAAI,gBAAgB,CAGhE,CAAC;AAUV,SAAS,SAAS,CAAC,WAA8B;IAC/C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,CAAC;IAClG,UAAU,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,qGAAqG;AACrG,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;AACpC,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;AAEhC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC;IACrB,CAAC,QAAQ,EAAE,IAAI,OAAO,EAA4B,CAAC;IACnD,CAAC,MAAM,EAAE,IAAI,OAAO,EAA4B,CAAC;CAClD,CAAC,CAAC;AAEH,SAAS,OAAO,CAAC,MAAc,EAAE,MAAwB;IACvD,MAAM,GAAG,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;IAC/B,IAAI,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzB,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,IAAa,EAAE,MAAwB;IAC9E,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAqB;IAChD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACtB,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,IAAK,CAAC,CAAC,MAAsC,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChH,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,YAAY,GAAG,OAAO,EAAE,IAAI,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,SAAS,EAAE,CAAC;IACzF,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/schema/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
/** Media type sem parâmetros e em minúsculas: `"Application/JSON; charset=utf-8"` → `"application/json"`. */
|
|
2
2
|
export declare function mediaType(header: string | undefined): string;
|
|
3
|
+
/**
|
|
4
|
+
* Escolhe, entre os tipos `available` (em ordem de preferência do servidor), o melhor para o
|
|
5
|
+
* header `Accept` (F-31). Respeita q-values e curingas (`text/*`, `*\/*`). Sem `Accept`,
|
|
6
|
+
* devolve o primeiro. Retorna `undefined` quando nenhum é aceitável (→ 406).
|
|
7
|
+
*/
|
|
8
|
+
export declare function negotiate(accept: string | undefined, available: readonly string[]): string | undefined;
|
|
9
|
+
/** Acrescenta `charset=utf-8` a tipos textuais sem charset. */
|
|
10
|
+
export declare function withCharset(type: string): string;
|
|
3
11
|
/** `application/json` ou `application/*+json`, com parâmetros opcionais (B-11). */
|
|
4
12
|
export declare function isJsonContentType(header: string | undefined): boolean;
|
|
5
13
|
//# sourceMappingURL=content-type.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-type.d.ts","sourceRoot":"","sources":["../../src/utils/content-type.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE5D;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGrE"}
|
|
1
|
+
{"version":3,"file":"content-type.d.ts","sourceRoot":"","sources":["../../src/utils/content-type.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAiBtG;AAYD,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKhD;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGrE"}
|