honest-node 1.0.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 (165) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +277 -0
  3. package/dist/app.d.ts +1 -0
  4. package/dist/app.js +36 -0
  5. package/dist/application/plugin-entries.d.ts +13 -0
  6. package/dist/application/plugin-entries.js +38 -0
  7. package/dist/application/startup-guide.d.ts +4 -0
  8. package/dist/application/startup-guide.js +53 -0
  9. package/dist/application-context.d.ts +13 -0
  10. package/dist/application-context.js +22 -0
  11. package/dist/application.d.ts +34 -0
  12. package/dist/application.js +224 -0
  13. package/dist/components/index.d.ts +1 -0
  14. package/dist/components/index.js +1 -0
  15. package/dist/components/layout.component.d.ts +31 -0
  16. package/dist/components/layout.component.js +94 -0
  17. package/dist/constants/index.d.ts +2 -0
  18. package/dist/constants/index.js +2 -0
  19. package/dist/constants/pipeline.constants.d.ts +6 -0
  20. package/dist/constants/pipeline.constants.js +6 -0
  21. package/dist/constants/version.constants.d.ts +5 -0
  22. package/dist/constants/version.constants.js +5 -0
  23. package/dist/decorators/controller.decorator.d.ts +9 -0
  24. package/dist/decorators/controller.decorator.js +16 -0
  25. package/dist/decorators/http-method.decorator.d.ts +43 -0
  26. package/dist/decorators/http-method.decorator.js +44 -0
  27. package/dist/decorators/index.d.ts +11 -0
  28. package/dist/decorators/index.js +11 -0
  29. package/dist/decorators/module.decorator.d.ts +8 -0
  30. package/dist/decorators/module.decorator.js +12 -0
  31. package/dist/decorators/mvc.decorator.d.ts +26 -0
  32. package/dist/decorators/mvc.decorator.js +36 -0
  33. package/dist/decorators/parameter.decorator.d.ts +41 -0
  34. package/dist/decorators/parameter.decorator.js +59 -0
  35. package/dist/decorators/service.decorator.d.ts +6 -0
  36. package/dist/decorators/service.decorator.js +11 -0
  37. package/dist/decorators/use-component.decorator.d.ts +10 -0
  38. package/dist/decorators/use-component.decorator.js +19 -0
  39. package/dist/decorators/use-filters.decorator.d.ts +8 -0
  40. package/dist/decorators/use-filters.decorator.js +17 -0
  41. package/dist/decorators/use-guards.decorator.d.ts +9 -0
  42. package/dist/decorators/use-guards.decorator.js +18 -0
  43. package/dist/decorators/use-middleware.decorator.d.ts +9 -0
  44. package/dist/decorators/use-middleware.decorator.js +18 -0
  45. package/dist/decorators/use-pipes.decorator.d.ts +9 -0
  46. package/dist/decorators/use-pipes.decorator.js +18 -0
  47. package/dist/di/container.d.ts +34 -0
  48. package/dist/di/container.js +114 -0
  49. package/dist/di/index.d.ts +1 -0
  50. package/dist/di/index.js +1 -0
  51. package/dist/errors/framework.error.d.ts +19 -0
  52. package/dist/errors/framework.error.js +23 -0
  53. package/dist/errors/index.d.ts +1 -0
  54. package/dist/errors/index.js +1 -0
  55. package/dist/handlers/error.handler.d.ts +28 -0
  56. package/dist/handlers/error.handler.js +17 -0
  57. package/dist/handlers/index.d.ts +2 -0
  58. package/dist/handlers/index.js +2 -0
  59. package/dist/handlers/not-found.handler.d.ts +14 -0
  60. package/dist/handlers/not-found.handler.js +17 -0
  61. package/dist/helpers/create-error-response.helper.d.ts +25 -0
  62. package/dist/helpers/create-error-response.helper.js +90 -0
  63. package/dist/helpers/create-http-method-decorator.helper.d.ts +16 -0
  64. package/dist/helpers/create-http-method-decorator.helper.js +30 -0
  65. package/dist/helpers/create-param-decorator.helper.d.ts +16 -0
  66. package/dist/helpers/create-param-decorator.helper.js +60 -0
  67. package/dist/helpers/index.d.ts +3 -0
  68. package/dist/helpers/index.js +3 -0
  69. package/dist/index.d.ts +16 -0
  70. package/dist/index.js +16 -0
  71. package/dist/interfaces/application-context.interface.d.ts +35 -0
  72. package/dist/interfaces/application-context.interface.js +1 -0
  73. package/dist/interfaces/controller-options.interface.d.ts +17 -0
  74. package/dist/interfaces/controller-options.interface.js +1 -0
  75. package/dist/interfaces/di-container.interface.d.ts +35 -0
  76. package/dist/interfaces/di-container.interface.js +1 -0
  77. package/dist/interfaces/error-response.interface.d.ts +13 -0
  78. package/dist/interfaces/error-response.interface.js +1 -0
  79. package/dist/interfaces/filter.interface.d.ts +20 -0
  80. package/dist/interfaces/filter.interface.js +1 -0
  81. package/dist/interfaces/guard.interface.d.ts +21 -0
  82. package/dist/interfaces/guard.interface.js +1 -0
  83. package/dist/interfaces/handler-invocation.interface.d.ts +10 -0
  84. package/dist/interfaces/handler-invocation.interface.js +1 -0
  85. package/dist/interfaces/honest-options.interface.d.ts +121 -0
  86. package/dist/interfaces/honest-options.interface.js +1 -0
  87. package/dist/interfaces/http-method-options.interface.d.ts +38 -0
  88. package/dist/interfaces/http-method-options.interface.js +1 -0
  89. package/dist/interfaces/index.d.ts +21 -0
  90. package/dist/interfaces/index.js +21 -0
  91. package/dist/interfaces/logger.interface.d.ts +23 -0
  92. package/dist/interfaces/logger.interface.js +1 -0
  93. package/dist/interfaces/metadata-repository.interface.d.ts +30 -0
  94. package/dist/interfaces/metadata-repository.interface.js +1 -0
  95. package/dist/interfaces/middleware.interface.d.ts +22 -0
  96. package/dist/interfaces/middleware.interface.js +1 -0
  97. package/dist/interfaces/module-options.interface.d.ts +18 -0
  98. package/dist/interfaces/module-options.interface.js +1 -0
  99. package/dist/interfaces/parameter-metadata.interface.d.ts +27 -0
  100. package/dist/interfaces/parameter-metadata.interface.js +1 -0
  101. package/dist/interfaces/parameter-resolution.interface.d.ts +14 -0
  102. package/dist/interfaces/parameter-resolution.interface.js +1 -0
  103. package/dist/interfaces/pipe.interface.d.ts +37 -0
  104. package/dist/interfaces/pipe.interface.js +1 -0
  105. package/dist/interfaces/pipeline-context.interface.d.ts +9 -0
  106. package/dist/interfaces/pipeline-context.interface.js +1 -0
  107. package/dist/interfaces/plugin.interface.d.ts +74 -0
  108. package/dist/interfaces/plugin.interface.js +1 -0
  109. package/dist/interfaces/route-definition.interface.d.ts +51 -0
  110. package/dist/interfaces/route-definition.interface.js +1 -0
  111. package/dist/interfaces/route-info.interface.d.ts +42 -0
  112. package/dist/interfaces/route-info.interface.js +1 -0
  113. package/dist/interfaces/service-registry.interface.d.ts +7 -0
  114. package/dist/interfaces/service-registry.interface.js +1 -0
  115. package/dist/loggers/console.logger.d.ts +7 -0
  116. package/dist/loggers/console.logger.js +21 -0
  117. package/dist/loggers/index.d.ts +2 -0
  118. package/dist/loggers/index.js +2 -0
  119. package/dist/loggers/noop.logger.d.ts +7 -0
  120. package/dist/loggers/noop.logger.js +8 -0
  121. package/dist/managers/component.manager.d.ts +48 -0
  122. package/dist/managers/component.manager.js +210 -0
  123. package/dist/managers/handler.invoker.d.ts +7 -0
  124. package/dist/managers/handler.invoker.js +37 -0
  125. package/dist/managers/index.d.ts +5 -0
  126. package/dist/managers/index.js +5 -0
  127. package/dist/managers/parameter.resolver.d.ts +13 -0
  128. package/dist/managers/parameter.resolver.js +58 -0
  129. package/dist/managers/pipeline.executor.d.ts +28 -0
  130. package/dist/managers/pipeline.executor.js +71 -0
  131. package/dist/managers/route.manager.d.ts +36 -0
  132. package/dist/managers/route.manager.js +149 -0
  133. package/dist/registries/index.d.ts +4 -0
  134. package/dist/registries/index.js +4 -0
  135. package/dist/registries/metadata.registry.d.ts +163 -0
  136. package/dist/registries/metadata.registry.js +250 -0
  137. package/dist/registries/metadata.repository.d.ts +30 -0
  138. package/dist/registries/metadata.repository.js +151 -0
  139. package/dist/registries/route.registry.d.ts +16 -0
  140. package/dist/registries/route.registry.js +46 -0
  141. package/dist/registries/service.registry.d.ts +8 -0
  142. package/dist/registries/service.registry.js +9 -0
  143. package/dist/testing/create-controller-test-application.d.ts +5 -0
  144. package/dist/testing/create-controller-test-application.js +11 -0
  145. package/dist/testing/create-service-test-container.d.ts +5 -0
  146. package/dist/testing/create-service-test-container.js +31 -0
  147. package/dist/testing/create-test-application.d.ts +5 -0
  148. package/dist/testing/create-test-application.js +20 -0
  149. package/dist/testing/create-testing-module.d.ts +6 -0
  150. package/dist/testing/create-testing-module.js +13 -0
  151. package/dist/testing/fixtures/application-test-fixtures.d.ts +17 -0
  152. package/dist/testing/fixtures/application-test-fixtures.js +230 -0
  153. package/dist/testing/index.d.ts +5 -0
  154. package/dist/testing/index.js +5 -0
  155. package/dist/testing/testing.interface.d.ts +96 -0
  156. package/dist/testing/testing.interface.js +1 -0
  157. package/dist/types/constructor.type.d.ts +12 -0
  158. package/dist/types/constructor.type.js +1 -0
  159. package/dist/types/index.d.ts +1 -0
  160. package/dist/types/index.js +1 -0
  161. package/dist/utils/common.util.d.ts +117 -0
  162. package/dist/utils/common.util.js +140 -0
  163. package/dist/utils/index.d.ts +1 -0
  164. package/dist/utils/index.js +1 -0
  165. package/package.json +42 -0
