wynkjs 1.0.3 → 1.0.4

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 (37) hide show
  1. package/README.md +252 -55
  2. package/dist/database.d.ts +1 -1
  3. package/dist/database.js +1 -1
  4. package/dist/decorators/exception.advanced.d.ts +286 -18
  5. package/dist/decorators/exception.advanced.d.ts.map +1 -1
  6. package/dist/decorators/exception.advanced.js +410 -17
  7. package/dist/decorators/exception.decorators.d.ts +92 -2
  8. package/dist/decorators/exception.decorators.d.ts.map +1 -1
  9. package/dist/decorators/exception.decorators.js +120 -5
  10. package/dist/decorators/formatter.decorators.d.ts +93 -0
  11. package/dist/decorators/formatter.decorators.d.ts.map +1 -0
  12. package/dist/decorators/formatter.decorators.js +131 -0
  13. package/dist/decorators/guard.decorators.d.ts +2 -2
  14. package/dist/decorators/http.decorators.d.ts +3 -2
  15. package/dist/decorators/http.decorators.d.ts.map +1 -1
  16. package/dist/decorators/pipe.decorators.d.ts +2 -2
  17. package/dist/decorators/pipe.decorators.d.ts.map +1 -1
  18. package/dist/decorators/pipe.decorators.js +2 -2
  19. package/dist/dto.js +1 -1
  20. package/dist/factory.d.ts +1 -1
  21. package/dist/factory.d.ts.map +1 -1
  22. package/dist/factory.js +55 -6
  23. package/dist/filters/exception.filters.d.ts +124 -0
  24. package/dist/filters/exception.filters.d.ts.map +1 -0
  25. package/dist/filters/exception.filters.js +208 -0
  26. package/dist/index.d.ts +3 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +4 -1
  29. package/dist/pipes/validation.pipe.d.ts +3 -3
  30. package/dist/pipes/validation.pipe.d.ts.map +1 -1
  31. package/dist/pipes/validation.pipe.js +39 -11
  32. package/dist/schema-registry.d.ts +51 -0
  33. package/dist/schema-registry.d.ts.map +1 -0
  34. package/dist/schema-registry.js +134 -0
  35. package/dist/testing/index.d.ts +2 -2
  36. package/dist/testing/index.js +2 -2
  37. package/package.json +8 -3
@@ -1,6 +1,23 @@
1
1
  import "reflect-metadata";
2
+ import { HttpException, } from "./exception.decorators";
2
3
  /**
3
4
  * FormatErrorFormatter - Formats as { field: [messages] } like NestJS
5
+ *
6
+ * Output example:
7
+ * {
8
+ * "statusCode": 400,
9
+ * "message": "Validation failed",
10
+ * "errors": {
11
+ * "email": ["Invalid email address"],
12
+ * "age": ["Must be at least 18"]
13
+ * }
14
+ * }
15
+ *
16
+ * @example
17
+ * const app = WynkFactory.create({
18
+ * controllers: [UserController],
19
+ * validationErrorFormatter: new FormatErrorFormatter(),
20
+ * });
4
21
  */
