@carno.js/core 1.1.1 → 1.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 (124) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +188 -188
  3. package/dist/Carno.js +45 -26
  4. package/dist/Carno.mjs +45 -26
  5. package/dist/bun/index.js +4 -4
  6. package/dist/bun/index.js.map +30 -29
  7. package/dist/compression/CompressionMiddleware.js +110 -0
  8. package/dist/compression/CompressionMiddleware.mjs +90 -0
  9. package/dist/index.js +3 -1
  10. package/dist/index.mjs +2 -0
  11. package/package.json +2 -2
  12. package/src/Carno.ts +728 -673
  13. package/src/DefaultRoutes.ts +34 -34
  14. package/src/cache/CacheDriver.ts +50 -50
  15. package/src/cache/CacheService.ts +139 -139
  16. package/src/cache/MemoryDriver.ts +104 -104
  17. package/src/cache/RedisDriver.ts +116 -116
  18. package/src/compiler/JITCompiler.ts +167 -167
  19. package/src/compression/CompressionMiddleware.ts +221 -0
  20. package/src/container/Container.ts +168 -168
  21. package/src/context/Context.ts +130 -130
  22. package/src/cors/CorsHandler.ts +145 -145
  23. package/src/decorators/Controller.ts +63 -63
  24. package/src/decorators/Inject.ts +16 -16
  25. package/src/decorators/Middleware.ts +22 -22
  26. package/src/decorators/Service.ts +18 -18
  27. package/src/decorators/methods.ts +58 -58
  28. package/src/decorators/params.ts +47 -47
  29. package/src/events/Lifecycle.ts +97 -97
  30. package/src/exceptions/HttpException.ts +99 -99
  31. package/src/index.ts +99 -95
  32. package/src/metadata.ts +46 -46
  33. package/src/middleware/CarnoMiddleware.ts +20 -14
  34. package/src/router/RadixRouter.ts +225 -225
  35. package/src/testing/TestHarness.ts +185 -185
  36. package/src/utils/Metadata.ts +43 -43
  37. package/src/utils/parseQuery.ts +161 -161
  38. package/src/validation/ValibotAdapter.ts +95 -95
  39. package/src/validation/ValidatorAdapter.ts +69 -69
  40. package/src/validation/ZodAdapter.ts +102 -102
  41. package/dist/Carno.d.js +0 -14
  42. package/dist/Carno.d.mjs +0 -1
  43. package/dist/DefaultRoutes.d.js +0 -13
  44. package/dist/DefaultRoutes.d.mjs +0 -0
  45. package/dist/cache/CacheDriver.d.js +0 -13
  46. package/dist/cache/CacheDriver.d.mjs +0 -0
  47. package/dist/cache/CacheService.d.js +0 -13
  48. package/dist/cache/CacheService.d.mjs +0 -0
  49. package/dist/cache/MemoryDriver.d.js +0 -13
  50. package/dist/cache/MemoryDriver.d.mjs +0 -0
  51. package/dist/cache/RedisDriver.d.js +0 -13
  52. package/dist/cache/RedisDriver.d.mjs +0 -0
  53. package/dist/compiler/JITCompiler.d.js +0 -13
  54. package/dist/compiler/JITCompiler.d.mjs +0 -0
  55. package/dist/container/Container.d.js +0 -13
  56. package/dist/container/Container.d.mjs +0 -0
  57. package/dist/context/Context.d.js +0 -13
  58. package/dist/context/Context.d.mjs +0 -0
  59. package/dist/cors/CorsHandler.d.js +0 -13
  60. package/dist/cors/CorsHandler.d.mjs +0 -0
  61. package/dist/decorators/Controller.d.js +0 -13
  62. package/dist/decorators/Controller.d.mjs +0 -0
  63. package/dist/decorators/Inject.d.js +0 -13
  64. package/dist/decorators/Inject.d.mjs +0 -0
  65. package/dist/decorators/Middleware.d.js +0 -13
  66. package/dist/decorators/Middleware.d.mjs +0 -0
  67. package/dist/decorators/Service.d.js +0 -13
  68. package/dist/decorators/Service.d.mjs +0 -0
  69. package/dist/decorators/methods.d.js +0 -13
  70. package/dist/decorators/methods.d.mjs +0 -0
  71. package/dist/decorators/params.d.js +0 -13
  72. package/dist/decorators/params.d.mjs +0 -0
  73. package/dist/events/Lifecycle.d.js +0 -13
  74. package/dist/events/Lifecycle.d.mjs +0 -0
  75. package/dist/exceptions/HttpException.d.js +0 -13
  76. package/dist/exceptions/HttpException.d.mjs +0 -0
  77. package/dist/index.d.js +0 -130
  78. package/dist/index.d.mjs +0 -78
  79. package/dist/metadata.d.js +0 -13
  80. package/dist/metadata.d.mjs +0 -0
  81. package/dist/middleware/CarnoMiddleware.d.js +0 -13
  82. package/dist/middleware/CarnoMiddleware.d.mjs +0 -0
  83. package/dist/router/RadixRouter.d.js +0 -13
  84. package/dist/router/RadixRouter.d.mjs +0 -0
  85. package/dist/testing/TestHarness.d.js +0 -13
  86. package/dist/testing/TestHarness.d.mjs +0 -0
  87. package/dist/utils/Metadata.d.js +0 -13
  88. package/dist/utils/Metadata.d.mjs +0 -0
  89. package/dist/utils/parseQuery.d.js +0 -13
  90. package/dist/utils/parseQuery.d.mjs +0 -0
  91. package/dist/validation/ValibotAdapter.d.js +0 -13
  92. package/dist/validation/ValibotAdapter.d.mjs +0 -0
  93. package/dist/validation/ValidatorAdapter.d.js +0 -13
  94. package/dist/validation/ValidatorAdapter.d.mjs +0 -0
  95. package/dist/validation/ZodAdapter.d.js +0 -13
  96. package/dist/validation/ZodAdapter.d.mjs +0 -0
  97. package/src/Carno.d.ts +0 -135
  98. package/src/DefaultRoutes.d.ts +0 -19
  99. package/src/cache/CacheDriver.d.ts +0 -43
  100. package/src/cache/CacheService.d.ts +0 -89
  101. package/src/cache/MemoryDriver.d.ts +0 -32
  102. package/src/cache/RedisDriver.d.ts +0 -34
  103. package/src/compiler/JITCompiler.d.ts +0 -36
  104. package/src/container/Container.d.ts +0 -38
  105. package/src/context/Context.d.ts +0 -36
  106. package/src/cors/CorsHandler.d.ts +0 -47
  107. package/src/decorators/Controller.d.ts +0 -13
  108. package/src/decorators/Inject.d.ts +0 -6
  109. package/src/decorators/Middleware.d.ts +0 -5
  110. package/src/decorators/Service.d.ts +0 -9
  111. package/src/decorators/methods.d.ts +0 -7
  112. package/src/decorators/params.d.ts +0 -13
  113. package/src/events/Lifecycle.d.ts +0 -54
  114. package/src/exceptions/HttpException.d.ts +0 -43
  115. package/src/index.d.ts +0 -42
  116. package/src/metadata.d.ts +0 -41
  117. package/src/middleware/CarnoMiddleware.d.ts +0 -12
  118. package/src/router/RadixRouter.d.ts +0 -19
  119. package/src/testing/TestHarness.d.ts +0 -71
  120. package/src/utils/Metadata.d.ts +0 -20
  121. package/src/utils/parseQuery.d.ts +0 -23
  122. package/src/validation/ValibotAdapter.d.ts +0 -30
  123. package/src/validation/ValidatorAdapter.d.ts +0 -54
  124. package/src/validation/ZodAdapter.d.ts +0 -35
