nestjs-exception-handler 4.2.0 → 4.3.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.
package/dist/index.mjs CHANGED
@@ -10,6 +10,40 @@ var __decorateClass = (decorators, target, key, kind) => {
10
10
  return result;
11
11
  };
12
12
 
13
+ // src/formatters/validation-error.formatter.ts
14
+ var ValidationErrorFormatter = class {
15
+ formatValidationErrors(exception) {
16
+ const response = exception.getResponse();
17
+ if (typeof response === "object" && response !== null) {
18
+ const responseObj = response;
19
+ if (Array.isArray(responseObj.message)) {
20
+ const messages = responseObj.message;
21
+ if (messages.length > 0 && typeof messages[0] === "object" && "property" in messages[0]) {
22
+ return this.formatNestedValidationErrors(messages);
23
+ }
24
+ return [
25
+ {
26
+ path: "http_error",
27
+ message: messages
28
+ }
29
+ ];
30
+ }
31
+ }
32
+ return [
33
+ {
34
+ path: "http_error",
35
+ message: ["Validation failed"]
36
+ }
37
+ ];
38
+ }
39
+ formatNestedValidationErrors(errors) {
40
+ return errors.map((error) => ({
41
+ path: error.property,
42
+ message: error.constraints ? Object.values(error.constraints) : ["Validation error"]
43
+ }));
44
+ }
45
+ };
46
+
13
47
  // src/formatters/prisma-exception.formatter.ts
14
48
  import { Injectable } from "@nestjs/common";
15
49
  import {
@@ -50,7 +84,7 @@ var PrismaExceptionFormatter = class {
50
84
  return [
51
85
  {
52
86
  path: field,
53
- message: `A record with this ${field} already exists.`
87
+ message: [`A record with this ${field} already exists.`]
54
88
  }
55
89
  ];
56
90
  }
@@ -59,7 +93,7 @@ var PrismaExceptionFormatter = class {
59
93
  return [
60
94
  {
61
95
  path: fieldName || "field",
62
- message: `The referenced ${fieldName || "record"} does not exist.`
96
+ message: [`The referenced ${fieldName || "record"} does not exist.`]
63
97
  }
64
98
  ];
65
99
  }
@@ -68,7 +102,7 @@ var PrismaExceptionFormatter = class {
68
102
  return [
69
103
  {
70
104
  path: fieldName || "field",
71
- message: `The value for ${fieldName || "field"} is invalid.`
105
+ message: [`The value for ${fieldName || "field"} is invalid.`]
72
106
  }
73
107
  ];
74
108
  }
@@ -77,7 +111,7 @@ var PrismaExceptionFormatter = class {
77
111
  return [
78
112
  {
79
113
  path: fieldName || "field",
80
- message: `The ${fieldName || "field"} field is required.`
114
+ message: [`The ${fieldName || "field"} field is required.`]
81
115
  }
82
116
  ];
83
117
  }
@@ -85,7 +119,7 @@ var PrismaExceptionFormatter = class {
85
119
  return [
86
120
  {
87
121
  path: "record",
88
- message: "The requested record does not exist."
122
+ message: ["The requested record does not exist."]
89
123
  }
90
124
  ];
91
125
  }
@@ -93,7 +127,7 @@ var PrismaExceptionFormatter = class {
93
127
  return [
94
128
  {
95
129
  path: "database",
96
- message: "Database operation failed."
130
+ message: ["Database operation failed."]
97
131
  }
98
132
  ];
99
133
  }
@@ -106,7 +140,7 @@ var PrismaExceptionFormatter = class {
106
140
  return [
107
141
  {
108
142
  path: "database",
109
- message
143
+ message: [message]
110
144
  }
111
145
  ];
112
146
  }
@@ -114,7 +148,7 @@ var PrismaExceptionFormatter = class {
114
148
  return [
115
149
  {
116
150
  path: "database",
117
- message: `Database initialization error: ${exception.message}`
151
+ message: [`Database initialization error: ${exception.message}`]
118
152
  }
119
153
  ];
120
154
  }
@@ -122,7 +156,7 @@ var PrismaExceptionFormatter = class {
122
156
  return [
123
157
  {
124
158
  path: "unknown",
125
- message: exception instanceof Error ? exception.message : "An unexpected database error occurred."
159
+ message: exception instanceof Error ? [exception.message] : ["An unexpected database error occurred."]
126
160
  }
127
161
  ];
128
162
  }
@@ -143,14 +177,22 @@ var DtoValidationFormatter = class {
143
177
  const validationErrors = messages;
144
178
  return validationErrors.map((error) => ({
145
179
  path: error.property,
146
- message: error.constraints ? Object.values(error.constraints).join(", ") : "Validation error"
180
+ message: error.constraints ? Object.values(error.constraints) : ["Validation error"]
147
181
  }));
148
182
  }
183
+ if (typeof firstMessage === "string") {
184
+ return [
185
+ {
186
+ path: "http_error",
187
+ message: messages
188
+ }
189
+ ];
190
+ }
149
191
  }
