sashiko 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +94 -5
  2. package/dist/core/app.d.ts +37 -1
  3. package/dist/core/app.d.ts.map +1 -1
  4. package/dist/core/app.js +85 -13
  5. package/dist/core/app.js.map +1 -1
  6. package/dist/core/body-parser.js +2 -2
  7. package/dist/core/body-parser.js.map +1 -1
  8. package/dist/core/compiler.d.ts +25 -1
  9. package/dist/core/compiler.d.ts.map +1 -1
  10. package/dist/core/compiler.js +55 -8
  11. package/dist/core/compiler.js.map +1 -1
  12. package/dist/core/context.d.ts +14 -9
  13. package/dist/core/context.d.ts.map +1 -1
  14. package/dist/core/context.js +1 -0
  15. package/dist/core/context.js.map +1 -1
  16. package/dist/core/errors.d.ts +26 -0
  17. package/dist/core/errors.d.ts.map +1 -1
  18. package/dist/core/errors.js +2 -0
  19. package/dist/core/errors.js.map +1 -1
  20. package/dist/core/index.d.ts +5 -5
  21. package/dist/core/index.d.ts.map +1 -1
  22. package/dist/core/index.js +1 -1
  23. package/dist/core/index.js.map +1 -1
  24. package/dist/core/infer.d.ts +26 -0
  25. package/dist/core/infer.d.ts.map +1 -1
  26. package/dist/core/mounted-group.d.ts +20 -2
  27. package/dist/core/mounted-group.d.ts.map +1 -1
  28. package/dist/core/mounted-group.js +34 -2
  29. package/dist/core/mounted-group.js.map +1 -1
  30. package/dist/core/response.d.ts +12 -3
  31. package/dist/core/response.d.ts.map +1 -1
  32. package/dist/core/response.js +35 -10
  33. package/dist/core/response.js.map +1 -1
  34. package/dist/decorators/http.d.ts +10 -5
  35. package/dist/decorators/http.d.ts.map +1 -1
  36. package/dist/decorators/http.js +7 -14
  37. package/dist/decorators/http.js.map +1 -1
  38. package/dist/index.d.ts +1 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +1 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/openapi/generate.d.ts +43 -0
  43. package/dist/openapi/generate.d.ts.map +1 -0
  44. package/dist/openapi/generate.js +136 -0
  45. package/dist/openapi/generate.js.map +1 -0
  46. package/dist/utils/path.d.ts +5 -0
  47. package/dist/utils/path.d.ts.map +1 -1
  48. package/dist/utils/path.js +49 -0
  49. package/dist/utils/path.js.map +1 -1
  50. package/package.json +1 -1
@@ -1,11 +1,11 @@
1
1
  import { kRawSend } from './context.js';
2
+ import { STATUS_CODES } from 'node:http';
2
3
  import { HttpError } from './errors.js';
3
4
  import { isResponseContent } from './metadata.js';
4
5
  import { Readable } from 'node:stream';
5
6
  import { serialize } from '../schema/serialization.js';
6
7
  import { stripToSchema } from '../schema/validation.js';
7
8
  import { isJsonContentType, mediaType, negotiate, withCharset } from '../utils/content-type.js';
8
- const GENERIC_500 = 'Internal Server Error';
9
9
  const JSON_TYPE = 'application/json';
