@hazeljs/core 0.2.0-alpha.1

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 (195) hide show
  1. package/LICENSE +192 -0
  2. package/README.md +560 -0
  3. package/dist/__tests__/container.test.d.ts +2 -0
  4. package/dist/__tests__/container.test.d.ts.map +1 -0
  5. package/dist/__tests__/container.test.js +454 -0
  6. package/dist/__tests__/decorators.test.d.ts +2 -0
  7. package/dist/__tests__/decorators.test.d.ts.map +1 -0
  8. package/dist/__tests__/decorators.test.js +1237 -0
  9. package/dist/__tests__/errors/http.error.test.d.ts +2 -0
  10. package/dist/__tests__/errors/http.error.test.d.ts.map +1 -0
  11. package/dist/__tests__/errors/http.error.test.js +117 -0
  12. package/dist/__tests__/filters/exception-filter.test.d.ts +2 -0
  13. package/dist/__tests__/filters/exception-filter.test.d.ts.map +1 -0
  14. package/dist/__tests__/filters/exception-filter.test.js +135 -0
  15. package/dist/__tests__/filters/http-exception.filter.test.d.ts +2 -0
  16. package/dist/__tests__/filters/http-exception.filter.test.d.ts.map +1 -0
  17. package/dist/__tests__/filters/http-exception.filter.test.js +119 -0
  18. package/dist/__tests__/hazel-app.test.d.ts +2 -0
  19. package/dist/__tests__/hazel-app.test.d.ts.map +1 -0
  20. package/dist/__tests__/hazel-app.test.js +810 -0
  21. package/dist/__tests__/hazel-module.test.d.ts +2 -0
  22. package/dist/__tests__/hazel-module.test.d.ts.map +1 -0
  23. package/dist/__tests__/hazel-module.test.js +408 -0
  24. package/dist/__tests__/hazel-response.test.d.ts +2 -0
  25. package/dist/__tests__/hazel-response.test.d.ts.map +1 -0
  26. package/dist/__tests__/hazel-response.test.js +138 -0
  27. package/dist/__tests__/health.test.d.ts +2 -0
  28. package/dist/__tests__/health.test.d.ts.map +1 -0
  29. package/dist/__tests__/health.test.js +147 -0
  30. package/dist/__tests__/index.test.d.ts +2 -0
  31. package/dist/__tests__/index.test.d.ts.map +1 -0
  32. package/dist/__tests__/index.test.js +239 -0
  33. package/dist/__tests__/interceptors/interceptor.test.d.ts +2 -0
  34. package/dist/__tests__/interceptors/interceptor.test.d.ts.map +1 -0
  35. package/dist/__tests__/interceptors/interceptor.test.js +166 -0
  36. package/dist/__tests__/logger.test.d.ts +2 -0
  37. package/dist/__tests__/logger.test.d.ts.map +1 -0
  38. package/dist/__tests__/logger.test.js +141 -0
  39. package/dist/__tests__/middleware/cors.test.d.ts +2 -0
  40. package/dist/__tests__/middleware/cors.test.d.ts.map +1 -0
  41. package/dist/__tests__/middleware/cors.test.js +129 -0
  42. package/dist/__tests__/middleware/csrf.test.d.ts +2 -0
  43. package/dist/__tests__/middleware/csrf.test.d.ts.map +1 -0
  44. package/dist/__tests__/middleware/csrf.test.js +247 -0
  45. package/dist/__tests__/middleware/global-middleware.test.d.ts +2 -0
  46. package/dist/__tests__/middleware/global-middleware.test.d.ts.map +1 -0
  47. package/dist/__tests__/middleware/global-middleware.test.js +259 -0
  48. package/dist/__tests__/middleware/rate-limit.test.d.ts +2 -0
  49. package/dist/__tests__/middleware/rate-limit.test.d.ts.map +1 -0
  50. package/dist/__tests__/middleware/rate-limit.test.js +264 -0
  51. package/dist/__tests__/middleware/security-headers.test.d.ts +2 -0
  52. package/dist/__tests__/middleware/security-headers.test.d.ts.map +1 -0
  53. package/dist/__tests__/middleware/security-headers.test.js +229 -0
  54. package/dist/__tests__/middleware/timeout.test.d.ts +2 -0
  55. package/dist/__tests__/middleware/timeout.test.d.ts.map +1 -0
  56. package/dist/__tests__/middleware/timeout.test.js +132 -0
  57. package/dist/__tests__/middleware.test.d.ts +2 -0
  58. package/dist/__tests__/middleware.test.d.ts.map +1 -0
  59. package/dist/__tests__/middleware.test.js +180 -0
  60. package/dist/__tests__/pipes/pipe.test.d.ts +2 -0
  61. package/dist/__tests__/pipes/pipe.test.d.ts.map +1 -0
  62. package/dist/__tests__/pipes/pipe.test.js +245 -0
  63. package/dist/__tests__/pipes/validation.pipe.test.d.ts +2 -0
  64. package/dist/__tests__/pipes/validation.pipe.test.d.ts.map +1 -0
  65. package/dist/__tests__/pipes/validation.pipe.test.js +297 -0
  66. package/dist/__tests__/request-parser.test.d.ts +2 -0
  67. package/dist/__tests__/request-parser.test.d.ts.map +1 -0
  68. package/dist/__tests__/request-parser.test.js +182 -0
  69. package/dist/__tests__/router.test.d.ts +2 -0
  70. package/dist/__tests__/router.test.d.ts.map +1 -0
  71. package/dist/__tests__/router.test.js +1183 -0
  72. package/dist/__tests__/routing/route-matcher.test.d.ts +2 -0
  73. package/dist/__tests__/routing/route-matcher.test.d.ts.map +1 -0
  74. package/dist/__tests__/routing/route-matcher.test.js +219 -0
  75. package/dist/__tests__/routing/version.decorator.test.d.ts +2 -0
  76. package/dist/__tests__/routing/version.decorator.test.d.ts.map +1 -0
  77. package/dist/__tests__/routing/version.decorator.test.js +298 -0
  78. package/dist/__tests__/service.test.d.ts +2 -0
  79. package/dist/__tests__/service.test.d.ts.map +1 -0
  80. package/dist/__tests__/service.test.js +121 -0
  81. package/dist/__tests__/shutdown.test.d.ts +2 -0
  82. package/dist/__tests__/shutdown.test.d.ts.map +1 -0
  83. package/dist/__tests__/shutdown.test.js +250 -0
  84. package/dist/__tests__/testing/testing.module.test.d.ts +2 -0
  85. package/dist/__tests__/testing/testing.module.test.d.ts.map +1 -0
  86. package/dist/__tests__/testing/testing.module.test.js +370 -0
  87. package/dist/__tests__/upload/file-upload.test.d.ts +2 -0
  88. package/dist/__tests__/upload/file-upload.test.d.ts.map +1 -0
  89. package/dist/__tests__/upload/file-upload.test.js +498 -0
  90. package/dist/__tests__/utils/sanitize.test.d.ts +2 -0
  91. package/dist/__tests__/utils/sanitize.test.d.ts.map +1 -0
  92. package/dist/__tests__/utils/sanitize.test.js +291 -0
  93. package/dist/__tests__/validator.test.d.ts +2 -0
  94. package/dist/__tests__/validator.test.d.ts.map +1 -0
  95. package/dist/__tests__/validator.test.js +300 -0
  96. package/dist/container.d.ts +80 -0
  97. package/dist/container.d.ts.map +1 -0
  98. package/dist/container.js +271 -0
  99. package/dist/decorators.d.ts +166 -0
  100. package/dist/decorators.d.ts.map +1 -0
  101. package/dist/decorators.js +538 -0
  102. package/dist/errors/http.error.d.ts +34 -0
  103. package/dist/errors/http.error.d.ts.map +1 -0
  104. package/dist/errors/http.error.js +69 -0
  105. package/dist/filters/exception-filter.d.ts +39 -0
  106. package/dist/filters/exception-filter.d.ts.map +1 -0
  107. package/dist/filters/exception-filter.js +38 -0
  108. package/dist/filters/http-exception.filter.d.ts +9 -0
  109. package/dist/filters/http-exception.filter.d.ts.map +1 -0
  110. package/dist/filters/http-exception.filter.js +42 -0
  111. package/dist/hazel-app.d.ts +94 -0
  112. package/dist/hazel-app.d.ts.map +1 -0
  113. package/dist/hazel-app.js +516 -0
  114. package/dist/hazel-module.d.ts +29 -0
  115. package/dist/hazel-module.d.ts.map +1 -0
  116. package/dist/hazel-module.js +137 -0
  117. package/dist/hazel-response.d.ts +25 -0
  118. package/dist/hazel-response.d.ts.map +1 -0
  119. package/dist/hazel-response.js +89 -0
  120. package/dist/health.d.ts +73 -0
  121. package/dist/health.d.ts.map +1 -0
  122. package/dist/health.js +174 -0
  123. package/dist/index.d.ts +41 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +159 -0
  126. package/dist/interceptors/interceptor.d.ts +30 -0
  127. package/dist/interceptors/interceptor.d.ts.map +1 -0
  128. package/dist/interceptors/interceptor.js +71 -0
  129. package/dist/logger.d.ts +8 -0
  130. package/dist/logger.d.ts.map +1 -0
  131. package/dist/logger.js +261 -0
  132. package/dist/middleware/cors.middleware.d.ts +44 -0
  133. package/dist/middleware/cors.middleware.d.ts.map +1 -0
  134. package/dist/middleware/cors.middleware.js +118 -0
  135. package/dist/middleware/csrf.middleware.d.ts +82 -0
  136. package/dist/middleware/csrf.middleware.d.ts.map +1 -0
  137. package/dist/middleware/csrf.middleware.js +183 -0
  138. package/dist/middleware/global-middleware.d.ts +111 -0
  139. package/dist/middleware/global-middleware.d.ts.map +1 -0
  140. package/dist/middleware/global-middleware.js +179 -0
  141. package/dist/middleware/rate-limit.middleware.d.ts +73 -0
  142. package/dist/middleware/rate-limit.middleware.d.ts.map +1 -0
  143. package/dist/middleware/rate-limit.middleware.js +124 -0
  144. package/dist/middleware/security-headers.middleware.d.ts +76 -0
  145. package/dist/middleware/security-headers.middleware.d.ts.map +1 -0
  146. package/dist/middleware/security-headers.middleware.js +123 -0
  147. package/dist/middleware/timeout.middleware.d.ts +25 -0
  148. package/dist/middleware/timeout.middleware.d.ts.map +1 -0
  149. package/dist/middleware/timeout.middleware.js +74 -0
  150. package/dist/middleware.d.ts +13 -0
  151. package/dist/middleware.d.ts.map +1 -0
  152. package/dist/middleware.js +47 -0
  153. package/dist/pipes/pipe.d.ts +50 -0
  154. package/dist/pipes/pipe.d.ts.map +1 -0
  155. package/dist/pipes/pipe.js +96 -0
  156. package/dist/pipes/validation.pipe.d.ts +6 -0
  157. package/dist/pipes/validation.pipe.d.ts.map +1 -0
  158. package/dist/pipes/validation.pipe.js +61 -0
  159. package/dist/request-context.d.ts +22 -0
  160. package/dist/request-context.d.ts.map +1 -0
  161. package/dist/request-context.js +2 -0
  162. package/dist/request-parser.d.ts +7 -0
  163. package/dist/request-parser.d.ts.map +1 -0
  164. package/dist/request-parser.js +60 -0
  165. package/dist/router.d.ts +33 -0
  166. package/dist/router.d.ts.map +1 -0
  167. package/dist/router.js +506 -0
  168. package/dist/routing/route-matcher.d.ts +39 -0
  169. package/dist/routing/route-matcher.d.ts.map +1 -0
  170. package/dist/routing/route-matcher.js +93 -0
  171. package/dist/routing/version.decorator.d.ts +36 -0
  172. package/dist/routing/version.decorator.d.ts.map +1 -0
  173. package/dist/routing/version.decorator.js +89 -0
  174. package/dist/service.d.ts +9 -0
  175. package/dist/service.d.ts.map +1 -0
  176. package/dist/service.js +39 -0
  177. package/dist/shutdown.d.ts +32 -0
  178. package/dist/shutdown.d.ts.map +1 -0
  179. package/dist/shutdown.js +109 -0
  180. package/dist/testing/testing.module.d.ts +83 -0
  181. package/dist/testing/testing.module.d.ts.map +1 -0
  182. package/dist/testing/testing.module.js +164 -0
  183. package/dist/types.d.ts +82 -0
  184. package/dist/types.d.ts.map +1 -0
  185. package/dist/types.js +2 -0
  186. package/dist/upload/file-upload.d.ts +75 -0
  187. package/dist/upload/file-upload.d.ts.map +1 -0
  188. package/dist/upload/file-upload.js +261 -0
  189. package/dist/utils/sanitize.d.ts +45 -0
  190. package/dist/utils/sanitize.d.ts.map +1 -0
  191. package/dist/utils/sanitize.js +165 -0
  192. package/dist/validator.d.ts +7 -0
  193. package/dist/validator.d.ts.map +1 -0
  194. package/dist/validator.js +119 -0
  195. package/package.json +67 -0
