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