wynkjs 1.0.3 → 1.0.6

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 (63) hide show
  1. package/README.md +528 -348
  2. package/dist/cors.d.ts +28 -0
  3. package/dist/cors.d.ts.map +1 -0
  4. package/dist/cors.js +121 -0
  5. package/dist/database.d.ts +1 -1
  6. package/dist/database.js +1 -1
  7. package/dist/decorators/exception.advanced.d.ts +286 -18
  8. package/dist/decorators/exception.advanced.d.ts.map +1 -1
  9. package/dist/decorators/exception.advanced.js +410 -17
  10. package/dist/decorators/exception.decorators.d.ts +93 -2
  11. package/dist/decorators/exception.decorators.d.ts.map +1 -1
  12. package/dist/decorators/exception.decorators.js +140 -8
  13. package/dist/decorators/formatter.decorators.d.ts +93 -0
  14. package/dist/decorators/formatter.decorators.d.ts.map +1 -0
  15. package/dist/decorators/formatter.decorators.js +131 -0
  16. package/dist/decorators/guard.decorators.d.ts +2 -2
  17. package/dist/decorators/guard.decorators.d.ts.map +1 -1
  18. package/dist/decorators/guard.decorators.js +11 -5
  19. package/dist/decorators/http.decorators.d.ts +10 -4
  20. package/dist/decorators/http.decorators.d.ts.map +1 -1
  21. package/dist/decorators/http.decorators.js +9 -2
  22. package/dist/decorators/interceptor.advanced.d.ts +9 -9
  23. package/dist/decorators/interceptor.advanced.d.ts.map +1 -1
  24. package/dist/decorators/interceptor.advanced.js +7 -7
  25. package/dist/decorators/interceptor.decorators.d.ts +9 -7
  26. package/dist/decorators/interceptor.decorators.d.ts.map +1 -1
  27. package/dist/decorators/interceptor.decorators.js +29 -18
  28. package/dist/decorators/param.decorators.d.ts +2 -2
  29. package/dist/decorators/param.decorators.js +1 -1
  30. package/dist/decorators/pipe.decorators.d.ts +4 -4
  31. package/dist/decorators/pipe.decorators.d.ts.map +1 -1
  32. package/dist/decorators/pipe.decorators.js +4 -4
  33. package/dist/dto.js +1 -1
  34. package/dist/factory.d.ts +30 -2
  35. package/dist/factory.d.ts.map +1 -1
  36. package/dist/factory.js +210 -186
  37. package/dist/filters/exception.filters.d.ts +124 -0
  38. package/dist/filters/exception.filters.d.ts.map +1 -0
  39. package/dist/filters/exception.filters.js +208 -0
  40. package/dist/global-prefix.d.ts +49 -0
  41. package/dist/global-prefix.d.ts.map +1 -0
  42. package/dist/global-prefix.js +155 -0
  43. package/dist/index.d.ts +7 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +6 -1
  46. package/dist/interfaces/interceptor.interface.d.ts +15 -0
  47. package/dist/interfaces/interceptor.interface.d.ts.map +1 -0
  48. package/dist/interfaces/interceptor.interface.js +1 -0
  49. package/dist/optimized-handler.d.ts +31 -0
  50. package/dist/optimized-handler.d.ts.map +1 -0
  51. package/dist/optimized-handler.js +180 -0
  52. package/dist/pipes/validation.pipe.d.ts +12 -12
  53. package/dist/pipes/validation.pipe.d.ts.map +1 -1
  54. package/dist/pipes/validation.pipe.js +43 -15
  55. package/dist/schema-registry.d.ts +51 -0
  56. package/dist/schema-registry.d.ts.map +1 -0
  57. package/dist/schema-registry.js +134 -0
  58. package/dist/testing/index.d.ts +2 -2
  59. package/dist/testing/index.js +2 -2
  60. package/dist/ultra-optimized-handler.d.ts +51 -0
  61. package/dist/ultra-optimized-handler.d.ts.map +1 -0
  62. package/dist/ultra-optimized-handler.js +302 -0
  63. package/package.json +17 -10
@@ -13,7 +13,7 @@ import "reflect-metadata";
13
13
  * export class HttpWynkExceptionFilter implements WynkExceptionFilter {}
14
14
  *
15
15
  * @Catch() // Catches all exceptions
16
- * export class AllExceptionsFilter implements WynkExceptionFilter {}
16
+ * export class AllExceptions implements WynkExceptionFilter {}
17
17
  */
