sashiko 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +132 -27
  2. package/dist/core/app.d.ts +30 -6
  3. package/dist/core/app.d.ts.map +1 -1
  4. package/dist/core/app.js +73 -18
  5. package/dist/core/app.js.map +1 -1
  6. package/dist/core/compiler.d.ts +34 -10
  7. package/dist/core/compiler.d.ts.map +1 -1
  8. package/dist/core/compiler.js +60 -36
  9. package/dist/core/compiler.js.map +1 -1
  10. package/dist/core/context.d.ts +43 -7
  11. package/dist/core/context.d.ts.map +1 -1
  12. package/dist/core/context.js +41 -11
  13. package/dist/core/context.js.map +1 -1
  14. package/dist/core/index.d.ts +6 -3
  15. package/dist/core/index.d.ts.map +1 -1
  16. package/dist/core/index.js +2 -1
  17. package/dist/core/index.js.map +1 -1
  18. package/dist/core/infer.d.ts +9 -1
  19. package/dist/core/infer.d.ts.map +1 -1
  20. package/dist/core/metadata.d.ts +21 -5
  21. package/dist/core/metadata.d.ts.map +1 -1
  22. package/dist/core/metadata.js +6 -0
  23. package/dist/core/metadata.js.map +1 -1
  24. package/dist/core/mounted-group.d.ts +41 -0
  25. package/dist/core/mounted-group.d.ts.map +1 -0
  26. package/dist/core/mounted-group.js +43 -0
  27. package/dist/core/mounted-group.js.map +1 -0
  28. package/dist/core/response.d.ts +22 -8
  29. package/dist/core/response.d.ts.map +1 -1
  30. package/dist/core/response.js +93 -15
  31. package/dist/core/response.js.map +1 -1
  32. package/dist/core/shutdown.d.ts +36 -0
  33. package/dist/core/shutdown.d.ts.map +1 -0
  34. package/dist/core/shutdown.js +53 -0
  35. package/dist/core/shutdown.js.map +1 -0
  36. package/dist/decorators/index.d.ts +1 -1
  37. package/dist/decorators/index.d.ts.map +1 -1
  38. package/dist/decorators/index.js +1 -1
  39. package/dist/decorators/index.js.map +1 -1
  40. package/dist/decorators/middlewares.d.ts +28 -0
  41. package/dist/decorators/middlewares.d.ts.map +1 -0
  42. package/dist/decorators/middlewares.js +40 -0
  43. package/dist/decorators/middlewares.js.map +1 -0
  44. package/dist/middlewares/index.d.ts +1 -1
  45. package/dist/middlewares/index.d.ts.map +1 -1
  46. package/dist/middlewares/index.js.map +1 -1
  47. package/dist/middlewares/security-headers.d.ts +4 -2
  48. package/dist/middlewares/security-headers.d.ts.map +1 -1
  49. package/dist/middlewares/security-headers.js +10 -2
  50. package/dist/middlewares/security-headers.js.map +1 -1
  51. package/dist/schema/validation.d.ts +11 -0
  52. package/dist/schema/validation.d.ts.map +1 -1
  53. package/dist/schema/validation.js +18 -0
  54. package/dist/schema/validation.js.map +1 -1
  55. package/dist/utils/content-type.d.ts +8 -0
  56. package/dist/utils/content-type.d.ts.map +1 -1
  57. package/dist/utils/content-type.js +42 -0
  58. package/dist/utils/content-type.js.map +1 -1
  59. package/dist/utils/index.d.ts +1 -1
  60. package/dist/utils/index.d.ts.map +1 -1
  61. package/dist/utils/index.js +1 -1
  62. package/dist/utils/index.js.map +1 -1
  63. package/package.json +1 -1
  64. package/dist/decorators/use.d.ts +0 -26
  65. package/dist/decorators/use.d.ts.map +0 -1
  66. package/dist/decorators/use.js +0 -38
  67. package/dist/decorators/use.js.map +0 -1
