@quilla-be-kit/http 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.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +400 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/adapter/hono/create-http-request.d.ts +15 -0
  5. package/dist/adapter/hono/create-http-request.d.ts.map +1 -0
  6. package/dist/adapter/hono/create-http-request.js +57 -0
  7. package/dist/adapter/hono/create-http-request.js.map +1 -0
  8. package/dist/adapter/hono/get-request-attributes.d.ts +2 -0
  9. package/dist/adapter/hono/get-request-attributes.d.ts.map +1 -0
  10. package/dist/adapter/hono/get-request-attributes.js +10 -0
  11. package/dist/adapter/hono/get-request-attributes.js.map +1 -0
  12. package/dist/adapter/hono/hono-middleware.adapter.d.ts +10 -0
  13. package/dist/adapter/hono/hono-middleware.adapter.d.ts.map +1 -0
  14. package/dist/adapter/hono/hono-middleware.adapter.js +13 -0
  15. package/dist/adapter/hono/hono-middleware.adapter.js.map +1 -0
  16. package/dist/adapter/hono/hono-request.adapter.d.ts +12 -0
  17. package/dist/adapter/hono/hono-request.adapter.d.ts.map +1 -0
  18. package/dist/adapter/hono/hono-request.adapter.js +99 -0
  19. package/dist/adapter/hono/hono-request.adapter.js.map +1 -0
  20. package/dist/adapter/hono/hono.server.d.ts +30 -0
  21. package/dist/adapter/hono/hono.server.d.ts.map +1 -0
  22. package/dist/adapter/hono/hono.server.js +64 -0
  23. package/dist/adapter/hono/hono.server.js.map +1 -0
  24. package/dist/adapter/hono/hono.types.d.ts +9 -0
  25. package/dist/adapter/hono/hono.types.d.ts.map +1 -0
  26. package/dist/adapter/hono/hono.types.js +4 -0
  27. package/dist/adapter/hono/hono.types.js.map +1 -0
  28. package/dist/adapter/hono/index.d.ts +2 -0
  29. package/dist/adapter/hono/index.d.ts.map +1 -0
  30. package/dist/adapter/hono/index.js +2 -0
  31. package/dist/adapter/hono/index.js.map +1 -0
  32. package/dist/decorator/authorize-scope.decorator.d.ts +6 -0
  33. package/dist/decorator/authorize-scope.decorator.d.ts.map +1 -0
  34. package/dist/decorator/authorize-scope.decorator.js +30 -0
  35. package/dist/decorator/authorize-scope.decorator.js.map +1 -0
  36. package/dist/decorator/controller.decorator.d.ts +2 -0
  37. package/dist/decorator/controller.decorator.d.ts.map +1 -0
  38. package/dist/decorator/controller.decorator.js +7 -0
  39. package/dist/decorator/controller.decorator.js.map +1 -0
  40. package/dist/decorator/index.d.ts +5 -0
  41. package/dist/decorator/index.d.ts.map +1 -0
  42. package/dist/decorator/index.js +5 -0
  43. package/dist/decorator/index.js.map +1 -0
  44. package/dist/decorator/method.decorators.d.ts +11 -0
  45. package/dist/decorator/method.decorators.d.ts.map +1 -0
  46. package/dist/decorator/method.decorators.js +27 -0
  47. package/dist/decorator/method.decorators.js.map +1 -0
  48. package/dist/decorator/route.metadata.d.ts +22 -0
  49. package/dist/decorator/route.metadata.d.ts.map +1 -0
  50. package/dist/decorator/route.metadata.js +61 -0
  51. package/dist/decorator/route.metadata.js.map +1 -0
  52. package/dist/decorator/validate-request.decorator.d.ts +7 -0
  53. package/dist/decorator/validate-request.decorator.d.ts.map +1 -0
  54. package/dist/decorator/validate-request.decorator.js +57 -0
  55. package/dist/decorator/validate-request.decorator.js.map +1 -0
  56. package/dist/error/index.d.ts +2 -0
  57. package/dist/error/index.d.ts.map +1 -0
  58. package/dist/error/index.js +2 -0
  59. package/dist/error/index.js.map +1 -0
  60. package/dist/error/resolve-http-error.d.ts +7 -0
  61. package/dist/error/resolve-http-error.d.ts.map +1 -0
  62. package/dist/error/resolve-http-error.js +43 -0
  63. package/dist/error/resolve-http-error.js.map +1 -0
  64. package/dist/index.d.ts +6 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +6 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/request/authenticated-token.interface.d.ts +4 -0
  69. package/dist/request/authenticated-token.interface.d.ts.map +1 -0
  70. package/dist/request/authenticated-token.interface.js +2 -0
  71. package/dist/request/authenticated-token.interface.js.map +1 -0
  72. package/dist/request/http-attributes.d.ts +6 -0
  73. package/dist/request/http-attributes.d.ts.map +1 -0
  74. package/dist/request/http-attributes.js +6 -0
  75. package/dist/request/http-attributes.js.map +1 -0
  76. package/dist/request/http-middleware.type.d.ts +3 -0
  77. package/dist/request/http-middleware.type.d.ts.map +1 -0
  78. package/dist/request/http-middleware.type.js +2 -0
  79. package/dist/request/http-middleware.type.js.map +1 -0
  80. package/dist/request/http-request.interface.d.ts +18 -0
  81. package/dist/request/http-request.interface.d.ts.map +1 -0
  82. package/dist/request/http-request.interface.js +2 -0
  83. package/dist/request/http-request.interface.js.map +1 -0
  84. package/dist/request/http-response.type.d.ts +18 -0
  85. package/dist/request/http-response.type.d.ts.map +1 -0
  86. package/dist/request/http-response.type.js +2 -0
  87. package/dist/request/http-response.type.js.map +1 -0
  88. package/dist/request/index.d.ts +6 -0
  89. package/dist/request/index.d.ts.map +1 -0
  90. package/dist/request/index.js +2 -0
  91. package/dist/request/index.js.map +1 -0
  92. package/dist/router/auth-middleware-stack.type.d.ts +13 -0
  93. package/dist/router/auth-middleware-stack.type.d.ts.map +1 -0
  94. package/dist/router/auth-middleware-stack.type.js +2 -0
  95. package/dist/router/auth-middleware-stack.type.js.map +1 -0
  96. package/dist/router/controller-registration.type.d.ts +7 -0
  97. package/dist/router/controller-registration.type.d.ts.map +1 -0
  98. package/dist/router/controller-registration.type.js +2 -0
  99. package/dist/router/controller-registration.type.js.map +1 -0
  100. package/dist/router/http-module-meta.type.d.ts +8 -0
  101. package/dist/router/http-module-meta.type.d.ts.map +1 -0
  102. package/dist/router/http-module-meta.type.js +2 -0
  103. package/dist/router/http-module-meta.type.js.map +1 -0
  104. package/dist/router/index.d.ts +6 -0
  105. package/dist/router/index.d.ts.map +1 -0
  106. package/dist/router/index.js +2 -0
  107. package/dist/router/index.js.map +1 -0
  108. package/dist/router/normalized-route.type.d.ts +20 -0
  109. package/dist/router/normalized-route.type.d.ts.map +1 -0
  110. package/dist/router/normalized-route.type.js +2 -0
  111. package/dist/router/normalized-route.type.js.map +1 -0
  112. package/dist/router/router-options.type.d.ts +37 -0
  113. package/dist/router/router-options.type.d.ts.map +1 -0
  114. package/dist/router/router-options.type.js +2 -0
  115. package/dist/router/router-options.type.js.map +1 -0
  116. package/dist/router/router.d.ts +11 -0
  117. package/dist/router/router.d.ts.map +1 -0
  118. package/dist/router/router.js +143 -0
  119. package/dist/router/router.js.map +1 -0
  120. package/dist/server/index.d.ts +2 -0
  121. package/dist/server/index.d.ts.map +1 -0
  122. package/dist/server/index.js +2 -0
  123. package/dist/server/index.js.map +1 -0
  124. package/dist/server/middleware-adapter.interface.d.ts +5 -0
  125. package/dist/server/middleware-adapter.interface.d.ts.map +1 -0
  126. package/dist/server/middleware-adapter.interface.js +2 -0
  127. package/dist/server/middleware-adapter.interface.js.map +1 -0
  128. package/dist/server/request-adapter.interface.d.ts +7 -0
  129. package/dist/server/request-adapter.interface.d.ts.map +1 -0
  130. package/dist/server/request-adapter.interface.js +2 -0
  131. package/dist/server/request-adapter.interface.js.map +1 -0
  132. package/dist/server/web-server.interface.d.ts +6 -0
  133. package/dist/server/web-server.interface.d.ts.map +1 -0
  134. package/dist/server/web-server.interface.js +2 -0
  135. package/dist/server/web-server.interface.js.map +1 -0
  136. package/dist/validator/index.d.ts +4 -0
  137. package/dist/validator/index.d.ts.map +1 -0
  138. package/dist/validator/index.js +2 -0
  139. package/dist/validator/index.js.map +1 -0
  140. package/dist/validator/request-source.type.d.ts +2 -0
  141. package/dist/validator/request-source.type.d.ts.map +1 -0
  142. package/dist/validator/request-source.type.js +2 -0
  143. package/dist/validator/request-source.type.js.map +1 -0
  144. package/dist/validator/request-validator.interface.d.ts +30 -0
  145. package/dist/validator/request-validator.interface.d.ts.map +1 -0
  146. package/dist/validator/request-validator.interface.js +2 -0
  147. package/dist/validator/request-validator.interface.js.map +1 -0
  148. package/dist/validator/validation-result.type.d.ts +8 -0
  149. package/dist/validator/validation-result.type.d.ts.map +1 -0
  150. package/dist/validator/validation-result.type.js +2 -0
  151. package/dist/validator/validation-result.type.js.map +1 -0
  152. package/dist/validator/zod.d.ts +29 -0
  153. package/dist/validator/zod.d.ts.map +1 -0
  154. package/dist/validator/zod.js +43 -0
  155. package/dist/validator/zod.js.map +1 -0
  156. package/package.json +85 -0