18
18
  export function Catch(...exceptions) {
19
19
  return (target) => {
@@ -63,6 +63,9 @@ export class HttpException extends Error {
63
63
  this.error = error;
64
64
  this.name = "HttpException";
65
65
  }
66
+ get status() {
67
+ return this.statusCode;
68
+ }
66
69
  getStatus() {
67
70
  return this.statusCode;
68
71
  }
@@ -179,13 +182,27 @@ export async function executeExceptionFilters(filters, exception, context) {
179
182
  // Check if filter handles this exception type
180
183
  const catchTypes = Reflect.getMetadata("catch:exceptions", filterInstance.constructor);
181
184
  if (!catchTypes || catchTypes.length === 0) {
182
- // Catches all exceptions
183
- return filterInstance.catch(exception, context);
185
+ // Catches all exceptions - try it
186
+ try {
187
+ return await filterInstance.catch(exception, context);
188
+ }
189
+ catch (err) {
190
+ // Filter didn't handle it, try next filter
191
+ exception = err;
192
+ continue;
193
+ }
184
194
  }
185
195
  // Check if exception matches any of the catch types
186
196
  for (const catchType of catchTypes) {
187
197
  if (exception instanceof catchType) {
188
- return filterInstance.catch(exception, context);
198
+ try {
199
+ return await filterInstance.catch(exception, context);
200
+ }
201
+ catch (err) {
202
+ // Filter didn't handle it, try next filter
203
+ exception = err;
204
+ continue;
205
+ }
189
206
  }
190
207
  }
191
208
  }
@@ -216,7 +233,7 @@ export { HttpWynkExceptionFilter };
216
233
  /**
217
234
  * All exceptions filter - catches everything
218
235
  */
219
- let AllExceptionsFilter = class AllExceptionsFilter {
236
+ let AllExceptions = class AllExceptions {
220
237
  catch(exception, context) {
221
238
  const response = context.getResponse();
222
239
  if (exception instanceof HttpException) {
@@ -236,7 +253,122 @@ let AllExceptionsFilter = class AllExceptionsFilter {
236
253
  };
237
254
  }
238
255
  };
239
- AllExceptionsFilter = __decorate([
256
+ AllExceptions = __decorate([
240
257
  Catch()
241
- ], AllExceptionsFilter);
242
- export { AllExceptionsFilter };
258
+ ], AllExceptions);
259
+ export { AllExceptions };
260
+ /**
261
+ * Authentication Exception Filter - Handles auth errors
262
+ *
263
+ * ⚠️ IMPORTANT: This catches ALL UnauthorizedException instances!
264
+ * Use on specific routes/controllers, not globally.
265
+ *
266
+ * @example
267
+ * // ✅ GOOD: Use on auth-protected controller
268
+ * @UseFilters(AuthenticationExceptionFilter)
269
+ * @Controller('/auth')
270
+ * export class AuthController {
271
+ * @Post('/login')
272
+ * async login() {
273
+ * throw new UnauthorizedException('Invalid credentials');
274
+ * }
275
+ * }
276
+ */
277
+ export class AuthenticationException {
278
+ catch(exception, context) {
279
+ const response = context.getResponse();
280
+ const request = context.getRequest();
281
+ return {
282
+ statusCode: exception.statusCode,
283
+ error: "Authentication Failed",
284
+ message: exception.message || "Invalid credentials",
285
+ timestamp: new Date().toISOString(),
286
+ path: request.url,
287
+ hint: "Please check your authentication token or credentials",
288
+ };
289
+ }
290
+ }
291
+ /**
292
+ * Authorization Exception Filter - Handles permission errors
293
+ *
294
+ * ⚠️ IMPORTANT: This catches ALL ForbiddenException instances!
295
+ * Use on specific routes/controllers, not globally.
296
+ *
297
+ * @example
298
+ * // ✅ GOOD: Use on admin-only controller
299
+ * @UseFilters(AuthorizationExceptionFilter)
300
+ * @Controller('/admin')
301
+ * export class AdminController {
302
+ * @Get('/users')
303
+ * async getAllUsers() {
304
+ * throw new ForbiddenException('Admin access required');
305
+ * }
306
+ * }
307
+ */
308
+ export class AuthorizationException {
309
+ catch(exception, context) {
310
+ const response = context.getResponse();
311
+ const request = context.getRequest();
312
+ return {
313
+ statusCode: exception.statusCode,
314
+ error: "Authorization Failed",
315
+ message: exception.message ||
316
+ "You don't have permission to access this resource",
317
+ timestamp: new Date().toISOString(),
318
+ path: request.url,
319
+ requiredPermissions: exception.requiredPermissions || [],
320
+ };
321
+ }
322
+ }
323
+ /**
324
+ * Rate Limit Exception Filter - Handles rate limit errors
325
+ * @example
326
+ * @UseFilters(RateLimitExceptionFilter)
327
+ * @Post()
328
+ * async create() {}
329
+ */
330
+ export class RateLimitException {
331
+ catch(exception, context) {
332
+ const response = context.getResponse();
333
+ const request = context.getRequest();
334
+ // Don't catch HttpException or its subclasses
335
+ if (exception instanceof HttpException) {
336
+ throw exception;
337
+ }
338
+ return {
339
+ statusCode: 429,
340
+ error: "Too Many Requests",
341
+ message: exception.message || "Rate limit exceeded",
342
+ timestamp: new Date().toISOString(),
343
+ path: request.url,
344
+ retryAfter: exception.retryAfter || 60,
345
+ hint: "Please wait before making another request",
346
+ };
347
+ }
348
+ }
349
+ /**
350
+ * Business Logic Exception Filter - Handles business rule violations
351
+ * @example
352
+ * @UseFilters(BusinessLogicExceptionFilter)
353
+ * @Post('/transfer')
354
+ * async transfer(@Body() data: any) {}
355
+ */
356
+ export class BusinessLogicException {
357
+ catch(exception, context) {
358
+ const response = context.getResponse();
359
+ const request = context.getRequest();
360
+ // Don't catch HttpException or its subclasses
361
+ if (exception instanceof HttpException) {
362
+ throw exception;
363
+ }
364
+ return {
365
+ statusCode: exception.statusCode || 422,
366
+ error: "Business Rule Violation",
367
+ message: exception.message || "Business logic constraint violated",
368
+ timestamp: new Date().toISOString(),
369
+ path: request.url,
370
+ rule: exception.rule || "unknown",
371
+ details: exception.details || {},
372
+ };
373
+ }
374
+ }
@@ -0,0 +1,93 @@
1
+ import "reflect-metadata";
2
+ /**
3
+ * Error Formatter Interface
4
+ * Used by WynkFactory to format validation errors
5
+ *
6
+ * IMPORTANT: These formatters are passed to WynkFactory.create(), NOT to useGlobalFilters()!
7
+ *
8
+ * @example
9
+ * // CORRECT usage:
10
+ * const app = WynkFactory.create({
11
+ * controllers: [UserController],
12
+ * validationErrorFormatter: new FormatErrorFormatter(), // ✅ Pass here
13
+ * });
14
+ *
15
+ * // WRONG usage:
16
+ * app.useGlobalFilters(
17
+ * new FormatErrorFormatter() // ❌ This is not a filter!
18
+ * );
19
+ */
20
+ export interface ErrorFormatter {
21
+ format(validationError: any): any;
22
+ }
23
+ /**
24
+ * FormatErrorFormatter - Formats as { field: [messages] } object structure
25
+ *
26
+ * Output example:
27
+ * {
28
+ * "statusCode": 400,
29
+ * "message": "Validation failed",
30
+ * "errors": {
31
+ * "email": ["Invalid email address"],
32
+ * "age": ["Must be at least 18"]
33
+ * }
34
+ * }
35
+ *
36
+ * @example
37
+ * const app = WynkFactory.create({
38
+ * controllers: [UserController],
39
+ * validationErrorFormatter: new FormatErrorFormatter(),
40
+ * });
41
+ */
42
+ export declare class FormatErrorFormatter implements ErrorFormatter {
43
+ format(error: any): any;
44
+ }
45
+ /**
46
+ * SimpleErrorFormatter - Formats as simple array of messages
47
+ *
48
+ * Output example:
49
+ * {
50
+ * "statusCode": 400,
51
+ * "message": "Validation failed",
52
+ * "errors": [
53
+ * "Invalid email address",
54
+ * "Must be at least 18"
55
+ * ]
56
+ * }
57
+ *
58
+ * @example
59
+ * const app = WynkFactory.create({
60
+ * controllers: [UserController],
61
+ * validationErrorFormatter: new SimpleErrorFormatter(),
62
+ * });
63
+ */
64
+ export declare class SimpleErrorFormatter implements ErrorFormatter {
65
+ format(error: any): any;
66
+ }
67
+ /**
68
+ * DetailedErrorFormatter - Formats with detailed field info
69
+ *
70
+ * Output example:
71
+ * {
72
+ * "statusCode": 400,
73
+ * "message": "Validation failed",
74
+ * "errors": [
75
+ * {
76
+ * "field": "email",
77
+ * "message": "Invalid email address",
78
+ * "value": "invalid-email",
79
+ * "expected": {...schema...}
80
+ * }
81
+ * ]
82
+ * }
83
+ *
84
+ * @example
85
+ * const app = WynkFactory.create({
86
+ * controllers: [UserController],
87
+ * validationErrorFormatter: new DetailedErrorFormatter(),
88
+ * });
89
+ */
90
+ export declare class DetailedErrorFormatter implements ErrorFormatter {
91
+ format(error: any): any;
92
+ }
93
+ //# sourceMappingURL=formatter.decorators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.decorators.d.ts","sourceRoot":"","sources":["../../core/decorators/formatter.decorators.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,eAAe,EAAE,GAAG,GAAG,GAAG,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,oBAAqB,YAAW,cAAc;IACzD,MAAM,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG;CAsBxB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,oBAAqB,YAAW,cAAc;IACzD,MAAM,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG;CAiBxB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,sBAAuB,YAAW,cAAc;IAC3D,MAAM,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG;CAgCxB"}
@@ -0,0 +1,131 @@
1
+ import "reflect-metadata";
2
+ /**
3
+ * FormatErrorFormatter - Formats as { field: [messages] } object structure
4
+ *
5
+ * Output example:
6
+ * {
7
+ * "statusCode": 400,
8
+ * "message": "Validation failed",
9
+ * "errors": {
10
+ * "email": ["Invalid email address"],
11
+ * "age": ["Must be at least 18"]
12
+ * }
13
+ * }
14
+ *
15
+ * @example
16
+ * const app = WynkFactory.create({
17
+ * controllers: [UserController],
18
+ * validationErrorFormatter: new FormatErrorFormatter(),
19
+ * });
20
+ */
21
+ export class FormatErrorFormatter {
22
+ format(error) {
23
+ const formattedErrors = {};
24
+ if (error.errors && error.errors.length > 0) {
25
+ error.errors.forEach((err) => {
26
+ const field = err.path?.replace(/^\//, "") || "unknown";
27
+ if (!formattedErrors[field]) {
28
+ formattedErrors[field] = [];
29
+ }
30
+ formattedErrors[field].push(err.summary || err.message);
31
+ });
32
+ }
33
+ else {
34
+ const field = error.property?.replace(/^\//, "") || "unknown";
35
+ formattedErrors[field] = [error.summary || error.message];
36
+ }
37
+ return {
38
+ statusCode: 400,
39
+ message: "Validation failed",
40
+ errors: formattedErrors,
41
+ };
42
+ }
43
+ }
44
+ /**
45
+ * SimpleErrorFormatter - Formats as simple array of messages
46
+ *
47
+ * Output example:
48
+ * {
49
+ * "statusCode": 400,
50
+ * "message": "Validation failed",
51
+ * "errors": [
52
+ * "Invalid email address",
53
+ * "Must be at least 18"
54
+ * ]
55
+ * }
56
+ *
57
+ * @example
58
+ * const app = WynkFactory.create({
59
+ * controllers: [UserController],
60
+ * validationErrorFormatter: new SimpleErrorFormatter(),
61
+ * });
62
+ */
63
+ export class SimpleErrorFormatter {
64
+ format(error) {
65
+ const messages = [];
66
+ if (error.errors && error.errors.length > 0) {
67
+ error.errors.forEach((err) => {
68
+ messages.push(err.summary || err.message);
69
+ });
70
+ }
71
+ else {
72
+ messages.push(error.summary || error.message);
73
+ }
74
+ return {
75
+ statusCode: 400,
76
+ message: "Validation failed",
77
+ errors: messages,
78
+ };
79
+ }
80
+ }
81
+ /**
82
+ * DetailedErrorFormatter - Formats with detailed field info
83
+ *
84
+ * Output example:
85
+ * {
86
+ * "statusCode": 400,
87
+ * "message": "Validation failed",
88
+ * "errors": [
89
+ * {
90
+ * "field": "email",
91
+ * "message": "Invalid email address",
92
+ * "value": "invalid-email",
93
+ * "expected": {...schema...}
94
+ * }
95
+ * ]
96
+ * }
97
+ *
98
+ * @example
99
+ * const app = WynkFactory.create({
100
+ * controllers: [UserController],
101
+ * validationErrorFormatter: new DetailedErrorFormatter(),
102
+ * });
103
+ */
104
+ export class DetailedErrorFormatter {
105
+ format(error) {
106
+ const errors = [];
107
+ if (error.errors && error.errors.length > 0) {
108
+ error.errors.forEach((err) => {
109
+ errors.push({
110
+ field: err.path?.replace(/^\//, "") || "unknown",
111
+ message: err.summary || err.message,
112
+ value: err.value,
113
+ expected: err.schema,
114
+ });
115
+ });
116
+ }
117
+ else {
118
+ errors.push({
119
+ field: error.property?.replace(/^\//, "") || "unknown",
120
+ message: error.summary || error.message,
121
+ value: error.found,
122
+ expected: error.expected,
123
+ });
124
+ }
125
+ return {
126
+ statusCode: 400,
127
+ message: "Validation failed",
128
+ errors,
129
+ };
130
+ }
131
+ }
@@ -1,7 +1,7 @@
1
1
  import "reflect-metadata";
2
2
  /**
3
- * Guard Decorators and Interfaces for ElysiaJS Framework
4
- * Similar to NestJS guards for route protection
3
+ * Guard Decorators and Interfaces for WynkJS Framework
4
+ * Guards for route protection and authorization
5
5
  */
6
6
  /**
7
7
  * Execution context interface - provides access to request details
@@ -1 +1 @@
1
- {"version":3,"file":"guard.decorators.d.ts","sourceRoot":"","sources":["../../core/decorators/guard.decorators.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IACzB,WAAW,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IAC1B,UAAU,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IACzB,UAAU,IAAI,QAAQ,CAAC;IACvB,QAAQ,IAAI,GAAG,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,GAAG,MAAM,EAAE,CAAC,QAAQ,GAAG,WAAW,CAAC,EAAE,GACpC,eAAe,GAAG,cAAc,CAwBlC;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,QAAQ,EACjB,eAAe,EAAE,GAAG,GACnB,gBAAgB,CAQlB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,CAAC,QAAQ,GAAG,WAAW,CAAC,EAAE,EAClC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,OAAO,CAAC,CAyBlB"}
1
+ {"version":3,"file":"guard.decorators.d.ts","sourceRoot":"","sources":["../../core/decorators/guard.decorators.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IACzB,WAAW,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IAC1B,UAAU,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IACzB,UAAU,IAAI,QAAQ,CAAC;IACvB,QAAQ,IAAI,GAAG,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,GAAG,MAAM,EAAE,CAAC,QAAQ,GAAG,WAAW,CAAC,EAAE,GACpC,eAAe,GAAG,cAAc,CAwBlC;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,QAAQ,EACjB,eAAe,EAAE,GAAG,GACnB,gBAAgB,CAQlB;AAOD;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,CAAC,QAAQ,GAAG,WAAW,CAAC,EAAE,EAClC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,OAAO,CAAC,CA8BlB"}
@@ -39,6 +39,10 @@ export function createExecutionContext(ctx, handler, controllerClass) {
39
39
  getClass: () => controllerClass,
40
40
  };
41
41
  }
42
+ /**
43
+ * Guard instance cache for singleton pattern
44
+ */
45
+ const guardInstanceCache = new Map();
42
46
  /**
43
47
  * Helper function to execute guards
44
48
  */
@@ -46,14 +50,16 @@ export async function executeGuards(guards, context) {
46
50
  for (const guard of guards) {
47
51
  let result;
48
52
  if (typeof guard === "function") {
49
- // Guard is a class, instantiate it
50
- const guardInstance = new guard();
51
- if (guardInstance.canActivate) {
52
- result = await guardInstance.canActivate(context);
53
+ // Guard is a class, get or create singleton instance
54
+ let guardInstance = guardInstanceCache.get(guard);
55
+ if (!guardInstance) {
56
+ guardInstance = new guard();
57
+ guardInstanceCache.set(guard, guardInstance);
53
58
  }
54
- else {
59
+ if (!guardInstance.canActivate) {
55
60
  throw new Error(`Guard ${guard.name} must implement CanActivate interface`);
56
61
  }
62
+ result = await guardInstance.canActivate(context);
57
63
  }
58
64
  else {
59
65
  // Guard is already an instance
@@ -1,7 +1,8 @@
1
1
  import "reflect-metadata";
2
2
  /**
3
- * HTTP Method Decorators for ElysiaJS Framework
4
- * Inspired by NestJS but optimized for Elysia's performance
3
+ * HTTP Method Decorators for WynkJS Framework
4
+ * RESTful route handlers with TypeScript decorators
5
+ * Optimized for WynkJS's performance on Bun runtime
5
6
  */
6
7
  export interface RouteOptions {
7
8
  path?: string;
@@ -13,12 +14,17 @@ export interface RouteOptions {
13
14
  }
14
15
  /**
15
16
  * Controller decorator - Defines a controller with a base path
16
- * @param path Base path for all routes in this controller
17
+ * @param pathOrOptions Base path string or options object with path
17
18
  * @example
18
19
  * @Controller('/users')
19
20
  * export class UserController {}
21
+ *
22
+ * @Controller({ path: '/users' })
23
+ * export class UserController {}
20
24
  */
21
- export declare function Controller(path?: string): ClassDecorator;
25
+ export declare function Controller(pathOrOptions?: string | {
26
+ path?: string;
27
+ }): ClassDecorator;
22
28
  /**
23
29
  * HTTP GET decorator
24
30
  * @param pathOrOptions Route path or options with DTO
@@ -1 +1 @@
1
- {"version":3,"file":"http.decorators.d.ts","sourceRoot":"","sources":["../../core/decorators/http.decorators.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,QAAQ,CAAC,EAAE,GAAG,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,MAAW,GAAG,cAAc,CAK5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,GAAG,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM1E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,IAAI,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,GAAG,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM1E;AAED;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM5E;AAED;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM7E;AAED;;;GAGG;AACH,wBAAgB,OAAO,CACrB,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GACpC,eAAe,CAMjB;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM3E;AAmDD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAStD;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAYnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,UAAU,GAAE,MAAY,GACvB,eAAe,CAcjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,GAAG,CAAC,GAAG,WAAW,EAAE,GAAG,EAAE,GAAG,cAAc,GAAG,eAAe,CAuB3E"}
1
+ {"version":3,"file":"http.decorators.d.ts","sourceRoot":"","sources":["../../core/decorators/http.decorators.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B;;;;GAIG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,QAAQ,CAAC,EAAE,GAAG,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACxB,aAAa,CAAC,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACzC,cAAc,CAWhB;AAED;;;;;;;;;GASG;AACH,wBAAgB,GAAG,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM1E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,IAAI,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,GAAG,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM1E;AAED;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM5E;AAED;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM7E;AAED;;;GAGG;AACH,wBAAgB,OAAO,CACrB,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GACpC,eAAe,CAMjB;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,CAM3E;AAmDD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAStD;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAYnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,UAAU,GAAE,MAAY,GACvB,eAAe,CAcjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,GAAG,CAAC,GAAG,WAAW,EAAE,GAAG,EAAE,GAAG,cAAc,GAAG,eAAe,CAuB3E"}
@@ -1,13 +1,20 @@
1
1
  import "reflect-metadata";
2
2
  /**
3
3
  * Controller decorator - Defines a controller with a base path
4
- * @param path Base path for all routes in this controller
4
+ * @param pathOrOptions Base path string or options object with path
5
5
  * @example
6
6
  * @Controller('/users')
7
7
  * export class UserController {}
8
+ *
9
+ * @Controller({ path: '/users' })
10
+ * export class UserController {}
8
11
  */
9
- export function Controller(path = "") {
12
+ export function Controller(pathOrOptions) {
10
13
  return (target) => {
14
+ // Handle both string and object formats
15
+ const path = typeof pathOrOptions === "string"
16
+ ? pathOrOptions
17
+ : pathOrOptions?.path || "";
11
18
  Reflect.defineMetadata("basePath", path, target);
12
19
  Reflect.defineMetadata("routes", [], target);
13
20
  };
@@ -1,6 +1,6 @@
1
1
  import "reflect-metadata";
2
- import { WynkInterceptor, CallHandler } from "./interceptor.decorators";
3
- import { ExecutionContext } from "./guard.decorators";
2
+ import { WynkInterceptor } from "./interceptor.decorators";
3
+ import { InterceptorContext } from "../interfaces/interceptor.interface";
4
4
  /**
5
5
  * Advanced Interceptors for WynkJS Framework
6
6
  * Additional interceptors for common use cases
@@ -13,7 +13,7 @@ import { ExecutionContext } from "./guard.decorators";
13
13
  * export class ApiController {}
14
14
  */
15
15
  export declare class ResponseInterceptor implements WynkInterceptor {
16
- intercept(context: ExecutionContext, next: CallHandler): Promise<any>;
16
+ intercept(context: InterceptorContext, next: () => Promise<any>): Promise<any>;
17
17
  }
18
18
  /**
19
19
  * Error Handling Interceptor - Catches and transforms errors
@@ -23,7 +23,7 @@ export declare class ResponseInterceptor implements WynkInterceptor {
23
23
  * async getData() {}
24
24
  */
25
25
  export declare class ErrorHandlingInterceptor implements WynkInterceptor {
26
- intercept(context: ExecutionContext, next: CallHandler): Promise<any>;
26
+ intercept(context: InterceptorContext, next: () => Promise<any>): Promise<any>;
27
27
  }
28
28
  /**
29
29
  * Compression Interceptor - Simulates response compression metadata
@@ -35,7 +35,7 @@ export declare class ErrorHandlingInterceptor implements WynkInterceptor {
35
35
  export declare class CompressionInterceptor implements WynkInterceptor {
36
36
  private threshold;
37
37
  constructor(threshold?: number);
38
- intercept(context: ExecutionContext, next: CallHandler): Promise<any>;
38
+ intercept(context: InterceptorContext, next: () => Promise<any>): Promise<any>;
39
39
  }
40
40
  /**
41
41
  * Rate Limit Interceptor - Basic rate limiting
@@ -49,7 +49,7 @@ export declare class RateLimitInterceptor implements WynkInterceptor {
49
49
  private windowMs;
50
50
  private requests;
51
51
  constructor(maxRequests?: number, windowMs?: number);
52
- intercept(context: ExecutionContext, next: CallHandler): Promise<any>;
52
+ intercept(context: InterceptorContext, next: () => Promise<any>): Promise<any>;
53
53
  }
54
54
  /**
55
55
  * CORS Interceptor - Add CORS headers to responses
@@ -65,7 +65,7 @@ export declare class CorsInterceptor implements WynkInterceptor {
65
65
  methods?: string[];
66
66
  credentials?: boolean;
67
67
  });
68
- intercept(context: ExecutionContext, next: CallHandler): Promise<any>;
68
+ intercept(context: InterceptorContext, next: () => Promise<any>): Promise<any>;
69
69
  }
70
70
  /**
71
71
  * Sanitize Interceptor - Sanitizes response data
@@ -77,7 +77,7 @@ export declare class CorsInterceptor implements WynkInterceptor {
77
77
  export declare class SanitizeInterceptor implements WynkInterceptor {
78
78
  private fieldsToRemove;
79
79
  constructor(fieldsToRemove?: string[]);
80
- intercept(context: ExecutionContext, next: CallHandler): Promise<any>;
80
+ intercept(context: InterceptorContext, next: () => Promise<any>): Promise<any>;
81
81
  private sanitize;
82
82
  }
83
83
  /**
@@ -88,6 +88,6 @@ export declare class SanitizeInterceptor implements WynkInterceptor {
88
88
  * async getUsers(@Query('page') page: number, @Query('limit') limit: number) {}
89
89
  */
90
90
  export declare class PaginationInterceptor implements WynkInterceptor {
91
- intercept(context: ExecutionContext, next: CallHandler): Promise<any>;
91
+ intercept(context: InterceptorContext, next: () => Promise<any>): Promise<any>;
92
92
  }
93
93
  //# sourceMappingURL=interceptor.advanced.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interceptor.advanced.d.ts","sourceRoot":"","sources":["../../core/decorators/interceptor.advanced.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;GAGG;AAEH;;;;;;GAMG;AACH,qBAAa,mBAAoB,YAAW,eAAe;IACnD,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;CAsC5E;AAED;;;;;;GAMG;AACH,qBAAa,wBAAyB,YAAW,eAAe;IACxD,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;CAkB5E;AAED;;;;;;GAMG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IAChD,OAAO,CAAC,SAAS;gBAAT,SAAS,GAAE,MAAa;IAEtC,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;CAa5E;AAED;;;;;;GAMG;AACH,qBAAa,oBAAqB,YAAW,eAAe;IAIxD,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,QAAQ;IAJlB,OAAO,CAAC,QAAQ,CAAoC;gBAG1C,WAAW,GAAE,MAAY,EACzB,QAAQ,GAAE,MAAc;IAG5B,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;CA0B5E;AAED;;;;;;GAMG;AACH,qBAAa,eAAgB,YAAW,eAAe;IAEnD,OAAO,CAAC,OAAO;gBAAP,OAAO,GAAE;QACf,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,WAAW,CAAC,EAAE,OAAO,CAAC;KAClB;IAGF,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;CA8B5E;AAED;;;;;;GAMG;AACH,qBAAa,mBAAoB,YAAW,eAAe;IACzD,OAAO,CAAC,cAAc,CAAW;gBAErB,cAAc,GAAE,MAAM,EAAoC;IAIhE,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;IAK3E,OAAO,CAAC,QAAQ;CAmBjB;AAED;;;;;;GAMG;AACH,qBAAa,qBAAsB,YAAW,eAAe;IACrD,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;CA2B5E"}
1
+ {"version":3,"file":"interceptor.advanced.d.ts","sourceRoot":"","sources":["../../core/decorators/interceptor.advanced.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAEzE;;;GAGG;AAEH;;;;;;GAMG;AACH,qBAAa,mBAAoB,YAAW,eAAe;IACnD,SAAS,CACb,OAAO,EAAE,kBAAkB,EAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACvB,OAAO,CAAC,GAAG,CAAC;CAsChB;AAED;;;;;;GAMG;AACH,qBAAa,wBAAyB,YAAW,eAAe;IACxD,SAAS,CACb,OAAO,EAAE,kBAAkB,EAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACvB,OAAO,CAAC,GAAG,CAAC;CAoBhB;AAED;;;;;;GAMG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IAChD,OAAO,CAAC,SAAS;gBAAT,SAAS,GAAE,MAAa;IAEtC,SAAS,CACb,OAAO,EAAE,kBAAkB,EAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACvB,OAAO,CAAC,GAAG,CAAC;CAahB;AAED;;;;;;GAMG;AACH,qBAAa,oBAAqB,YAAW,eAAe;IAIxD,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,QAAQ;IAJlB,OAAO,CAAC,QAAQ,CAAoC;gBAG1C,WAAW,GAAE,MAAY,EACzB,QAAQ,GAAE,MAAc;IAG5B,SAAS,CACb,OAAO,EAAE,kBAAkB,EAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACvB,OAAO,CAAC,GAAG,CAAC;CA0BhB;AAED;;;;;;GAMG;AACH,qBAAa,eAAgB,YAAW,eAAe;IAEnD,OAAO,CAAC,OAAO;gBAAP,OAAO,GAAE;QACf,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,WAAW,CAAC,EAAE,OAAO,CAAC;KAClB;IAGF,SAAS,CACb,OAAO,EAAE,kBAAkB,EAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACvB,OAAO,CAAC,GAAG,CAAC;CA8BhB;AAED;;;;;;GAMG;AACH,qBAAa,mBAAoB,YAAW,eAAe;IACzD,OAAO,CAAC,cAAc,CAAW;gBAErB,cAAc,GAAE,MAAM,EAAoC;IAIhE,SAAS,CACb,OAAO,EAAE,kBAAkB,EAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACvB,OAAO,CAAC,GAAG,CAAC;IAKf,OAAO,CAAC,QAAQ;CAmBjB;AAED;;;;;;GAMG;AACH,qBAAa,qBAAsB,YAAW,eAAe;IACrD,SAAS,CACb,OAAO,EAAE,kBAAkB,EAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACvB,OAAO,CAAC,GAAG,CAAC;CA2BhB"}
@@ -15,7 +15,7 @@ export class ResponseInterceptor {
15
15
  const request = context.getRequest();
16
16
  const startTime = Date.now();
17
17
  try {
18
- const data = await next.handle();
18
+ const data = await next();
19
19
  const duration = Date.now() - startTime;
20
20
  return {
21
21
  success: true,
@@ -58,7 +58,7 @@ export class ResponseInterceptor {
58
58
  export class ErrorHandlingInterceptor {
59
59
  async intercept(context, next) {
60
60
  try {
61
- return await next.handle();
61
+ return await next();
62
62
  }
63
63
  catch (error) {
64
64
  console.error(`❌ Error in ${context.getRequest().method} ${context.getRequest().url}:`, error);
@@ -85,7 +85,7 @@ export class CompressionInterceptor {
85
85
  this.threshold = threshold;
86
86
  }
87
87
  async intercept(context, next) {
88
- const data = await next.handle();
88
+ const data = await next();
89
89
  const dataSize = JSON.stringify(data).length;
90
90
  if (dataSize > this.threshold) {
91
91
  // In a real implementation, you'd compress the data here
@@ -128,7 +128,7 @@ export class RateLimitInterceptor {
128
128
  // Add current request
129
129
  history.push(now);
130
130
  this.requests.set(clientIp, history);
131
- return next.handle();
131
+ return next();
132
132
  }
133
133
  }
134
134
  /**
@@ -162,7 +162,7 @@ export class CorsInterceptor {
162
162
  response.headers.set("Access-Control-Allow-Credentials", "true");
163
163
  }
164
164
  }
165
- return next.handle();
165
+ return next();
166
166
  }
167
167
  }
168
168
  /**
@@ -178,7 +178,7 @@ export class SanitizeInterceptor {
178
178
  this.fieldsToRemove = fieldsToRemove;
179
179
  }
180
180
  async intercept(context, next) {
181
- const data = await next.handle();
181
+ const data = await next();
182
182
  return this.sanitize(data);
183
183
  }
184
184
  sanitize(data) {
@@ -210,7 +210,7 @@ export class PaginationInterceptor {
210
210
  const url = new URL(request.url, `http://${request.headers?.get?.("host")}`);
211
211
  const page = parseInt(url.searchParams.get("page") || "1");
212
212
  const limit = parseInt(url.searchParams.get("limit") || "10");
213
- const data = await next.handle();
213
+ const data = await next();
214
214
  // If data is an array, add pagination
215
215
  if (Array.isArray(data)) {
216
216
  return {