150
192
  return [
151
193
  {
152
194
  path: "http_error",
153
- message: typeof responseBody === "object" && responseBody !== null && "message" in responseBody ? String(responseBody.message) : "An HTTP error occurred"
195
+ message: typeof responseBody === "object" && responseBody !== null && "message" in responseBody ? [responseBody.message] : ["An HTTP error occurred"]
154
196
  }
155
197
  ];
156
198
  }
@@ -159,169 +201,18 @@ DtoValidationFormatter = __decorateClass([
159
201
  Injectable2()
160
202
  ], DtoValidationFormatter);
161
203
 
162
- // src/formatters/other-exception.formatter.ts
163
- import { Injectable as Injectable3 } from "@nestjs/common";
164
- var OtherExceptionFormatter = class {
165
- formatOtherError(exception) {
166
- if (exception && typeof exception === "object" && "path" in exception && "message" in exception) {
167
- return [
168
- {
169
- path: String(exception.path),
170
- message: String(exception.message)
171
- }
172
- ];
173
- }
174
- const message = exception && typeof exception === "object" && "message" in exception ? String(exception.message) : "An unexpected error occurred";
175
- return [
176
- {
177
- path: "unknown",
178
- message
179
- }
180
- ];
181
- }
182
- };
183
- OtherExceptionFormatter = __decorateClass([
184
- Injectable3()
185
- ], OtherExceptionFormatter);
186
-
187
- // src/exception-filter/global-exception.filter.ts
204
+ // src/filter/global-exception.filter.ts
188
205
  import {
189
206
  Catch,
190
207
  HttpException,
191
208
  HttpStatus,
192
- Logger
209
+ Logger,
210
+ NotFoundException
193
211
  } from "@nestjs/common";