@@ -0,0 +1,59 @@
1
+ import { HONEST_PIPELINE_BODY_CACHE_KEY } from '../constants';
2
+ import { createParamDecorator } from '../helpers';
3
+ /**
4
+ * Decorator that binds the request body to a parameter
5
+ * @param data - Optional property name to extract from the body
6
+ */
7
+ export const Body = createParamDecorator('body', async (data, ctx) => {
8
+ let body = ctx.get(HONEST_PIPELINE_BODY_CACHE_KEY);
9
+ if (body === undefined) {
10
+ body = await ctx.req.json();
11
+ ctx.set(HONEST_PIPELINE_BODY_CACHE_KEY, body);
12
+ }
13
+ if (data && body && typeof body === 'object') {
14
+ return body[String(data)];
15
+ }
16
+ return body;
17
+ });
18
+ /**
19
+ * Decorator that binds a route parameter to a parameter
20
+ * @param data - The parameter name in the route
21
+ */
22
+ export const Param = createParamDecorator('param', (data, ctx) => {
23
+ return data ? ctx.req.param(String(data)) : ctx.req.param();
24
+ });
25
+ /**
26
+ * Decorator that binds a query parameter to a parameter
27
+ * @param data - The query parameter name
28
+ */
29
+ export const Query = createParamDecorator('query', (data, ctx) => {
30
+ return data ? ctx.req.query(String(data)) : ctx.req.query();
31
+ });
32
+ /**
33
+ * Decorator that binds a header value to a parameter
34
+ * @param data - The header name
35
+ */
36
+ export const Header = createParamDecorator('header', (data, ctx) => {
37
+ return data ? ctx.req.header(String(data)) : ctx.req.header();
38
+ });
39
+ /**
40
+ * Decorator that binds the request object to a parameter
41
+ */
42
+ export const Req = createParamDecorator('request', (_, ctx) => ctx.req);
43
+ export const Request = createParamDecorator('request', (_, ctx) => ctx.req);
44
+ /**
45
+ * Decorator that binds the response object to a parameter
46
+ */
47
+ export const Res = createParamDecorator('response', (_, ctx) => ctx.res);
48
+ export const Response = createParamDecorator('response', (_, ctx) => ctx.res);
49
+ /**
50
+ * Decorator that binds the context object to a parameter
51
+ */
52
+ export const Ctx = createParamDecorator('context', (_, ctx) => ctx);
53
+ export const Context = createParamDecorator('context', (_, ctx) => ctx);
54
+ /**
55
+ * Decorator that binds a context variable to a parameter
56
+ * @param data - The variable name to retrieve from context
57
+ */
58
+ export const Var = createParamDecorator('variable', (data, ctx) => data === undefined ? undefined : ctx.get(String(data)));
59
+ export const Variable = createParamDecorator('variable', (data, ctx) => data === undefined ? undefined : ctx.get(String(data)));
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Decorator that marks a class as a service
3
+ * Services are singleton classes that can be injected as dependencies
4
+ * @returns A class decorator function
5
+ */
6
+ export declare function Service(): ClassDecorator;
@@ -0,0 +1,11 @@
1
+ import { MetadataRegistry } from '../registries';
2
+ /**
3
+ * Decorator that marks a class as a service
4
+ * Services are singleton classes that can be injected as dependencies
5
+ * @returns A class decorator function
6
+ */
7
+ export function Service() {
8
+ return (target) => {
9
+ MetadataRegistry.addService(target);
10
+ };
11
+ }
@@ -0,0 +1,10 @@
1
+ import type { ComponentType, ComponentTypeMap } from '../registries';
2
+ import type { Constructor } from '../types';
3
+ /**
4
+ * Generic decorator that applies components of a specific type to a controller class or method
5
+ * @template T - The type of component being applied
6
+ * @param type - The component type identifier
7
+ * @param components - Array of components to apply
8
+ * @returns A decorator function that can be used at class or method level
9
+ */
10
+ export declare function UseComponent<T extends ComponentType>(type: T, ...components: ComponentTypeMap[T][]): (target: Constructor | object, propertyKey?: string | symbol) => void;
@@ -0,0 +1,19 @@
1
+ import { MetadataRegistry } from '../registries';
2
+ /**
3
+ * Generic decorator that applies components of a specific type to a controller class or method
4
+ * @template T - The type of component being applied
5
+ * @param type - The component type identifier
6
+ * @param components - Array of components to apply
7
+ * @returns A decorator function that can be used at class or method level
8
+ */
9
+ export function UseComponent(type, ...components) {
10
+ return (target, propertyKey) => {
11
+ if (propertyKey) {
12
+ const controllerClass = target.constructor;
13
+ components.forEach((component) => MetadataRegistry.registerHandler(type, controllerClass, propertyKey, component));
14
+ }
15
+ else {
16
+ components.forEach((component) => MetadataRegistry.registerController(type, target, component));
17
+ }
18
+ };
19
+ }
@@ -0,0 +1,8 @@
1
+ import type { FilterType } from '../interfaces';
2
+ import type { Constructor } from '../types';
3
+ /**
4
+ * Decorator that applies exception filters to a controller class or method
5
+ * @param filters - Array of exception filters to apply
6
+ * @returns A decorator function that can be used at class or method level
7
+ */
8
+ export declare function UseFilters(...filters: FilterType[]): (target: Constructor | object, propertyKey?: string | symbol) => void;
@@ -0,0 +1,17 @@
1
+ import { MetadataRegistry } from '../registries';
2
+ /**
3
+ * Decorator that applies exception filters to a controller class or method
4
+ * @param filters - Array of exception filters to apply
5
+ * @returns A decorator function that can be used at class or method level
6
+ */
7
+ export function UseFilters(...filters) {
8
+ return (target, propertyKey) => {
9
+ if (propertyKey) {
10
+ const controllerClass = target.constructor;
11
+ filters.forEach((filter) => MetadataRegistry.registerHandler('filter', controllerClass, propertyKey, filter));
12
+ }
13
+ else {
14
+ filters.forEach((filter) => MetadataRegistry.registerController('filter', target, filter));
15
+ }
16
+ };
17
+ }
@@ -0,0 +1,9 @@
1
+ import type { GuardType } from '../interfaces';
2
+ import type { Constructor } from '../types';
3
+ /**
4
+ * Decorator that applies guards to a controller class or method
5
+ * Guards determine whether a request should be handled by the route handler
6
+ * @param guards - Array of guards to apply
7
+ * @returns A decorator function that can be used at class or method level
8
+ */
9
+ export declare function UseGuards(...guards: GuardType[]): (target: Constructor | object, propertyKey?: string | symbol) => void;
@@ -0,0 +1,18 @@
1
+ import { MetadataRegistry } from '../registries';
2
+ /**
3
+ * Decorator that applies guards to a controller class or method
4
+ * Guards determine whether a request should be handled by the route handler
5
+ * @param guards - Array of guards to apply
6
+ * @returns A decorator function that can be used at class or method level
7
+ */
8
+ export function UseGuards(...guards) {
9
+ return (target, propertyKey) => {
10
+ if (propertyKey) {
11
+ const controllerClass = target.constructor;
12
+ guards.forEach((guard) => MetadataRegistry.registerHandler('guard', controllerClass, propertyKey, guard));
13
+ }
14
+ else {
15
+ guards.forEach((guard) => MetadataRegistry.registerController('guard', target, guard));
16
+ }
17
+ };
18
+ }
@@ -0,0 +1,9 @@
1
+ import type { MiddlewareType } from '../interfaces';
2
+ import type { Constructor } from '../types';
3
+ /**
4
+ * Decorator that applies middleware to a controller class or method
5
+ * Middleware functions run before the route handler and can modify the request/response
6
+ * @param middleware - Array of middleware functions to apply
7
+ * @returns A decorator function that can be used at class or method level
8
+ */
9
+ export declare function UseMiddleware(...middleware: MiddlewareType[]): (target: Constructor | object, propertyKey?: string | symbol) => void;
@@ -0,0 +1,18 @@
1
+ import { MetadataRegistry } from '../registries';
2
+ /**
3
+ * Decorator that applies middleware to a controller class or method
4
+ * Middleware functions run before the route handler and can modify the request/response
5
+ * @param middleware - Array of middleware functions to apply
6
+ * @returns A decorator function that can be used at class or method level
7
+ */
8
+ export function UseMiddleware(...middleware) {
9
+ return (target, propertyKey) => {
10
+ if (propertyKey) {
11
+ const controllerClass = target.constructor;
12
+ middleware.forEach((mw) => MetadataRegistry.registerHandler('middleware', controllerClass, propertyKey, mw));
13
+ }
14
+ else {
15
+ middleware.forEach((mw) => MetadataRegistry.registerController('middleware', target, mw));
16
+ }
17
+ };
18
+ }
@@ -0,0 +1,9 @@
1
+ import type { PipeType } from '../interfaces';
2
+ import type { Constructor } from '../types';
3
+ /**
4
+ * Decorator that applies transformation pipes to a controller class or method
5
+ * Pipes transform input data before it reaches the route handler
6
+ * @param pipes - Array of pipes to apply
7
+ * @returns A decorator function that can be used at class or method level
8
+ */
9
+ export declare function UsePipes(...pipes: PipeType[]): (target: Constructor | object, propertyKey?: string | symbol) => void;
@@ -0,0 +1,18 @@
1
+ import { MetadataRegistry } from '../registries';
2
+ /**
3
+ * Decorator that applies transformation pipes to a controller class or method
4
+ * Pipes transform input data before it reaches the route handler
5
+ * @param pipes - Array of pipes to apply
6
+ * @returns A decorator function that can be used at class or method level
7
+ */
8
+ export function UsePipes(...pipes) {
9
+ return (target, propertyKey) => {
10
+ if (propertyKey) {
11
+ const controllerClass = target.constructor;
12
+ pipes.forEach((pipe) => MetadataRegistry.registerHandler('pipe', controllerClass, propertyKey, pipe));
13
+ }
14
+ else {
15
+ pipes.forEach((pipe) => MetadataRegistry.registerController('pipe', target, pipe));
16
+ }
17
+ };
18
+ }
@@ -0,0 +1,34 @@
1
+ import type { DiContainer, ILogger, IServiceRegistry } from '../interfaces';
2
+ import type { Constructor } from '../types';
3
+ /**
4
+ * Dependency Injection container that manages class instances and their dependencies
5
+ */
6
+ export declare class Container implements DiContainer {
7
+ private readonly serviceRegistry;
8
+ private readonly logger;
9
+ private readonly debugDi;
10
+ constructor(serviceRegistry?: IServiceRegistry, logger?: ILogger, debugDi?: boolean);
11
+ /**
12
+ * Map of class constructors to their instances
13
+ */
14
+ private instances;
15
+ private emitLog;
16
+ /**
17
+ * Resolves a class instance, creating it if necessary and injecting its dependencies
18
+ * @param target - The class constructor to resolve
19
+ * @returns An instance of the target class
20
+ */
21
+ resolve<T>(target: Constructor<T>): T;
22
+ /**
23
+ * Internal recursive resolver with circular dependency tracking
24
+ */
25
+ private resolveWithTracking;
26
+ /**
27
+ * Registers a pre-created instance for a class
28
+ * @param target - The class constructor to register
29
+ * @param instance - The instance to register
30
+ */
31
+ register<T>(target: Constructor<T>, instance: T): void;
32
+ has<T>(target: Constructor<T>): boolean;
33
+ clear(): void;
34
+ }
@@ -0,0 +1,114 @@
1
+ import { NoopLogger } from '../loggers';
2
+ import { StaticServiceRegistry } from '../registries';
3
+ /**
4
+ * Dependency Injection container that manages class instances and their dependencies
5
+ */
6
+ export class Container {
7
+ serviceRegistry;
8
+ logger;
9
+ debugDi;
10
+ constructor(serviceRegistry = new StaticServiceRegistry(), logger = new NoopLogger(), debugDi = false) {
11
+ this.serviceRegistry = serviceRegistry;
12
+ this.logger = logger;
13
+ this.debugDi = debugDi;
14
+ }
15
+ /**
16
+ * Map of class constructors to their instances
17
+ */
18
+ instances = new Map();
19
+ emitLog(event) {
20
+ if (!this.debugDi) {
21
+ return;
22
+ }
23
+ this.logger.emit(event);
24
+ }
25
+ /**
26
+ * Resolves a class instance, creating it if necessary and injecting its dependencies
27
+ * @param target - The class constructor to resolve
28
+ * @returns An instance of the target class
29
+ */
30
+ resolve(target) {
31
+ return this.resolveWithTracking(target, new Set());
32
+ }
33
+ /**
34
+ * Internal recursive resolver with circular dependency tracking
35
+ */
36
+ resolveWithTracking(target, resolving) {
37
+ if (this.instances.has(target)) {
38
+ this.emitLog({
39
+ level: 'debug',
40
+ category: 'di',
41
+ message: `Resolved ${target.name} from DI cache`
42
+ });
43
+ return this.instances.get(target);
44
+ }
45
+ if (resolving.has(target)) {
46
+ const cycle = [...resolving.keys(), target].map((t) => t.name).join(' -> ');
47
+ this.emitLog({
48
+ level: 'error',
49
+ category: 'di',
50
+ message: `Circular dependency detected while resolving ${target.name}`,
51
+ details: { cycle }
52
+ });
53
+ throw new Error(`Circular dependency detected: ${cycle}`);
54
+ }
55
+ resolving.add(target);
56
+ this.emitLog({
57
+ level: 'debug',
58
+ category: 'di',
59
+ message: `Resolving ${target.name}`,
60
+ details: { resolving: [...resolving].map((constructor) => constructor.name) }
61
+ });
62
+ const paramTypes = Reflect.getMetadata('design:paramtypes', target) || [];
63
+ if (target.length > 0 && paramTypes.length === 0) {
64
+ if (!this.serviceRegistry.isService(target)) {
65
+ this.emitLog({
66
+ level: 'error',
67
+ category: 'di',
68
+ message: `Cannot resolve ${target.name}: missing @Service() decorator`
69
+ });
70
+ throw new Error(`Cannot resolve ${target.name}: it is not decorated with @Service(). Did you forget to add @Service() to the class?`);
71
+ }
72
+ this.emitLog({
73
+ level: 'error',
74
+ category: 'di',
75
+ message: `Cannot resolve ${target.name}: missing constructor metadata`
76
+ });
77
+ throw new Error(`Cannot resolve dependencies for ${target.name}: constructor metadata is missing. Ensure 'reflect-metadata' is imported and 'emitDecoratorMetadata' is enabled.`);
78
+ }
79
+ const dependencies = paramTypes.map((paramType, index) => {
80
+ if (!paramType || paramType === Object || paramType === Array || paramType === Function) {
81
+ this.emitLog({
82
+ level: 'error',
83
+ category: 'di',
84
+ message: `Cannot resolve dependency at index ${index} of ${target.name}`
85
+ });
86
+ throw new Error(`Cannot resolve dependency at index ${index} of ${target.name}. Use concrete class types for constructor dependencies.`);
87
+ }
88
+ return this.resolveWithTracking(paramType, new Set(resolving));
89
+ });
90
+ const instance = new target(...dependencies);
91
+ this.instances.set(target, instance);
92
+ this.emitLog({
93
+ level: 'debug',
94
+ category: 'di',
95
+ message: `Created ${target.name} instance`,
96
+ details: { dependencyCount: dependencies.length }
97
+ });
98
+ return instance;
99
+ }
100
+ /**
101
+ * Registers a pre-created instance for a class
102
+ * @param target - The class constructor to register
103
+ * @param instance - The instance to register
104
+ */
105
+ register(target, instance) {
106
+ this.instances.set(target, instance);
107
+ }
108
+ has(target) {
109
+ return this.instances.has(target);
110
+ }
111
+ clear() {
112
+ this.instances.clear();
113
+ }
114
+ }
@@ -0,0 +1 @@
1
+ export * from './container';
@@ -0,0 +1 @@
1
+ export * from './container';
@@ -0,0 +1,19 @@
1
+ export interface FrameworkErrorOptions {
2
+ status?: number;
3
+ code: string;
4
+ category: string;
5
+ remediation?: string;
6
+ details?: Record<string, unknown>;
7
+ cause?: unknown;
8
+ }
9
+ /**
10
+ * Structured framework-level error with machine-readable metadata.
11
+ */
12
+ export declare class FrameworkError extends Error {
13
+ readonly status?: number;
14
+ readonly code: string;
15
+ readonly category: string;
16
+ readonly remediation?: string;
17
+ readonly details?: Record<string, unknown>;
18
+ constructor(message: string, options: FrameworkErrorOptions);
19
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Structured framework-level error with machine-readable metadata.
3
+ */
4
+ export class FrameworkError extends Error {
5
+ status;
6
+ code;
7
+ category;
8
+ remediation;
9
+ details;
10
+ constructor(message, options) {
11
+ super(message);
12
+ this.name = 'FrameworkError';
13
+ this.status = options.status;
14
+ this.code = options.code;
15
+ this.category = options.category;
16
+ this.remediation = options.remediation;
17
+ this.details = options.details;
18
+ if (options.cause !== undefined) {
19
+ ;
20
+ this.cause = options.cause;
21
+ }
22
+ }
23
+ }
@@ -0,0 +1 @@
1
+ export * from './framework.error';
@@ -0,0 +1 @@
1
+ export * from './framework.error';
@@ -0,0 +1,28 @@
1
+ import type { Context } from 'hono';
2
+ /**
3
+ * Handler for managing application-wide error responses
4
+ * Provides a consistent way to handle and format error responses across the application
5
+ */
6
+ export declare class ErrorHandler {
7
+ /**
8
+ * Creates a middleware function that handles error responses
9
+ * @returns A middleware function that formats and returns error responses using createErrorResponse
10
+ */
11
+ static handle(): (err: unknown, c: Context) => Promise<Response & import("hono").TypedResponse<{
12
+ status: number;
13
+ message: string;
14
+ timestamp: string;
15
+ path: string;
16
+ requestId?: string | undefined;
17
+ code?: string | undefined;
18
+ details?: {
19
+ [x: string]: any;
20
+ } | undefined;
21
+ errors?: {
22
+ property: string;
23
+ constraints: {
24
+ [x: string]: string;
25
+ };
26
+ }[] | undefined;
27
+ }, -1 | 100 | 102 | 103 | 200 | 201 | 202 | 203 | 206 | 207 | 208 | 226 | 300 | 301 | 302 | 303 | 305 | 306 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511, "json">>;
28
+ }
@@ -0,0 +1,17 @@
1
+ import { createErrorResponse } from '../helpers';
2
+ /**
3
+ * Handler for managing application-wide error responses
4
+ * Provides a consistent way to handle and format error responses across the application
5
+ */
6
+ export class ErrorHandler {
7
+ /**
8
+ * Creates a middleware function that handles error responses
9
+ * @returns A middleware function that formats and returns error responses using createErrorResponse
10
+ */
11
+ static handle() {
12
+ return async (err, c) => {
13
+ const { response, status } = createErrorResponse(err, c);
14
+ return c.json(response, status);
15
+ };
16
+ }
17
+ }
@@ -0,0 +1,2 @@
1
+ export * from './error.handler';
2
+ export * from './not-found.handler';
@@ -0,0 +1,2 @@
1
+ export * from './error.handler';
2
+ export * from './not-found.handler';
@@ -0,0 +1,14 @@
1
+ import type { Context } from 'hono';
2
+ /**
3
+ * Handler for managing 404 Not Found responses
4
+ * Provides a consistent way to handle requests to non-existent routes
5
+ */
6
+ export declare class NotFoundHandler {
7
+ /**
8
+ * Creates a middleware function that handles 404 Not Found responses
9
+ * @returns A middleware function that returns a JSON response with a 404 status
10
+ */
11
+ static handle(): (c: Context) => Promise<Response & import("hono").TypedResponse<{
12
+ message: string;
13
+ }, 404, "json">>;
14
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Handler for managing 404 Not Found responses
3
+ * Provides a consistent way to handle requests to non-existent routes
4
+ */
5
+ export class NotFoundHandler {
6
+ /**
7
+ * Creates a middleware function that handles 404 Not Found responses
8
+ * @returns A middleware function that returns a JSON response with a 404 status
9
+ */
10
+ static handle() {
11
+ return async (c) => {
12
+ return c.json({
13
+ message: `Not Found - ${c.req.path}`
14
+ }, 404);
15
+ };
16
+ }
17
+ }
@@ -0,0 +1,25 @@
1
+ import type { Context } from 'hono';
2
+ import type { ContentfulStatusCode } from 'hono/utils/http-status';
3
+ import type { ErrorResponse } from '../interfaces';
4
+ /**
5
+ * Creates a standardized error response object
6
+ * @param exception - The error or exception object to process
7
+ * @param context - The Hono context object containing request information
8
+ * @param options - Optional configuration for the error response
9
+ * @param options.status - HTTP status code to override the default
10
+ * @param options.title - Custom error message to override the default
11
+ * @param options.detail - Additional error details
12
+ * @param options.code - Custom error code
13
+ * @param options.additionalDetails - Extra information to include in the response
14
+ * @returns Object containing the formatted error response and HTTP status code
15
+ */
16
+ export declare function createErrorResponse(exception: unknown, context: Context, options?: {
17
+ status?: number;
18
+ title?: string;
19
+ detail?: string;
20
+ code?: string;
21
+ additionalDetails?: Record<string, unknown>;
22
+ }): {
23
+ response: ErrorResponse;
24
+ status: ContentfulStatusCode;
25
+ };
@@ -0,0 +1,90 @@
1
+ import { HTTPException } from 'hono/http-exception';
2
+ import { FrameworkError } from '../errors';
3
+ /**
4
+ * Creates a standardized error response object
5
+ * @param exception - The error or exception object to process
6
+ * @param context - The Hono context object containing request information
7
+ * @param options - Optional configuration for the error response
8
+ * @param options.status - HTTP status code to override the default
9
+ * @param options.title - Custom error message to override the default
10
+ * @param options.detail - Additional error details
11
+ * @param options.code - Custom error code
12
+ * @param options.additionalDetails - Extra information to include in the response
13
+ * @returns Object containing the formatted error response and HTTP status code
14
+ */
15
+ export function createErrorResponse(exception, context, options) {
16
+ const normalizedException = exception instanceof Error ? exception : new Error(String(exception));
17
+ const timestamp = new Date().toISOString();
18
+ const requestId = context.get('requestId');
19
+ const path = context.req.path;
20
+ // Handle HTTPException (Hono's built-in exception)
21
+ if (normalizedException instanceof HTTPException) {
22
+ const response = {
23
+ status: options?.status || normalizedException.status,
24
+ message: options?.title || normalizedException.message,
25
+ timestamp,
26
+ path,
27
+ requestId,
28
+ code: options?.code,
29
+ details: options?.additionalDetails,
30
+ ...(options?.detail && { detail: options.detail })
31
+ };
32
+ return { response, status: (options?.status || normalizedException.status) };
33
+ }
34
+ if (normalizedException instanceof FrameworkError) {
35
+ const status = (options?.status || normalizedException.status || 500);
36
+ const response = {
37
+ status,
38
+ message: options?.title || normalizedException.message,
39
+ timestamp,
40
+ path,
41
+ requestId,
42
+ code: options?.code || normalizedException.code,
43
+ details: {
44
+ category: normalizedException.category,
45
+ remediation: normalizedException.remediation,
46
+ ...normalizedException.details,
47
+ ...options?.additionalDetails
48
+ },
49
+ ...(options?.detail && { detail: options.detail })
50
+ };
51
+ return { response, status };
52
+ }
53
+ // Combined status handling
54
+ if (normalizedException.statusCode ||
55
+ normalizedException.status) {
56
+ const defaultStatus = normalizedException.statusCode ||
57
+ normalizedException.status ||
58
+ 500;
59
+ const status = options?.status || defaultStatus;
60
+ const response = {
61
+ status,
62
+ message: options?.title || normalizedException.message,
63
+ timestamp,
64
+ path,
65
+ requestId,
66
+ code: options?.code || normalizedException.name,
67
+ details: options?.additionalDetails,
68
+ ...(options?.detail && { detail: options.detail })
69
+ };
70
+ return {
71
+ response,
72
+ status: status
73
+ };
74
+ }
75
+ // Handle unexpected errors
76
+ const status = (options?.status || 500);
77
+ const response = {
78
+ status,
79
+ message: options?.title ||
80
+ (process.env.NODE_ENV === 'production' ? 'Internal Server Error' : normalizedException.message),
81
+ timestamp,
82
+ path,
83
+ requestId,
84
+ code: options?.code || normalizedException.name,
85
+ details: options?.additionalDetails ||
86
+ (process.env.NODE_ENV === 'development' ? { stack: normalizedException.stack } : undefined),
87
+ ...(options?.detail && { detail: options.detail })
88
+ };
89
+ return { response, status };
90
+ }
@@ -0,0 +1,16 @@
1
+ import type { HttpMethodOptions } from '../interfaces';
2
+ /**
3
+ * Creates a decorator factory for HTTP method handlers
4
+ * @param method - The HTTP method type (GET, POST, PUT, etc.)
5
+ * @returns A method decorator factory that accepts a path and options
6
+ * @example
7
+ * ```ts
8
+ * const Get = createHttpMethodDecorator(HttpMethod.GET);
9
+ *
10
+ * class Controller {
11
+ * @Get('/users')
12
+ * getUsers() { }
13
+ * }
14
+ * ```
15
+ */
16
+ export declare function createHttpMethodDecorator(method: string): (path?: string, options?: HttpMethodOptions) => MethodDecorator;