10
10
  /**
11
11
  * Envia o retorno do handler.
@@ -103,11 +103,38 @@ function ensureValid(ctx, schema, value) {
103
103
  }
104
104
  return checked.value;
105
105
  }
106
+ /** Monta um Problem Details (RFC 9457). Sem `type`, usa `about:blank` e a frase do status como título. */
107
+ export function problem(status, detail, extra = {}) {
108
+ const out = { type: extra.type ?? 'about:blank', title: STATUS_CODES[status] ?? 'Error', status };
109
+ if (detail !== undefined && detail !== out.title)
110
+ out.detail = detail;
111
+ if (extra.code !== undefined)
112
+ out.code = extra.code;
113
+ if (extra.details !== undefined)
114
+ out.details = extra.details;
115
+ return out;
116
+ }
117
+ /** Escreve um problema (status + corpo), sem passar pelo schema da rota (F-32). */
118
+ export function sendProblem(ctx, body, format) {
119
+ ctx.res.statusCode = body.status;
120
+ if (format) {
121
+ let custom;
122
+ try {
123
+ custom = format(body, ctx);
124
+ }
125
+ catch (err) {
126
+ ctx.log.error({ err, method: ctx.method, path: ctx.path }, 'formatError failed; sending the default problem');
127
+ return void ctx[kRawSend](JSON.stringify(body), 'application/problem+json; charset=utf-8');
128
+ }
129
+ return void ctx[kRawSend](JSON.stringify(custom), 'application/json; charset=utf-8');
130
+ }
131
+ ctx[kRawSend](JSON.stringify(body), 'application/problem+json; charset=utf-8');
132
+ }
106
133
  /**
107
- * Resposta de erro padrão. Só mensagens marcadas como `expose` chegam ao cliente;
108
- * o resto vira 500 genérico e o erro original é logado no servidor (S-05).
134
+ * Resposta de erro padrão, no formato Problem Details (F-15). Só mensagens marcadas como `expose`
135
+ * chegam ao cliente; o resto vira 500 genérico e o erro original é logado no servidor (S-05).
109
136
  */