@@ -0,0 +1,538 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.HazelApp = exports.SkipAuth = exports.Module = exports.HazelModule = exports.CUSTOM_METADATA_PREFIX = void 0;
7
+ exports.Controller = Controller;
8
+ exports.Injectable = Injectable;
9
+ exports.Get = Get;
10
+ exports.Post = Post;
11
+ exports.Put = Put;
12
+ exports.Delete = Delete;
13
+ exports.Patch = Patch;
14
+ exports.Inject = Inject;
15
+ exports.Service = Service;
16
+ exports.Body = Body;
17
+ exports.Request = Request;
18
+ exports.Param = Param;
19
+ exports.Query = Query;
20
+ exports.UsePipes = UsePipes;
21
+ exports.UseInterceptors = UseInterceptors;
22
+ exports.UseGuards = UseGuards;
23
+ exports.AITask = AITask;
24
+ exports.Req = Req;
25
+ exports.Headers = Headers;
26
+ exports.HttpCode = HttpCode;
27
+ exports.Header = Header;
28
+ exports.Redirect = Redirect;
29
+ exports.Res = Res;
30
+ exports.Ip = Ip;
31
+ exports.Host = Host;
32
+ exports.Public = Public;
33
+ exports.Timeout = Timeout;
34
+ exports.Optional = Optional;
35
+ exports.Session = Session;
36
+ exports.Retry = Retry;
37
+ exports.ApiTags = ApiTags;
38
+ exports.ApiOperation = ApiOperation;
39
+ exports.SetMetadata = SetMetadata;
40
+ exports.getMetadata = getMetadata;
41
+ exports.createParamDecorator = createParamDecorator;
42
+ require("reflect-metadata");
43
+ const logger_1 = __importDefault(require("./logger"));
44
+ const interceptor_1 = require("./interceptors/interceptor");
45
+ const hazel_app_1 = require("./hazel-app");
46
+ Object.defineProperty(exports, "HazelApp", { enumerable: true, get: function () { return hazel_app_1.HazelApp; } });
47
+ const CONTROLLER_METADATA_KEY = 'hazel:controller';
48
+ const INJECTABLE_METADATA_KEY = 'hazel:injectable';
49
+ const ROUTE_METADATA_KEY = 'hazel:routes';
50
+ const SERVICE_METADATA_KEY = 'hazel:service';
51
+ const INJECT_METADATA_KEY = 'hazel:inject';
52
+ const PIPE_METADATA_KEY = 'hazel:pipe';
53
+ const INTERCEPTOR_METADATA_KEY = 'hazel:interceptor';
54
+ const CLASS_INTERCEPTOR_METADATA_KEY = 'hazel:class-interceptors';
55
+ const HTTP_CODE_METADATA_KEY = 'hazel:http-code';
56
+ const HEADER_METADATA_KEY = 'hazel:headers';
57
+ const REDIRECT_METADATA_KEY = 'hazel:redirect';
58
+ const PUBLIC_METADATA_KEY = 'hazel:public';
59
+ const TIMEOUT_METADATA_KEY = 'hazel:timeout';
60
+ const OPTIONAL_INDICES_METADATA_KEY = 'hazel:optional-indices';
61
+ const RETRY_METADATA_KEY = 'hazel:retry';
62
+ const API_TAGS_METADATA_KEY = 'hazel:api:tags';
63
+ const API_OPERATION_METADATA_KEY = 'hazel:api:operation';
64
+ exports.CUSTOM_METADATA_PREFIX = 'hazel:meta:';
65
+ // Re-export from hazel-module for backward compatibility
66
+ var hazel_module_1 = require("./hazel-module");
67
+ Object.defineProperty(exports, "HazelModule", { enumerable: true, get: function () { return hazel_module_1.HazelModule; } });
68
+ Object.defineProperty(exports, "Module", { enumerable: true, get: function () { return hazel_module_1.Module; } });
69
+ function Controller(options) {
70
+ return (target) => {
71
+ const opts = typeof options === 'string' ? { path: options } : options;
72
+ logger_1.default.debug(`Registering controller: ${target.constructor?.name || target.name} at path: ${opts.path}`);
73
+ Reflect.defineMetadata(CONTROLLER_METADATA_KEY, opts, target);
74
+ };
75
+ }
76
+ function Injectable(options = {}) {
77
+ return (target) => {
78
+ logger_1.default.debug(`Registering injectable: ${target.constructor?.name || target.name}`);
79
+ Reflect.defineMetadata(INJECTABLE_METADATA_KEY, options, target);
80
+ // Store scope metadata for container
81
+ if (options.scope) {
82
+ Reflect.defineMetadata('hazel:scope', options.scope, target);
83
+ }
84
+ };
85
+ }
86
+ function Get(options) {
87
+ const opts = typeof options === 'string' ? { path: options } : options || {};
88
+ return createRouteDecorator('GET', opts);
89
+ }
90
+ function Post(options) {
91
+ const opts = typeof options === 'string' ? { path: options } : options || {};
92
+ return createRouteDecorator('POST', opts);
93
+ }
94
+ function Put(options) {
95
+ const opts = typeof options === 'string' ? { path: options } : options || {};
96
+ return createRouteDecorator('PUT', opts);
97
+ }
98
+ function Delete(options) {
99
+ const opts = typeof options === 'string' ? { path: options } : options || {};
100
+ return createRouteDecorator('DELETE', opts);
101
+ }
102
+ function Patch(options) {
103
+ const opts = typeof options === 'string' ? { path: options } : options || {};
104
+ return createRouteDecorator('PATCH', opts);
105
+ }
106
+ function Inject(token) {
107
+ return (target, propertyKey, parameterIndex) => {
108
+ logger_1.default.debug(`Registering injection for parameter ${parameterIndex} in ${target.constructor?.name}`);
109
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, target) || [];
110
+ injections[parameterIndex] = token;
111
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, target);
112
+ };
113
+ }
114
+ function Service(options = {}) {
115
+ return function (target) {
116
+ Reflect.defineMetadata(SERVICE_METADATA_KEY, options, target);
117
+ // Store scope metadata for container
118
+ if (options.scope) {
119
+ Reflect.defineMetadata('hazel:scope', options.scope, target);
120
+ }
121
+ // Get constructor parameters
122
+ const paramTypes = Reflect.getMetadata('design:paramtypes', target) || [];
123
+ const repositories = paramTypes
124
+ .map((paramType, index) => {
125
+ const model = Reflect.getMetadata('hazel:repository', paramType)?.model;
126
+ if (model) {
127
+ return { index, model };
128
+ }
129
+ return null;
130
+ })
131
+ .filter(Boolean);
132
+ if (repositories.length > 0) {
133
+ Reflect.defineMetadata('hazel:repositories', repositories, target);
134
+ }
135
+ };
136
+ }
137
+ function Body(dtoType) {
138
+ return (target, propertyKey, parameterIndex) => {
139
+ if (!propertyKey) {
140
+ throw new Error('Body decorator must be used on a method parameter');
141
+ }
142
+ logger_1.default.debug(`Registering body parameter ${parameterIndex} in ${target.constructor?.name}`);
143
+ // Get the constructor of the target
144
+ const constructor = target
145
+ .constructor;
146
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, constructor, propertyKey) || [];
147
+ // Store the injection metadata
148
+ injections[parameterIndex] = {
149
+ type: 'body',
150
+ dtoType,
151
+ token: dtoType,
152
+ };
153
+ logger_1.default.debug('Setting DTO type from Body decorator:', dtoType?.name);
154
+ logger_1.default.debug('Updated injections:', JSON.stringify(injections, null, 2));
155
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, constructor, propertyKey);
156
+ };
157
+ }
158
+ function Request() {
159
+ return (target, propertyKey, parameterIndex) => {
160
+ if (!propertyKey) {
161
+ throw new Error('Request decorator must be used on a method parameter');
162
+ }
163
+ const constructor = target
164
+ .constructor;
165
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, constructor, propertyKey) || [];
166
+ injections[parameterIndex] = { type: 'request' };
167
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, constructor, propertyKey);
168
+ };
169
+ }
170
+ function Param(paramName, pipe) {
171
+ return (target, propertyKey, parameterIndex) => {
172
+ if (!propertyKey) {
173
+ throw new Error('Param decorator must be used on a method parameter');
174
+ }
175
+ logger_1.default.debug(`Registering param ${paramName} at index ${parameterIndex} in ${target.constructor?.name} with pipe:`, pipe?.name);
176
+ // Get the constructor of the target
177
+ const constructor = target
178
+ .constructor;
179
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, constructor, propertyKey) || [];
180
+ injections[parameterIndex] = { type: 'param', name: paramName, pipe };
181
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, constructor, propertyKey);
182
+ logger_1.default.debug('Updated injections:', JSON.stringify(injections, null, 2));
183
+ };
184
+ }
185
+ function Query(paramName, pipe) {
186
+ return (target, propertyKey, parameterIndex) => {
187
+ if (!propertyKey) {
188
+ throw new Error('Query decorator must be used on a method parameter');
189
+ }
190
+ logger_1.default.debug(`Registering query param ${paramName || 'all'} at index ${parameterIndex} in ${target.constructor?.name} with pipe:`, pipe?.name);
191
+ // Get the constructor of the target
192
+ const constructor = target
193
+ .constructor;
194
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, constructor, propertyKey) || [];
195
+ injections[parameterIndex] = { type: 'query', name: paramName, pipe };
196
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, constructor, propertyKey);
197
+ logger_1.default.debug('Updated injections:', JSON.stringify(injections, null, 2));
198
+ };
199
+ }
200
+ function UsePipes(...pipes) {
201
+ const decorator = (target, propertyKey) => {
202
+ const pipeMetadata = pipes.map((pipe) => {
203
+ if (typeof pipe === 'function') {
204
+ return { type: pipe };
205
+ }
206
+ return pipe;
207
+ });
208
+ if (propertyKey) {
209
+ // Method decorator
210
+ const routes = Reflect.getMetadata(ROUTE_METADATA_KEY, target.constructor) || [];
211
+ const route = routes.find((r) => r.propertyKey === propertyKey);
212
+ if (route) {
213
+ route.pipes = pipeMetadata;
214
+ logger_1.default.debug('Setting pipes for route:', {
215
+ method: route.method,
216
+ path: route.path,
217
+ pipes: pipeMetadata.map((p) => p.type.name),
218
+ });
219
+ Reflect.defineMetadata(ROUTE_METADATA_KEY, routes, target.constructor);
220
+ }
221
+ }
222
+ else {
223
+ // Class decorator
224
+ const existingPipes = Reflect.getMetadata(PIPE_METADATA_KEY, target) || [];
225
+ Reflect.defineMetadata(PIPE_METADATA_KEY, [...existingPipes, ...pipeMetadata], target);
226
+ }
227
+ };
228
+ return decorator;
229
+ }
230
+ function UseInterceptors(...interceptors) {
231
+ const decorator = (target, propertyKey, descriptor) => {
232
+ const interceptorMetadata = interceptors.map((interceptor) => {
233
+ if (typeof interceptor === 'function') {
234
+ return { type: interceptor };
235
+ }
236
+ return interceptor;
237
+ });
238
+ if (propertyKey && descriptor) {
239
+ // Method decorator
240
+ logger_1.default.debug(`Registering interceptors for method ${String(propertyKey)} in ${target.constructor?.name}`);
241
+ Reflect.defineMetadata(INTERCEPTOR_METADATA_KEY, interceptorMetadata, target, propertyKey);
242
+ return descriptor;
243
+ }
244
+ else {
245
+ // Class decorator
246
+ logger_1.default.debug(`Registering interceptors for class ${target.name}`);
247
+ Reflect.defineMetadata(CLASS_INTERCEPTOR_METADATA_KEY, interceptorMetadata, target);
248
+ }
249
+ };
250
+ return decorator;
251
+ }
252
+ function UseGuards(...guards) {
253
+ const decorator = (target, propertyKey, descriptor) => {
254
+ if (propertyKey && descriptor) {
255
+ // Method decorator
256
+ const existingGuards = Reflect.getMetadata('hazel:guards', target, propertyKey) || [];
257
+ Reflect.defineMetadata('hazel:guards', [...existingGuards, ...guards], target, propertyKey);
258
+ return descriptor;
259
+ }
260
+ else {
261
+ // Class decorator
262
+ const existingGuards = Reflect.getMetadata('hazel:guards', target) || [];
263
+ Reflect.defineMetadata('hazel:guards', [...existingGuards, ...guards], target);
264
+ }
265
+ };
266
+ return decorator;
267
+ }
268
+ function AITask(options) {
269
+ return (target, propertyKey, descriptor) => {
270
+ Reflect.defineMetadata('hazel:ai-task', options, target, propertyKey);
271
+ return descriptor;
272
+ };
273
+ }
274
+ function Req() {
275
+ return (target, propertyKey, parameterIndex) => {
276
+ if (!propertyKey) {
277
+ throw new Error('Req decorator must be used on a method parameter');
278
+ }
279
+ const constructor = target
280
+ .constructor;
281
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, constructor, propertyKey) || [];
282
+ injections[parameterIndex] = { type: 'request' };
283
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, constructor, propertyKey);
284
+ };
285
+ }
286
+ function Headers(headerName) {
287
+ return (target, propertyKey, parameterIndex) => {
288
+ if (!propertyKey) {
289
+ throw new Error('Headers decorator must be used on a method parameter');
290
+ }
291
+ const constructor = target
292
+ .constructor;
293
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, constructor, propertyKey) || [];
294
+ injections[parameterIndex] = { type: 'headers', name: headerName };
295
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, constructor, propertyKey);
296
+ };
297
+ }
298
+ function HttpCode(statusCode) {
299
+ return (target, propertyKey, descriptor) => {
300
+ Reflect.defineMetadata(HTTP_CODE_METADATA_KEY, statusCode, target, propertyKey);
301
+ return descriptor;
302
+ };
303
+ }
304
+ function Header(name, value) {
305
+ return (target, propertyKey, descriptor) => {
306
+ const existingHeaders = Reflect.getMetadata(HEADER_METADATA_KEY, target, propertyKey) || [];
307
+ existingHeaders.push({ name, value });
308
+ Reflect.defineMetadata(HEADER_METADATA_KEY, existingHeaders, target, propertyKey);
309
+ return descriptor;
310
+ };
311
+ }
312
+ function Redirect(url, statusCode = 302) {
313
+ return (target, propertyKey, descriptor) => {
314
+ Reflect.defineMetadata(REDIRECT_METADATA_KEY, { url, statusCode }, target, propertyKey);
315
+ return descriptor;
316
+ };
317
+ }
318
+ function Res() {
319
+ return (target, propertyKey, parameterIndex) => {
320
+ if (!propertyKey) {
321
+ throw new Error('Res decorator must be used on a method parameter');
322
+ }
323
+ logger_1.default.debug(`Registering response parameter ${parameterIndex} in ${target.constructor?.name}`);
324
+ // Get the constructor of the target
325
+ const constructor = target
326
+ .constructor;
327
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, constructor, propertyKey) || [];
328
+ // Store the injection metadata
329
+ injections[parameterIndex] = {
330
+ type: 'response',
331
+ };
332
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, constructor, propertyKey);
333
+ logger_1.default.debug('Updated injections:', JSON.stringify(injections, null, 2));
334
+ };
335
+ }
336
+ function Ip() {
337
+ return (target, propertyKey, parameterIndex) => {
338
+ if (!propertyKey) {
339
+ throw new Error('Ip decorator must be used on a method parameter');
340
+ }
341
+ const constructor = target
342
+ .constructor;
343
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, constructor, propertyKey) || [];
344
+ injections[parameterIndex] = { type: 'ip' };
345
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, constructor, propertyKey);
346
+ };
347
+ }
348
+ function Host() {
349
+ return (target, propertyKey, parameterIndex) => {
350
+ if (!propertyKey) {
351
+ throw new Error('Host decorator must be used on a method parameter');
352
+ }
353
+ const constructor = target
354
+ .constructor;
355
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, constructor, propertyKey) || [];
356
+ injections[parameterIndex] = { type: 'host' };
357
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, constructor, propertyKey);
358
+ };
359
+ }
360
+ /**
361
+ * Marks a controller or route as public (no auth required).
362
+ * Guards should check Reflect.getMetadata(PUBLIC_METADATA_KEY, target, propertyKey)
363
+ * or Reflect.getMetadata(PUBLIC_METADATA_KEY, target) and allow the request when true.
364
+ */
365
+ function Public() {
366
+ const setPublic = (target, propertyKey) => {
367
+ if (propertyKey === undefined) {
368
+ Reflect.defineMetadata(PUBLIC_METADATA_KEY, true, target);
369
+ }
370
+ else {
371
+ Reflect.defineMetadata(PUBLIC_METADATA_KEY, true, target, propertyKey);
372
+ }
373
+ };
374
+ const decorator = (target, propertyKey, descriptor) => {
375
+ if (propertyKey !== undefined && descriptor !== undefined) {
376
+ setPublic(target, propertyKey);
377
+ return descriptor;
378
+ }
379
+ setPublic(target);
380
+ };
381
+ return decorator;
382
+ }
383
+ /** Alias for @Public(). Use when you want to skip auth for specific routes. */
384
+ exports.SkipAuth = Public;
385
+ function Timeout(ms) {
386
+ return (target, propertyKey, descriptor) => {
387
+ Reflect.defineMetadata(TIMEOUT_METADATA_KEY, ms, target, propertyKey);
388
+ return descriptor;
389
+ };
390
+ }
391
+ function Optional() {
392
+ return (target, propertyKey, parameterIndex) => {
393
+ if (!propertyKey) {
394
+ throw new Error('Optional decorator must be used on a method parameter');
395
+ }
396
+ const constructor = target
397
+ .constructor;
398
+ const indices = Reflect.getMetadata(OPTIONAL_INDICES_METADATA_KEY, constructor, propertyKey) || [];
399
+ if (!indices.includes(parameterIndex)) {
400
+ indices.push(parameterIndex);
401
+ }
402
+ Reflect.defineMetadata(OPTIONAL_INDICES_METADATA_KEY, indices, constructor, propertyKey);
403
+ };
404
+ }
405
+ function Session() {
406
+ return (target, propertyKey, parameterIndex) => {
407
+ if (!propertyKey) {
408
+ throw new Error('Session decorator must be used on a method parameter');
409
+ }
410
+ const constructor = target
411
+ .constructor;
412
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, constructor, propertyKey) || [];
413
+ injections[parameterIndex] = { type: 'session' };
414
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, constructor, propertyKey);
415
+ };
416
+ }
417
+ function Retry(options) {
418
+ return (target, propertyKey, descriptor) => {
419
+ Reflect.defineMetadata(RETRY_METADATA_KEY, options, target, propertyKey);
420
+ const routes = Reflect.getMetadata(ROUTE_METADATA_KEY, target.constructor) || [];
421
+ const route = routes.find((r) => r.propertyKey === propertyKey);
422
+ if (route) {
423
+ route.interceptors = route.interceptors || [];
424
+ route.interceptors.unshift({ type: interceptor_1.RetryInterceptor, options });
425
+ Reflect.defineMetadata(ROUTE_METADATA_KEY, routes, target.constructor);
426
+ }
427
+ return descriptor;
428
+ };
429
+ }
430
+ function ApiTags(...tags) {
431
+ const setTags = (target, propertyKey) => {
432
+ if (propertyKey === undefined) {
433
+ Reflect.defineMetadata(API_TAGS_METADATA_KEY, tags, target);
434
+ }
435
+ else {
436
+ Reflect.defineMetadata(API_TAGS_METADATA_KEY, tags, target, propertyKey);
437
+ }
438
+ };
439
+ const decorator = (target, propertyKey, descriptor) => {
440
+ if (propertyKey !== undefined && descriptor !== undefined) {
441
+ setTags(target, propertyKey);
442
+ return descriptor;
443
+ }
444
+ setTags(target);
445
+ };
446
+ return decorator;
447
+ }
448
+ function ApiOperation(options) {
449
+ const opts = typeof options === 'string' ? { summary: options } : options;
450
+ return (target, propertyKey, descriptor) => {
451
+ Reflect.defineMetadata(API_OPERATION_METADATA_KEY, opts, target, propertyKey);
452
+ return descriptor;
453
+ };
454
+ }
455
+ /**
456
+ * Sets arbitrary metadata on a class or method.
457
+ * Guards, interceptors, and other components can read it via getMetadata(key, target, propertyKey?).
458
+ *
459
+ * @param key - Metadata key (stored under hazel:meta:<key> to avoid collisions)
460
+ * @param value - Value to store (any serializable or object)
461
+ * @example
462
+ * SetMetadata('roles', ['admin'])(MyController)
463
+ * SetMetadata('roles', ['user'])(MyController.prototype, 'getProfile')
464
+ */
465
+ function SetMetadata(key, value) {
466
+ const metaKey = `${exports.CUSTOM_METADATA_PREFIX}${key}`;
467
+ const decorator = (target, propertyKey, descriptor) => {
468
+ if (propertyKey !== undefined && descriptor !== undefined) {
469
+ Reflect.defineMetadata(metaKey, value, target, propertyKey);
470
+ return descriptor;
471
+ }
472
+ Reflect.defineMetadata(metaKey, value, target);
473
+ };
474
+ return decorator;
475
+ }
476
+ /**
477
+ * Reads custom metadata set with SetMetadata.
478
+ *
479
+ * @param key - Key passed to SetMetadata(key, value)
480
+ * @param target - Class or prototype
481
+ * @param propertyKey - Optional method name (for method-level metadata)
482
+ */
483
+ function getMetadata(key, target, propertyKey) {
484
+ const metaKey = `${exports.CUSTOM_METADATA_PREFIX}${key}`;
485
+ if (propertyKey !== undefined) {
486
+ return Reflect.getMetadata(metaKey, target, propertyKey);
487
+ }
488
+ return Reflect.getMetadata(metaKey, target);
489
+ }
490
+ /**
491
+ * Creates a custom parameter decorator that injects a value computed from the request.
492
+ * The resolver receives the raw request, parsed request context, and the DI container.
493
+ * Return value can be a Promise for async resolution (e.g. loading the current user from DB).
494
+ *
495
+ * @param resolve - Function (req, context, container) => value | Promise<value>
496
+ * @example
497
+ * const CurrentUser = createParamDecorator(async (req, ctx, container) => ctx.user ?? req.user);
498
+ * // In controller: getProfile(@CurrentUser() user: User) { ... }
499
+ */
500
+ function createParamDecorator(resolve) {
501
+ return (target, propertyKey, parameterIndex) => {
502
+ if (!propertyKey) {
503
+ throw new Error('createParamDecorator must be used on a method parameter');
504
+ }
505
+ const constructor = target.constructor;
506
+ const injections = Reflect.getMetadata(INJECT_METADATA_KEY, constructor, propertyKey) || [];
507
+ injections[parameterIndex] = { type: 'custom', resolve };
508
+ Reflect.defineMetadata(INJECT_METADATA_KEY, injections, constructor, propertyKey);
509
+ };
510
+ }
511
+ function createRouteDecorator(method, options) {
512
+ return (target, propertyKey, descriptor) => {
513
+ logger_1.default.debug(`Registering ${method} route: ${String(propertyKey)}`);
514
+ const routes = Reflect.getMetadata(ROUTE_METADATA_KEY, target.constructor) ||
515
+ [];
516
+ const routeOptions = typeof options === 'string' ? { path: options } : options || {};
517
+ const pipes = Reflect.getMetadata(PIPE_METADATA_KEY, target, propertyKey) || [];
518
+ const interceptors = Reflect.getMetadata(INTERCEPTOR_METADATA_KEY, target, propertyKey) || [];
519
+ const classInterceptors = Reflect.getMetadata(CLASS_INTERCEPTOR_METADATA_KEY, target.constructor) || [];
520
+ logger_1.default.debug('Route metadata:', {
521
+ method,
522
+ path: routeOptions.path || '/',
523
+ propertyKey: String(propertyKey),
524
+ pipes: pipes.map((p) => p.type.name),
525
+ interceptors: interceptors.map((i) => i.type.name),
526
+ });
527
+ routes.push({
528
+ method,
529
+ path: routeOptions.path || '/',
530
+ propertyKey,
531
+ middlewares: routeOptions.middlewares || [],
532
+ pipes: [...pipes, ...(routeOptions.pipes || [])],
533
+ interceptors: [...classInterceptors, ...interceptors, ...(routeOptions.interceptors || [])],
534
+ });
535
+ Reflect.defineMetadata(ROUTE_METADATA_KEY, routes, target.constructor);
536
+ return descriptor;
537
+ };
538
+ }
@@ -0,0 +1,34 @@
1
+ export declare class HttpError extends Error {
2
+ readonly statusCode: number;
3
+ readonly errors?: string[] | undefined;
4
+ constructor(statusCode: number, message: string, errors?: string[] | undefined);
5
+ }
6
+ export declare class BadRequestError extends HttpError {
7
+ constructor(message: string, errors?: string[]);
8
+ }
9
+ export declare class UnauthorizedError extends HttpError {
10
+ constructor(message?: string);
11
+ }
12
+ export declare class ForbiddenError extends HttpError {
13
+ constructor(message?: string);
14
+ }
15
+ export declare class NotFoundError extends HttpError {
16
+ constructor(message?: string);
17
+ }
18
+ export declare class ConflictError extends HttpError {
19
+ constructor(message: string);
20
+ }
21
+ export declare class RequestTimeoutError extends HttpError {
22
+ constructor(message?: string);
23
+ }
24
+ export declare class InternalServerError extends HttpError {
25
+ constructor(message?: string);
26
+ }
27
+ export declare const HttpException: typeof HttpError;
28
+ export declare const BadRequestException: typeof BadRequestError;
29
+ export declare const UnauthorizedException: typeof UnauthorizedError;
30
+ export declare const ForbiddenException: typeof ForbiddenError;
31
+ export declare const NotFoundException: typeof NotFoundError;
32
+ export declare const ConflictException: typeof ConflictError;
33
+ export declare const InternalServerErrorException: typeof InternalServerError;
34
+ //# sourceMappingURL=http.error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.error.d.ts","sourceRoot":"","sources":["../../src/errors/http.error.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAU,SAAQ,KAAK;aAEhB,UAAU,EAAE,MAAM;aAElB,MAAM,CAAC,EAAE,MAAM,EAAE;gBAFjB,UAAU,EAAE,MAAM,EAClC,OAAO,EAAE,MAAM,EACC,MAAM,CAAC,EAAE,MAAM,EAAE,YAAA;CAKpC;AAED,qBAAa,eAAgB,SAAQ,SAAS;gBAChC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE;CAI/C;AAED,qBAAa,iBAAkB,SAAQ,SAAS;gBAClC,OAAO,GAAE,MAAuB;CAI7C;AAED,qBAAa,cAAe,SAAQ,SAAS;gBAC/B,OAAO,GAAE,MAAoB;CAI1C;AAED,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,OAAO,GAAE,MAAoB;CAI1C;AAED,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,GAAE,MAA0B;CAIhD;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,GAAE,MAAgC;CAItD;AAGD,eAAO,MAAM,aAAa,kBAAY,CAAC;AACvC,eAAO,MAAM,mBAAmB,wBAAkB,CAAC;AACnD,eAAO,MAAM,qBAAqB,0BAAoB,CAAC;AACvD,eAAO,MAAM,kBAAkB,uBAAiB,CAAC;AACjD,eAAO,MAAM,iBAAiB,sBAAgB,CAAC;AAC/C,eAAO,MAAM,iBAAiB,sBAAgB,CAAC;AAC/C,eAAO,MAAM,4BAA4B,4BAAsB,CAAC"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InternalServerErrorException = exports.ConflictException = exports.NotFoundException = exports.ForbiddenException = exports.UnauthorizedException = exports.BadRequestException = exports.HttpException = exports.InternalServerError = exports.RequestTimeoutError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.BadRequestError = exports.HttpError = void 0;
4
+ class HttpError extends Error {
5
+ constructor(statusCode, message, errors) {
6
+ super(message);
7
+ this.statusCode = statusCode;
8
+ this.errors = errors;
9
+ this.name = 'HttpError';
10
+ }
11
+ }
12
+ exports.HttpError = HttpError;
13
+ class BadRequestError extends HttpError {
14
+ constructor(message, errors) {
15
+ super(400, message, errors);
16
+ this.name = 'BadRequestError';
17
+ }
18
+ }
19
+ exports.BadRequestError = BadRequestError;
20
+ class UnauthorizedError extends HttpError {
21
+ constructor(message = 'Unauthorized') {
22
+ super(401, message);
23
+ this.name = 'UnauthorizedError';
24
+ }
25
+ }
26
+ exports.UnauthorizedError = UnauthorizedError;
27
+ class ForbiddenError extends HttpError {
28
+ constructor(message = 'Forbidden') {
29
+ super(403, message);
30
+ this.name = 'ForbiddenError';
31
+ }
32
+ }
33
+ exports.ForbiddenError = ForbiddenError;
34
+ class NotFoundError extends HttpError {
35
+ constructor(message = 'Not Found') {
36
+ super(404, message);
37
+ this.name = 'NotFoundError';
38
+ }
39
+ }
40
+ exports.NotFoundError = NotFoundError;
41
+ class ConflictError extends HttpError {
42
+ constructor(message) {
43
+ super(409, message);
44
+ this.name = 'ConflictError';
45
+ }
46
+ }
47
+ exports.ConflictError = ConflictError;
48
+ class RequestTimeoutError extends HttpError {
49
+ constructor(message = 'Request Timeout') {
50
+ super(408, message);
51
+ this.name = 'RequestTimeoutError';
52
+ }
53
+ }
54
+ exports.RequestTimeoutError = RequestTimeoutError;
55
+ class InternalServerError extends HttpError {
56
+ constructor(message = 'Internal Server Error') {
57
+ super(500, message);
58
+ this.name = 'InternalServerError';
59
+ }
60
+ }
61
+ exports.InternalServerError = InternalServerError;
62
+ // Aliases using Exception naming convention (matches documentation)
63
+ exports.HttpException = HttpError;
64
+ exports.BadRequestException = BadRequestError;
65
+ exports.UnauthorizedException = UnauthorizedError;
66
+ exports.ForbiddenException = ForbiddenError;
67
+ exports.NotFoundException = NotFoundError;
68
+ exports.ConflictException = ConflictError;
69
+ exports.InternalServerErrorException = InternalServerError;
@@ -0,0 +1,39 @@
1
+ import { Request, Response } from '../types';
2
+ /**
3
+ * Arguments host provides access to the underlying platform request/response
4
+ */
5
+ export interface ArgumentsHost {
6
+ switchToHttp(): {
7
+ getRequest<T = Request>(): T;
8
+ getResponse<T = Response>(): T;
9
+ };
10
+ getType(): string;
11
+ }
12
+ /**
13
+ * Exception filter interface
14
+ */
15
+ export interface ExceptionFilter<T = unknown> {
16
+ catch(exception: T, host: ArgumentsHost): void | Promise<void>;
17
+ }
18
+ /**
19
+ * Implementation of ArgumentsHost
20
+ */
21
+ export declare class ArgumentsHostImpl implements ArgumentsHost {
22
+ private readonly request;
23
+ private readonly response;
24
+ constructor(request: Request, response: Response);
25
+ switchToHttp(): {
26
+ getRequest: <T = Request>() => T;
27
+ getResponse: <T = Response>() => T;
28
+ };
29
+ getType(): string;
30
+ }
31
+ /**
32
+ * Decorator to mark a class as an exception filter
33
+ */
34
+ export declare function Catch(...exceptions: Array<new (...args: never[]) => unknown>): ClassDecorator;
35
+ /**
36
+ * Get exception types that a filter handles
37
+ */
38
+ export declare function getFilterExceptions(filter: object): Array<new (...args: unknown[]) => unknown>;
39
+ //# sourceMappingURL=exception-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exception-filter.d.ts","sourceRoot":"","sources":["../../src/filters/exception-filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,YAAY,IAAI;QACd,UAAU,CAAC,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC;QAC7B,WAAW,CAAC,CAAC,GAAG,QAAQ,KAAK,CAAC,CAAC;KAChC,CAAC;IACF,OAAO,IAAI,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE;AAED;;GAEG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IAEnD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBADR,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ;IAGrC,YAAY,IAAI;QAAE,UAAU,EAAE,CAAC,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC;QAAC,WAAW,EAAE,CAAC,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAA;KAAE;IAOxF,OAAO,IAAI,MAAM;CAGlB;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,GAAG,cAAc,CAI7F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAE9F"}