@@ -1,16 +1,16 @@
1
- import { INJECT_META } from '../metadata';
2
- import type { Token } from '../container/Container';
3
-
4
- /**
5
- * Explicitly specifies which token to inject.
6
- * Useful for interfaces or when automatic detection fails.
7
- */
8
- export function Inject(token: Token): ParameterDecorator {
9
- return (target, propertyKey, parameterIndex) => {
10
- const existing: Map<number, Token> = Reflect.getMetadata(INJECT_META, target) || new Map();
11
-
12
- existing.set(parameterIndex, token);
13
-
14
- Reflect.defineMetadata(INJECT_META, existing, target);
15
- };
16
- }
1
+ import { INJECT_META } from '../metadata';
2
+ import type { Token } from '../container/Container';
3
+
4
+ /**
5
+ * Explicitly specifies which token to inject.
6
+ * Useful for interfaces or when automatic detection fails.
7
+ */
8
+ export function Inject(token: Token): ParameterDecorator {
9
+ return (target, propertyKey, parameterIndex) => {
10
+ const existing: Map<number, Token> = Reflect.getMetadata(INJECT_META, target) || new Map();
11
+
12
+ existing.set(parameterIndex, token);
13
+
14
+ Reflect.defineMetadata(INJECT_META, existing, target);
15
+ };
16
+ }
@@ -1,22 +1,22 @@
1
- import { MIDDLEWARE_META, type MiddlewareInfo } from '../metadata';
2
-
3
- /**
4
- * Middleware decorator.
5
- * Can be applied to controllers or individual methods.
6
- */
7
- export function Use(...middlewares: Function[]): ClassDecorator & MethodDecorator {
8
- return function (target: any, propertyKey?: string) {
9
- const isMethod = propertyKey !== undefined;
10
- const metaTarget = isMethod ? target.constructor : target;
11
- const existing: MiddlewareInfo[] = Reflect.getMetadata(MIDDLEWARE_META, metaTarget) || [];
12
-
13
- for (const handler of middlewares) {
14
- existing.push({
15
- handler,
16
- target: isMethod ? propertyKey : undefined
17
- });
18
- }
19
-
20
- Reflect.defineMetadata(MIDDLEWARE_META, existing, metaTarget);
21
- } as ClassDecorator & MethodDecorator;
22
- }
1
+ import { MIDDLEWARE_META, type MiddlewareInfo } from '../metadata';
2
+
3
+ /**
4
+ * Middleware decorator.
5
+ * Can be applied to controllers or individual methods.
6
+ */
7
+ export function Use(...middlewares: Function[]): ClassDecorator & MethodDecorator {
8
+ return function (target: any, propertyKey?: string) {
9
+ const isMethod = propertyKey !== undefined;
10
+ const metaTarget = isMethod ? target.constructor : target;
11
+ const existing: MiddlewareInfo[] = Reflect.getMetadata(MIDDLEWARE_META, metaTarget) || [];
12
+
13
+ for (const handler of middlewares) {
14
+ existing.push({
15
+ handler,
16
+ target: isMethod ? propertyKey : undefined
17
+ });
18
+ }
19
+
20
+ Reflect.defineMetadata(MIDDLEWARE_META, existing, metaTarget);
21
+ } as ClassDecorator & MethodDecorator;
22
+ }
@@ -1,18 +1,18 @@
1
- import { SERVICE_META } from '../metadata';
2
- import { Scope } from '../container/Container';
3
-
4
- export interface ServiceOptions {
5
- scope?: Scope;
6
- }
7
-
8
- /**
9
- * Marks a class as an injectable service.
10
- * Services are singleton by default.
11
- */
12
- export function Service(options: ServiceOptions = {}): ClassDecorator {
13
- return (target) => {
14
- Reflect.defineMetadata(SERVICE_META, {
15
- scope: options.scope ?? Scope.SINGLETON
16
- }, target);
17
- };
18
- }
1
+ import { SERVICE_META } from '../metadata';
2
+ import { Scope } from '../container/Container';
3
+
4
+ export interface ServiceOptions {
5
+ scope?: Scope;
6
+ }
7
+
8
+ /**
9
+ * Marks a class as an injectable service.
10
+ * Services are singleton by default.
11
+ */
12
+ export function Service(options: ServiceOptions = {}): ClassDecorator {
13
+ return (target) => {
14
+ Reflect.defineMetadata(SERVICE_META, {
15
+ scope: options.scope ?? Scope.SINGLETON
16
+ }, target);
17
+ };
18
+ }
@@ -1,58 +1,58 @@
1
- import { ROUTES_META, type RouteInfo } from '../metadata';
2
-
3
- type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head' | 'options';
4
-
5
- /**
6
- * Creates a method decorator for HTTP methods.
7
- * Supports both legacy decorators (experimentalDecorators) and TS5 stage 3 decorators.
8
- */
9
- function createMethodDecorator(method: HttpMethod) {
10
- return function (path: string = ''): any {
11
- return function (
12
- targetOrMethod: any,
13
- contextOrPropertyKey?: string | symbol | ClassMethodDecoratorContext,
14
- descriptor?: PropertyDescriptor
15
- ): any {
16
- // TS5 Stage 3 decorators: context is ClassMethodDecoratorContext
17
- if (contextOrPropertyKey && typeof contextOrPropertyKey === 'object' && 'kind' in contextOrPropertyKey) {
18
- const context = contextOrPropertyKey as ClassMethodDecoratorContext;
19
-
20
- context.addInitializer(function (this: any) {
21
- const constructor = this.constructor;
22
- const routes: RouteInfo[] = Reflect.getMetadata(ROUTES_META, constructor) || [];
23
-
24
- routes.push({
25
- method,
26
- path: path.startsWith('/') ? path : '/' + path,
27
- handlerName: String(context.name)
28
- });
29
-
30
- Reflect.defineMetadata(ROUTES_META, routes, constructor);
31
- });
32
-
33
- return targetOrMethod;
34
- }
35
-
36
- // Legacy decorators (experimentalDecorators: true)
37
- const constructor = targetOrMethod.constructor;
38
- const propertyKey = contextOrPropertyKey as string | symbol;
39
- const routes: RouteInfo[] = Reflect.getMetadata(ROUTES_META, constructor) || [];
40
-
41
- routes.push({
42
- method,
43
- path: path.startsWith('/') ? path : '/' + path,
44
- handlerName: String(propertyKey)
45
- });
46
-
47
- Reflect.defineMetadata(ROUTES_META, routes, constructor);
48
- };
49
- };
50
- }
51
-
52
- export const Get = createMethodDecorator('get');
53
- export const Post = createMethodDecorator('post');
54
- export const Put = createMethodDecorator('put');
55
- export const Delete = createMethodDecorator('delete');
56
- export const Patch = createMethodDecorator('patch');
57
- export const Head = createMethodDecorator('head');
58
- export const Options = createMethodDecorator('options');
1
+ import { ROUTES_META, type RouteInfo } from '../metadata';
2
+
3
+ type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head' | 'options';
4
+
5
+ /**
6
+ * Creates a method decorator for HTTP methods.
7
+ * Supports both legacy decorators (experimentalDecorators) and TS5 stage 3 decorators.
8
+ */
9
+ function createMethodDecorator(method: HttpMethod) {
10
+ return function (path: string = ''): any {
11
+ return function (
12
+ targetOrMethod: any,
13
+ contextOrPropertyKey?: string | symbol | ClassMethodDecoratorContext,
14
+ descriptor?: PropertyDescriptor
15
+ ): any {
16
+ // TS5 Stage 3 decorators: context is ClassMethodDecoratorContext
17
+ if (contextOrPropertyKey && typeof contextOrPropertyKey === 'object' && 'kind' in contextOrPropertyKey) {
18
+ const context = contextOrPropertyKey as ClassMethodDecoratorContext;
19
+
20
+ context.addInitializer(function (this: any) {
21
+ const constructor = this.constructor;
22
+ const routes: RouteInfo[] = Reflect.getMetadata(ROUTES_META, constructor) || [];
23
+
24
+ routes.push({
25
+ method,
26
+ path: path.startsWith('/') ? path : '/' + path,
27
+ handlerName: String(context.name)
28
+ });
29
+
30
+ Reflect.defineMetadata(ROUTES_META, routes, constructor);
31
+ });
32
+
33
+ return targetOrMethod;
34
+ }
35
+
36
+ // Legacy decorators (experimentalDecorators: true)
37
+ const constructor = targetOrMethod.constructor;
38
+ const propertyKey = contextOrPropertyKey as string | symbol;
39
+ const routes: RouteInfo[] = Reflect.getMetadata(ROUTES_META, constructor) || [];
40
+
41
+ routes.push({
42
+ method,
43
+ path: path.startsWith('/') ? path : '/' + path,
44
+ handlerName: String(propertyKey)
45
+ });
46
+
47
+ Reflect.defineMetadata(ROUTES_META, routes, constructor);
48
+ };
49
+ };
50
+ }
51
+
52
+ export const Get = createMethodDecorator('get');
53
+ export const Post = createMethodDecorator('post');
54
+ export const Put = createMethodDecorator('put');
55
+ export const Delete = createMethodDecorator('delete');
56
+ export const Patch = createMethodDecorator('patch');
57
+ export const Head = createMethodDecorator('head');
58
+ export const Options = createMethodDecorator('options');
@@ -1,47 +1,47 @@
1
- import { PARAMS_META } from '../metadata';
2
-
3
- export type ParamType = 'param' | 'query' | 'body' | 'header' | 'req' | 'ctx' | 'locals';
4
-
5
- export interface ParamMetadata {
6
- type: ParamType;
7
- key?: string;
8
- index: number;
9
- }
10
-
11
- function createParamDecorator(type: ParamType, key?: string) {
12
- return function (target: any, propertyKey: string, index: number) {
13
- const params: ParamMetadata[] = Reflect.getMetadata(PARAMS_META, target.constructor, propertyKey) || [];
14
-
15
- params.push({ type, key, index });
16
-
17
- Reflect.defineMetadata(PARAMS_META, params, target.constructor, propertyKey);
18
- };
19
- }
20
-
21
- export function Param(key?: string): ParameterDecorator {
22
- return createParamDecorator('param', key) as ParameterDecorator;
23
- }
24
-
25
- export function Query(key?: string): ParameterDecorator {
26
- return createParamDecorator('query', key) as ParameterDecorator;
27
- }
28
-
29
- export function Body(key?: string): ParameterDecorator {
30
- return createParamDecorator('body', key) as ParameterDecorator;
31
- }
32
-
33
- export function Header(key?: string): ParameterDecorator {
34
- return createParamDecorator('header', key) as ParameterDecorator;
35
- }
36
-
37
- export function Req(): ParameterDecorator {
38
- return createParamDecorator('req') as ParameterDecorator;
39
- }
40
-
41
- export function Ctx(): ParameterDecorator {
42
- return createParamDecorator('ctx') as ParameterDecorator;
43
- }
44
-
45
- export function Locals(key?: string): ParameterDecorator {
46
- return createParamDecorator('locals', key) as ParameterDecorator;
47
- }
1
+ import { PARAMS_META } from '../metadata';
2
+
3
+ export type ParamType = 'param' | 'query' | 'body' | 'header' | 'req' | 'ctx' | 'locals';
4
+
5
+ export interface ParamMetadata {
6
+ type: ParamType;
7
+ key?: string;
8
+ index: number;
9
+ }
10
+
11
+ function createParamDecorator(type: ParamType, key?: string) {
12
+ return function (target: any, propertyKey: string, index: number) {
13
+ const params: ParamMetadata[] = Reflect.getMetadata(PARAMS_META, target.constructor, propertyKey) || [];
14
+
15
+ params.push({ type, key, index });
16
+
17
+ Reflect.defineMetadata(PARAMS_META, params, target.constructor, propertyKey);
18
+ };
19
+ }
20
+
21
+ export function Param(key?: string): ParameterDecorator {
22
+ return createParamDecorator('param', key) as ParameterDecorator;
23
+ }
24
+
25
+ export function Query(key?: string): ParameterDecorator {
26
+ return createParamDecorator('query', key) as ParameterDecorator;
27
+ }
28
+
29
+ export function Body(key?: string): ParameterDecorator {
30
+ return createParamDecorator('body', key) as ParameterDecorator;
31
+ }
32
+
33
+ export function Header(key?: string): ParameterDecorator {
34
+ return createParamDecorator('header', key) as ParameterDecorator;
35
+ }
36
+
37
+ export function Req(): ParameterDecorator {
38
+ return createParamDecorator('req') as ParameterDecorator;
39
+ }
40
+
41
+ export function Ctx(): ParameterDecorator {
42
+ return createParamDecorator('ctx') as ParameterDecorator;
43
+ }
44
+
45
+ export function Locals(key?: string): ParameterDecorator {
46
+ return createParamDecorator('locals', key) as ParameterDecorator;
47
+ }
@@ -1,97 +1,97 @@
1
- /**
2
- * Lifecycle Event Types.
3
- */
4
- export enum EventType {
5
- /** Called when DI container initializes, before server starts */
6
- INIT = 'onInit',
7
- /** Called right after application is fully bootstrapped */
8
- BOOT = 'onBoot',
9
- /** Called when application receives SIGTERM/SIGINT */
10
- SHUTDOWN = 'onShutdown'
11
- }
12
-
13
- /**
14
- * Stored event handler info.
15
- */
16
- export interface EventHandler {
17
- target: any;
18
- methodName: string;
19
- priority: number;
20
- }
21
-
22
- /**
23
- * Metadata key for storing events.
24
- */
25
- export const EVENTS_META = Symbol('turbo:events');
26
-
27
- /**
28
- * Event registry - stores all decorated event handlers.
29
- * Populated at decoration time, read at bootstrap.
30
- */
31
- const eventRegistry = new Map<EventType, EventHandler[]>();
32
-
33
- /**
34
- * Register an event handler (called by decorators).
35
- */
36
- export function registerEvent(type: EventType, target: any, methodName: string, priority: number = 0): void {
37
- let handlers = eventRegistry.get(type);
38
- if (!handlers) {
39
- handlers = [];
40
- eventRegistry.set(type, handlers);
41
- }
42
- handlers.push({ target, methodName, priority });
43
- }
44
-
45
- /**
46
- * Get all handlers for an event type, sorted by priority (descending).
47
- */
48
- export function getEventHandlers(type: EventType): EventHandler[] {
49
- const handlers = eventRegistry.get(type) || [];
50
- return handlers.sort((a, b) => b.priority - a.priority);
51
- }
52
-
53
- /**
54
- * Check if any handlers exist for an event type.
55
- */
56
- export function hasEventHandlers(type: EventType): boolean {
57
- return (eventRegistry.get(type)?.length ?? 0) > 0;
58
- }
59
-
60
- /**
61
- * Clear all event handlers (for testing).
62
- */
63
- export function clearEventRegistry(): void {
64
- eventRegistry.clear();
65
- }
66
-
67
- // ============ Decorators ============
68
-
69
- /**
70
- * Called when DI container initializes, before the server starts.
71
- * Use for database connections, cache warming, etc.
72
- */
73
- export function OnApplicationInit(priority: number = 0) {
74
- return function (target: any, propertyKey: string) {
75
- registerEvent(EventType.INIT, target.constructor, propertyKey, priority);
76
- };
77
- }
78
-
79
- /**
80
- * Called right after the application is fully bootstrapped and server is ready.
81
- * Use for logging, health checks, etc.
82
- */
83
- export function OnApplicationBoot(priority: number = 0) {
84
- return function (target: any, propertyKey: string) {
85
- registerEvent(EventType.BOOT, target.constructor, propertyKey, priority);
86
- };
87
- }
88
-
89
- /**
90
- * Called when application receives SIGTERM or SIGINT.
91
- * Use for graceful cleanup, closing connections, etc.
92
- */
93
- export function OnApplicationShutdown(priority: number = 0) {
94
- return function (target: any, propertyKey: string) {
95
- registerEvent(EventType.SHUTDOWN, target.constructor, propertyKey, priority);
96
- };
97
- }
1
+ /**
2
+ * Lifecycle Event Types.
3
+ */
4
+ export enum EventType {
5
+ /** Called when DI container initializes, before server starts */
6
+ INIT = 'onInit',
7
+ /** Called right after application is fully bootstrapped */
8
+ BOOT = 'onBoot',
9
+ /** Called when application receives SIGTERM/SIGINT */
10
+ SHUTDOWN = 'onShutdown'
11
+ }
12
+
13
+ /**
14
+ * Stored event handler info.
15
+ */
16
+ export interface EventHandler {
17
+ target: any;
18
+ methodName: string;
19
+ priority: number;
20
+ }
21
+
22
+ /**
23
+ * Metadata key for storing events.
24
+ */
25
+ export const EVENTS_META = Symbol('turbo:events');
26
+
27
+ /**
28
+ * Event registry - stores all decorated event handlers.
29
+ * Populated at decoration time, read at bootstrap.
30
+ */
31
+ const eventRegistry = new Map<EventType, EventHandler[]>();
32
+
33
+ /**
34
+ * Register an event handler (called by decorators).
35
+ */
36
+ export function registerEvent(type: EventType, target: any, methodName: string, priority: number = 0): void {
37
+ let handlers = eventRegistry.get(type);
38
+ if (!handlers) {
39
+ handlers = [];
40
+ eventRegistry.set(type, handlers);
41
+ }
42
+ handlers.push({ target, methodName, priority });
43
+ }
44
+
45
+ /**
46
+ * Get all handlers for an event type, sorted by priority (descending).
47
+ */
48
+ export function getEventHandlers(type: EventType): EventHandler[] {
49
+ const handlers = eventRegistry.get(type) || [];
50
+ return handlers.sort((a, b) => b.priority - a.priority);
51
+ }
52
+
53
+ /**
54
+ * Check if any handlers exist for an event type.
55
+ */
56
+ export function hasEventHandlers(type: EventType): boolean {
57
+ return (eventRegistry.get(type)?.length ?? 0) > 0;
58
+ }
59
+
60
+ /**
61
+ * Clear all event handlers (for testing).
62
+ */
63
+ export function clearEventRegistry(): void {
64
+ eventRegistry.clear();
65
+ }
66
+
67
+ // ============ Decorators ============
68
+
69
+ /**
70
+ * Called when DI container initializes, before the server starts.
71
+ * Use for database connections, cache warming, etc.
72
+ */
73
+ export function OnApplicationInit(priority: number = 0) {
74
+ return function (target: any, propertyKey: string) {
75
+ registerEvent(EventType.INIT, target.constructor, propertyKey, priority);
76
+ };
77
+ }
78
+
79
+ /**
80
+ * Called right after the application is fully bootstrapped and server is ready.
81
+ * Use for logging, health checks, etc.
82
+ */
83
+ export function OnApplicationBoot(priority: number = 0) {
84
+ return function (target: any, propertyKey: string) {
85
+ registerEvent(EventType.BOOT, target.constructor, propertyKey, priority);
86
+ };
87
+ }
88
+
89
+ /**
90
+ * Called when application receives SIGTERM or SIGINT.
91
+ * Use for graceful cleanup, closing connections, etc.
92
+ */
93
+ export function OnApplicationShutdown(priority: number = 0) {
94
+ return function (target: any, propertyKey: string) {
95
+ registerEvent(EventType.SHUTDOWN, target.constructor, propertyKey, priority);
96
+ };
97
+ }