5
22
  export class FormatErrorFormatter {
6
23
  format(error) {
@@ -27,6 +44,22 @@ export class FormatErrorFormatter {
27
44
  }
28
45
  /**
29
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
+ * });
30
63
  */
31
64
  export class SimpleErrorFormatter {
32
65
  format(error) {
@@ -48,6 +81,26 @@ export class SimpleErrorFormatter {
48
81
  }
49
82
  /**
50
83
  * DetailedErrorFormatter - Formats with detailed field info
84
+ *
85
+ * Output example:
86
+ * {
87
+ * "statusCode": 400,
88
+ * "message": "Validation failed",
89
+ * "errors": [
90
+ * {
91
+ * "field": "email",
92
+ * "message": "Invalid email address",
93
+ * "value": "invalid-email",
94
+ * "expected": {...schema...}
95
+ * }
96
+ * ]
97
+ * }
98
+ *
99
+ * @example
100
+ * const app = WynkFactory.create({
101
+ * controllers: [UserController],
102
+ * validationErrorFormatter: new DetailedErrorFormatter(),
103
+ * });
51
104
  */
52
105
  export class DetailedErrorFormatter {
53
106
  format(error) {
@@ -78,19 +131,25 @@ export class DetailedErrorFormatter {
78
131
  }
79
132
  }
80
133
  /**
81
- * Validation Exception Filter - Handles validation errors with customizable formatting
82
- * @example
83
- * // With FormatErrorFormatter (NestJS-style)
84
- * app.useGlobalFilters(new ValidationExceptionFilter(new FormatErrorFormatter()));
134
+ * Validation Exception Filter - DEPRECATED / NOT RECOMMENDED
135
+ *
136
+ * ⚠️ WARNING: This filter is NOT used by WynkJS for validation errors!
85
137
  *
86
- * // With SimpleErrorFormatter
87
- * app.useGlobalFilters(new ValidationExceptionFilter(new SimpleErrorFormatter()));
138
+ * Validation errors are handled directly in the factory's onError hook.
139
+ * To format validation errors, use the validationErrorFormatter option:
88
140
  *
89
- * // With DetailedErrorFormatter
90
- * app.useGlobalFilters(new ValidationExceptionFilter(new DetailedErrorFormatter()));
141
+ * @example
142
+ * // CORRECT: Use validationErrorFormatter in factory options
143
+ * const app = WynkFactory.create({
144
+ * controllers: [UserController],
145
+ * validationErrorFormatter: new FormatErrorFormatter(), // This works!
146
+ * });
147
+ *
148
+ * // ❌ WRONG: This does nothing for validation errors
149
+ * app.useGlobalFilters(new ValidationExceptionFilter(new FormatErrorFormatter()));
91
150
  *
92
- * // Without formatter (default detailed format)
93
- * app.useGlobalFilters(new ValidationExceptionFilter());
151
+ * This class is kept for backward compatibility and custom use cases,
152
+ * but it's not part of the standard validation error flow.
94
153
  */
95
154
  export class ValidationExceptionFilter {
96
155
  formatter = null;
@@ -142,16 +201,48 @@ export class ValidationExceptionFilter {
142
201
  }
143
202
  }
144
203
  /**
145
- * Database Exception Filter - Handles database errors
204
+ * Database Exception Filter - Handles database errors ONLY (not HttpExceptions)
205
+ *
206
+ * This filter catches actual database errors (like unique constraint violations,
207
+ * foreign key errors, etc.) and converts them to user-friendly messages.
208
+ *
209
+ * It will NOT catch HttpException or its subclasses (ConflictException, etc.)
210
+ * that you throw manually - those will pass through to be handled correctly.
211
+ *
146
212
  * @example
213
+ * // Use as global filter
214
+ * app.useGlobalFilters(new DatabaseExceptionFilter());
215
+ *
216
+ * // Use on specific controller
147
217
  * @UseFilters(DatabaseExceptionFilter)
148
218
  * @Controller('/users')
149
- * export class UserController {}
219
+ * export class UserController {
220
+ * @Post()
221
+ * async create(@Body() data: any) {
222
+ * // If you throw manually, it passes through:
223
+ * if (await this.userExists(data.email)) {
224
+ * throw new ConflictException('User with this email already exists'); // ✅ Works correctly
225
+ * }
226
+ *
227
+ * // If database throws error, filter catches it:
228
+ * return await this.db.insert(users).values(data); // ❌ DB unique constraint error → caught by filter
229
+ * }
230
+ * }
231
+ *
232
+ * Handles these database error codes:
233
+ * - 23505: Unique constraint violation → 409 Conflict
234
+ * - 23503: Foreign key constraint violation → 400 Bad Request
235
+ * - 23502: Not null constraint violation → 400 Bad Request
150
236
  */
151
237
  export class DatabaseExceptionFilter {
152
238
  catch(exception, context) {
153
239
  const response = context.getResponse();
154
240
  const request = context.getRequest();
241
+ // Don't catch HttpException or its subclasses (like ConflictException)
242
+ // These are intentionally thrown by the user
243
+ if (exception instanceof HttpException) {
244
+ throw exception;
245
+ }
155
246
  // Check for common database errors
156
247
  let message = "Database error occurred";
157
248
  let statusCode = 500;
@@ -180,10 +271,20 @@ export class DatabaseExceptionFilter {
180
271
  }
181
272
  /**
182
273
  * Authentication Exception Filter - Handles auth errors
274
+ *
275
+ * ⚠️ IMPORTANT: This catches ALL UnauthorizedException instances!
276
+ * Use on specific routes/controllers, not globally.
277
+ *
183
278
  * @example
279
+ * // ✅ GOOD: Use on auth-protected controller
184
280
  * @UseFilters(AuthenticationExceptionFilter)
185
281
  * @Controller('/auth')
186
- * export class AuthController {}
282
+ * export class AuthController {
283
+ * @Post('/login')
284
+ * async login() {
285
+ * throw new UnauthorizedException('Invalid credentials');
286
+ * }
287
+ * }
187
288
  */
188
289
  export class AuthenticationExceptionFilter {
189
290
  catch(exception, context) {
@@ -201,10 +302,20 @@ export class AuthenticationExceptionFilter {
201
302
  }
202
303
  /**
203
304
  * Authorization Exception Filter - Handles permission errors
305
+ *
306
+ * ⚠️ IMPORTANT: This catches ALL ForbiddenException instances!
307
+ * Use on specific routes/controllers, not globally.
308
+ *
204
309
  * @example
310
+ * // ✅ GOOD: Use on admin-only controller
205
311
  * @UseFilters(AuthorizationExceptionFilter)
206
312
  * @Controller('/admin')
207
- * export class AdminController {}
313
+ * export class AdminController {
314
+ * @Get('/users')
315
+ * async getAllUsers() {
316
+ * throw new ForbiddenException('Admin access required');
317
+ * }
318
+ * }
208
319
  */
209
320
  export class AuthorizationExceptionFilter {
210
321
  catch(exception, context) {
@@ -222,16 +333,64 @@ export class AuthorizationExceptionFilter {
222
333
  }
223
334
  }
224
335
  /**
225
- * Not Found Exception Filter - Handles 404 errors
336
+ * Not Found Exception Filter - Handles 404 errors with smart detection
337
+ *
338
+ * This filter is SMART - it only handles NotFoundExceptionFilter if:
339
+ * 1. The exception is NotFoundException, AND
340
+ * 2. No response data has been set (empty, null, empty array, or empty object)
341
+ *
342
+ * This allows it to be used globally without breaking routes that return
343
+ * legitimate empty responses or have their own error handling.
344
+ *
226
345
  * @example
227
- * @UseFilters(NotFoundExceptionFilter)
346
+ * // ✅ Can be used globally - smart filtering
347
+ * app.useGlobalFilters(
348
+ * new NotFoundExceptionFilter(), // Safe to use globally now!
349
+ * new GlobalExceptionFilter()
350
+ * );
351
+ *
352
+ * @example
353
+ * // Works correctly in all scenarios:
354
+ *
355
+ * // Scenario 1: Empty response with NotFoundException
228
356
  * @Get('/:id')
229
- * async findOne(@Param('id') id: string) {}
357
+ * async findOne(@Param('id') id: string) {
358
+ * const item = await this.service.findOne(id);
359
+ * if (!item) {
360
+ * throw new NotFoundException('Item not found'); // ✅ Caught and formatted by NotFoundExceptionFilter
361
+ * }
362
+ * return item;
363
+ * }
364
+ *
365
+ * // Scenario 2: Valid empty array response
366
+ * @Get('/search')
367
+ * async search(@Query('q') query: string) {
368
+ * const results = await this.service.search(query);
369
+ * return results; // ✅ Returns [] without triggering NotFoundExceptionFilter (no NotFoundException thrown)
370
+ * }
371
+ *
372
+ * // Scenario 3: NotFoundException with existing response data
373
+ * @Get('/custom')
374
+ * async custom() {
375
+ * const data = { message: 'Custom data' };
376
+ * throw new NotFoundException('Not found'); // ✅ Passes through (has response data)
377
+ * }
230
378
  */
231
379
  export class NotFoundExceptionFilter {
232
380
  catch(exception, context) {
233
381
  const response = context.getResponse();
234
382
  const request = context.getRequest();
383
+ // Check if there's any meaningful response data already set
384
+ // If there is, this might be an intentional NotFoundException with custom handling
385
+ // So we pass it through to the next filter
386
+ const hasResponseData = this.hasResponseData(response);
387
+ if (hasResponseData) {
388
+ // There's already response data, don't override it
389
+ // Pass to next filter
390
+ throw exception;
391
+ }
392
+ // No response data and we have a NotFoundException
393
+ // This is likely a "resource not found" scenario
235
394
  return {
236
395
  statusCode: exception.statusCode,
237
396
  error: "Not Found",
@@ -241,6 +400,30 @@ export class NotFoundExceptionFilter {
241
400
  suggestion: "Please check the resource ID or URL",
242
401
  };
243
402
  }
403
+ /**
404
+ * Check if response has meaningful data
405
+ * Returns false for: null, undefined, {}, [], ""
406
+ * Returns true for: anything else
407
+ */
408
+ hasResponseData(response) {
409
+ if (response === null || response === undefined) {
410
+ return false;
411
+ }
412
+ // Check for empty object
413
+ if (typeof response === 'object' && !Array.isArray(response)) {
414
+ return Object.keys(response).length > 0;
415
+ }
416
+ // Check for empty array
417
+ if (Array.isArray(response)) {
418
+ return response.length > 0;
419
+ }
420
+ // Check for empty string
421
+ if (typeof response === 'string') {
422
+ return response.length > 0;
423
+ }
424
+ // For numbers, booleans, etc. - consider them as having data
425
+ return true;
426
+ }
244
427
  }
245
428
  /**
246
429
  * Rate Limit Exception Filter - Handles rate limit errors
@@ -253,6 +436,10 @@ export class RateLimitExceptionFilter {
253
436
  catch(exception, context) {
254
437
  const response = context.getResponse();
255
438
  const request = context.getRequest();
439
+ // Don't catch HttpException or its subclasses
440
+ if (exception instanceof HttpException) {
441
+ throw exception;
442
+ }
256
443
  return {
257
444
  statusCode: 429,
258
445
  error: "Too Many Requests",
@@ -275,6 +462,10 @@ export class BusinessLogicExceptionFilter {
275
462
  catch(exception, context) {
276
463
  const response = context.getResponse();
277
464
  const request = context.getRequest();
465
+ // Don't catch HttpException or its subclasses
466
+ if (exception instanceof HttpException) {
467
+ throw exception;
468
+ }
278
469
  return {
279
470
  statusCode: exception.statusCode || 422,
280
471
  error: "Business Rule Violation",
@@ -297,6 +488,10 @@ export class FileUploadExceptionFilter {
297
488
  catch(exception, context) {
298
489
  const response = context.getResponse();
299
490
  const request = context.getRequest();
491
+ // Don't catch HttpException or its subclasses
492
+ if (exception instanceof HttpException) {
493
+ throw exception;
494
+ }
300
495
  let message = "File upload failed";
301
496
  if (exception.message?.includes("size")) {
302
497
  message = "File size exceeds limit";
@@ -347,3 +542,201 @@ export class GlobalExceptionFilter {
347
542
  };
348
543
  }
349
544
  }
545
+ /**
546
+ * ============================================================================
547
+ * COMPLETE EXAMPLE: Using Multiple Exception Filters
548
+ * ============================================================================
549
+ *
550
+ * Here's a complete example showing how to properly use multiple exception
551
+ * filters in a WynkJS application with the correct order and behavior.
552
+ */
553
+ /*
554
+ // ============================================================================
555
+ // Example 1: Validation Error Formatting (CORRECT WAY)
556
+ // ============================================================================
557
+
558
+ import { WynkFactory, FormatErrorFormatter, DetailedErrorFormatter } from 'wynkjs';
559
+
560
+ // ✅ CORRECT: Pass formatter to factory options
561
+ const app = WynkFactory.create({
562
+ controllers: [UserController, ProductController],
563
+ validationErrorFormatter: new FormatErrorFormatter(), // Formats validation errors
564
+ });
565
+
566
+ // ❌ WRONG: Don't use ValidationExceptionFilter in useGlobalFilters
567
+ // app.useGlobalFilters(new ValidationExceptionFilter(new FormatErrorFormatter()));
568
+ // This does nothing because validation is handled in factory's onError hook
569
+
570
+ // ============================================================================
571
+ // Example 2: Exception Filters (For non-validation errors)
572
+ // ============================================================================
573
+
574
+ import { WynkFactory } from 'wynkjs';
575
+ import {
576
+ DatabaseExceptionFilter,
577
+ GlobalExceptionFilter,
578
+ } from 'wynkjs';
579
+
580
+ const app = WynkFactory.create({
581
+ controllers: [UserController, ProductController],
582
+ validationErrorFormatter: new FormatErrorFormatter(), // For validation errors
583
+ });
584
+
585
+ // Register filters for OTHER types of errors (DB errors, unexpected errors, etc.)
586
+ app.useGlobalFilters(
587
+ new DatabaseExceptionFilter(), // Handles DB errors
588
+ new GlobalExceptionFilter() // Catches everything else
589
+ );
590
+
591
+ await app.listen(3000);
592
+
593
+ // ============================================================================
594
+ // Example 3: Controller-Level Filters
595
+ // ============================================================================
596
+
597
+ import { Controller, Post, Body, UseFilters } from 'wynkjs';
598
+ import { DatabaseExceptionFilter, ConflictException } from 'wynkjs';
599
+
600
+ @UseFilters(DatabaseExceptionFilter) // Only for this controller
601
+ @Controller('/users')
602
+ export class UserController {
603
+
604
+ @Post()
605
+ async create(@Body() data: any) {
606
+ // Check if user exists
607
+ const exists = await this.checkUserExists(data.email);
608
+
609
+ if (exists) {
610
+ // ✅ This ConflictException will NOT be caught by DatabaseExceptionFilter
611
+ // It will pass through and be handled by the default HttpException handler
612
+ throw new ConflictException('User with this email already exists');
613
+ }
614
+
615
+ // If database throws a unique constraint error, DatabaseExceptionFilter will catch it
616
+ return await this.db.insert(users).values(data);
617
+ }
618
+ }
619
+
620
+ // ============================================================================
621
+ // Example 4: Method-Level Filters (Most Specific)
622
+ // ============================================================================
623
+
624
+ import { Controller, Post, Get, UseFilters, Param } from 'wynkjs';
625
+ import { NotFoundExceptionFilter, NotFoundException } from 'wynkjs';
626
+
627
+ @Controller('/products')
628
+ export class ProductController {
629
+
630
+ @Get('/:id')
631
+ @UseFilters(NotFoundExceptionFilter) // Only for this route
632
+ async findOne(@Param('id') id: string) {
633
+ const product = await this.db.findOne(id);
634
+
635
+ if (!product) {
636
+ // ✅ Caught by NotFoundExceptionFilter and formatted nicely
637
+ throw new NotFoundException(`Product with ID ${id} not found`);
638
+ }
639
+
640
+ return product;
641
+ }
642
+
643
+ @Post()
644
+ async create(@Body() data: any) {
645
+ // This route doesn't have NotFoundExceptionFilter
646
+ return await this.db.insert(products).values(data);
647
+ }
648
+ }
649
+
650
+ // ============================================================================
651
+ // Example 5: Understanding the Flow
652
+ // ============================================================================
653
+
654
+ // Given this setup:
655
+ const app = WynkFactory.create({
656
+ controllers: [UserController],
657
+ validationErrorFormatter: new FormatErrorFormatter(), // For validation errors
658
+ });
659
+
660
+ app.useGlobalFilters(
661
+ new DatabaseExceptionFilter(),
662
+ new GlobalExceptionFilter()
663
+ );
664
+
665
+ // SCENARIO 1: Validation Error
666
+ // ──────────────────────────────
667
+ POST /users with invalid data
668
+ → Handled by factory's onError hook (NOT by ValidationExceptionFilter)
669
+ → Formatted using validationErrorFormatter option
670
+ → Returns formatted validation error
671
+
672
+ // SCENARIO 2: Manual ConflictException
673
+ // ──────────────────────────────────────
674
+ throw new ConflictException('User exists');
675
+ → DatabaseExceptionFilter checks: It's an HttpException, re-throws
676
+ → GlobalExceptionFilter catches it
677
+ → Returns the ConflictException response
678
+
679
+ // SCENARIO 3: Database Unique Constraint Error
680
+ // ──────────────────────────────────────────────
681
+ Database throws: { code: '23505', message: 'unique constraint' }
682
+ → DatabaseExceptionFilter catches it (not an HttpException)
683
+ → Converts to user-friendly message
684
+ → Returns: { statusCode: 409, message: 'Resource already exists' }
685
+
686
+ // SCENARIO 4: Unexpected Error
687
+ // ──────────────────────────────
688
+ throw new Error('Something went wrong');
689
+ → DatabaseExceptionFilter checks: Not a DB error, re-throws
690
+ → GlobalExceptionFilter catches it
691
+ → Logs error and returns generic 500 response
692
+
693
+ // ============================================================================
694
+ // Example 6: Custom Exception Filter
695
+ // ============================================================================
696
+
697
+ import { WynkExceptionFilter, ExecutionContext, HttpException } from 'wynkjs';
698
+
699
+ export class CustomBusinessFilter implements WynkExceptionFilter {
700
+ catch(exception: any, context: ExecutionContext) {
701
+ const request = context.getRequest();
702
+
703
+ // Don't catch HttpExceptions (let them pass through)
704
+ if (exception instanceof HttpException) {
705
+ throw exception;
706
+ }
707
+
708
+ // Only catch errors with 'BUSINESS_RULE_VIOLATION' code
709
+ if (exception.code === 'BUSINESS_RULE_VIOLATION') {
710
+ return {
711
+ statusCode: 422,
712
+ error: 'Business Rule Violation',
713
+ message: exception.message,
714
+ rule: exception.rule,
715
+ timestamp: new Date().toISOString(),
716
+ path: request.url,
717
+ };
718
+ }
719
+
720
+ // Not our error type, re-throw it
721
+ throw exception;
722
+ }
723
+ }
724
+
725
+ // Use it:
726
+ app.useGlobalFilters(
727
+ new CustomBusinessFilter(),
728
+ new GlobalExceptionFilter()
729
+ );
730
+
731
+ // ============================================================================
732
+ // KEY TAKEAWAYS
733
+ // ============================================================================
734
+ //
735
+ // 1. Order matters: Specific → General
736
+ // 2. Filters can re-throw exceptions they don't handle
737
+ // 3. HttpException and subclasses should pass through specialized filters
738
+ // 4. Global filters catch everything not handled by controller/method filters
739
+ // 5. Always have a GlobalExceptionFilter as the last filter (catch-all)
740
+ //
741
+ // ============================================================================
742
+ */
@@ -18,7 +18,7 @@ export interface WynkExceptionFilter<T = any> {
18
18
  * export class HttpWynkExceptionFilter implements WynkExceptionFilter {}
19
19
  *
20
20
  * @Catch() // Catches all exceptions
21
- * export class AllExceptionsFilter implements WynkExceptionFilter {}
21
+ * export class AllExceptions implements WynkExceptionFilter {}
22
22
  */
23
23
  export declare function Catch(...exceptions: any[]): ClassDecorator;
24
24
  /**
@@ -115,7 +115,97 @@ export declare class HttpWynkExceptionFilter implements WynkExceptionFilter<Http
115
115
  /**
116
116
  * All exceptions filter - catches everything
117
117
  */
118
- export declare class AllExceptionsFilter implements WynkExceptionFilter {
118
+ export declare class AllExceptions implements WynkExceptionFilter {
119
119
  catch(exception: any, context: ExecutionContext): any;
120
120
  }
121
+ /**
122
+ * Authentication Exception Filter - Handles auth errors
123
+ *
124
+ * ⚠️ IMPORTANT: This catches ALL UnauthorizedException instances!
125
+ * Use on specific routes/controllers, not globally.
126
+ *
127
+ * @example
128
+ * // ✅ GOOD: Use on auth-protected controller
129
+ * @UseFilters(AuthenticationExceptionFilter)
130
+ * @Controller('/auth')
131
+ * export class AuthController {
132
+ * @Post('/login')
133
+ * async login() {
134
+ * throw new UnauthorizedException('Invalid credentials');
135
+ * }
136
+ * }
137
+ */
138
+ export declare class AuthenticationException implements WynkExceptionFilter<UnauthorizedException> {
139
+ catch(exception: UnauthorizedException, context: ExecutionContext): {
140
+ statusCode: number;
141
+ error: string;
142
+ message: string;
143
+ timestamp: string;
144
+ path: any;
145
+ hint: string;
146
+ };
147
+ }
148
+ /**
149
+ * Authorization Exception Filter - Handles permission errors
150
+ *
151
+ * ⚠️ IMPORTANT: This catches ALL ForbiddenException instances!
152
+ * Use on specific routes/controllers, not globally.
153
+ *
154
+ * @example
155
+ * // ✅ GOOD: Use on admin-only controller
156
+ * @UseFilters(AuthorizationExceptionFilter)
157
+ * @Controller('/admin')
158
+ * export class AdminController {
159
+ * @Get('/users')
160
+ * async getAllUsers() {
161
+ * throw new ForbiddenException('Admin access required');
162
+ * }
163
+ * }
164
+ */
165
+ export declare class AuthorizationException implements WynkExceptionFilter<ForbiddenException> {
166
+ catch(exception: ForbiddenException, context: ExecutionContext): {
167
+ statusCode: number;
168
+ error: string;
169
+ message: string;
170
+ timestamp: string;
171
+ path: any;
172
+ requiredPermissions: any;
173
+ };
174
+ }
175
+ /**
176
+ * Rate Limit Exception Filter - Handles rate limit errors
177
+ * @example
178
+ * @UseFilters(RateLimitExceptionFilter)
179
+ * @Post()
180
+ * async create() {}
181
+ */
182
+ export declare class RateLimitException implements WynkExceptionFilter {
183
+ catch(exception: any, context: ExecutionContext): {
184
+ statusCode: number;
185
+ error: string;
186
+ message: any;
187
+ timestamp: string;
188
+ path: any;
189
+ retryAfter: any;
190
+ hint: string;
191
+ };
192
+ }
193
+ /**
194
+ * Business Logic Exception Filter - Handles business rule violations
195
+ * @example
196
+ * @UseFilters(BusinessLogicExceptionFilter)
197
+ * @Post('/transfer')
198
+ * async transfer(@Body() data: any) {}
199
+ */
200
+ export declare class BusinessLogicException implements WynkExceptionFilter {
201
+ catch(exception: any, context: ExecutionContext): {
202
+ statusCode: any;
203
+ error: string;
204
+ message: any;
205
+ timestamp: string;
206
+ path: any;
207
+ rule: any;
208
+ details: any;
209
+ };
210
+ }
121
211
  //# sourceMappingURL=exception.decorators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"exception.decorators.d.ts","sourceRoot":"","sources":["../../core/decorators/exception.decorators.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"exception.decorators.d.ts","sourceRoot":"","sources":["../../core/decorators/exception.decorators.ts"],"names":[],"mappings":"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"}