110
- export function sendError(ctx, err) {
137
+ export function sendError(ctx, err, format) {
111
138
  const httpErr = err instanceof HttpError ? err : undefined;
112
139
  const status = httpErr?.status ?? 500;
113
140
  const exposed = httpErr?.expose === true;
@@ -117,11 +144,9 @@ export function sendError(ctx, err) {
117
144
  return;
118
145
  if (ctx.res.headersSent)
119
146
  return void ctx.res.end();
120
- const body = { error: exposed ? httpErr.message : GENERIC_500 };
121
- if (exposed && httpErr.details !== undefined)
122
- body.details = httpErr.details;
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');
147
+ const body = exposed
148
+ ? problem(status, httpErr.message, { code: httpErr.code, details: httpErr.details, type: httpErr.type })
149
+ : problem(status);
150
+ sendProblem(ctx, body, format);
126
151
  }
127
152
  //# sourceMappingURL=response.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/core/response.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/core/response.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,6 @@
1
+ import type { CheckParams } from '../core/infer.ts';
1
2
  import { type RouteSchemas } from '../core/metadata.ts';
3
+ declare function methodDecorator(httpMethod: string, path: string, schemas?: RouteSchemas): <This, Args extends [any, ...unknown[]], Return>(_target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>) => void;
2
4
  /**
3
5
  * Decorators de rota. O segundo argumento, opcional, são os schemas da rota: o mesmo que `@Schema`,
4
6
  * na mesma linha do verbo.
@@ -8,9 +10,12 @@ import { type RouteSchemas } from '../core/metadata.ts';
8
10
  * getUser(ctx: Context<typeof byId>) {}
9
11
  * ```
10
12
  */
11
- export declare const Get: (path?: string, schemas?: RouteSchemas) => <This, Args extends [any, ...unknown[]], Return>(_target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>) => void;
12
- export declare const Post: (path?: string, schemas?: RouteSchemas) => <This, Args extends [any, ...unknown[]], Return>(_target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>) => void;
13
- export declare const Put: (path?: string, schemas?: RouteSchemas) => <This, Args extends [any, ...unknown[]], Return>(_target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>) => void;
14
- export declare const Patch: (path?: string, schemas?: RouteSchemas) => <This, Args extends [any, ...unknown[]], Return>(_target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>) => void;
15
- export declare const Delete: (path?: string, schemas?: RouteSchemas) => <This, Args extends [any, ...unknown[]], Return>(_target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>) => void;
13
+ type Verb = <const P extends string = '/', const S extends RouteSchemas = {}>(path?: P, schemas?: S & CheckParams<P, S>) => ReturnType<typeof methodDecorator>;
14
+ /** Com schema de `params`, as chaves precisam ser exatamente as do path, ou o TypeScript acusa (F-29). */
15
+ export declare const Get: Verb;
16
+ export declare const Post: Verb;
17
+ export declare const Put: Verb;
18
+ export declare const Patch: Verb;
19
+ export declare const Delete: Verb;
20
+ export {};
16
21
  //# sourceMappingURL=http.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/decorators/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAgBtG;;;;;;;;GAQG;AACH,eAAO,MAAM,GAAG,4BAA0B,YAAY,MArBnC,IAAI,EAAE,IAAI,SAAS,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,MAAM,WACpD,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,WACrC,2BAA2B,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,SAmBW,CAAC;AACjG,eAAO,MAAM,IAAI,4BAA0B,YAAY,MAtBpC,IAAI,EAAE,IAAI,SAAS,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,MAAM,WACpD,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,WACrC,2BAA2B,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,SAoBa,CAAC;AACnG,eAAO,MAAM,GAAG,4BAA0B,YAAY,MAvBnC,IAAI,EAAE,IAAI,SAAS,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,MAAM,WACpD,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,WACrC,2BAA2B,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,SAqBW,CAAC;AACjG,eAAO,MAAM,KAAK,4BAA0B,YAAY,MAxBrC,IAAI,EAAE,IAAI,SAAS,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,MAAM,WACpD,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,WACrC,2BAA2B,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,SAsBe,CAAC;AACrG,eAAO,MAAM,MAAM,4BAA0B,YAAY,MAzBtC,IAAI,EAAE,IAAI,SAAS,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,MAAM,WACpD,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,WACrC,2BAA2B,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,SAuBiB,CAAC"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/decorators/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEtG,iBAAS,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,IAE9D,IAAI,EAAE,IAAI,SAAS,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,MAAM,WACpD,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,WACrC,2BAA2B,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,UAQpF;AAED;;;;;;;;GAQG;AACH,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC,SAAS,YAAY,GAAG,EAAE,EAC1E,IAAI,CAAC,EAAE,CAAC,EACR,OAAO,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,KAC5B,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAIxC,0GAA0G;AAC1G,eAAO,MAAM,GAAG,MAAc,CAAC;AAC/B,eAAO,MAAM,IAAI,MAAe,CAAC;AACjC,eAAO,MAAM,GAAG,MAAc,CAAC;AAC/B,eAAO,MAAM,KAAK,MAAgB,CAAC;AACnC,eAAO,MAAM,MAAM,MAAiB,CAAC"}
@@ -10,18 +10,11 @@ function methodDecorator(httpMethod, path, schemas) {
10
10
  mergeSchemas(m, schemas, `@${label}`);
11
11
  };
12
12
  }
13
- /**
14
- * Decorators de rota. O segundo argumento, opcional, são os schemas da rota: o mesmo que `@Schema`,
15
- * na mesma linha do verbo.
16
- *
17
- * ```ts
18
- * @Get('/:id', byId)
19
- * getUser(ctx: Context<typeof byId>) {}
20
- * ```
21
- */
22
- export const Get = (path = '/', schemas) => methodDecorator('GET', path, schemas);
23
- export const Post = (path = '/', schemas) => methodDecorator('POST', path, schemas);
24
- export const Put = (path = '/', schemas) => methodDecorator('PUT', path, schemas);
25
- export const Patch = (path = '/', schemas) => methodDecorator('PATCH', path, schemas);
26
- export const Delete = (path = '/', schemas) => methodDecorator('DELETE', path, schemas);
13
+ const verb = (httpMethod) => (path, schemas) => methodDecorator(httpMethod, path ?? '/', schemas);
14
+ /** Com schema de `params`, as chaves precisam ser exatamente as do path, ou o TypeScript acusa (F-29). */
15
+ export const Get = verb('GET');
16
+ export const Post = verb('POST');
17
+ export const Put = verb('PUT');
18
+ export const Patch = verb('PATCH');
19
+ export const Delete = verb('DELETE');
27
20
  //# sourceMappingURL=http.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/decorators/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAqB,MAAM,qBAAqB,CAAC;AAEtG,SAAS,eAAe,CAAC,UAAkB,EAAE,IAAY,EAAE,OAAsB;IAC/E,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAChE,OAAO,UACL,OAA8C,EAC9C,OAAiF;QAEjF,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACzC,MAAM,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAChD,CAAC,CAAC,MAAM,GAAG,UAAU,CAAC;QACtB,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC;QACd,IAAI,OAAO;YAAE,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,EAAE,OAAsB,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACjG,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,GAAG,GAAG,EAAE,OAAsB,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACnG,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,EAAE,OAAsB,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACjG,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,GAAG,EAAE,OAAsB,EAAE,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACrG,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,IAAI,GAAG,GAAG,EAAE,OAAsB,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/decorators/http.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAqB,MAAM,qBAAqB,CAAC;AAEtG,SAAS,eAAe,CAAC,UAAkB,EAAE,IAAY,EAAE,OAAsB;IAC/E,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAChE,OAAO,UACL,OAA8C,EAC9C,OAAiF;QAEjF,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACzC,MAAM,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAChD,CAAC,CAAC,MAAM,GAAG,UAAU,CAAC;QACtB,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC;QACd,IAAI,OAAO;YAAE,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC;AAgBD,MAAM,IAAI,GAAG,CAAC,UAAkB,EAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,EAAE,IAAI,IAAI,GAAG,EAAE,OAAO,CAAC,CAAC;AAEhH,0GAA0G;AAC1G,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;AACjC,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -2,5 +2,6 @@ import './shims/symbol-metadata.ts';
2
2
  export * from './core/index.ts';
3
3
  export * from './decorators/index.ts';
4
4
  export * from './middlewares/index.ts';
5
+ export { toOpenAPIPath, type OpenAPIOptions } from './openapi/generate.ts';
5
6
  export { Type, type Static, type TSchema } from '@sinclair/typebox';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,4BAA4B,CAAC;AAEpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AAGvC,OAAO,EAAE,IAAI,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,4BAA4B,CAAC;AAEpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG3E,OAAO,EAAE,IAAI,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import './shims/symbol-metadata.js';
4
4
  export * from './core/index.js';
5
5
  export * from './decorators/index.js';
6
6
  export * from './middlewares/index.js';
7
+ export { toOpenAPIPath } from './openapi/generate.js';
7
8
  // Re-exporta TypeBox para que os usuários não precisem instalar como dependência separada
8
9
  export { Type } from '@sinclair/typebox';
9
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,iEAAiE;AACjE,OAAO,4BAA4B,CAAC;AAEpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AAEvC,0FAA0F;AAC1F,OAAO,EAAE,IAAI,EAA6B,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,iEAAiE;AACjE,OAAO,4BAA4B,CAAC;AAEpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,OAAO,EAAE,aAAa,EAAuB,MAAM,uBAAuB,CAAC;AAE3E,0FAA0F;AAC1F,OAAO,EAAE,IAAI,EAA6B,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,43 @@
1
+ import type { CompiledRoute } from '../core/compiler.ts';
2
+ import type { Middleware } from '../core/compose.ts';
3
+ import type { Guard } from '../core/guard.ts';
4
+ /** Opções de `app.openapi()` (F-16). */
5
+ export interface OpenAPIOptions {
6
+ /** Padrão: `{ title: 'API', version: '0.0.0' }`. */
7
+ info?: {
8
+ title: string;
9
+ version: string;
10
+ description?: string;
11
+ [key: string]: unknown;
12
+ };
13
+ servers?: readonly {
14
+ url: string;
15
+ description?: string;
16
+ }[];
17
+ /** Onde servir o documento JSON. Padrão: `'/openapi.json'`. */
18
+ path?: string;
19
+ /** Swagger UI. Desligado por padrão: `true` serve em `'/docs'`, uma string escolhe o path. */
20
+ docs?: string | boolean;
21
+ /** Rodam antes de servir o documento e a página, depois dos middlewares globais. */
22
+ middlewares?: readonly Middleware[];
23
+ /** Rodam depois dos `middlewares`, como nas rotas (401/403 antes de gerar o documento). */
24
+ guards?: readonly Guard[];
25
+ }
26
+ type Json = Record<string, unknown>;
27
+ /** `/:org/users/:id(^\\d+)` → `/{org}/users/{id}`; `::` → `:`; `*` → `{*}`; sem barra final (o roteador a ignora). */
28
+ export declare function toOpenAPIPath(path: string): string;
29
+ /**
30
+ * Gera o documento OpenAPI 3.1 a partir das rotas registradas (F-16). Os schemas TypeBox já são
31
+ * JSON Schema, então entram como estão. Schemas que não são JSON Schema (Zod etc.) não são convertidos.
32
+ */
33
+ export declare function generateOpenAPI(routes: readonly CompiledRoute[], opts: OpenAPIOptions, problemErrors: boolean): Json;
34
+ /**
35
+ * Página do Swagger UI (versão fixada, com SRI) e a CSP própria dela: scripts só do CDN e o inline com
36
+ * `nonce`, `connect-src 'self'` para buscar o documento.
37
+ */
38
+ export declare function docsPage(specUrl: string, title: string, nonce: string): {
39
+ html: string;
40
+ csp: string;
41
+ };
42
+ export {};
43
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/openapi/generate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACxF,OAAO,CAAC,EAAE,SAAS;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3D,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8FAA8F;IAC9F,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,oFAAoF;IACpF,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACpC,2FAA2F;IAC3F,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;CAC3B;AAED,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAKpC,sHAAsH;AACtH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOlD;AAiED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,GAAG,IAAI,CAoBpH;AASD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CA2BrG"}
@@ -0,0 +1,136 @@
1
+ import { STATUS_CODES } from 'node:http';
2
+ import { isResponseContent } from '../core/metadata.js';
3
+ /** Cópia em JSON puro: tira as chaves `Symbol` do TypeBox e qualquer coisa não serializável. */
4
+ const plain = (schema) => JSON.parse(JSON.stringify(schema));
5
+ /** `/:org/users/:id(^\\d+)` → `/{org}/users/{id}`; `::` → `:`; `*` → `{*}`; sem barra final (o roteador a ignora). */
6
+ export function toOpenAPIPath(path) {
7
+ return path
8
+ .replace(/::/g, '\u0000')
9
+ .replace(/:([^/\-.(]+)(\((?:\\.|[^\\])*?\))?/g, '{$1}')
10
+ .replace(/\*$/, '{*}')
11
+ .replace(/\u0000/g, ':')
12
+ .replace(/(.)\/$/, '$1');
13
+ }
14
+ /** Problem Details (RFC 9457), o corpo padrão de todos os erros (F-15). */
15
+ const PROBLEM_SCHEMA = {
16
+ type: 'object',
17
+ required: ['type', 'title', 'status'],
18
+ properties: {
19
+ type: { type: 'string' },
20
+ title: { type: 'string' },
21
+ status: { type: 'integer' },
22
+ detail: { type: 'string' },
23
+ code: { type: 'string' },
24
+ details: {},
25
+ },
26
+ };
27
+ function parameters(where, schema) {
28
+ const json = schema ? plain(schema) : undefined;
29
+ const props = json?.properties;
30
+ if (!props)
31
+ return [];
32
+ const required = new Set(json.required ?? []);
33
+ return Object.entries(props).map(([name, s]) => ({
34
+ name,
35
+ in: where,
36
+ required: where === 'path' || required.has(name),
37
+ schema: s,
38
+ }));
39
+ }
40
+ function responseContent(entry) {
41
+ if (isResponseContent(entry)) {
42
+ const types = typeof entry.contentType === 'string' ? [entry.contentType] : entry.contentType;
43
+ return Object.fromEntries(types.map((t) => [t, entry.schema ? { schema: plain(entry.schema) } : {}]));
44
+ }
45
+ return { 'application/json': { schema: plain(entry) } };
46
+ }
47
+ function operation(route, problemErrors) {
48
+ const { schemas } = route;
49
+ const params = [
50
+ ...parameters('path', schemas.params),
51
+ ...parameters('query', schemas.query),
52
+ ...parameters('header', schemas.headers),
53
+ ];
54
+ const responses = {};
55
+ for (const [status, entry] of Object.entries(schemas.response ?? {})) {
56
+ const content = Number(status) === 204 ? undefined : responseContent(entry);
57
+ responses[status] = { description: STATUS_CODES[Number(status)] ?? 'Response', ...(content ? { content } : {}) };
58
+ }
59
+ if (Object.keys(responses).length === 0)
60
+ responses['200'] = { description: 'OK' };
61
+ responses.default = problemErrors
62
+ ? { description: 'Error', content: { 'application/problem+json': { schema: { $ref: '#/components/schemas/ProblemDetails' } } } }
63
+ : { description: 'Error' };
64
+ return {
65
+ operationId: `${route.owner}.${route.handlerName}`,
66
+ tags: [route.owner],
67
+ ...(params.length ? { parameters: params } : {}),
68
+ ...(schemas.body
69
+ ? { requestBody: { required: true, content: { 'application/json': { schema: plain(schemas.body) } } } }
70
+ : {}),
71
+ responses,
72
+ };
73
+ }
74
+ /**
75
+ * Gera o documento OpenAPI 3.1 a partir das rotas registradas (F-16). Os schemas TypeBox já são
76
+ * JSON Schema, então entram como estão. Schemas que não são JSON Schema (Zod etc.) não são convertidos.
77
+ */
78
+ export function generateOpenAPI(routes, opts, problemErrors) {
79
+ const paths = {};
80
+ const ids = new Map();
81
+ for (const route of routes) {
82
+ const path = toOpenAPIPath(route.path);
83
+ const op = operation(route, problemErrors);
84
+ // A mesma classe montada em dois prefixos gera o mesmo id; o OpenAPI exige ids únicos.
85
+ const base = op.operationId;
86
+ const n = (ids.get(base) ?? 0) + 1;
87
+ ids.set(base, n);
88
+ if (n > 1)
89
+ op.operationId = `${base}_${n}`;
90
+ (paths[path] ??= {})[route.method.toLowerCase()] = op;
91
+ }
92
+ return {
93
+ openapi: '3.1.0',
94
+ info: opts.info ?? { title: 'API', version: '0.0.0' },
95
+ ...(opts.servers ? { servers: opts.servers } : {}),
96
+ paths,
97
+ ...(problemErrors ? { components: { schemas: { ProblemDetails: PROBLEM_SCHEMA } } } : {}),
98
+ };
99
+ }
100
+ const SWAGGER = 'https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.34.1';
101
+ const SWAGGER_JS_SRI = 'sha384-XFYN47VzPiDY6qPtxYKg0nqUeW/upo20xf1j2SUE7gT/i35FJB4cuS/71Iegzk8Z';
102
+ const SWAGGER_CSS_SRI = 'sha384-4c3vsE5f+trhFyHrFrLM1fFGUn531NIaC7dcqEWIJdoRQJ5CkJbSuSCwXLpaS1KF';
103
+ const escapeHtml = (s) => s.replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[c]);
104
+ /**
105
+ * Página do Swagger UI (versão fixada, com SRI) e a CSP própria dela: scripts só do CDN e o inline com
106
+ * `nonce`, `connect-src 'self'` para buscar o documento.
107
+ */
108
+ export function docsPage(specUrl, title, nonce) {
109
+ const html = `<!DOCTYPE html>
110
+ <html lang="en">
111
+ <head>
112
+ <meta charset="utf-8">
113
+ <meta name="viewport" content="width=device-width, initial-scale=1">
114
+ <title>${escapeHtml(title)}</title>
115
+ <link rel="stylesheet" href="${SWAGGER}/swagger-ui.css" integrity="${SWAGGER_CSS_SRI}" crossorigin="anonymous">
116
+ </head>
117
+ <body>
118
+ <div id="swagger-ui"></div>
119
+ <script src="${SWAGGER}/swagger-ui-bundle.js" integrity="${SWAGGER_JS_SRI}" crossorigin="anonymous"></script>
120
+ <script nonce="${nonce}">SwaggerUIBundle({ url: ${JSON.stringify(specUrl).replace(/</g, '\\u003c')}, dom_id: '#swagger-ui' });</script>
121
+ </body>
122
+ </html>
123
+ `;
124
+ const csp = [
125
+ "default-src 'none'",
126
+ `script-src https://cdn.jsdelivr.net 'nonce-${nonce}'`,
127
+ "style-src https://cdn.jsdelivr.net 'unsafe-inline'",
128
+ "img-src 'self' data: https:",
129
+ "connect-src 'self'",
130
+ "frame-ancestors 'none'",
131
+ "base-uri 'none'",
132
+ "form-action 'none'",
133
+ ].join('; ');
134
+ return { html, csp };
135
+ }
136
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/openapi/generate.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,8 @@
1
1
  /** Junta prefixo e caminho com exatamente uma barra entre eles: `('/users/', 'id')` → `/users/id`. */
2
2
  export declare function joinPaths(prefix: string, path: string): string;
3
+ /**
4
+ * Parâmetros de um path na sintaxe do find-my-way (`/:org/users/:id(^\\d+)`, `/files/*`), em ordem (F-29).
5
+ * Lança erro para parâmetro sem nome (`/:`), nome repetido, regex sem fechamento e `*` fora do fim.
6
+ */
7
+ export declare function pathParams(path: string): string[];
3
8
  //# sourceMappingURL=path.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9D"}
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9D;AAID;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA6BjD"}
@@ -4,4 +4,53 @@ export function joinPaths(prefix, path) {
4
4
  const s = path.startsWith('/') ? path : `/${path}`;
5
5
  return `${p}${s}` || '/';
6
6
  }
7
+ const NAME_END = new Set(['/', '-', '.', '(']);
8
+ /**
9
+ * Parâmetros de um path na sintaxe do find-my-way (`/:org/users/:id(^\\d+)`, `/files/*`), em ordem (F-29).
10
+ * Lança erro para parâmetro sem nome (`/:`), nome repetido, regex sem fechamento e `*` fora do fim.
11
+ */
12
+ export function pathParams(path) {
13
+ const names = [];
14
+ for (let i = 0; i < path.length; i++) {
15
+ const ch = path[i];
16
+ if (ch === '*') {
17
+ if (i !== path.length - 1)
18
+ throw new Error(`invalid path "${path}": "*" is only allowed at the end`);
19
+ names.push('*');
20
+ continue;
21
+ }
22
+ if (ch !== ':')
23
+ continue;
24
+ if (path[i + 1] === ':') {
25
+ i++;
26
+ continue;
27
+ } // `::` é um ':' literal
28
+ let j = i + 1;
29
+ while (j < path.length && !NAME_END.has(path[j]))
30
+ j++;
31
+ const name = path.slice(i + 1, j);
32
+ if (!name)
33
+ throw new Error(`invalid path "${path}": parameter without a name`);
34
+ if (names.includes(name))
35
+ throw new Error(`invalid path "${path}": parameter "${name}" is repeated`);
36
+ names.push(name);
37
+ if (path[j] === '(') {
38
+ let depth = 0;
39
+ for (; j < path.length; j++) {
40
+ if (path[j] === '\\') {
41
+ j++;
42
+ continue;
43
+ }
44
+ if (path[j] === '(')
45
+ depth++;
46
+ else if (path[j] === ')' && --depth === 0)
47
+ break;
48
+ }
49
+ if (depth !== 0)
50
+ throw new Error(`invalid path "${path}": unterminated regex for "${name}"`);
51
+ }
52
+ i = j - (path[j] === ')' ? 0 : 1);
53
+ }
54
+ return names;
55
+ }
7
56
  //# sourceMappingURL=path.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,IAAY;IACpD,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;IACnD,OAAO,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC;AAC3B,CAAC"}
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sashiko",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Micro-framework HTTP para Node.js com decorators TC39 nativos, schema-first (TypeBox + Ajv) e defaults seguros.",
5
5
  "keywords": [
6
6
  "http",