194
- import {
195
- PrismaClientKnownRequestError as PrismaClientKnownRequestError2,
196
- PrismaClientValidationError as PrismaClientValidationError2,
197
- PrismaClientRustPanicError as PrismaClientRustPanicError2,
198
- PrismaClientUnknownRequestError,
199
- PrismaClientInitializationError as PrismaClientInitializationError2
200
- } from "@prisma/client/runtime/library";
201
212
  var GlobalExceptionFilter = class {
202
- constructor(prismaExceptionFormatter, dtoValidationFormatter, otherValidationFormatter) {
203
- this.prismaExceptionFormatter = prismaExceptionFormatter;
204
- this.dtoValidationFormatter = dtoValidationFormatter;
205
- this.otherValidationFormatter = otherValidationFormatter;
206
- this.logger = new Logger(GlobalExceptionFilter.name);
207
- }
208
- getErrorMessage(exception) {
209
- if (exception instanceof PrismaClientKnownRequestError2 || exception instanceof PrismaClientValidationError2 || exception instanceof PrismaClientRustPanicError2 || exception instanceof PrismaClientUnknownRequestError || exception instanceof PrismaClientInitializationError2) {
210
- return "Database error";
211
- }
212
- if (exception instanceof HttpException) {
213
- return exception.message || "HTTP error";
214
- }
215
- return "Internal server error";
216
- }
217
- catch(exception, host) {
218
- const ctx = host.switchToHttp();
219
- const response = ctx.getResponse();
220
- const request = ctx.getRequest();
221
- const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR;
222
- let errorMessages = [{ path: "unknown", message: "Internal server error" }];
223
- if (exception instanceof PrismaClientKnownRequestError2 || exception instanceof PrismaClientValidationError2 || exception instanceof PrismaClientRustPanicError2 || exception instanceof PrismaClientUnknownRequestError || exception instanceof PrismaClientInitializationError2) {
224
- errorMessages = this.prismaExceptionFormatter.formatError(exception);
225
- } else if (exception instanceof HttpException) {
226
- errorMessages = this.dtoValidationFormatter.formatDtoValidationException(
227
- exception
228
- );
229
- } else {
230
- errorMessages = this.otherValidationFormatter.formatOtherError(exception);
231
- }
232
- this.logger.error(
233
- `${request.method} ${request.url}`,
234
- JSON.stringify(errorMessages),
235
- "ExceptionFilter"
236
- );
237
- response.status(status).json({
238
- success: false,
239
- message: this.getErrorMessage(exception),
240
- errorMessages
241
- });
242
- }
243
- };
244
- GlobalExceptionFilter = __decorateClass([
245
- Catch()
246
- ], GlobalExceptionFilter);
247
-
248
- // src/module/exception-handler.module.ts
249
- import { Module } from "@nestjs/common";
250
-
251
- // src/services/exception-handler.service.ts
252
- import { Injectable as Injectable4 } from "@nestjs/common";
253
-
254
- // src/constants/default-messages.ts
255
- var DEFAULT_PATH = "unknown";
256
-
257
- // src/formatters/unknown-exception.formatter.ts
258
- var UnknownExceptionFormatter = class {
259
- supports(_exception) {
260
- return true;
261
- }
262
- format(_exception) {
263
- return [
264
- {
265
- path: DEFAULT_PATH,
266
- message: "Internal server error"
267
- }
268
- ];
269
- }
270
- message(_exception) {
271
- return "Internal server error";
272
- }
273
- };
274
-
275
- // src/services/exception-handler.service.ts
276
- var ExceptionHandlerService = class {
277
- constructor() {
278
- this.formatters = [];
279
- this.defaultFormatter = new UnknownExceptionFormatter();
280
- }
281
- registerFormatter(formatter) {
282
- this.formatters.push(formatter);
283
- }
284
- getFormatter(exception) {
285
- for (const formatter of this.formatters) {
286
- if (formatter.supports(exception)) {
287
- return formatter;
288
- }
289
- }
290
- return this.defaultFormatter;
291
- }
292
- formatException(exception) {
293
- const formatter = this.getFormatter(exception);
294
- const errors = formatter.format(exception);
295
- const message = formatter.message(exception);
296
- return { errors, message };
297
- }
298
- formatErrors(exception) {
299
- const formatter = this.getFormatter(exception);
300
- return formatter.format(exception);
301
- }
302
- getErrorMessage(exception) {
303
- const formatter = this.getFormatter(exception);
304
- return formatter.message(exception);
305
- }
306
- getAllFormatters() {
307
- return [...this.formatters];
308
- }
309
- };
310
- ExceptionHandlerService = __decorateClass([
311
- Injectable4()
312
- ], ExceptionHandlerService);
313
-
314
- // src/filter/global-exception.filter.ts
315
- import {
316
- Catch as Catch2,
317
- HttpException as HttpException2,
318
- HttpStatus as HttpStatus2,
319
- Logger as Logger2
320
- } from "@nestjs/common";
321
- var GlobalExceptionFilter2 = class {
322
213
  constructor(exceptionHandlerService, config) {
323
214
  this.exceptionHandlerService = exceptionHandlerService;
324
- this.logger = new Logger2(GlobalExceptionFilter2.name);
215
+ this.logger = new Logger(GlobalExceptionFilter.name);
325
216
  this.config = config || { enableLogging: true, hideStackTrace: false };
326
217
  }
327
218
  catch(exception, host) {
@@ -329,22 +220,40 @@ var GlobalExceptionFilter2 = class {
329
220
  const response = ctx.getResponse();
330
221
  const request = ctx.getRequest();
331
222
  const { errors, message } = this.exceptionHandlerService.formatException(exception);
332
- const status = this.getStatusCode(exception);
223
+ let status = this.getStatusCode(exception);
224
+ let finalErrors = errors;
225
+ let finalMessage = message;
226
+ if (exception instanceof NotFoundException) {
227
+ const exceptionResponse = exception.getResponse();
228
+ if (typeof exceptionResponse === "object" && exceptionResponse !== null && "message" in exceptionResponse) {
229
+ const msg = exceptionResponse.message;
230
+ if (typeof msg === "string" && msg.includes("Cannot")) {
231
+ status = HttpStatus.NOT_FOUND;
232
+ finalMessage = "Route Not Found";
233
+ finalErrors = [
234
+ {
235
+ path: "route",
236
+ message: [msg]
237
+ }
238
+ ];
239
+ }
240
+ }
241
+ }
333
242
  const errorResponse = {
334
243
  success: false,
335
- message,
336
- errorMessages: errors
244
+ message: finalMessage,
245
+ errorMessages: finalErrors
337
246
  };
338
247
  if (this.config.enableLogging) {
339
- this.logError(request, status, errors, exception);
248
+ this.logError(request, status, finalErrors, exception);
340
249
  }
341
250
  response.status(status).json(errorResponse);
342
251
  }
343
252
  getStatusCode(exception) {
344
- if (exception instanceof HttpException2) {
253
+ if (exception instanceof HttpException) {
345
254
  return exception.getStatus();
346
255
  }
347
- return HttpStatus2.INTERNAL_SERVER_ERROR;
256
+ return HttpStatus.INTERNAL_SERVER_ERROR;
348
257
  }
349
258
  logError(request, status, errorMessages, exception) {
350
259
  const method = request.method;
@@ -361,9 +270,65 @@ var GlobalExceptionFilter2 = class {
361
270
  this.logger.error(`${method} ${url} - ${status}`, JSON.stringify(logData));
362
271
  }
363
272
  };
364
- GlobalExceptionFilter2 = __decorateClass([
365
- Catch2()
366
- ], GlobalExceptionFilter2);
273
+ GlobalExceptionFilter = __decorateClass([
274
+ Catch()
275
+ ], GlobalExceptionFilter);
276
+
277
+ // src/module/exception-handler.module.ts
278
+ import { Module } from "@nestjs/common";
279
+
280
+ // src/services/exception-handler.service.ts
281
+ import { Injectable as Injectable3 } from "@nestjs/common";
282
+
283
+ // src/formatters/http-exception.formatter.ts
284
+ import { HttpException as HttpException2 } from "@nestjs/common";
285
+ var HttpExceptionFormatter = class {
286
+ supports(exception) {
287
+ return exception instanceof HttpException2;
288
+ }
289
+ format(exception) {
290
+ const httpException = exception;
291
+ const response = httpException.getResponse();
292
+ if (typeof response === "string") {
293
+ return [{ path: "http_error", message: [response] }];
294
+ }
295
+ if (typeof response === "object" && response !== null) {
296
+ const responseObj = response;
297
+ if (responseObj.message && Array.isArray(responseObj.message)) {
298
+ return [
299
+ {
300
+ path: "http_error",
301
+ message: responseObj.message
302
+ }
303
+ ];
304
+ }
305
+ if (responseObj.message && typeof responseObj.message === "string") {
306
+ return [{ path: "http_error", message: [responseObj.message] }];
307
+ }
308
+ if (responseObj.error && typeof responseObj.error === "string") {
309
+ return [{ path: "http_error", message: [responseObj.error] }];
310
+ }
311
+ }
312
+ return [{ path: "http_error", message: ["An error occurred"] }];
313
+ }
314
+ message(exception) {
315
+ const httpException = exception;
316
+ const response = httpException.getResponse();
317
+ if (typeof response === "string") {
318
+ return response;
319
+ }
320
+ if (typeof response === "object" && response !== null) {
321
+ const responseObj = response;
322
+ if (responseObj.message && typeof responseObj.message === "string") {
323
+ return responseObj.message;
324
+ }
325
+ if (responseObj.error && typeof responseObj.error === "string") {
326
+ return responseObj.error;
327
+ }
328
+ }
329
+ return "An error occurred";
330
+ }
331
+ };
367
332
 
368
333
  // src/formatters/dto-exception.formatter.ts
369
334
  var DtoExceptionFormatter = class {
@@ -384,7 +349,7 @@ var DtoExceptionFormatter = class {
384
349
  if (children) {
385
350
  return this.formatChildrenErrors(children);
386
351
  }
387
- return [{ path: "unknown", message: "Validation failed" }];
352
+ return [{ path: "unknown", message: ["Validation failed"] }];
388
353
  }
389
354
  message(exception) {
390
355
  const error = exception;
@@ -406,10 +371,12 @@ var DtoExceptionFormatter = class {
406
371
  return errors.flatMap((error) => {
407
372
  const constraints = error.constraints;
408
373
  if (constraints) {
409
- return Object.entries(constraints).map(([, value]) => ({
410
- path: error.property,
411
- message: value
412
- }));
374
+ return [
375
+ {
376
+ path: error.property,
377
+ message: Object.values(constraints)
378
+ }
379
+ ];
413
380
  }
414
381
  return [];
415
382
  });
@@ -418,63 +385,85 @@ var DtoExceptionFormatter = class {
418
385
  return children.flatMap((child) => {
419
386
  const constraints = child.constraints;
420
387
  if (constraints) {
421
- return Object.entries(constraints).map(([, value]) => ({
422
- path: child.property,
423
- message: value
424
- }));
388
+ return [
389
+ {
390
+ path: child.property,
391
+ message: Object.values(constraints)
392
+ }
393
+ ];
425
394
  }
426
395
  return [];
427
396
  });
428
397
  }
429
398
  };
430
399
 
431
- // src/formatters/http-exception.formatter.ts
432
- import { HttpException as HttpException3 } from "@nestjs/common";
433
- var HttpExceptionFormatter = class {
434
- supports(exception) {
435
- return exception instanceof HttpException3;
400
+ // src/constants/default-messages.ts
401
+ var DEFAULT_PATH = "unknown";
402
+
403
+ // src/formatters/unknown-exception.formatter.ts
404
+ var UnknownExceptionFormatter = class {
405
+ supports(_exception) {
406
+ return true;
436
407
  }
437
- format(exception) {
438
- const httpException = exception;
439
- const response = httpException.getResponse();
440
- if (typeof response === "string") {
441
- return [{ path: "unknown", message: response }];
442
- }
443
- if (typeof response === "object" && response !== null) {
444
- const responseObj = response;
445
- if (responseObj.message && Array.isArray(responseObj.message)) {
446
- return responseObj.message.map((msg) => ({
447
- path: "unknown",
448
- message: msg
449
- }));
450
- }
451
- if (responseObj.message && typeof responseObj.message === "string") {
452
- return [{ path: "unknown", message: responseObj.message }];
453
- }
454
- if (responseObj.error && typeof responseObj.error === "string") {
455
- return [{ path: "unknown", message: responseObj.error }];
408
+ format(_exception) {
409
+ return [
410
+ {
411
+ path: DEFAULT_PATH,
412
+ message: ["Something went wrong"]
456
413
  }
457
- }
458
- return [{ path: "unknown", message: "An error occurred" }];
414
+ ];
459
415
  }
460
- message(exception) {
461
- const httpException = exception;
462
- const response = httpException.getResponse();
463
- if (typeof response === "string") {
464
- return response;
465
- }
466
- if (typeof response === "object" && response !== null) {
467
- const responseObj = response;
468
- if (responseObj.message && typeof responseObj.message === "string") {
469
- return responseObj.message;
470
- }
471
- if (responseObj.error && typeof responseObj.error === "string") {
472
- return responseObj.error;
416
+ message(_exception) {
417
+ return "Internal Server Error";
418
+ }
419
+ };
420
+
421
+ // src/services/exception-handler.service.ts
422
+ var ExceptionHandlerService = class {
423
+ constructor() {
424
+ this.formatters = [];
425
+ this.defaultFormatter = new UnknownExceptionFormatter();
426
+ this.registerFormatters();
427
+ }
428
+ registerFormatters() {
429
+ this.formatters = [
430
+ new PrismaExceptionFormatter(),
431
+ new HttpExceptionFormatter(),
432
+ new DtoExceptionFormatter()
433
+ ];
434
+ }
435
+ registerFormatter(formatter) {
436
+ this.formatters.push(formatter);
437
+ }
438
+ getFormatter(exception) {
439
+ for (const formatter of this.formatters) {
440
+ if (formatter.supports(exception)) {
441
+ return formatter;
473
442
  }
474
443
  }
475
- return "An error occurred";
444
+ return this.defaultFormatter;
445
+ }
446
+ formatException(exception) {
447
+ const formatter = this.getFormatter(exception);
448
+ const errors = formatter.format(exception);
449
+ const message = formatter.message(exception);
450
+ return { errors, message };
451
+ }
452
+ formatErrors(exception) {
453
+ const formatter = this.getFormatter(exception);
454
+ return formatter.format(exception);
455
+ }
456
+ getErrorMessage(exception) {
457
+ const formatter = this.getFormatter(exception);
458
+ return formatter.message(exception);
459
+ }
460
+ getAllFormatters() {
461
+ return [...this.formatters];
476
462
  }
477
463
  };
464
+ ExceptionHandlerService = __decorateClass([
465
+ Injectable3()
466
+ ], ExceptionHandlerService);
478
467
 
479
468
  // src/module/exception-handler.module.ts
480
469
  var ExceptionHandlerModule = class {
@@ -482,9 +471,9 @@ var ExceptionHandlerModule = class {
482
471
  const providers = [
483
472
  ExceptionHandlerService,
484
473
  {
485
- provide: GlobalExceptionFilter2,
474
+ provide: GlobalExceptionFilter,
486
475
  useFactory: (service) => {
487
- return new GlobalExceptionFilter2(service, config);
476
+ return new GlobalExceptionFilter(service, config);
488
477
  },
489
478
  inject: [ExceptionHandlerService]
490
479
  }
@@ -492,7 +481,7 @@ var ExceptionHandlerModule = class {
492
481
  return {
493
482
  module: ExceptionHandlerModule,
494
483
  providers,
495
- exports: [ExceptionHandlerService, GlobalExceptionFilter2],
484
+ exports: [ExceptionHandlerService, GlobalExceptionFilter],
496
485
  global: true
497
486
  };
498
487
  }
@@ -509,12 +498,58 @@ function initializeFormatters(service) {
509
498
  service.registerFormatter(new HttpExceptionFormatter());
510
499
  service.registerFormatter(new UnknownExceptionFormatter());
511
500
  }
501
+
502
+ // src/utils/http-error.formatter.ts
503
+ var HttpErrorFormatter = class {
504
+ formatHttpException(exception) {
505
+ const response = exception.getResponse();
506
+ if (typeof response === "string") {
507
+ return [{ path: "http_error", message: [response] }];
508
+ }
509
+ if (typeof response === "object" && response !== null) {
510
+ const responseObj = response;
511
+ if (Array.isArray(responseObj.message)) {
512
+ return [
513
+ {
514
+ path: "http_error",
515
+ message: responseObj.message
516
+ }
517
+ ];
518
+ }
519
+ if (typeof responseObj.message === "string") {
520
+ return [{ path: "http_error", message: [responseObj.message] }];
521
+ }
522
+ if (responseObj.error && typeof responseObj.error === "string") {
523
+ return [{ path: "http_error", message: [responseObj.error] }];
524
+ }
525
+ }
526
+ return [{ path: "http_error", message: ["An error occurred"] }];
527
+ }
528
+ getMessage(exception) {
529
+ const response = exception.getResponse();
530
+ if (typeof response === "string") {
531
+ return response;
532
+ }
533
+ if (typeof response === "object" && response !== null) {
534
+ const responseObj = response;
535
+ if (typeof responseObj.message === "string") {
536
+ return responseObj.message;
537
+ }
538
+ if (responseObj.error && typeof responseObj.error === "string") {
539
+ return responseObj.error;
540
+ }
541
+ }
542
+ return "An error occurred";
543
+ }
544
+ };
512
545
  export {
513
546
  DtoValidationFormatter,
514
547
  ExceptionHandlerModule,
548
+ ExceptionHandlerService,
515
549
  GlobalExceptionFilter,
516
- OtherExceptionFormatter,
550
+ HttpErrorFormatter,
517
551
  PrismaExceptionFormatter,
552
+ ValidationErrorFormatter,
518
553
  initializeFormatters
519
554
  };
520
555
  //# sourceMappingURL=index.mjs.map