@@ -2,6 +2,48 @@
2
2
  export function mediaType(header) {
3
3
  return header ? header.split(';', 1)[0].trim().toLowerCase() : '';
4
4
  }
5
+ /**
6
+ * Escolhe, entre os tipos `available` (em ordem de preferência do servidor), o melhor para o
7
+ * header `Accept` (F-31). Respeita q-values e curingas (`text/*`, `*\/*`). Sem `Accept`,
8
+ * devolve o primeiro. Retorna `undefined` quando nenhum é aceitável (→ 406).
9
+ */
10
+ export function negotiate(accept, available) {
11
+ if (!accept || !accept.trim())
12
+ return available[0];
13
+ const ranges = accept
14
+ .split(',')
15
+ .map((part, index) => {
16
+ const [range = '', ...params] = part.trim().toLowerCase().split(';');
17
+ const q = Number(params.map((p) => p.trim()).find((p) => p.startsWith('q='))?.slice(2) ?? '1');
18
+ return { range: range.trim(), q: Number.isFinite(q) ? q : 1, index };
19
+ })
20
+ .filter((r) => r.range && r.q > 0)
21
+ .sort((a, b) => b.q - a.q || specificity(b.range) - specificity(a.range) || a.index - b.index);
22
+ for (const { range } of ranges) {
23
+ const match = available.find((type) => matches(range, mediaType(type)));
24
+ if (match)
25
+ return match;
26
+ }
27
+ return undefined;
28
+ }
29
+ function specificity(range) {
30
+ if (range === '*/*')
31
+ return 0;
32
+ return range.endsWith('/*') ? 1 : 2;
33
+ }
34
+ function matches(range, type) {
35
+ if (range === '*/*' || range === type)
36
+ return true;
37
+ return range.endsWith('/*') && type.startsWith(range.slice(0, -1));
38
+ }
39
+ /** Acrescenta `charset=utf-8` a tipos textuais sem charset. */
40
+ export function withCharset(type) {
41
+ if (/;\s*charset=/i.test(type))
42
+ return type;
43
+ const base = mediaType(type);
44
+ const textual = base.startsWith('text/') || isJsonContentType(base) || /\+xml$|\/xml$|yaml$/.test(base);
45
+ return textual ? `${type}; charset=utf-8` : type;
46
+ }
5
47
  /** `application/json` ou `application/*+json`, com parâmetros opcionais (B-11). */