@@ -0,0 +1,64 @@
1
+ import { Hono } from 'hono';
2
+ import { resolveHttpError } from '../../error/resolve-http-error.js';
3
+ import { HttpAttributes } from '../../request/http-attributes.js';
4
+ import { getRequestAttributes } from './get-request-attributes.js';
5
+ import { HonoMiddlewareAdapter } from './hono-middleware.adapter.js';
6
+ import { HonoRequestAdapter } from './hono-request.adapter.js';
7
+ export class HonoServer {
8
+ options;
9
+ app = new Hono();
10
+ requestAdapter;
11
+ middlewareAdapter;
12
+ bootstrapped = false;
13
+ handle;
14
+ constructor(options) {
15
+ this.options = options;
16
+ this.requestAdapter = new HonoRequestAdapter(options.router.getExecutionContextProvider());
17
+ this.middlewareAdapter = new HonoMiddlewareAdapter(this.requestAdapter);
18
+ }
19
+ bootstrap() {
20
+ if (this.bootstrapped)
21
+ return;
22
+ this.bootstrapped = true;
23
+ this.app.onError((err, c) => {
24
+ this.options.logger?.error('HTTP error', err instanceof Error ? err : undefined);
25
+ const { httpCode, body } = resolveHttpError(err);
26
+ return c.json(body, httpCode);
27
+ });
28
+ const validator = this.options.requestValidator;
29
+ if (validator) {
30
+ this.app.use('*', async (c, next) => {
31
+ const attributes = getRequestAttributes(c);
32
+ attributes.set(HttpAttributes.REQUEST_VALIDATOR, validator);
33
+ await next();
34
+ });
35
+ }
36
+ for (const route of this.options.router.getRoutes()) {
37
+ this.registerRoute(route);
38
+ }
39
+ }
40
+ async listen() {
41
+ if (!this.bootstrapped)
42
+ this.bootstrap();
43
+ this.handle = this.options.serve(this.app, this.options.port);
44
+ this.options.logger?.info('HTTP server listening', { meta: { port: this.options.port } });
45
+ }
46
+ async close() {
47
+ if (!this.handle)
48
+ return;
49
+ await this.handle.close();
50
+ this.handle = undefined;
51
+ this.options.logger?.info('HTTP server closed');
52
+ }
53
+ registerRoute(route) {
54
+ const stack = [];
55
+ for (const mw of route.middlewareChain) {
56
+ stack.push(this.middlewareAdapter.wrap(mw));
57
+ }
58
+ const handler = this.requestAdapter.controller(route.handler);
59
+ const method = route.httpMethod.toLowerCase();
60
+ const register = this.app[method];
61
+ register.call(this.app, route.fullPath, ...stack, handler);
62
+ }
63
+ }
64
+ //# sourceMappingURL=hono.server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.server.js","sourceRoot":"","sources":["../../../src/adapter/hono/hono.server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export type ParsedBody = {
2
+ readonly body: unknown;
3
+ readonly formData: FormData | null;
4
+ readonly binary: Uint8Array | null;
5
+ };
6
+ export declare const HONO_CONTEXT_ATTRIBUTES_KEY = "__quilla_http_attributes__";
7
+ export declare const HONO_CONTEXT_PARSED_BODY_KEY = "__quilla_http_parsed_body__";
8
+ export declare const HONO_CONTEXT_HTTP_REQUEST_KEY = "__quilla_http_request__";
9
+ //# sourceMappingURL=hono.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.types.d.ts","sourceRoot":"","sources":["../../../src/adapter/hono/hono.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CACpC,CAAC;AAEF,eAAO,MAAM,2BAA2B,+BAA+B,CAAC;AACxE,eAAO,MAAM,4BAA4B,gCAAgC,CAAC;AAC1E,eAAO,MAAM,6BAA6B,4BAA4B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export const HONO_CONTEXT_ATTRIBUTES_KEY = '__quilla_http_attributes__';
2
+ export const HONO_CONTEXT_PARSED_BODY_KEY = '__quilla_http_parsed_body__';
3
+ export const HONO_CONTEXT_HTTP_REQUEST_KEY = '__quilla_http_request__';
4
+ //# sourceMappingURL=hono.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.types.js","sourceRoot":"","sources":["../../../src/adapter/hono/hono.types.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,2BAA2B,GAAG,4BAA4B,CAAC;AACxE,MAAM,CAAC,MAAM,4BAA4B,GAAG,6BAA6B,CAAC;AAC1E,MAAM,CAAC,MAAM,6BAA6B,GAAG,yBAAyB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { HonoServer, type HonoServerOptions, type HonoServeFn, type HonoServeHandle, } from './hono.server.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapter/hono/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { HonoServer, } from './hono.server.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapter/hono/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,GAIX,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { HttpRequest } from '../request/http-request.interface.js';
2
+ import type { HttpResponse } from '../request/http-response.type.js';
3
+ type ControllerMethod = (this: unknown, request: HttpRequest) => Promise<HttpResponse>;
4
+ export declare function AuthorizeScope(scopes: string | readonly string[], mode?: 'any' | 'all'): (originalMethod: ControllerMethod, context: ClassMethodDecoratorContext) => ControllerMethod;
5
+ export {};
6
+ //# sourceMappingURL=authorize-scope.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize-scope.decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/authorize-scope.decorator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAGrE,KAAK,gBAAgB,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAEvF,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,EAAE,IAAI,GAAE,KAAK,GAAG,KAAa,IAE1F,gBAAgB,gBAAgB,EAChC,SAAS,2BAA2B,KACnC,gBAAgB,CA+BpB"}
@@ -0,0 +1,30 @@
1
+ import { ForbiddenError } from '@quilla-be-kit/errors';
2
+ import { HttpAttributes } from '../request/http-attributes.js';
3
+ import { updateLastRoute } from './route.metadata.js';
4
+ export function AuthorizeScope(scopes, mode = 'any') {
5
+ return (originalMethod, context) => {
6
+ if (context.kind !== 'method') {
7
+ throw new Error('@AuthorizeScope can only be applied to methods');
8
+ }
9
+ const required = Array.isArray(scopes) ? scopes : [scopes];
10
+ updateLastRoute(context.metadata, context.name, {
11
+ scopes: required,
12
+ scopeMode: mode,
13
+ });
14
+ return function (request) {
15
+ const token = request.getAttribute(HttpAttributes.VERIFIED_TOKEN);
16
+ if (!token) {
17
+ throw new ForbiddenError({ message: 'Authentication is required for this action.' });
18
+ }
19
+ const granted = token.scopes ?? [];
20
+ const hasScope = mode === 'all'
21
+ ? required.every((s) => granted.includes(s))
22
+ : required.some((s) => granted.includes(s));
23
+ if (!hasScope) {
24
+ throw new ForbiddenError({ message: 'User is not authorized to perform this action.' });
25
+ }
26
+ return originalMethod.call(this, request);
27
+ };
28
+ };
29
+ }
30
+ //# sourceMappingURL=authorize-scope.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize-scope.decorator.js","sourceRoot":"","sources":["../../src/decorator/authorize-scope.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAG/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAItD,MAAM,UAAU,cAAc,CAAC,MAAkC,EAAE,OAAsB,KAAK;IAC5F,OAAO,CACL,cAAgC,EAChC,OAAoC,EAClB,EAAE;QACpB,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAgB,CAAC,CAAC;QAErE,eAAe,CAAC,OAAO,CAAC,QAA4C,EAAE,OAAO,CAAC,IAAc,EAAE;YAC5F,MAAM,EAAE,QAAQ;YAChB,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;QAEH,OAAO,UAAyB,OAAoB;YAClD,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAqB,cAAc,CAAC,cAAc,CAAC,CAAC;YACtF,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,cAAc,CAAC,EAAE,OAAO,EAAE,6CAA6C,EAAE,CAAC,CAAC;YACvF,CAAC;YAED,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;YACnC,MAAM,QAAQ,GACZ,IAAI,KAAK,KAAK;gBACZ,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAC5C,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YAEhD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,cAAc,CAAC,EAAE,OAAO,EAAE,gDAAgD,EAAE,CAAC,CAAC;YAC1F,CAAC;YAED,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5C,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function Controller(prefix: string): (_target: unknown, context: ClassDecoratorContext) => void;
2
+ //# sourceMappingURL=controller.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/controller.decorator.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,IAC/B,SAAS,OAAO,EAAE,SAAS,qBAAqB,KAAG,IAAI,CAGhE"}
@@ -0,0 +1,7 @@
1
+ import { setControllerPrefix } from './route.metadata.js';
2
+ export function Controller(prefix) {
3
+ return (_target, context) => {
4
+ setControllerPrefix(context.metadata, prefix);
5
+ };
6
+ }
7
+ //# sourceMappingURL=controller.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.decorator.js","sourceRoot":"","sources":["../../src/decorator/controller.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,OAAO,CAAC,OAAgB,EAAE,OAA8B,EAAQ,EAAE;QAChE,mBAAmB,CAAC,OAAO,CAAC,QAA4C,EAAE,MAAM,CAAC,CAAC;IACpF,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { Controller } from './controller.decorator.js';
2
+ export { Get, Post, Put, Patch, Delete, GetPublic, PostPublic, PutPublic, PatchPublic, DeletePublic, } from './method.decorators.js';
3
+ export { AuthorizeScope } from './authorize-scope.decorator.js';
4
+ export { ValidateRequest } from './validate-request.decorator.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EACL,GAAG,EACH,IAAI,EACJ,GAAG,EACH,KAAK,EACL,MAAM,EACN,SAAS,EACT,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,GACb,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { Controller } from './controller.decorator.js';
2
+ export { Get, Post, Put, Patch, Delete, GetPublic, PostPublic, PutPublic, PatchPublic, DeletePublic, } from './method.decorators.js';
3
+ export { AuthorizeScope } from './authorize-scope.decorator.js';
4
+ export { ValidateRequest } from './validate-request.decorator.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/decorator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EACL,GAAG,EACH,IAAI,EACJ,GAAG,EACH,KAAK,EACL,MAAM,EACN,SAAS,EACT,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,GACb,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare const Get: (path: string) => (_target: unknown, context: ClassMethodDecoratorContext) => void;
2
+ export declare const Post: (path: string) => (_target: unknown, context: ClassMethodDecoratorContext) => void;
3
+ export declare const Put: (path: string) => (_target: unknown, context: ClassMethodDecoratorContext) => void;
4
+ export declare const Patch: (path: string) => (_target: unknown, context: ClassMethodDecoratorContext) => void;
5
+ export declare const Delete: (path: string) => (_target: unknown, context: ClassMethodDecoratorContext) => void;
6
+ export declare const GetPublic: (path: string) => (_target: unknown, context: ClassMethodDecoratorContext) => void;
7
+ export declare const PostPublic: (path: string) => (_target: unknown, context: ClassMethodDecoratorContext) => void;
8
+ export declare const PutPublic: (path: string) => (_target: unknown, context: ClassMethodDecoratorContext) => void;
9
+ export declare const PatchPublic: (path: string) => (_target: unknown, context: ClassMethodDecoratorContext) => void;
10
+ export declare const DeletePublic: (path: string) => (_target: unknown, context: ClassMethodDecoratorContext) => void;
11
+ //# sourceMappingURL=method.decorators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"method.decorators.d.ts","sourceRoot":"","sources":["../../src/decorator/method.decorators.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,GAAG,SAfA,MAAM,MACV,SAAS,OAAO,EAAE,SAAS,2BAA2B,KAAG,IAcf,CAAC;AACvD,eAAO,MAAM,IAAI,SAhBD,MAAM,MACV,SAAS,OAAO,EAAE,SAAS,2BAA2B,KAAG,IAeb,CAAC;AACzD,eAAO,MAAM,GAAG,SAjBA,MAAM,MACV,SAAS,OAAO,EAAE,SAAS,2BAA2B,KAAG,IAgBf,CAAC;AACvD,eAAO,MAAM,KAAK,SAlBF,MAAM,MACV,SAAS,OAAO,EAAE,SAAS,2BAA2B,KAAG,IAiBX,CAAC;AAC3D,eAAO,MAAM,MAAM,SAnBH,MAAM,MACV,SAAS,OAAO,EAAE,SAAS,2BAA2B,KAAG,IAkBT,CAAC;AAE7D,eAAO,MAAM,SAAS,SArBN,MAAM,MACV,SAAS,OAAO,EAAE,SAAS,2BAA2B,KAAG,IAoBV,CAAC;AAC5D,eAAO,MAAM,UAAU,SAtBP,MAAM,MACV,SAAS,OAAO,EAAE,SAAS,2BAA2B,KAAG,IAqBR,CAAC;AAC9D,eAAO,MAAM,SAAS,SAvBN,MAAM,MACV,SAAS,OAAO,EAAE,SAAS,2BAA2B,KAAG,IAsBV,CAAC;AAC5D,eAAO,MAAM,WAAW,SAxBR,MAAM,MACV,SAAS,OAAO,EAAE,SAAS,2BAA2B,KAAG,IAuBN,CAAC;AAChE,eAAO,MAAM,YAAY,SAzBT,MAAM,MACV,SAAS,OAAO,EAAE,SAAS,2BAA2B,KAAG,IAwBJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { addRoute } from './route.metadata.js';
2
+ function createMethodDecorator(httpMethod, isPublic) {
3
+ return (path) => {
4
+ return (_target, context) => {
5
+ if (context.kind !== 'method') {
6
+ throw new Error(`@${httpMethod} can only be applied to methods`);
7
+ }
8
+ addRoute(context.metadata, {
9
+ handlerMethodName: context.name,
10
+ httpMethod,
11
+ path,
12
+ public: isPublic,
13
+ });
14
+ };
15
+ };
16
+ }
17
+ export const Get = createMethodDecorator('GET', false);
18
+ export const Post = createMethodDecorator('POST', false);
19
+ export const Put = createMethodDecorator('PUT', false);
20
+ export const Patch = createMethodDecorator('PATCH', false);
21
+ export const Delete = createMethodDecorator('DELETE', false);
22
+ export const GetPublic = createMethodDecorator('GET', true);
23
+ export const PostPublic = createMethodDecorator('POST', true);
24
+ export const PutPublic = createMethodDecorator('PUT', true);
25
+ export const PatchPublic = createMethodDecorator('PATCH', true);
26
+ export const DeletePublic = createMethodDecorator('DELETE', true);
27
+ //# sourceMappingURL=method.decorators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"method.decorators.js","sourceRoot":"","sources":["../../src/decorator/method.decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEhE,SAAS,qBAAqB,CAAC,UAAsB,EAAE,QAAiB;IACtE,OAAO,CAAC,IAAY,EAAE,EAAE;QACtB,OAAO,CAAC,OAAgB,EAAE,OAAoC,EAAQ,EAAE;YACtE,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CAAC,IAAI,UAAU,iCAAiC,CAAC,CAAC;YACnE,CAAC;YACD,QAAQ,CAAC,OAAO,CAAC,QAA4C,EAAE;gBAC7D,iBAAiB,EAAE,OAAO,CAAC,IAAc;gBACzC,UAAU;gBACV,IAAI;gBACJ,MAAM,EAAE,QAAQ;aACjB,CAAC,CAAC;QACL,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,GAAG,GAAG,qBAAqB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACvD,MAAM,CAAC,MAAM,IAAI,GAAG,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACzD,MAAM,CAAC,MAAM,GAAG,GAAG,qBAAqB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACvD,MAAM,CAAC,MAAM,KAAK,GAAG,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAC3D,MAAM,CAAC,MAAM,MAAM,GAAG,qBAAqB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AAE7D,MAAM,CAAC,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAG,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC9D,MAAM,CAAC,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,WAAW,GAAG,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAChE,MAAM,CAAC,MAAM,YAAY,GAAG,qBAAqB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { RequestSource } from '../validator/request-source.type.js';
2
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
3
+ export type RouteDefinition = {
4
+ readonly handlerMethodName: string;
5
+ readonly httpMethod: HttpMethod;
6
+ readonly path: string;
7
+ readonly public: boolean;
8
+ readonly scopes?: readonly string[];
9
+ readonly scopeMode?: 'any' | 'all';
10
+ readonly validation?: {
11
+ readonly schema: unknown;
12
+ readonly sources: readonly RequestSource[];
13
+ };
14
+ };
15
+ type MetadataBag = Record<string | symbol, unknown>;
16
+ export declare function setControllerPrefix(metadata: MetadataBag, prefix: string): void;
17
+ export declare function getControllerPrefix(controllerInstance: object): string;
18
+ export declare function addRoute(metadata: MetadataBag, route: RouteDefinition): void;
19
+ export declare function updateLastRoute(metadata: MetadataBag, methodName: string, patch: Partial<RouteDefinition>): void;
20
+ export declare function getControllerRoutes(controllerInstance: object): readonly RouteDefinition[];
21
+ export {};
22
+ //# sourceMappingURL=route.metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.metadata.d.ts","sourceRoot":"","sources":["../../src/decorator/route.metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAazE,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAErE,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACnC,QAAQ,CAAC,UAAU,CAAC,EAAE;QACpB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;KAC5C,CAAC;CACH,CAAC;AAKF,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAE/E;AAED,wBAAgB,mBAAmB,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM,CAOtE;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAI5E;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,WAAW,EACrB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,GAC9B,IAAI,CAUN;AAED,wBAAgB,mBAAmB,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,eAAe,EAAE,CAO1F"}
@@ -0,0 +1,61 @@
1
+ // Node 22 has no native Symbol.metadata; stage-3 decorator emit writes metadata
2
+ // via `Symbol.metadata`, so we install a shared well-known identity at module
3
+ // load before any decorated class is defined.
4
+ if (Symbol.metadata === undefined) {
5
+ Object.defineProperty(Symbol, 'metadata', {
6
+ value: Symbol.for('Symbol.metadata'),
7
+ writable: false,
8
+ configurable: false,
9
+ });
10
+ }
11
+ const CONTROLLER_PREFIX_KEY = Symbol.for('quilla-be-kit.http.controller-prefix');
12
+ const ROUTES_KEY = Symbol.for('quilla-be-kit.http.routes');
13
+ export function setControllerPrefix(metadata, prefix) {
14
+ metadata[CONTROLLER_PREFIX_KEY] = prefix;
15
+ }
16
+ export function getControllerPrefix(controllerInstance) {
17
+ for (const metadata of walkMetadata(controllerInstance)) {
18
+ if (typeof metadata[CONTROLLER_PREFIX_KEY] === 'string') {
19
+ return metadata[CONTROLLER_PREFIX_KEY];
20
+ }
21
+ }
22
+ return '';
23
+ }
24
+ export function addRoute(metadata, route) {
25
+ const existing = metadata[ROUTES_KEY] ?? [];
26
+ existing.push(route);
27
+ metadata[ROUTES_KEY] = existing;
28
+ }
29
+ export function updateLastRoute(metadata, methodName, patch) {
30
+ const routes = metadata[ROUTES_KEY];
31
+ if (!routes)
32
+ return;
33
+ for (let i = routes.length - 1; i >= 0; i--) {
34
+ const route = routes[i];
35
+ if (route && route.handlerMethodName === methodName) {
36
+ routes[i] = { ...route, ...patch };
37
+ return;
38
+ }
39
+ }
40
+ }
41
+ export function getControllerRoutes(controllerInstance) {
42
+ const collected = [];
43
+ for (const metadata of walkMetadata(controllerInstance)) {
44
+ const routes = metadata[ROUTES_KEY];
45
+ if (routes)
46
+ collected.unshift(...routes);
47
+ }
48
+ return collected;
49
+ }
50
+ function* walkMetadata(instance) {
51
+ // biome-ignore lint/suspicious/noExplicitAny: prototype reflection is inherently untyped
52
+ let ctor = instance.constructor;
53
+ while (ctor && ctor !== Object) {
54
+ const metadata = ctor[Symbol.metadata];
55
+ if (metadata)
56
+ yield metadata;
57
+ const proto = ctor.prototype;
58
+ ctor = proto ? Object.getPrototypeOf(proto)?.constructor : null;
59
+ }
60
+ }
61
+ //# sourceMappingURL=route.metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.metadata.js","sourceRoot":"","sources":["../../src/decorator/route.metadata.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { HttpRequest } from '../request/http-request.interface.js';
2
+ import type { HttpResponse } from '../request/http-response.type.js';
3
+ import type { RequestSource } from '../validator/request-source.type.js';
4
+ type ControllerMethod = (this: unknown, request: HttpRequest) => Promise<HttpResponse>;
5
+ export declare function ValidateRequest(schema: unknown, sources: readonly RequestSource[]): (originalMethod: ControllerMethod, context: ClassMethodDecoratorContext) => ControllerMethod;
6
+ export {};
7
+ //# sourceMappingURL=validate-request.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-request.decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/validate-request.decorator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAIzE,KAAK,gBAAgB,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAWvF,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,aAAa,EAAE,IAE9E,gBAAgB,gBAAgB,EAChC,SAAS,2BAA2B,KACnC,gBAAgB,CAiDpB"}
@@ -0,0 +1,57 @@
1
+ import { ValidationError } from '@quilla-be-kit/errors';
2
+ import { HttpAttributes } from '../request/http-attributes.js';
3
+ import { updateLastRoute } from './route.metadata.js';
4
+ const SOURCE_READERS = {
5
+ body: (req) => {
6
+ const body = req.getBody();
7
+ return body !== null && typeof body === 'object' ? body : {};
8
+ },
9
+ params: (req) => req.getParams(),
10
+ query: (req) => req.getQuery(),
11
+ };
12
+ export function ValidateRequest(schema, sources) {
13
+ return (originalMethod, context) => {
14
+ if (context.kind !== 'method') {
15
+ throw new Error('@ValidateRequest can only be applied to methods');
16
+ }
17
+ updateLastRoute(context.metadata, context.name, {
18
+ validation: { schema, sources },
19
+ });
20
+ return function (request) {
21
+ const validator = request.getAttribute(HttpAttributes.REQUEST_VALIDATOR);
22
+ if (!validator) {
23
+ throw new Error('@ValidateRequest used but no RequestValidator was registered on the WebServer');
24
+ }
25
+ const raw = {};
26
+ for (const source of sources) {
27
+ Object.assign(raw, SOURCE_READERS[source](request));
28
+ }
29
+ // Auth-derived fields (`scopeId`, `userId`) are injected only when the
30
+ // schema declares them — keeps the decorator from writing surprise
31
+ // fields into schemas that don't ask for them (which breaks strict
32
+ // validation and muddies the intent). Requires the `RequestValidator`
33
+ // to implement `describeSchema`; validators without it get fail-safe
34
+ // no-injection.
35
+ const description = validator.describeSchema?.(schema);
36
+ if (description) {
37
+ const session = request.getExecutionContext().session;
38
+ if (session) {
39
+ if (description.keys.includes('scopeId'))
40
+ raw.scopeId = session.scopeId;
41
+ if (description.keys.includes('userId'))
42
+ raw.userId = session.userId;
43
+ }
44
+ }
45
+ const result = validator.validate(schema, raw);
46
+ if (!result.success) {
47
+ throw new ValidationError({
48
+ message: 'Request validation failed',
49
+ context: { issues: result.error },
50
+ });
51
+ }
52
+ request.setAttribute(HttpAttributes.VALIDATED_INPUT, result.data);
53
+ return originalMethod.call(this, request);
54
+ };
55
+ };
56
+ }
57
+ //# sourceMappingURL=validate-request.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-request.decorator.js","sourceRoot":"","sources":["../../src/decorator/validate-request.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAK/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAItD,MAAM,cAAc,GAAwD;IAC1E,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE;QACZ,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;QAC3B,OAAO,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/D,CAAC;IACD,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE;IAChC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE;CAC/B,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,MAAe,EAAE,OAAiC;IAChF,OAAO,CACL,cAAgC,EAChC,OAAoC,EAClB,EAAE;QACpB,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QAED,eAAe,CAAC,OAAO,CAAC,QAA4C,EAAE,OAAO,CAAC,IAAc,EAAE;YAC5F,UAAU,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;SAChC,CAAC,CAAC;QAEH,OAAO,UAAyB,OAAoB;YAClD,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAmB,cAAc,CAAC,iBAAiB,CAAC,CAAC;YAC3F,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CACb,+EAA+E,CAChF,CAAC;YACJ,CAAC;YAED,MAAM,GAAG,GAA4B,EAAE,CAAC;YACxC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YACtD,CAAC;YAED,uEAAuE;YACvE,mEAAmE;YACnE,mEAAmE;YACnE,sEAAsE;YACtE,qEAAqE;YACrE,gBAAgB;YAChB,MAAM,WAAW,GAAG,SAAS,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,CAAC;YACvD,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,OAAO,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,OAAO,CAAC;gBACtD,IAAI,OAAO,EAAE,CAAC;oBACZ,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;wBAAE,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;oBACxE,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;wBAAE,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;gBACvE,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC/C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,eAAe,CAAC;oBACxB,OAAO,EAAE,2BAA2B;oBACpC,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE;iBAClC,CAAC,CAAC;YACL,CAAC;YAED,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,eAAe,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;YAClE,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5C,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { resolveHttpError, type ResolvedHttpError } from './resolve-http-error.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/error/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { resolveHttpError } from './resolve-http-error.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/error/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA0B,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { HttpResponse } from '../request/http-response.type.js';
2
+ export type ResolvedHttpError = {
3
+ readonly httpCode: number;
4
+ readonly body: Omit<HttpResponse, 'httpCode'>;
5
+ };
6
+ export declare function resolveHttpError(err: unknown): ResolvedHttpError;
7
+ //# sourceMappingURL=resolve-http-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-http-error.d.ts","sourceRoot":"","sources":["../../src/error/resolve-http-error.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAErE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;CAC/C,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,CAwBhE"}
@@ -0,0 +1,43 @@
1
+ import { ConflictError, ExternalError, ForbiddenError, InternalError, NotFoundError, QuillaError, UnauthorizedError, ValidationError, } from '@quilla-be-kit/errors';
2
+ export function resolveHttpError(err) {
3
+ if (QuillaError.is(err)) {
4
+ const json = err.toJSON();
5
+ return {
6
+ httpCode: mapQuillaErrorToHttpCode(err),
7
+ body: {
8
+ error: {
9
+ name: json.name,
10
+ message: json.message,
11
+ ...(json.context !== undefined ? { details: json.context } : {}),
12
+ },
13
+ },
14
+ };
15
+ }
16
+ return {
17
+ httpCode: 500,
18
+ body: {
19
+ error: {
20
+ name: 'InternalError',
21
+ message: 'Internal server error',
22
+ },
23
+ },
24
+ };
25
+ }
26
+ function mapQuillaErrorToHttpCode(err) {
27
+ if (err instanceof ValidationError)
28
+ return 400;
29
+ if (err instanceof UnauthorizedError)
30
+ return 401;
31
+ if (err instanceof ForbiddenError)
32
+ return 403;
33
+ if (err instanceof NotFoundError)
34
+ return 404;
35
+ if (err instanceof ConflictError)
36
+ return 409;
37
+ if (err instanceof ExternalError)
38
+ return 502;
39
+ if (err instanceof InternalError)
40
+ return 500;
41
+ return 500;
42
+ }
43
+ //# sourceMappingURL=resolve-http-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-http-error.js","sourceRoot":"","sources":["../../src/error/resolve-http-error.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAQ/B,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,IAAI,WAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;QAC1B,OAAO;YACL,QAAQ,EAAE,wBAAwB,CAAC,GAAG,CAAC;YACvC,IAAI,EAAE;gBACJ,KAAK,EAAE;oBACL,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACjE;aACF;SACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,GAAG;QACb,IAAI,EAAE;YACJ,KAAK,EAAE;gBACL,IAAI,EAAE,eAAe;gBACrB,OAAO,EAAE,uBAAuB;aACjC;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,GAAgB;IAChD,IAAI,GAAG,YAAY,eAAe;QAAE,OAAO,GAAG,CAAC;IAC/C,IAAI,GAAG,YAAY,iBAAiB;QAAE,OAAO,GAAG,CAAC;IACjD,IAAI,GAAG,YAAY,cAAc;QAAE,OAAO,GAAG,CAAC;IAC9C,IAAI,GAAG,YAAY,aAAa;QAAE,OAAO,GAAG,CAAC;IAC7C,IAAI,GAAG,YAAY,aAAa;QAAE,OAAO,GAAG,CAAC;IAC7C,IAAI,GAAG,YAAY,aAAa;QAAE,OAAO,GAAG,CAAC;IAC7C,IAAI,GAAG,YAAY,aAAa;QAAE,OAAO,GAAG,CAAC;IAC7C,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './request/index.js';
2
+ export * from './validator/index.js';
3
+ export * from './decorator/index.js';
4
+ export * from './router/index.js';
5
+ export * from './server/index.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export * from './request/index.js';
2
+ export * from './validator/index.js';
3
+ export * from './decorator/index.js';
4
+ export * from './router/index.js';
5
+ export * from './server/index.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export interface AuthenticatedToken {
2
+ readonly scopes?: readonly string[];
3
+ }
4
+ //# sourceMappingURL=authenticated-token.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authenticated-token.interface.d.ts","sourceRoot":"","sources":["../../src/request/authenticated-token.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=authenticated-token.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authenticated-token.interface.js","sourceRoot":"","sources":["../../src/request/authenticated-token.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export declare const HttpAttributes: {
2
+ readonly VERIFIED_TOKEN: "verifiedToken";
3
+ readonly VALIDATED_INPUT: "__validated_input__";
4
+ readonly REQUEST_VALIDATOR: "__request_validator__";
5
+ };
6
+ //# sourceMappingURL=http-attributes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-attributes.d.ts","sourceRoot":"","sources":["../../src/request/http-attributes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc;;;;CAIjB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export const HttpAttributes = {
2
+ VERIFIED_TOKEN: 'verifiedToken',
3
+ VALIDATED_INPUT: '__validated_input__',
4
+ REQUEST_VALIDATOR: '__request_validator__',
5
+ };
6
+ //# sourceMappingURL=http-attributes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-attributes.js","sourceRoot":"","sources":["../../src/request/http-attributes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,cAAc,EAAE,eAAe;IAC/B,eAAe,EAAE,qBAAqB;IACtC,iBAAiB,EAAE,uBAAuB;CAClC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { HttpRequest } from './http-request.interface.js';
2
+ export type HttpMiddleware = (request: HttpRequest, next: () => Promise<void>) => Promise<void>;
3
+ //# sourceMappingURL=http-middleware.type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-middleware.type.d.ts","sourceRoot":"","sources":["../../src/request/http-middleware.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=http-middleware.type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-middleware.type.js","sourceRoot":"","sources":["../../src/request/http-middleware.type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import type { ExecutionContext } from '@quilla-be-kit/execution-context';
2
+ export interface HttpRequest {
3
+ getPath(): string;
4
+ getMethod(): string;
5
+ getQuery(): Record<string, string | readonly string[]>;
6
+ getParams(): Record<string, string>;
7
+ getHeaders(): Record<string, string>;
8
+ getHeader(name: string): string | null;
9
+ getBody(): unknown;
10
+ getBinary(): Uint8Array | null;
11
+ getFile(name: string): File | null;
12
+ getFormFields(): Record<string, string | readonly string[]>;
13
+ getExecutionContext(): ExecutionContext;
14
+ setAttribute<T>(key: string, value: T): void;
15
+ getAttribute<T>(key: string): T | undefined;
16
+ getValidatedInput<T>(): T;
17
+ }
18
+ //# sourceMappingURL=http-request.interface.d.ts.map