@ajke/core 0.1.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 (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +357 -0
  3. package/dist/chunk-AT2R2CGV.js +234 -0
  4. package/dist/chunk-AT2R2CGV.js.map +1 -0
  5. package/dist/chunk-EUXUH3YW.js +15 -0
  6. package/dist/chunk-EUXUH3YW.js.map +1 -0
  7. package/dist/chunk-YUBEJL4T.cjs +234 -0
  8. package/dist/chunk-YUBEJL4T.cjs.map +1 -0
  9. package/dist/chunk-ZBDE64SD.cjs +15 -0
  10. package/dist/chunk-ZBDE64SD.cjs.map +1 -0
  11. package/dist/config.cjs +10 -0
  12. package/dist/config.cjs.map +1 -0
  13. package/dist/config.d.cts +13 -0
  14. package/dist/config.d.ts +13 -0
  15. package/dist/config.js +10 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/index.cjs +974 -0
  18. package/dist/index.cjs.map +1 -0
  19. package/dist/index.d.cts +255 -0
  20. package/dist/index.d.ts +255 -0
  21. package/dist/index.js +974 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/middleware/index.cjs +10 -0
  24. package/dist/middleware/index.cjs.map +1 -0
  25. package/dist/middleware/index.d.cts +18 -0
  26. package/dist/middleware/index.d.ts +18 -0
  27. package/dist/middleware/index.js +10 -0
  28. package/dist/middleware/index.js.map +1 -0
  29. package/package.json +56 -0
  30. package/src/README.md +285 -0
  31. package/src/config.ts +14 -0
  32. package/src/context/execution-context.ts +36 -0
  33. package/src/context/index.ts +1 -0
  34. package/src/decorators/core/exception-filters.decorator.ts +24 -0
  35. package/src/decorators/core/index.ts +6 -0
  36. package/src/decorators/core/injectable.decorator.ts +41 -0
  37. package/src/decorators/core/optional.decorator.ts +9 -0
  38. package/src/decorators/core/set-metadata.decorator.ts +20 -0
  39. package/src/decorators/core/use-guards.decorator.ts +14 -0
  40. package/src/decorators/core/use-interceptors.decorator.ts +16 -0
  41. package/src/decorators/http/controller.decorator.ts +230 -0
  42. package/src/decorators/http/header.decorator.ts +11 -0
  43. package/src/decorators/http/http-code.decorator.ts +8 -0
  44. package/src/decorators/http/index.ts +6 -0
  45. package/src/decorators/http/redirect.decorator.ts +13 -0
  46. package/src/decorators/http/route-mapping.decorator.ts +22 -0
  47. package/src/decorators/http/route-params.decorator.ts +60 -0
  48. package/src/decorators/index.ts +3 -0
  49. package/src/decorators/modules/global.decorator.ts +8 -0
  50. package/src/decorators/modules/index.ts +2 -0
  51. package/src/decorators/modules/module.decorator.ts +16 -0
  52. package/src/exceptions/http-exception.ts +17 -0
  53. package/src/exceptions/http-exceptions.ts +85 -0
  54. package/src/exceptions/index.ts +2 -0
  55. package/src/index.ts +11 -0
  56. package/src/injector/index.ts +1 -0
  57. package/src/injector/injector.ts +103 -0
  58. package/src/injector/module-compiler.ts +48 -0
  59. package/src/injector/module.factory.ts +74 -0
  60. package/src/interfaces/core/filter.interface.ts +5 -0
  61. package/src/interfaces/core/guard.interface.ts +5 -0
  62. package/src/interfaces/core/index.ts +5 -0
  63. package/src/interfaces/core/interceptor.interface.ts +9 -0
  64. package/src/interfaces/core/lifecycle.interface.ts +19 -0
  65. package/src/interfaces/core/pipe.interface.ts +9 -0
  66. package/src/interfaces/http/index.ts +1 -0
  67. package/src/interfaces/http/response.interface.ts +27 -0
  68. package/src/interfaces/index.ts +3 -0
  69. package/src/interfaces/modules/index.ts +1 -0
  70. package/src/interfaces/modules/module.interface.ts +17 -0
  71. package/src/middleware/error-handler.middleware.ts +63 -0
  72. package/src/middleware/index.ts +2 -0
  73. package/src/middleware/request-logger.middleware.ts +17 -0
  74. package/src/pipes/index.ts +3 -0
  75. package/src/pipes/validate.pipe.ts +79 -0
  76. package/src/pipes/zod-query.pipe.ts +42 -0
  77. package/src/pipes/zod-validate.pipe.ts +49 -0
  78. package/src/services/index.ts +1 -0
  79. package/src/services/reflector.service.ts +24 -0
  80. package/src/utils/apply-decorators.util.ts +17 -0
  81. package/src/utils/forward-ref.util.ts +14 -0
  82. package/src/utils/index.ts +22 -0
  83. package/src/utils/logger.util.ts +189 -0
  84. package/src/utils/response.util.ts +72 -0
package/dist/index.js ADDED
@@ -0,0 +1,974 @@
1
+ import {
2
+ HttpException,
3
+ errorHandler,
4
+ logger,
5
+ requestLogger
6
+ } from "./chunk-AT2R2CGV.js";
7
+ import {
8
+ __decorateClass
9
+ } from "./chunk-EUXUH3YW.js";
10
+
11
+ // src/decorators/core/injectable.decorator.ts
12
+ import { injectable, inject as tsyringeInject } from "tsyringe";
13
+
14
+ // src/utils/forward-ref.util.ts
15
+ function forwardRef(fn) {
16
+ return { forwardRef: fn };
17
+ }
18
+ function isForwardRef(val) {
19
+ return val !== null && val !== void 0 && typeof val === "object" && typeof val.forwardRef === "function";
20
+ }
21
+
22
+ // src/decorators/core/injectable.decorator.ts
23
+ var INJECT_CUSTOM_TOKENS_KEY = "wilt:inject:custom:tokens";
24
+ function Injectable() {
25
+ return (target) => {
26
+ injectable()(target);
27
+ };
28
+ }
29
+ function Inject(token) {
30
+ return (target, propertyKey, parameterIndex) => {
31
+ if (isForwardRef(token)) {
32
+ const existing2 = Reflect.getMetadata(INJECT_CUSTOM_TOKENS_KEY, target) || {};
33
+ existing2[parameterIndex] = token;
34
+ Reflect.defineMetadata(INJECT_CUSTOM_TOKENS_KEY, existing2, target);
35
+ return;
36
+ }
37
+ if (!token) {
38
+ const paramTypes = Reflect.getMetadata("design:paramtypes", target) || [];
39
+ const paramType = paramTypes[parameterIndex];
40
+ if (paramType) {
41
+ return tsyringeInject(paramType)(target, propertyKey, parameterIndex);
42
+ }
43
+ return;
44
+ }
45
+ const existing = Reflect.getMetadata(INJECT_CUSTOM_TOKENS_KEY, target) || {};
46
+ existing[parameterIndex] = token;
47
+ Reflect.defineMetadata(INJECT_CUSTOM_TOKENS_KEY, existing, target);
48
+ return tsyringeInject(token)(target, propertyKey, parameterIndex);
49
+ };
50
+ }
51
+
52
+ // src/decorators/core/set-metadata.decorator.ts
53
+ function SetMetadata(metadataKey, metadataValue) {
54
+ const decoratorFactory = (target, key, descriptor) => {
55
+ if (descriptor) {
56
+ Reflect.defineMetadata(metadataKey, metadataValue, descriptor.value);
57
+ return descriptor;
58
+ }
59
+ Reflect.defineMetadata(metadataKey, metadataValue, target);
60
+ return target;
61
+ };
62
+ decoratorFactory.KEY = metadataKey;
63
+ return decoratorFactory;
64
+ }
65
+
66
+ // src/decorators/core/use-guards.decorator.ts
67
+ var GUARDS_METADATA = "wilt:guards";
68
+ function UseGuards(...guards) {
69
+ return (target, key, descriptor) => {
70
+ if (descriptor) {
71
+ const existing2 = Reflect.getMetadata(GUARDS_METADATA, descriptor.value) || [];
72
+ Reflect.defineMetadata(GUARDS_METADATA, [...existing2, ...guards], descriptor.value);
73
+ return descriptor;
74
+ }
75
+ const existing = Reflect.getMetadata(GUARDS_METADATA, target) || [];
76
+ Reflect.defineMetadata(GUARDS_METADATA, [...existing, ...guards], target);
77
+ return target;
78
+ };
79
+ }
80
+
81
+ // src/decorators/core/use-interceptors.decorator.ts
82
+ var INTERCEPTORS_METADATA = "wilt:interceptors";
83
+ function UseInterceptors(...interceptors) {
84
+ return (target, key, descriptor) => {
85
+ if (descriptor) {
86
+ const existing2 = Reflect.getMetadata(INTERCEPTORS_METADATA, descriptor.value) || [];
87
+ Reflect.defineMetadata(INTERCEPTORS_METADATA, [...existing2, ...interceptors], descriptor.value);
88
+ return descriptor;
89
+ }
90
+ const existing = Reflect.getMetadata(INTERCEPTORS_METADATA, target) || [];
91
+ Reflect.defineMetadata(INTERCEPTORS_METADATA, [...existing, ...interceptors], target);
92
+ return target;
93
+ };
94
+ }
95
+
96
+ // src/decorators/core/exception-filters.decorator.ts
97
+ var FILTERS_METADATA = "wilt:filters";
98
+ var CATCH_METADATA = "wilt:catch";
99
+ function Catch(...exceptions) {
100
+ return (target) => {
101
+ Reflect.defineMetadata(CATCH_METADATA, exceptions, target);
102
+ return target;
103
+ };
104
+ }
105
+ function UseFilters(...filters) {
106
+ return (target, key, descriptor) => {
107
+ if (descriptor) {
108
+ const existing2 = Reflect.getMetadata(FILTERS_METADATA, descriptor.value) || [];
109
+ Reflect.defineMetadata(FILTERS_METADATA, [...existing2, ...filters], descriptor.value);
110
+ return descriptor;
111
+ }
112
+ const existing = Reflect.getMetadata(FILTERS_METADATA, target) || [];
113
+ Reflect.defineMetadata(FILTERS_METADATA, [...existing, ...filters], target);
114
+ return target;
115
+ };
116
+ }
117
+
118
+ // src/decorators/core/optional.decorator.ts
119
+ var OPTIONAL_METADATA = "wilt:optional";
120
+ function Optional() {
121
+ return (target, _key, parameterIndex) => {
122
+ const existing = Reflect.getMetadata(OPTIONAL_METADATA, target) || [];
123
+ existing.push(parameterIndex);
124
+ Reflect.defineMetadata(OPTIONAL_METADATA, existing, target);
125
+ };
126
+ }
127
+
128
+ // src/decorators/http/controller.decorator.ts
129
+ import { injectable as injectable2 } from "tsyringe";
130
+
131
+ // src/context/execution-context.ts
132
+ function createExecutionContext(c, controllerClass, handler) {
133
+ return {
134
+ getClass: () => controllerClass,
135
+ getHandler: () => handler,
136
+ switchToHttp: () => ({
137
+ getRequest: () => c
138
+ })
139
+ };
140
+ }
141
+ function createArgumentsHost(c) {
142
+ return {
143
+ switchToHttp: () => ({
144
+ getRequest: () => c
145
+ })
146
+ };
147
+ }
148
+
149
+ // src/decorators/http/header.decorator.ts
150
+ var HEADER_METADATA = "wilt:response-headers";
151
+ function Header(name, value) {
152
+ return (_target, _key, descriptor) => {
153
+ const existing = Reflect.getMetadata(HEADER_METADATA, descriptor.value) || [];
154
+ existing.push({ name, value });
155
+ Reflect.defineMetadata(HEADER_METADATA, existing, descriptor.value);
156
+ return descriptor;
157
+ };
158
+ }
159
+
160
+ // src/decorators/http/http-code.decorator.ts
161
+ var HTTP_CODE_METADATA = "wilt:http-code";
162
+ function HttpCode(statusCode) {
163
+ return (_target, _key, descriptor) => {
164
+ Reflect.defineMetadata(HTTP_CODE_METADATA, statusCode, descriptor.value);
165
+ return descriptor;
166
+ };
167
+ }
168
+
169
+ // src/decorators/http/redirect.decorator.ts
170
+ var REDIRECT_METADATA = "wilt:redirect";
171
+ function Redirect(url, statusCode = 302) {
172
+ return (_target, _key, descriptor) => {
173
+ Reflect.defineMetadata(REDIRECT_METADATA, { url, statusCode }, descriptor.value);
174
+ return descriptor;
175
+ };
176
+ }
177
+
178
+ // src/decorators/http/route-params.decorator.ts
179
+ var ROUTE_PARAMS_METADATA = "wilt:route-params";
180
+ var TOTAL_PARAMS_METADATA = "wilt:total-params";
181
+ function recordTotalParams(target, key) {
182
+ if (!Reflect.hasMetadata(TOTAL_PARAMS_METADATA, target, key)) {
183
+ const fn = target[key];
184
+ if (typeof fn === "function") {
185
+ Reflect.defineMetadata(TOTAL_PARAMS_METADATA, fn.length, target, key);
186
+ }
187
+ }
188
+ }
189
+ function createParamDecorator(type) {
190
+ return (data) => (target, propertyKey, parameterIndex) => {
191
+ const key = propertyKey;
192
+ const existing = Reflect.getMetadata(ROUTE_PARAMS_METADATA, target, key) || [];
193
+ existing.push({ index: parameterIndex, type, data });
194
+ Reflect.defineMetadata(ROUTE_PARAMS_METADATA, existing, target, key);
195
+ recordTotalParams(target, key);
196
+ };
197
+ }
198
+ var Body = createParamDecorator("body");
199
+ var Param = createParamDecorator("param");
200
+ var Query = createParamDecorator("query");
201
+ var Headers = createParamDecorator("headers");
202
+ function Ip() {
203
+ return (target, propertyKey, parameterIndex) => {
204
+ const key = propertyKey;
205
+ const existing = Reflect.getMetadata(ROUTE_PARAMS_METADATA, target, key) || [];
206
+ existing.push({ index: parameterIndex, type: "ip" });
207
+ Reflect.defineMetadata(ROUTE_PARAMS_METADATA, existing, target, key);
208
+ recordTotalParams(target, key);
209
+ };
210
+ }
211
+ function Req() {
212
+ return (target, propertyKey, parameterIndex) => {
213
+ const key = propertyKey;
214
+ const existing = Reflect.getMetadata(ROUTE_PARAMS_METADATA, target, key) || [];
215
+ existing.push({ index: parameterIndex, type: "req" });
216
+ Reflect.defineMetadata(ROUTE_PARAMS_METADATA, existing, target, key);
217
+ recordTotalParams(target, key);
218
+ };
219
+ }
220
+
221
+ // src/exceptions/http-exceptions.ts
222
+ var BadRequestException = class extends HttpException {
223
+ constructor(message = "Bad Request") {
224
+ super(message, 400);
225
+ this.name = "BadRequestException";
226
+ }
227
+ };
228
+ var UnauthorizedException = class extends HttpException {
229
+ constructor(message = "Unauthorized") {
230
+ super(message, 401);
231
+ this.name = "UnauthorizedException";
232
+ }
233
+ };
234
+ var ForbiddenException = class extends HttpException {
235
+ constructor(message = "Forbidden") {
236
+ super(message, 403);
237
+ this.name = "ForbiddenException";
238
+ }
239
+ };
240
+ var NotFoundException = class extends HttpException {
241
+ constructor(message = "Not Found") {
242
+ super(message, 404);
243
+ this.name = "NotFoundException";
244
+ }
245
+ };
246
+ var MethodNotAllowedException = class extends HttpException {
247
+ constructor(message = "Method Not Allowed") {
248
+ super(message, 405);
249
+ this.name = "MethodNotAllowedException";
250
+ }
251
+ };
252
+ var ConflictException = class extends HttpException {
253
+ constructor(message = "Conflict") {
254
+ super(message, 409);
255
+ this.name = "ConflictException";
256
+ }
257
+ };
258
+ var GoneException = class extends HttpException {
259
+ constructor(message = "Gone") {
260
+ super(message, 410);
261
+ this.name = "GoneException";
262
+ }
263
+ };
264
+ var UnprocessableEntityException = class extends HttpException {
265
+ constructor(message = "Unprocessable Entity") {
266
+ super(message, 422);
267
+ this.name = "UnprocessableEntityException";
268
+ }
269
+ };
270
+ var TooManyRequestsException = class extends HttpException {
271
+ constructor(message = "Too Many Requests") {
272
+ super(message, 429);
273
+ this.name = "TooManyRequestsException";
274
+ }
275
+ };
276
+ var InternalServerErrorException = class extends HttpException {
277
+ constructor(message = "Internal Server Error") {
278
+ super(message, 500);
279
+ this.name = "InternalServerErrorException";
280
+ }
281
+ };
282
+ var NotImplementedException = class extends HttpException {
283
+ constructor(message = "Not Implemented") {
284
+ super(message, 501);
285
+ this.name = "NotImplementedException";
286
+ }
287
+ };
288
+ var ServiceUnavailableException = class extends HttpException {
289
+ constructor(message = "Service Unavailable") {
290
+ super(message, 503);
291
+ this.name = "ServiceUnavailableException";
292
+ }
293
+ };
294
+
295
+ // src/decorators/http/controller.decorator.ts
296
+ function Controller(prefix = "") {
297
+ return (target) => {
298
+ injectable2()(target);
299
+ target.prototype.prefix = prefix;
300
+ target.prototype.constructorParams = target.prototype.constructorParams || [];
301
+ target.prototype.constructorClass = target;
302
+ };
303
+ }
304
+ function resolveFromRegistry(ClassOrInstance, instanceRegistry) {
305
+ if (typeof ClassOrInstance !== "function") return ClassOrInstance;
306
+ if (instanceRegistry?.has(ClassOrInstance)) return instanceRegistry.get(ClassOrInstance);
307
+ return new ClassOrInstance();
308
+ }
309
+ async function resolveParamArgs(paramMeta, c, totalParams) {
310
+ const maxIndex = Math.max(totalParams - 1, ...paramMeta.map((p) => p.index));
311
+ const args = new Array(maxIndex + 1).fill(void 0);
312
+ const filledIndices = new Set(paramMeta.map((p) => p.index));
313
+ let body;
314
+ const needsBody = paramMeta.some((p) => p.type === "body");
315
+ if (needsBody) {
316
+ const ct = c.req.header("content-type") || "";
317
+ if (ct.includes("multipart/form-data")) {
318
+ const fd = await c.req.formData();
319
+ body = {};
320
+ fd.forEach((v, k) => {
321
+ body[k] = v;
322
+ });
323
+ } else {
324
+ body = await c.req.json().catch(() => ({}));
325
+ }
326
+ }
327
+ for (const p of paramMeta) {
328
+ switch (p.type) {
329
+ case "body":
330
+ args[p.index] = p.data ? body?.[p.data] : body;
331
+ break;
332
+ case "param":
333
+ args[p.index] = p.data ? c.req.param(p.data) : c.req.param();
334
+ break;
335
+ case "query":
336
+ args[p.index] = p.data ? c.req.query(p.data) : c.req.query();
337
+ break;
338
+ case "headers":
339
+ args[p.index] = p.data ? c.req.header(p.data) : Object.fromEntries(c.req.raw.headers.entries());
340
+ break;
341
+ case "ip":
342
+ args[p.index] = c.req.header("cf-connecting-ip") || c.req.header("x-forwarded-for") || "";
343
+ break;
344
+ case "req":
345
+ args[p.index] = c;
346
+ break;
347
+ }
348
+ }
349
+ for (let i = 0; i <= maxIndex; i++) {
350
+ if (!filledIndices.has(i)) args[i] = c;
351
+ }
352
+ return args;
353
+ }
354
+ function registerControllerRoutes(router, controller, prefix = "", instanceRegistry) {
355
+ const routes = controller.constructor.prototype.routes || [];
356
+ const controllerClass = controller.constructor;
357
+ for (const route of routes) {
358
+ const handlerFn = controller[route.handler];
359
+ const fullPath = prefix + route.path;
360
+ const proto = controllerClass.prototype;
361
+ const classGuards = Reflect.getMetadata(GUARDS_METADATA, controllerClass) || [];
362
+ const methodGuards = Reflect.getMetadata(GUARDS_METADATA, handlerFn) || [];
363
+ const guards = [...classGuards, ...methodGuards];
364
+ const classInterceptors = Reflect.getMetadata(INTERCEPTORS_METADATA, controllerClass) || [];
365
+ const methodInterceptors = Reflect.getMetadata(INTERCEPTORS_METADATA, handlerFn) || [];
366
+ const interceptors = [...classInterceptors, ...methodInterceptors];
367
+ const classFilters = Reflect.getMetadata(FILTERS_METADATA, controllerClass) || [];
368
+ const methodFilters = Reflect.getMetadata(FILTERS_METADATA, handlerFn) || [];
369
+ const filters = [...classFilters, ...methodFilters];
370
+ const httpCode = Reflect.getMetadata(HTTP_CODE_METADATA, handlerFn);
371
+ const headersToSet = Reflect.getMetadata(HEADER_METADATA, handlerFn) || [];
372
+ const redirectMeta = Reflect.getMetadata(REDIRECT_METADATA, handlerFn);
373
+ const paramMeta = Reflect.getMetadata(ROUTE_PARAMS_METADATA, proto, route.handler) || [];
374
+ const totalParams = Reflect.getMetadata(TOTAL_PARAMS_METADATA, proto, route.handler) ?? 0;
375
+ const methodMiddlewares = handlerFn.middlewares || [];
376
+ const finalHandler = async (c) => {
377
+ const execCtx = createExecutionContext(c, controllerClass, handlerFn);
378
+ const runCore = async () => {
379
+ for (const G of guards) {
380
+ const guard = resolveFromRegistry(G, instanceRegistry);
381
+ const ok = await guard.canActivate(execCtx);
382
+ if (!ok) throw new ForbiddenException();
383
+ }
384
+ const callHandler = async () => {
385
+ let result;
386
+ if (paramMeta.length > 0) {
387
+ const args = await resolveParamArgs(paramMeta, c, totalParams);
388
+ result = await handlerFn.call(controller, ...args);
389
+ } else {
390
+ result = await handlerFn.call(controller, c);
391
+ }
392
+ for (const { name, value } of headersToSet) {
393
+ c.header(name, value);
394
+ }
395
+ if (redirectMeta) {
396
+ const url = result && typeof result === "object" && "url" in result ? result.url : redirectMeta.url;
397
+ const code = result && typeof result === "object" && "statusCode" in result ? result.statusCode : redirectMeta.statusCode;
398
+ return c.redirect(url, code);
399
+ }
400
+ if (result instanceof Response) return result;
401
+ if (result !== void 0 && result !== null) {
402
+ return c.json(result, httpCode ?? 200);
403
+ }
404
+ return new Response(null, { status: httpCode ?? 204 });
405
+ };
406
+ if (methodMiddlewares.length > 0) {
407
+ let idx = 0;
408
+ const next = async () => {
409
+ if (idx < methodMiddlewares.length) {
410
+ return await methodMiddlewares[idx++](c, next);
411
+ }
412
+ return callHandler();
413
+ };
414
+ return await next();
415
+ }
416
+ return callHandler();
417
+ };
418
+ const runWithInterceptors = async () => {
419
+ if (interceptors.length === 0) return runCore();
420
+ let chain = runCore;
421
+ for (let i = interceptors.length - 1; i >= 0; i--) {
422
+ const interceptor = resolveFromRegistry(interceptors[i], instanceRegistry);
423
+ const inner = chain;
424
+ chain = () => interceptor.intercept(execCtx, { handle: inner });
425
+ }
426
+ return chain();
427
+ };
428
+ if (filters.length === 0) return runWithInterceptors();
429
+ try {
430
+ return await runWithInterceptors();
431
+ } catch (err) {
432
+ for (const F of filters) {
433
+ const filter = resolveFromRegistry(F, instanceRegistry);
434
+ const catchTypes = Reflect.getMetadata(CATCH_METADATA, filter.constructor ?? F) || [];
435
+ if (catchTypes.length === 0 || catchTypes.some((T) => err instanceof T)) {
436
+ const host = createArgumentsHost(c);
437
+ const res = await filter.catch(err, host);
438
+ if (res instanceof Response) return res;
439
+ }
440
+ }
441
+ throw err;
442
+ }
443
+ };
444
+ switch (route.method) {
445
+ case "GET":
446
+ router.get(fullPath, finalHandler);
447
+ break;
448
+ case "POST":
449
+ router.post(fullPath, finalHandler);
450
+ break;
451
+ case "PUT":
452
+ router.put(fullPath, finalHandler);
453
+ break;
454
+ case "DELETE":
455
+ router.delete(fullPath, finalHandler);
456
+ break;
457
+ case "PATCH":
458
+ router.patch(fullPath, finalHandler);
459
+ break;
460
+ }
461
+ }
462
+ }
463
+
464
+ // src/decorators/http/route-mapping.decorator.ts
465
+ function createMethodDecorator(method) {
466
+ return (path = "") => (target, propertyKey, descriptor) => {
467
+ if (!target.constructor.prototype.routes) {
468
+ target.constructor.prototype.routes = [];
469
+ }
470
+ target.constructor.prototype.routes.push({
471
+ method,
472
+ path,
473
+ handler: propertyKey
474
+ });
475
+ return descriptor;
476
+ };
477
+ }
478
+ var Get = createMethodDecorator("GET");
479
+ var Post = createMethodDecorator("POST");
480
+ var Put = createMethodDecorator("PUT");
481
+ var Delete = createMethodDecorator("DELETE");
482
+ var Patch = createMethodDecorator("PATCH");
483
+
484
+ // src/decorators/modules/module.decorator.ts
485
+ import { injectable as injectable3 } from "tsyringe";
486
+ function Module(config) {
487
+ return (target) => {
488
+ target.prototype.moduleConfig = config;
489
+ if (config.providers) {
490
+ config.providers.forEach((ProviderClass) => {
491
+ if (ProviderClass && typeof ProviderClass === "function") {
492
+ injectable3()(ProviderClass);
493
+ }
494
+ });
495
+ }
496
+ };
497
+ }
498
+
499
+ // src/decorators/modules/global.decorator.ts
500
+ var GLOBAL_MODULE_METADATA = "wilt:global";
501
+ function Global() {
502
+ return (target) => {
503
+ Reflect.defineMetadata(GLOBAL_MODULE_METADATA, true, target);
504
+ return target;
505
+ };
506
+ }
507
+
508
+ // src/injector/module.factory.ts
509
+ import { Hono } from "hono";
510
+
511
+ // src/injector/module-compiler.ts
512
+ function collectModuleTree(moduleClass, visiting, visited, controllers, providers, globalProviders = []) {
513
+ if (visited.has(moduleClass)) return;
514
+ visiting.add(moduleClass);
515
+ const instance = new moduleClass();
516
+ const config = instance.moduleConfig || {};
517
+ const isGlobal = Reflect.getMetadata(GLOBAL_MODULE_METADATA, moduleClass) === true;
518
+ for (const c of config.controllers ?? []) {
519
+ if (!controllers.includes(c)) controllers.push(c);
520
+ }
521
+ for (const p of config.providers ?? []) {
522
+ if (!providers.includes(p)) providers.push(p);
523
+ if (isGlobal && !globalProviders.includes(p)) globalProviders.push(p);
524
+ }
525
+ for (const importRef of config.imports ?? []) {
526
+ const isRef = isForwardRef(importRef);
527
+ const ImportedClass = isRef ? importRef.forwardRef() : importRef;
528
+ if (visiting.has(ImportedClass)) {
529
+ if (!isRef) {
530
+ throw new Error(
531
+ `[Wilt DI] Circular module dependency detected: "${moduleClass.name}" imports "${ImportedClass.name}" without forwardRef. Wrap it with forwardRef(() => ${ImportedClass.name}) in "${moduleClass.name}" imports array, and do the same in "${ImportedClass.name}".`
532
+ );
533
+ }
534
+ continue;
535
+ }
536
+ collectModuleTree(ImportedClass, visiting, visited, controllers, providers, globalProviders);
537
+ }
538
+ visiting.delete(moduleClass);
539
+ visited.add(moduleClass);
540
+ }
541
+
542
+ // src/injector/injector.ts
543
+ function createCircularProxy(registry, tokenClass) {
544
+ return new Proxy(
545
+ {},
546
+ {
547
+ get(_target, prop) {
548
+ const instance = registry.get(tokenClass);
549
+ if (!instance) {
550
+ throw new Error(
551
+ `[Wilt DI] Circular dependency proxy for "${tokenClass.name}" was accessed before the real instance was created. Make sure both sides use @Inject(forwardRef(() => ...)).`
552
+ );
553
+ }
554
+ const val = instance[prop];
555
+ return typeof val === "function" ? val.bind(instance) : val;
556
+ },
557
+ set(_target, prop, value) {
558
+ const instance = registry.get(tokenClass);
559
+ if (instance) instance[prop] = value;
560
+ return true;
561
+ }
562
+ }
563
+ );
564
+ }
565
+ function resolveInstance(ProviderClass, instanceRegistry, inProgress) {
566
+ if (instanceRegistry.has(ProviderClass)) {
567
+ return instanceRegistry.get(ProviderClass);
568
+ }
569
+ if (inProgress.has(ProviderClass)) {
570
+ logger.warn(
571
+ `Circular dependency detected for "${ProviderClass.name}". Injecting a lazy proxy \u2014 ensure forwardRef() is used on both sides.`,
572
+ "ModuleFactory"
573
+ );
574
+ return createCircularProxy(instanceRegistry, ProviderClass);
575
+ }
576
+ inProgress.add(ProviderClass);
577
+ const paramTypes = Reflect.getMetadata("design:paramtypes", ProviderClass) || [];
578
+ const customTokens = Reflect.getMetadata(INJECT_CUSTOM_TOKENS_KEY, ProviderClass) || {};
579
+ const optionalIndices = Reflect.getMetadata(OPTIONAL_METADATA, ProviderClass) || [];
580
+ const customIndices = Object.keys(customTokens).map(Number);
581
+ const paramCount = Math.max(
582
+ paramTypes.length,
583
+ customIndices.length > 0 ? Math.max(...customIndices) + 1 : 0
584
+ );
585
+ const deps = Array.from({ length: paramCount }, (_, i) => {
586
+ const customToken = customTokens[i];
587
+ const paramType = paramTypes[i];
588
+ const isOptional = optionalIndices.includes(i);
589
+ let actualClass;
590
+ if (customToken) {
591
+ actualClass = isForwardRef(customToken) ? customToken.forwardRef() : customToken;
592
+ } else {
593
+ actualClass = paramType;
594
+ }
595
+ if (!actualClass || actualClass === Object || actualClass === Function) {
596
+ if (!isOptional) {
597
+ logger.warn(
598
+ `Cannot resolve param[${i}] for "${ProviderClass.name}": no type info. Use @Inject(TheClass) to specify it explicitly.`,
599
+ "ModuleFactory"
600
+ );
601
+ }
602
+ return void 0;
603
+ }
604
+ try {
605
+ return resolveInstance(actualClass, instanceRegistry, inProgress);
606
+ } catch (err) {
607
+ if (isOptional) return void 0;
608
+ throw err;
609
+ }
610
+ });
611
+ const instance = new ProviderClass(...deps);
612
+ instanceRegistry.set(ProviderClass, instance);
613
+ inProgress.delete(ProviderClass);
614
+ logger.debug(`Created instance: ${ProviderClass.name}`, "ModuleFactory");
615
+ return instance;
616
+ }
617
+
618
+ // src/injector/module.factory.ts
619
+ function createModule(moduleClass, { middlewares = [] } = {}) {
620
+ const router = new Hono();
621
+ logger.info(`Creating module: ${moduleClass.name}`, "ModuleFactory");
622
+ middlewares.forEach((middleware) => router.use("*", middleware));
623
+ const controllers = [];
624
+ const providers = [];
625
+ const globalProviders = [];
626
+ collectModuleTree(moduleClass, /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set(), controllers, providers, globalProviders);
627
+ logger.info(
628
+ `Resolved ${providers.length} providers, ${controllers.length} controllers`,
629
+ "ModuleFactory"
630
+ );
631
+ const instanceRegistry = /* @__PURE__ */ new Map();
632
+ const inProgress = /* @__PURE__ */ new Set();
633
+ for (const ProviderClass of globalProviders) {
634
+ resolveInstance(ProviderClass, instanceRegistry, inProgress);
635
+ }
636
+ for (const ProviderClass of providers) {
637
+ resolveInstance(ProviderClass, instanceRegistry, inProgress);
638
+ }
639
+ for (const ControllerClass of controllers) {
640
+ try {
641
+ resolveInstance(ControllerClass, instanceRegistry, inProgress);
642
+ const controller = instanceRegistry.get(ControllerClass);
643
+ const prefix = controller.constructor.prototype.prefix || "";
644
+ registerControllerRoutes(router, controller, prefix, instanceRegistry);
645
+ logger.debug(
646
+ `Registered controller: ${ControllerClass.name} at "${prefix}"`,
647
+ "ModuleFactory"
648
+ );
649
+ } catch (error) {
650
+ logger.error(
651
+ `Failed to create controller "${ControllerClass.name}": ${error}`,
652
+ "ModuleFactory"
653
+ );
654
+ throw error;
655
+ }
656
+ }
657
+ for (const instance of instanceRegistry.values()) {
658
+ if (typeof instance?.onModuleInit === "function") {
659
+ const result = instance.onModuleInit();
660
+ if (result instanceof Promise) {
661
+ result.catch(
662
+ (err) => logger.error(`onModuleInit failed for ${instance.constructor?.name}: ${err}`, "ModuleFactory")
663
+ );
664
+ }
665
+ }
666
+ }
667
+ logger.info(`Module "${moduleClass.name}" created successfully`, "ModuleFactory");
668
+ return router;
669
+ }
670
+
671
+ // src/pipes/validate.pipe.ts
672
+ function Validate(rules) {
673
+ return function(target, propertyKey, descriptor) {
674
+ const originalMethod = descriptor.value;
675
+ descriptor.value = async function(...args) {
676
+ const c = args.find((a) => a != null && typeof a.json === "function" && a.req != null) ?? args[0];
677
+ const body = await c.req.json().catch(() => ({}));
678
+ const errors = [];
679
+ for (const rule of rules) {
680
+ const value = body[rule.field];
681
+ if (rule.required && (value === void 0 || value === null || value === "")) {
682
+ errors.push(`${rule.field} is required`);
683
+ continue;
684
+ }
685
+ if (value === void 0 || value === null) {
686
+ continue;
687
+ }
688
+ if (rule.type) {
689
+ const actualType = Array.isArray(value) ? "array" : typeof value;
690
+ if (actualType !== rule.type) {
691
+ errors.push(`${rule.field} must be of type ${rule.type}`);
692
+ }
693
+ }
694
+ if (rule.type === "string" || typeof value === "string") {
695
+ if (rule.minLength && value.length < rule.minLength) {
696
+ errors.push(`${rule.field} must be at least ${rule.minLength} characters long`);
697
+ }
698
+ if (rule.maxLength && value.length > rule.maxLength) {
699
+ errors.push(`${rule.field} must be at most ${rule.maxLength} characters long`);
700
+ }
701
+ }
702
+ if (rule.pattern && typeof value === "string" && !rule.pattern.test(value)) {
703
+ errors.push(`${rule.field} format is invalid`);
704
+ }
705
+ if (rule.custom && !rule.custom(value)) {
706
+ errors.push(`${rule.field} validation failed`);
707
+ }
708
+ }
709
+ if (errors.length > 0) {
710
+ return c.json(
711
+ {
712
+ success: false,
713
+ error: {
714
+ code: "VALIDATION_ERROR",
715
+ message: "Validation failed",
716
+ details: errors
717
+ },
718
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
719
+ },
720
+ 400
721
+ );
722
+ }
723
+ return originalMethod.call(this, ...args);
724
+ };
725
+ return descriptor;
726
+ };
727
+ }
728
+
729
+ // src/pipes/zod-validate.pipe.ts
730
+ import { z } from "zod";
731
+ function ZodValidate(schema) {
732
+ return function(target, propertyKey, descriptor) {
733
+ const originalMethod = descriptor.value;
734
+ descriptor.value = async function(...args) {
735
+ const c = args.find((a) => a != null && typeof a.json === "function" && a.req != null) ?? args[0];
736
+ try {
737
+ const contentType = c.req.header("content-type") || "";
738
+ let input = {};
739
+ if (contentType.includes("multipart/form-data")) {
740
+ const formData = await c.req.formData();
741
+ formData.forEach((val, key) => {
742
+ input[key] = val;
743
+ });
744
+ } else {
745
+ input = await c.req.json().catch(() => ({}));
746
+ }
747
+ const validatedData = schema.parse(input);
748
+ c.set("validatedData", validatedData);
749
+ return originalMethod.call(this, ...args);
750
+ } catch (error) {
751
+ if (error instanceof z.ZodError) {
752
+ const errors = error.issues.map((err) => ({
753
+ field: err.path.join("."),
754
+ message: err.message,
755
+ code: err.code
756
+ }));
757
+ return c.json(
758
+ {
759
+ success: false,
760
+ error: { code: "VALIDATION_ERROR", message: "Validation failed", details: errors },
761
+ message: errors[0].message ?? "Validation failed",
762
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
763
+ },
764
+ 400
765
+ );
766
+ }
767
+ throw error;
768
+ }
769
+ };
770
+ return descriptor;
771
+ };
772
+ }
773
+
774
+ // src/pipes/zod-query.pipe.ts
775
+ import { z as z2 } from "zod";
776
+ function QueryValidate(schema) {
777
+ return function(target, propertyKey, descriptor) {
778
+ const originalMethod = descriptor.value;
779
+ descriptor.value = async function(...args) {
780
+ const c = args.find((a) => a != null && typeof a.json === "function" && a.req != null) ?? args[0];
781
+ try {
782
+ const queryParams = c.req.query();
783
+ const validatedData = schema.parse(queryParams);
784
+ c.set("validatedQuery", validatedData);
785
+ return originalMethod.call(this, ...args);
786
+ } catch (error) {
787
+ if (error instanceof z2.ZodError) {
788
+ const errors = error.issues.map((err) => ({
789
+ field: err.path.join("."),
790
+ message: err.message,
791
+ code: err.code
792
+ }));
793
+ return c.json(
794
+ {
795
+ success: false,
796
+ error: {
797
+ code: "VALIDATION_ERROR",
798
+ message: "Query validation failed",
799
+ details: errors
800
+ },
801
+ message: errors[0].message ?? "Validation failed",
802
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
803
+ },
804
+ 400
805
+ );
806
+ }
807
+ throw error;
808
+ }
809
+ };
810
+ return descriptor;
811
+ };
812
+ }
813
+
814
+ // src/services/reflector.service.ts
815
+ var Reflector = class {
816
+ get(metadataKey, target) {
817
+ return Reflect.getMetadata(metadataKey, target);
818
+ }
819
+ getAllAndOverride(metadataKey, targets) {
820
+ for (const target of targets) {
821
+ const value = Reflect.getMetadata(metadataKey, target);
822
+ if (value !== void 0) return value;
823
+ }
824
+ return void 0;
825
+ }
826
+ getAllAndMerge(metadataKey, targets) {
827
+ return targets.reduce((acc, target) => {
828
+ const value = Reflect.getMetadata(metadataKey, target);
829
+ if (Array.isArray(value)) return [...acc, ...value];
830
+ return acc;
831
+ }, []);
832
+ }
833
+ };
834
+ Reflector = __decorateClass([
835
+ Injectable()
836
+ ], Reflector);
837
+
838
+ // src/utils/response.util.ts
839
+ var _ResponseUtil = class __ResponseUtil {
840
+ static instance;
841
+ logger = console;
842
+ constructor() {
843
+ }
844
+ // Prevent direct instantiation
845
+ static getInstance() {
846
+ if (!__ResponseUtil.instance) {
847
+ __ResponseUtil.instance = new __ResponseUtil();
848
+ }
849
+ return __ResponseUtil.instance;
850
+ }
851
+ success(c, data, message, status = 200) {
852
+ const response = {
853
+ success: true,
854
+ data,
855
+ message,
856
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
857
+ };
858
+ return c.json(response, status);
859
+ }
860
+ error(c, message, status = 400) {
861
+ const response = {
862
+ success: false,
863
+ error: {
864
+ message
865
+ },
866
+ message,
867
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
868
+ };
869
+ return c.json(response, status);
870
+ }
871
+ paginated(c, data, page, limit, total, message) {
872
+ const totalPages = Math.ceil(total / limit) ?? 1;
873
+ const response = {
874
+ success: true,
875
+ data,
876
+ message,
877
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
878
+ pagination: {
879
+ page,
880
+ limit,
881
+ total,
882
+ totalPages
883
+ }
884
+ };
885
+ return c.json(response);
886
+ }
887
+ };
888
+ var ResponseUtil = _ResponseUtil.getInstance();
889
+
890
+ // src/utils/apply-decorators.util.ts
891
+ function applyDecorators(...decorators) {
892
+ return (target, key, descriptor) => {
893
+ for (const decorator of decorators.reverse()) {
894
+ const result = decorator(target, key, descriptor);
895
+ if (result !== void 0) {
896
+ if (descriptor !== void 0) {
897
+ descriptor = result;
898
+ } else {
899
+ target = result;
900
+ }
901
+ }
902
+ }
903
+ return descriptor ?? target;
904
+ };
905
+ }
906
+ export {
907
+ BadRequestException,
908
+ Body,
909
+ CATCH_METADATA,
910
+ Catch,
911
+ ConflictException,
912
+ Controller,
913
+ Delete,
914
+ FILTERS_METADATA,
915
+ ForbiddenException,
916
+ GLOBAL_MODULE_METADATA,
917
+ GUARDS_METADATA,
918
+ Get,
919
+ Global,
920
+ GoneException,
921
+ HEADER_METADATA,
922
+ HTTP_CODE_METADATA,
923
+ Header,
924
+ Headers,
925
+ HttpCode,
926
+ HttpException,
927
+ INJECT_CUSTOM_TOKENS_KEY,
928
+ INTERCEPTORS_METADATA,
929
+ Inject,
930
+ Injectable,
931
+ InternalServerErrorException,
932
+ Ip,
933
+ MethodNotAllowedException,
934
+ Module,
935
+ NotFoundException,
936
+ NotImplementedException,
937
+ OPTIONAL_METADATA,
938
+ Optional,
939
+ Param,
940
+ Patch,
941
+ Post,
942
+ Put,
943
+ Query,
944
+ QueryValidate,
945
+ REDIRECT_METADATA,
946
+ ROUTE_PARAMS_METADATA,
947
+ Redirect,
948
+ Reflector,
949
+ Req,
950
+ Req as Request,
951
+ ResponseUtil,
952
+ ServiceUnavailableException,
953
+ SetMetadata,
954
+ TOTAL_PARAMS_METADATA,
955
+ TooManyRequestsException,
956
+ UnauthorizedException,
957
+ UnprocessableEntityException,
958
+ UseFilters,
959
+ UseGuards,
960
+ UseInterceptors,
961
+ Validate,
962
+ ZodValidate,
963
+ _ResponseUtil,
964
+ applyDecorators,
965
+ createArgumentsHost,
966
+ createExecutionContext,
967
+ createModule,
968
+ errorHandler,
969
+ forwardRef,
970
+ isForwardRef,
971
+ registerControllerRoutes,
972
+ requestLogger
973
+ };
974
+ //# sourceMappingURL=index.js.map