6
48
  export function isJsonContentType(header) {
7
49
  const type = mediaType(header);
@@ -1 +1 @@
1
- {"version":3,"file":"content-type.js","sourceRoot":"","sources":["../../src/utils/content-type.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,MAAM,UAAU,SAAS,CAAC,MAA0B;IAClD,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACrE,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,iBAAiB,CAAC,MAA0B;IAC1D,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,IAAI,KAAK,kBAAkB,IAAI,wCAAwC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5F,CAAC"}
1
+ {"version":3,"file":"content-type.js","sourceRoot":"","sources":["../../src/utils/content-type.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export { isJsonContentType, mediaType } from './content-type.ts';
1
+ export { isJsonContentType, mediaType, negotiate, withCharset } from './content-type.ts';
2
2
  export { joinPaths } from './path.ts';
3
3
  export { DEFAULT_MAX_QUERY_KEYS, parseQuery, type ParsedQuery } from './query.ts';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -1,4 +1,4 @@
1
- export { isJsonContentType, mediaType } from './content-type.js';
1
+ export { isJsonContentType, mediaType, negotiate, withCharset } from './content-type.js';
2
2
  export { joinPaths } from './path.js';
3
3
  export { DEFAULT_MAX_QUERY_KEYS, parseQuery } from './query.js';
4
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,UAAU,EAAoB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,UAAU,EAAoB,MAAM,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sashiko",
3
- "version": "0.1.0",
3
+ "version": "0.3.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",
@@ -1,26 +0,0 @@
1
- import type { Middleware } from '../core/compose.ts';
2
- import type { Guard } from '../core/guard.ts';
3
- type ClassOrMethodContext = ClassDecoratorContext | ClassMethodDecoratorContext;
4
- /**
5
- * Middlewares por classe ou por rota (F-01). Rodam depois dos globais e antes dos guards.
6
- *
7
- * ```ts
8
- * @Use(rateLimit({ max: 10 })) // todas as rotas da classe
9
- * @Router('/auth')
10
- * class AuthRoutes {
11
- * @Use(audit) @Post('/login') login() {}
12
- * }
13
- * ```
14
- */
15
- export declare function Use(...middlewares: Middleware[]): (_value: unknown, context: ClassOrMethodContext) => void;
16
- /**
17
- * Guards por classe ou por rota (F-01). Rodam antes da validação; `false` responde 403.
18
- *
19
- * ```ts
20
- * const isAdmin: Guard = (ctx) => ctx.state.user?.role === 'admin';
21
- * @UseGuards(isAdmin) @Delete('/:id') remove() {}
22
- * ```
23
- */
24
- export declare function UseGuards(...guards: Guard[]): (_value: unknown, context: ClassOrMethodContext) => void;
25
- export {};
26
- //# sourceMappingURL=use.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use.d.ts","sourceRoot":"","sources":["../../src/decorators/use.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C,KAAK,oBAAoB,GAAG,qBAAqB,GAAG,2BAA2B,CAAC;AAchF;;;;;;;;;;GAUG;AACH,wBAAgB,GAAG,CAAC,GAAG,WAAW,EAAE,UAAU,EAAE,YAlBrB,OAAO,WAAW,oBAAoB,KAAG,IAAI,CAoBvE;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,YA9BjB,OAAO,WAAW,oBAAoB,KAAG,IAAI,CAgCvE"}
@@ -1,38 +0,0 @@
1
- import { getOrCreateMethod, metadataFor } from '../core/metadata.js';
2
- /**
3
- * Aplica `items` na classe (todas as rotas) ou no método. Decorators são avaliados de baixo para
4
- * cima; inserimos no início para que a ordem de execução siga a ordem de leitura (de cima para baixo).
5
- */
6
- function register(decorator, pick, items) {
7
- return function (_value, context) {
8
- const meta = metadataFor(context, decorator);
9
- const target = context.kind === 'class' ? meta : getOrCreateMethod(meta, context.name);
10
- target[pick].unshift(...items);
11
- };
12
- }
13
- /**
14
- * Middlewares por classe ou por rota (F-01). Rodam depois dos globais e antes dos guards.
15
- *
16
- * ```ts
17
- * @Use(rateLimit({ max: 10 })) // todas as rotas da classe
18
- * @Router('/auth')
19
- * class AuthRoutes {
20
- * @Use(audit) @Post('/login') login() {}
21
- * }
22
- * ```
23
- */
24
- export function Use(...middlewares) {
25
- return register('Use', 'middlewares', middlewares);
26
- }
27
- /**
28
- * Guards por classe ou por rota (F-01). Rodam antes da validação; `false` responde 403.
29
- *
30
- * ```ts
31
- * const isAdmin: Guard = (ctx) => ctx.state.user?.role === 'admin';
32
- * @UseGuards(isAdmin) @Delete('/:id') remove() {}
33
- * ```
34
- */
35
- export function UseGuards(...guards) {
36
- return register('UseGuards', 'guards', guards);
37
- }
38
- //# sourceMappingURL=use.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use.js","sourceRoot":"","sources":["../../src/decorators/use.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIrE;;;GAGG;AACH,SAAS,QAAQ,CAAC,SAAiB,EAAE,IAA8B,EAAE,KAAyB;IAC5F,OAAO,UAAU,MAAe,EAAE,OAA6B;QAC7D,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACtF,MAAM,CAAC,IAAI,CAAe,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;IAChD,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,GAAG,CAAC,GAAG,WAAyB;IAC9C,OAAO,QAAQ,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,GAAG,MAAe;IAC1C,OAAO,QAAQ,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AACjD,CAAC"}