nestjs-exception-handler 1.0.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 ADDED
@@ -0,0 +1,240 @@
1
+ # NestJS Exception Handler
2
+
3
+ [![npm version](https://badge.fury.io/js/nestjs-exception-handler.svg)](https://badge.fury.io/js/nestjs-exception-handler)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ A production-grade global exception handling system for NestJS applications that provides standardized error responses, supports Prisma errors, DTO validation, HTTP exceptions, and more.
7
+
8
+ ## Features
9
+
10
+ - **Standardized Error Responses**: Consistent error format across your application
11
+ - **Prisma Integration**: Built-in support for Prisma error codes (P2002, P2003, etc.)
12
+ - **DTO Validation**: Automatic extraction of validation errors from class-validator
13
+ - **HTTP Exception Support**: Handles all NestJS HTTP exceptions
14
+ - **Extensible**: Plugin system for custom formatters
15
+ - **Type Safe**: Full TypeScript support
16
+ - **Production Ready**: Includes logging and stack trace control
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install nestjs-exception-handler
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### 1. Import the module
27
+
28
+ ```typescript
29
+ import { Module } from '@nestjs/common';
30
+ import { ExceptionHandlerModule } from 'nestjs-exception-handler';
31
+
32
+ @Module({
33
+ imports: [ExceptionHandlerModule.forRoot()],
34
+ })
35
+ export class AppModule {}
36
+ ```
37
+
38
+ ### 2. Apply the global filter
39
+
40
+ ```typescript
41
+ import { NestFactory } from '@nestjs/core';
42
+ import { AppModule } from './app.module';
43
+ import { GlobalExceptionFilter } from 'nestjs-exception-handler';
44
+
45
+ async function bootstrap() {
46
+ const app = await NestFactory.create(AppModule);
47
+
48
+ const filter = app.get(GlobalExceptionFilter);
49
+ app.useGlobalFilters(filter);
50
+
51
+ await app.listen(3000);
52
+ }
53
+ bootstrap();
54
+ ```
55
+
56
+ ## Configuration
57
+
58
+ ```typescript
59
+ ExceptionHandlerModule.forRoot({
60
+ enableLogging: true, // Enable structured logging
61
+ hideStackTrace: true, // Hide stack traces in production
62
+ });
63
+ ```
64
+
65
+ ## Standard Error Response Format
66
+
67
+ All responses follow this structure:
68
+
69
+ ```json
70
+ {
71
+ "success": false,
72
+ "message": "Database error",
73
+ "errorMessages": [
74
+ {
75
+ "path": "email",
76
+ "message": "User with this email already exists"
77
+ }
78
+ ]
79
+ }
80
+ ```
81
+
82
+ ## Supported Error Types
83
+
84
+ ### Prisma Errors
85
+
86
+ Handles all Prisma error types with automatic path extraction:
87
+
88
+ - `P2002` - Unique constraint violation
89
+ - `P2003` - Foreign key constraint violation
90
+ - `P2005` - Invalid value
91
+ - `P2006` - Invalid format
92
+ - `P2025` - Record not found
93
+
94
+ **Example:**
95
+
96
+ ```json
97
+ {
98
+ "path": "email",
99
+ "message": "A record with this email already exists."
100
+ }
101
+ ```
102
+
103
+ ### DTO Validation Errors
104
+
105
+ Automatically extracts validation errors from class-validator:
106
+
107
+ ```typescript
108
+ // Example validation error
109
+ {
110
+ "path": "email",
111
+ "message": "email must be a valid email"
112
+ }
113
+ ```
114
+
115
+ ### HTTP Exceptions
116
+
117
+ Handles all NestJS HTTP exceptions:
118
+
119
+ ```typescript
120
+ throw new BadRequestException('Invalid input');
121
+ ```
122
+
123
+ ### Unknown Errors
124
+
125
+ Fallback handler returns generic error message.
126
+
127
+ ## Creating Custom Formatters
128
+
129
+ Extend the `ExceptionFormatter` interface to create custom formatters:
130
+
131
+ ```typescript
132
+ import { ExceptionFormatter, ErrorMessage } from 'nestjs-exception-handler';
133
+
134
+ export class CustomExceptionFormatter implements ExceptionFormatter {
135
+ supports(exception: unknown): boolean {
136
+ return exception instanceof CustomError;
137
+ }
138
+
139
+ format(exception: unknown): ErrorMessage[] {
140
+ const error = exception as CustomError;
141
+ return [{ path: error.field, message: error.message }];
142
+ }
143
+
144
+ message(exception: unknown): string {
145
+ return 'Custom error occurred';
146
+ }
147
+ }
148
+ ```
149
+
150
+ ## API Reference
151
+
152
+ ### ExceptionHandlerModule
153
+
154
+ - `forRoot(config?)` - Register globally with optional configuration
155
+ - `forFeature(config?)` - Register for specific modules
156
+
157
+ ### ExceptionHandlerService
158
+
159
+ - `registerFormatter(formatter)` - Add custom formatter
160
+ - `formatException(exception)` - Format exception to standardized response
161
+ - `formatErrors(exception)` - Get error messages array
162
+ - `getErrorMessage(exception)` - Get error message string
163
+ - `getAllFormatters()` - Get registered formatters
164
+
165
+ ### GlobalExceptionFilter
166
+
167
+ - Catches all unhandled exceptions
168
+ - Logs structured errors
169
+ - Returns standardized responses
170
+
171
+ ## Error Response Examples
172
+
173
+ ### Prisma Unique Constraint
174
+
175
+ ```json
176
+ {
177
+ "success": false,
178
+ "message": "A record with this email already exists.",
179
+ "errorMessages": [
180
+ {
181
+ "path": "email",
182
+ "message": "A record with this email already exists."
183
+ }
184
+ ]
185
+ }
186
+ ```
187
+
188
+ ### Validation Error
189
+
190
+ ```json
191
+ {
192
+ "success": false,
193
+ "message": "Validation failed",
194
+ "errorMessages": [
195
+ {
196
+ "path": "email",
197
+ "message": "email must be a valid email"
198
+ },
199
+ {
200
+ "path": "password",
201
+ "message": "password must be longer than 8 characters"
202
+ }
203
+ ]
204
+ }
205
+ ```
206
+
207
+ ### HTTP Exception
208
+
209
+ ```json
210
+ {
211
+ "success": false,
212
+ "message": "Resource not found",
213
+ "errorMessages": [
214
+ {
215
+ "path": "unknown",
216
+ "message": "Resource not found"
217
+ }
218
+ ]
219
+ }
220
+ ```
221
+
222
+ ## Contributing
223
+
224
+ Contributions are welcome! Please feel free to submit a Pull Request.
225
+
226
+ 1. Fork the repository
227
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
228
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
229
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
230
+ 5. Open a Pull Request
231
+
232
+ ## License
233
+
234
+ MIT
235
+
236
+ ## Author
237
+
238
+ **Nurul Islam Rimon**
239
+
240
+ - GitHub: [nurulislamrimon](https://github.com/nurulislamrimon)
@@ -0,0 +1,96 @@
1
+ import { ExceptionFilter, ArgumentsHost, DynamicModule } from '@nestjs/common';
2
+
3
+ interface ErrorMessage {
4
+ path: string;
5
+ message: string;
6
+ }
7
+ interface StandardErrorResponse {
8
+ success: boolean;
9
+ message: string;
10
+ errorMessages: ErrorMessage[];
11
+ }
12
+
13
+ interface ExceptionFormatter {
14
+ supports(exception: unknown): boolean;
15
+ format(exception: unknown): ErrorMessage[];
16
+ message(exception: unknown): string;
17
+ }
18
+
19
+ interface ExceptionHandlerConfig {
20
+ enableLogging?: boolean;
21
+ hideStackTrace?: boolean;
22
+ }
23
+
24
+ declare const DEFAULT_ERROR_MESSAGES: {
25
+ UNKNOWN_ERROR: string;
26
+ VALIDATION_ERROR: string;
27
+ DATABASE_ERROR: string;
28
+ NOT_FOUND: string;
29
+ UNAUTHORIZED: string;
30
+ FORBIDDEN: string;
31
+ CONFLICT: string;
32
+ BAD_REQUEST: string;
33
+ };
34
+ declare const PRISMA_ERROR_MESSAGES: Record<string, string>;
35
+ declare const DEFAULT_PATH = "unknown";
36
+
37
+ declare function isPrismaError(exception: unknown): boolean;
38
+
39
+ declare class PrismaExceptionFormatter implements ExceptionFormatter {
40
+ supports(exception: unknown): boolean;
41
+ format(exception: unknown): ErrorMessage[];
42
+ message(exception: unknown): string;
43
+ }
44
+
45
+ declare class DtoExceptionFormatter implements ExceptionFormatter {
46
+ supports(exception: unknown): boolean;
47
+ format(exception: unknown): ErrorMessage[];
48
+ message(exception: unknown): string;
49
+ private formatValidationErrors;
50
+ private formatChildrenErrors;
51
+ }
52
+
53
+ declare class HttpExceptionFormatter implements ExceptionFormatter {
54
+ supports(exception: unknown): boolean;
55
+ format(exception: unknown): ErrorMessage[];
56
+ message(exception: unknown): string;
57
+ }
58
+
59
+ declare class UnknownExceptionFormatter implements ExceptionFormatter {
60
+ supports(_exception: unknown): boolean;
61
+ format(_exception: unknown): ErrorMessage[];
62
+ message(_exception: unknown): string;
63
+ }
64
+
65
+ declare class ExceptionHandlerService {
66
+ private formatters;
67
+ private defaultFormatter;
68
+ constructor();
69
+ registerFormatter(formatter: ExceptionFormatter): void;
70
+ getFormatter(exception: unknown): ExceptionFormatter;
71
+ formatException(exception: unknown): {
72
+ errors: ErrorMessage[];
73
+ message: string;
74
+ };
75
+ formatErrors(exception: unknown): ErrorMessage[];
76
+ getErrorMessage(exception: unknown): string;
77
+ getAllFormatters(): ExceptionFormatter[];
78
+ }
79
+
80
+ declare class GlobalExceptionFilter implements ExceptionFilter {
81
+ private exceptionHandlerService;
82
+ private readonly logger;
83
+ private config;
84
+ constructor(exceptionHandlerService: ExceptionHandlerService, config?: ExceptionHandlerConfig);
85
+ catch(exception: unknown, host: ArgumentsHost): void;
86
+ private getStatusCode;
87
+ private logError;
88
+ }
89
+
90
+ declare class ExceptionHandlerModule {
91
+ static forRoot(config?: ExceptionHandlerConfig): DynamicModule;
92
+ static forFeature(config?: ExceptionHandlerConfig): DynamicModule;
93
+ }
94
+ declare function initializeFormatters(service: ExceptionHandlerService): void;
95
+
96
+ export { DEFAULT_ERROR_MESSAGES, DEFAULT_PATH, DtoExceptionFormatter, ErrorMessage, ExceptionFormatter, ExceptionHandlerConfig, ExceptionHandlerModule, ExceptionHandlerService, GlobalExceptionFilter, HttpExceptionFormatter, PRISMA_ERROR_MESSAGES, PrismaExceptionFormatter, StandardErrorResponse, UnknownExceptionFormatter, initializeFormatters, isPrismaError };
@@ -0,0 +1,96 @@
1
+ import { ExceptionFilter, ArgumentsHost, DynamicModule } from '@nestjs/common';
2
+
3
+ interface ErrorMessage {
4
+ path: string;
5
+ message: string;
6
+ }
7
+ interface StandardErrorResponse {
8
+ success: boolean;
9
+ message: string;
10
+ errorMessages: ErrorMessage[];
11
+ }
12
+
13
+ interface ExceptionFormatter {
14
+ supports(exception: unknown): boolean;
15
+ format(exception: unknown): ErrorMessage[];
16
+ message(exception: unknown): string;
17
+ }
18
+
19
+ interface ExceptionHandlerConfig {
20
+ enableLogging?: boolean;
21
+ hideStackTrace?: boolean;
22
+ }
23
+
24
+ declare const DEFAULT_ERROR_MESSAGES: {
25
+ UNKNOWN_ERROR: string;
26
+ VALIDATION_ERROR: string;
27
+ DATABASE_ERROR: string;
28
+ NOT_FOUND: string;
29
+ UNAUTHORIZED: string;
30
+ FORBIDDEN: string;
31
+ CONFLICT: string;
32
+ BAD_REQUEST: string;
33
+ };
34
+ declare const PRISMA_ERROR_MESSAGES: Record<string, string>;
35
+ declare const DEFAULT_PATH = "unknown";
36
+
37
+ declare function isPrismaError(exception: unknown): boolean;
38
+
39
+ declare class PrismaExceptionFormatter implements ExceptionFormatter {
40
+ supports(exception: unknown): boolean;
41
+ format(exception: unknown): ErrorMessage[];
42
+ message(exception: unknown): string;
43
+ }
44
+
45
+ declare class DtoExceptionFormatter implements ExceptionFormatter {
46
+ supports(exception: unknown): boolean;
47
+ format(exception: unknown): ErrorMessage[];
48
+ message(exception: unknown): string;
49
+ private formatValidationErrors;
50
+ private formatChildrenErrors;
51
+ }
52
+
53
+ declare class HttpExceptionFormatter implements ExceptionFormatter {
54
+ supports(exception: unknown): boolean;
55
+ format(exception: unknown): ErrorMessage[];
56
+ message(exception: unknown): string;
57
+ }
58
+
59
+ declare class UnknownExceptionFormatter implements ExceptionFormatter {
60
+ supports(_exception: unknown): boolean;
61
+ format(_exception: unknown): ErrorMessage[];
62
+ message(_exception: unknown): string;
63
+ }
64
+
65
+ declare class ExceptionHandlerService {
66
+ private formatters;
67
+ private defaultFormatter;
68
+ constructor();
69
+ registerFormatter(formatter: ExceptionFormatter): void;
70
+ getFormatter(exception: unknown): ExceptionFormatter;
71
+ formatException(exception: unknown): {
72
+ errors: ErrorMessage[];
73
+ message: string;
74
+ };
75
+ formatErrors(exception: unknown): ErrorMessage[];
76
+ getErrorMessage(exception: unknown): string;
77
+ getAllFormatters(): ExceptionFormatter[];
78
+ }
79
+
80
+ declare class GlobalExceptionFilter implements ExceptionFilter {
81
+ private exceptionHandlerService;
82
+ private readonly logger;
83
+ private config;
84
+ constructor(exceptionHandlerService: ExceptionHandlerService, config?: ExceptionHandlerConfig);
85
+ catch(exception: unknown, host: ArgumentsHost): void;
86
+ private getStatusCode;
87
+ private logError;
88
+ }
89
+
90
+ declare class ExceptionHandlerModule {
91
+ static forRoot(config?: ExceptionHandlerConfig): DynamicModule;
92
+ static forFeature(config?: ExceptionHandlerConfig): DynamicModule;
93
+ }
94
+ declare function initializeFormatters(service: ExceptionHandlerService): void;
95
+
96
+ export { DEFAULT_ERROR_MESSAGES, DEFAULT_PATH, DtoExceptionFormatter, ErrorMessage, ExceptionFormatter, ExceptionHandlerConfig, ExceptionHandlerModule, ExceptionHandlerService, GlobalExceptionFilter, HttpExceptionFormatter, PRISMA_ERROR_MESSAGES, PrismaExceptionFormatter, StandardErrorResponse, UnknownExceptionFormatter, initializeFormatters, isPrismaError };
package/dist/index.js ADDED
@@ -0,0 +1,384 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var __decorateClass = (decorators, target, key, kind) => {
20
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
21
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
22
+ if (decorator = decorators[i])
23
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
24
+ if (kind && result)
25
+ __defProp(target, key, result);
26
+ return result;
27
+ };
28
+
29
+ // src/index.ts
30
+ var src_exports = {};
31
+ __export(src_exports, {
32
+ DEFAULT_ERROR_MESSAGES: () => DEFAULT_ERROR_MESSAGES,
33
+ DEFAULT_PATH: () => DEFAULT_PATH,
34
+ DtoExceptionFormatter: () => DtoExceptionFormatter,
35
+ ExceptionHandlerModule: () => ExceptionHandlerModule,
36
+ ExceptionHandlerService: () => ExceptionHandlerService,
37
+ GlobalExceptionFilter: () => GlobalExceptionFilter,
38
+ HttpExceptionFormatter: () => HttpExceptionFormatter,
39
+ PRISMA_ERROR_MESSAGES: () => PRISMA_ERROR_MESSAGES,
40
+ PrismaExceptionFormatter: () => PrismaExceptionFormatter,
41
+ UnknownExceptionFormatter: () => UnknownExceptionFormatter,
42
+ initializeFormatters: () => initializeFormatters,
43
+ isPrismaError: () => isPrismaError
44
+ });
45
+ module.exports = __toCommonJS(src_exports);
46
+
47
+ // src/constants/default-messages.ts
48
+ var DEFAULT_ERROR_MESSAGES = {
49
+ UNKNOWN_ERROR: "An unexpected error occurred",
50
+ VALIDATION_ERROR: "Validation failed",
51
+ DATABASE_ERROR: "Database error",
52
+ NOT_FOUND: "Resource not found",
53
+ UNAUTHORIZED: "Unauthorized access",
54
+ FORBIDDEN: "Access forbidden",
55
+ CONFLICT: "Conflict occurred",
56
+ BAD_REQUEST: "Bad request"
57
+ };
58
+ var PRISMA_ERROR_MESSAGES = {
59
+ P2002: "A record with this {field} already exists.",
60
+ P2003: "This {field} does not exist.",
61
+ P2005: "Invalid value for {field}.",
62
+ P2006: "Invalid format for {field}.",
63
+ P2025: "Record not found."
64
+ };
65
+ var DEFAULT_PATH = "unknown";
66
+
67
+ // src/utils/is-prisma-error.ts
68
+ function isPrismaError(exception) {
69
+ if (!exception || typeof exception !== "object") {
70
+ return false;
71
+ }
72
+ const error = exception;
73
+ const hasErrorCode = typeof error.code === "string";
74
+ const hasClientVersion = typeof error.clientVersion === "string";
75
+ const hasMeta = typeof error.meta === "object";
76
+ return hasErrorCode && (hasClientVersion || hasMeta);
77
+ }
78
+
79
+ // src/formatters/prisma-exception.formatter.ts
80
+ var PrismaExceptionFormatter = class {
81
+ supports(exception) {
82
+ return isPrismaError(exception);
83
+ }
84
+ format(exception) {
85
+ const error = exception;
86
+ const code = error.code;
87
+ const meta = error.meta;
88
+ const target = error.target;
89
+ const messageTemplate = PRISMA_ERROR_MESSAGES[code] || "Database operation failed";
90
+ let path = "unknown";
91
+ let message = messageTemplate;
92
+ if (code === "P2002" && target && target.length > 0) {
93
+ path = target[0];
94
+ message = messageTemplate.replace("{field}", path);
95
+ } else if (code === "P2003" && meta?.field_name) {
96
+ path = meta.field_name;
97
+ message = messageTemplate.replace("{field}", path);
98
+ } else if (code === "P2005" && meta?.field_name) {
99
+ path = meta.field_name;
100
+ message = messageTemplate.replace("{field}", path);
101
+ } else if (code === "P2006" && meta?.field_name) {
102
+ path = meta.field_name;
103
+ message = messageTemplate.replace("{field}", path);
104
+ } else if (code === "P2025") {
105
+ path = "record";
106
+ message = messageTemplate;
107
+ }
108
+ return [{ path, message }];
109
+ }
110
+ message(exception) {
111
+ const error = exception;
112
+ const code = error.code;
113
+ return PRISMA_ERROR_MESSAGES[code] || "Database error";
114
+ }
115
+ };
116
+
117
+ // src/formatters/dto-exception.formatter.ts
118
+ var DtoExceptionFormatter = class {
119
+ supports(exception) {
120
+ if (!exception || typeof exception !== "object") {
121
+ return false;
122
+ }
123
+ const error = exception;
124
+ return Array.isArray(error.validationErrors) || Array.isArray(error.children) && error.constraints !== void 0;
125
+ }
126
+ format(exception) {
127
+ const error = exception;
128
+ const validationErrors = error.validationErrors;
129
+ const children = error.children;
130
+ if (validationErrors) {
131
+ return this.formatValidationErrors(validationErrors);
132
+ }
133
+ if (children) {
134
+ return this.formatChildrenErrors(children);
135
+ }
136
+ return [{ path: "unknown", message: "Validation failed" }];
137
+ }
138
+ message(exception) {
139
+ const error = exception;
140
+ const validationErrors = error.validationErrors;
141
+ const children = error.children;
142
+ if (validationErrors && validationErrors.length > 0) {
143
+ const firstError = validationErrors[0];
144
+ const constraints = firstError.constraints;
145
+ if (constraints) {
146
+ return Object.values(constraints)[0];
147
+ }
148
+ }
149
+ if (children && children.length > 0) {
150
+ return "Validation failed for nested fields";
151
+ }
152
+ return "Validation failed";
153
+ }
154
+ formatValidationErrors(errors) {
155
+ return errors.flatMap((error) => {
156
+ const constraints = error.constraints;
157
+ if (constraints) {
158
+ return Object.entries(constraints).map(([, value]) => ({
159
+ path: error.property,
160
+ message: value
161
+ }));
162
+ }
163
+ return [];
164
+ });
165
+ }
166
+ formatChildrenErrors(children) {
167
+ return children.flatMap((child) => {
168
+ const constraints = child.constraints;
169
+ if (constraints) {
170
+ return Object.entries(constraints).map(([, value]) => ({
171
+ path: child.property,
172
+ message: value
173
+ }));
174
+ }
175
+ return [];
176
+ });
177
+ }
178
+ };
179
+
180
+ // src/formatters/http-exception.formatter.ts
181
+ var import_common = require("@nestjs/common");
182
+ var HttpExceptionFormatter = class {
183
+ supports(exception) {
184
+ return exception instanceof import_common.HttpException;
185
+ }
186
+ format(exception) {
187
+ const httpException = exception;
188
+ const response = httpException.getResponse();
189
+ if (typeof response === "string") {
190
+ return [{ path: "unknown", message: response }];
191
+ }
192
+ if (typeof response === "object" && response !== null) {
193
+ const responseObj = response;
194
+ if (responseObj.message && Array.isArray(responseObj.message)) {
195
+ return responseObj.message.map((msg) => ({
196
+ path: "unknown",
197
+ message: msg
198
+ }));
199
+ }
200
+ if (responseObj.message && typeof responseObj.message === "string") {
201
+ return [{ path: "unknown", message: responseObj.message }];
202
+ }
203
+ if (responseObj.error && typeof responseObj.error === "string") {
204
+ return [{ path: "unknown", message: responseObj.error }];
205
+ }
206
+ }
207
+ return [{ path: "unknown", message: "An error occurred" }];
208
+ }
209
+ message(exception) {
210
+ const httpException = exception;
211
+ const response = httpException.getResponse();
212
+ if (typeof response === "string") {
213
+ return response;
214
+ }
215
+ if (typeof response === "object" && response !== null) {
216
+ const responseObj = response;
217
+ if (responseObj.message && typeof responseObj.message === "string") {
218
+ return responseObj.message;
219
+ }
220
+ if (responseObj.error && typeof responseObj.error === "string") {
221
+ return responseObj.error;
222
+ }
223
+ }
224
+ return "An error occurred";
225
+ }
226
+ };
227
+
228
+ // src/formatters/unknown-exception.formatter.ts
229
+ var UnknownExceptionFormatter = class {
230
+ supports(_exception) {
231
+ return true;
232
+ }
233
+ format(_exception) {
234
+ return [
235
+ {
236
+ path: DEFAULT_PATH,
237
+ message: "Internal server error"
238
+ }
239
+ ];
240
+ }
241
+ message(_exception) {
242
+ return "Internal server error";
243
+ }
244
+ };
245
+
246
+ // src/services/exception-handler.service.ts
247
+ var import_common2 = require("@nestjs/common");
248
+ var ExceptionHandlerService = class {
249
+ constructor() {
250
+ this.formatters = [];
251
+ this.defaultFormatter = new UnknownExceptionFormatter();
252
+ }
253
+ registerFormatter(formatter) {
254
+ this.formatters.push(formatter);
255
+ }
256
+ getFormatter(exception) {
257
+ for (const formatter of this.formatters) {
258
+ if (formatter.supports(exception)) {
259
+ return formatter;
260
+ }
261
+ }
262
+ return this.defaultFormatter;
263
+ }
264
+ formatException(exception) {
265
+ const formatter = this.getFormatter(exception);
266
+ const errors = formatter.format(exception);
267
+ const message = formatter.message(exception);
268
+ return { errors, message };
269
+ }
270
+ formatErrors(exception) {
271
+ const formatter = this.getFormatter(exception);
272
+ return formatter.format(exception);
273
+ }
274
+ getErrorMessage(exception) {
275
+ const formatter = this.getFormatter(exception);
276
+ return formatter.message(exception);
277
+ }
278
+ getAllFormatters() {
279
+ return [...this.formatters];
280
+ }
281
+ };
282
+ ExceptionHandlerService = __decorateClass([
283
+ (0, import_common2.Injectable)()
284
+ ], ExceptionHandlerService);
285
+
286
+ // src/filter/global-exception.filter.ts
287
+ var import_common3 = require("@nestjs/common");
288
+ var GlobalExceptionFilter = class {
289
+ constructor(exceptionHandlerService, config) {
290
+ this.exceptionHandlerService = exceptionHandlerService;
291
+ this.logger = new import_common3.Logger(GlobalExceptionFilter.name);
292
+ this.config = config || { enableLogging: true, hideStackTrace: false };
293
+ }
294
+ catch(exception, host) {
295
+ const ctx = host.switchToHttp();
296
+ const response = ctx.getResponse();
297
+ const request = ctx.getRequest();
298
+ const { errors, message } = this.exceptionHandlerService.formatException(exception);
299
+ const status = this.getStatusCode(exception);
300
+ const errorResponse = {
301
+ success: false,
302
+ message,
303
+ errorMessages: errors
304
+ };
305
+ if (this.config.enableLogging) {
306
+ this.logError(request, status, errors, exception);
307
+ }
308
+ response.status(status).json(errorResponse);
309
+ }
310
+ getStatusCode(exception) {
311
+ if (exception instanceof import_common3.HttpException) {
312
+ return exception.getStatus();
313
+ }
314
+ return import_common3.HttpStatus.INTERNAL_SERVER_ERROR;
315
+ }
316
+ logError(request, status, errorMessages, exception) {
317
+ const method = request.method;
318
+ const url = request.url;
319
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
320
+ const logData = {
321
+ timestamp,
322
+ method,
323
+ url,
324
+ status,
325
+ errorMessages,
326
+ stack: this.config.hideStackTrace ? void 0 : exception?.stack
327
+ };
328
+ this.logger.error(`${method} ${url} - ${status}`, JSON.stringify(logData));
329
+ }
330
+ };
331
+ GlobalExceptionFilter = __decorateClass([
332
+ (0, import_common3.Catch)()
333
+ ], GlobalExceptionFilter);
334
+
335
+ // src/module/exception-handler.module.ts
336
+ var import_common4 = require("@nestjs/common");
337
+ var ExceptionHandlerModule = class {
338
+ static forRoot(config) {
339
+ const providers = [
340
+ ExceptionHandlerService,
341
+ {
342
+ provide: GlobalExceptionFilter,
343
+ useFactory: (service) => {
344
+ return new GlobalExceptionFilter(service, config);
345
+ },
346
+ inject: [ExceptionHandlerService]
347
+ }
348
+ ];
349
+ return {
350
+ module: ExceptionHandlerModule,
351
+ providers,
352
+ exports: [ExceptionHandlerService, GlobalExceptionFilter],
353
+ global: true
354
+ };
355
+ }
356
+ static forFeature(config) {
357
+ return this.forRoot(config);
358
+ }
359
+ };
360
+ ExceptionHandlerModule = __decorateClass([
361
+ (0, import_common4.Module)({})
362
+ ], ExceptionHandlerModule);
363
+ function initializeFormatters(service) {
364
+ service.registerFormatter(new PrismaExceptionFormatter());
365
+ service.registerFormatter(new DtoExceptionFormatter());
366
+ service.registerFormatter(new HttpExceptionFormatter());
367
+ service.registerFormatter(new UnknownExceptionFormatter());
368
+ }
369
+ // Annotate the CommonJS export names for ESM import in node:
370
+ 0 && (module.exports = {
371
+ DEFAULT_ERROR_MESSAGES,
372
+ DEFAULT_PATH,
373
+ DtoExceptionFormatter,
374
+ ExceptionHandlerModule,
375
+ ExceptionHandlerService,
376
+ GlobalExceptionFilter,
377
+ HttpExceptionFormatter,
378
+ PRISMA_ERROR_MESSAGES,
379
+ PrismaExceptionFormatter,
380
+ UnknownExceptionFormatter,
381
+ initializeFormatters,
382
+ isPrismaError
383
+ });
384
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/constants/default-messages.ts","../src/utils/is-prisma-error.ts","../src/formatters/prisma-exception.formatter.ts","../src/formatters/dto-exception.formatter.ts","../src/formatters/http-exception.formatter.ts","../src/formatters/unknown-exception.formatter.ts","../src/services/exception-handler.service.ts","../src/filter/global-exception.filter.ts","../src/module/exception-handler.module.ts"],"sourcesContent":["// Interfaces\nexport * from './interfaces';\n\n// Constants\nexport * from './constants';\n\n// Utilities\nexport * from './utils/is-prisma-error';\n\n// Formatters\nexport * from './formatters';\n\n// Services\nexport * from './services/exception-handler.service';\n\n// Filters\nexport * from './filter/global-exception.filter';\n\n// Module\nexport * from './module/exception-handler.module';\n","export const DEFAULT_ERROR_MESSAGES = {\n UNKNOWN_ERROR: 'An unexpected error occurred',\n VALIDATION_ERROR: 'Validation failed',\n DATABASE_ERROR: 'Database error',\n NOT_FOUND: 'Resource not found',\n UNAUTHORIZED: 'Unauthorized access',\n FORBIDDEN: 'Access forbidden',\n CONFLICT: 'Conflict occurred',\n BAD_REQUEST: 'Bad request',\n};\n\nexport const PRISMA_ERROR_MESSAGES: Record<string, string> = {\n P2002: 'A record with this {field} already exists.',\n P2003: 'This {field} does not exist.',\n P2005: 'Invalid value for {field}.',\n P2006: 'Invalid format for {field}.',\n P2025: 'Record not found.',\n};\n\nexport const DEFAULT_PATH = 'unknown';\n","export function isPrismaError(exception: unknown): boolean {\n if (!exception || typeof exception !== 'object') {\n return false;\n }\n\n const error = exception as Record<string, unknown>;\n\n // Check for Prisma error characteristics\n const hasErrorCode = typeof error.code === 'string';\n const hasClientVersion = typeof error.clientVersion === 'string';\n const hasMeta = typeof error.meta === 'object';\n\n // Prisma errors typically have these properties\n return hasErrorCode && (hasClientVersion || hasMeta);\n}\n","import { ExceptionFormatter } from '../interfaces/exception-formatter.interface';\nimport { ErrorMessage } from '../interfaces/error-message.interface';\nimport { isPrismaError } from '../utils/is-prisma-error';\nimport { PRISMA_ERROR_MESSAGES } from '../constants/default-messages';\n\nexport class PrismaExceptionFormatter implements ExceptionFormatter {\n supports(exception: unknown): boolean {\n return isPrismaError(exception);\n }\n\n format(exception: unknown): ErrorMessage[] {\n const error = exception as Record<string, unknown>;\n const code = error.code as string;\n const meta = error.meta as Record<string, string> | undefined;\n const target = error.target as string[] | undefined;\n\n const messageTemplate = PRISMA_ERROR_MESSAGES[code] || 'Database operation failed';\n let path = 'unknown';\n let message = messageTemplate;\n\n if (code === 'P2002' && target && target.length > 0) {\n path = target[0];\n message = messageTemplate.replace('{field}', path);\n } else if (code === 'P2003' && meta?.field_name) {\n path = meta.field_name;\n message = messageTemplate.replace('{field}', path);\n } else if (code === 'P2005' && meta?.field_name) {\n path = meta.field_name;\n message = messageTemplate.replace('{field}', path);\n } else if (code === 'P2006' && meta?.field_name) {\n path = meta.field_name;\n message = messageTemplate.replace('{field}', path);\n } else if (code === 'P2025') {\n path = 'record';\n message = messageTemplate;\n }\n\n return [{ path, message }];\n }\n\n message(exception: unknown): string {\n const error = exception as Record<string, unknown>;\n const code = error.code as string;\n return PRISMA_ERROR_MESSAGES[code] || 'Database error';\n }\n}\n","import { ValidationError } from '@nestjs/common';\nimport { ExceptionFormatter } from '../interfaces/exception-formatter.interface';\nimport { ErrorMessage } from '../interfaces/error-message.interface';\n\nexport class DtoExceptionFormatter implements ExceptionFormatter {\n supports(exception: unknown): boolean {\n if (!exception || typeof exception !== 'object') {\n return false;\n }\n\n const error = exception as Record<string, unknown>;\n return (\n Array.isArray(error.validationErrors) ||\n (Array.isArray(error.children) && error.constraints !== undefined)\n );\n }\n\n format(exception: unknown): ErrorMessage[] {\n const error = exception as Record<string, unknown>;\n const validationErrors = error.validationErrors as ValidationError[] | undefined;\n const children = error.children as ValidationError[] | undefined;\n\n if (validationErrors) {\n return this.formatValidationErrors(validationErrors);\n }\n\n if (children) {\n return this.formatChildrenErrors(children);\n }\n\n return [{ path: 'unknown', message: 'Validation failed' }];\n }\n\n message(exception: unknown): string {\n const error = exception as Record<string, unknown>;\n const validationErrors = error.validationErrors as ValidationError[] | undefined;\n const children = error.children as ValidationError[] | undefined;\n\n if (validationErrors && validationErrors.length > 0) {\n const firstError = validationErrors[0];\n const constraints = firstError.constraints;\n if (constraints) {\n return Object.values(constraints)[0];\n }\n }\n\n if (children && children.length > 0) {\n return 'Validation failed for nested fields';\n }\n\n return 'Validation failed';\n }\n\n private formatValidationErrors(errors: ValidationError[]): ErrorMessage[] {\n return errors.flatMap((error) => {\n const constraints = error.constraints;\n if (constraints) {\n return Object.entries(constraints).map(([, value]) => ({\n path: error.property,\n message: value,\n }));\n }\n return [];\n });\n }\n\n private formatChildrenErrors(children: ValidationError[]): ErrorMessage[] {\n return children.flatMap((child) => {\n const constraints = child.constraints;\n if (constraints) {\n return Object.entries(constraints).map(([, value]) => ({\n path: child.property,\n message: value,\n }));\n }\n return [];\n });\n }\n}\n","import { HttpException } from '@nestjs/common';\nimport { ExceptionFormatter } from '../interfaces/exception-formatter.interface';\nimport { ErrorMessage } from '../interfaces/error-message.interface';\n\nexport class HttpExceptionFormatter implements ExceptionFormatter {\n supports(exception: unknown): boolean {\n return exception instanceof HttpException;\n }\n\n format(exception: unknown): ErrorMessage[] {\n const httpException = exception as HttpException;\n const response = httpException.getResponse();\n\n if (typeof response === 'string') {\n return [{ path: 'unknown', message: response }];\n }\n\n if (typeof response === 'object' && response !== null) {\n const responseObj = response as Record<string, unknown>;\n\n if (responseObj.message && Array.isArray(responseObj.message)) {\n // Handle validation errors from class-validator in HTTP exceptions\n return (responseObj.message as string[]).map((msg) => ({\n path: 'unknown',\n message: msg,\n }));\n }\n\n if (responseObj.message && typeof responseObj.message === 'string') {\n return [{ path: 'unknown', message: responseObj.message }];\n }\n\n if (responseObj.error && typeof responseObj.error === 'string') {\n return [{ path: 'unknown', message: responseObj.error }];\n }\n }\n\n return [{ path: 'unknown', message: 'An error occurred' }];\n }\n\n message(exception: unknown): string {\n const httpException = exception as HttpException;\n const response = httpException.getResponse();\n\n if (typeof response === 'string') {\n return response;\n }\n\n if (typeof response === 'object' && response !== null) {\n const responseObj = response as Record<string, unknown>;\n\n if (responseObj.message && typeof responseObj.message === 'string') {\n return responseObj.message;\n }\n\n if (responseObj.error && typeof responseObj.error === 'string') {\n return responseObj.error;\n }\n }\n\n return 'An error occurred';\n }\n}\n","import { ExceptionFormatter } from '../interfaces/exception-formatter.interface';\nimport { ErrorMessage } from '../interfaces/error-message.interface';\nimport { DEFAULT_PATH } from '../constants/default-messages';\n\nexport class UnknownExceptionFormatter implements ExceptionFormatter {\n supports(_exception: unknown): boolean {\n return true;\n }\n\n format(_exception: unknown): ErrorMessage[] {\n return [\n {\n path: DEFAULT_PATH,\n message: 'Internal server error',\n },\n ];\n }\n\n message(_exception: unknown): string {\n return 'Internal server error';\n }\n}\n","import { Injectable } from '@nestjs/common';\nimport { ExceptionFormatter } from '../interfaces/exception-formatter.interface';\nimport { ErrorMessage } from '../interfaces/error-message.interface';\nimport { UnknownExceptionFormatter } from '../formatters/unknown-exception.formatter';\n\n@Injectable()\nexport class ExceptionHandlerService {\n private formatters: ExceptionFormatter[] = [];\n private defaultFormatter: ExceptionFormatter;\n\n constructor() {\n this.defaultFormatter = new UnknownExceptionFormatter();\n }\n\n registerFormatter(formatter: ExceptionFormatter): void {\n this.formatters.push(formatter);\n }\n\n getFormatter(exception: unknown): ExceptionFormatter {\n for (const formatter of this.formatters) {\n if (formatter.supports(exception)) {\n return formatter;\n }\n }\n return this.defaultFormatter;\n }\n\n formatException(exception: unknown): { errors: ErrorMessage[]; message: string } {\n const formatter = this.getFormatter(exception);\n const errors = formatter.format(exception);\n const message = formatter.message(exception);\n\n return { errors, message };\n }\n\n formatErrors(exception: unknown): ErrorMessage[] {\n const formatter = this.getFormatter(exception);\n return formatter.format(exception);\n }\n\n getErrorMessage(exception: unknown): string {\n const formatter = this.getFormatter(exception);\n return formatter.message(exception);\n }\n\n getAllFormatters(): ExceptionFormatter[] {\n return [...this.formatters];\n }\n}\n","import {\n ExceptionFilter,\n Catch,\n ArgumentsHost,\n HttpException,\n HttpStatus,\n Logger,\n} from '@nestjs/common';\nimport { Request, Response } from 'express';\nimport { ExceptionHandlerService } from '../services/exception-handler.service';\nimport { StandardErrorResponse } from '../interfaces/error-message.interface';\nimport { ExceptionHandlerConfig } from '../interfaces/exception-handler-config.interface';\n\n@Catch()\nexport class GlobalExceptionFilter implements ExceptionFilter {\n private readonly logger = new Logger(GlobalExceptionFilter.name);\n private config: ExceptionHandlerConfig;\n\n constructor(\n private exceptionHandlerService: ExceptionHandlerService,\n config?: ExceptionHandlerConfig,\n ) {\n this.config = config || { enableLogging: true, hideStackTrace: false };\n }\n\n catch(exception: unknown, host: ArgumentsHost): void {\n const ctx = host.switchToHttp();\n const response = ctx.getResponse<Response>();\n const request = ctx.getRequest<Request>();\n\n const { errors, message } = this.exceptionHandlerService.formatException(exception);\n const status = this.getStatusCode(exception);\n\n const errorResponse: StandardErrorResponse = {\n success: false,\n message,\n errorMessages: errors,\n };\n\n if (this.config.enableLogging) {\n this.logError(request, status, errors, exception);\n }\n\n response.status(status).json(errorResponse);\n }\n\n private getStatusCode(exception: unknown): number {\n if (exception instanceof HttpException) {\n return exception.getStatus();\n }\n return HttpStatus.INTERNAL_SERVER_ERROR;\n }\n\n private logError(\n request: Request,\n status: number,\n errorMessages: { path: string; message: string }[],\n exception: unknown,\n ): void {\n const method = request.method;\n const url = request.url;\n const timestamp = new Date().toISOString();\n\n const logData = {\n timestamp,\n method,\n url,\n status,\n errorMessages,\n stack: this.config.hideStackTrace ? undefined : (exception as Error)?.stack,\n };\n\n this.logger.error(`${method} ${url} - ${status}`, JSON.stringify(logData));\n }\n}\n","import { DynamicModule, Module } from '@nestjs/common';\nimport { ExceptionHandlerService } from '../services/exception-handler.service';\nimport { GlobalExceptionFilter } from '../filter/global-exception.filter';\nimport { ExceptionHandlerConfig } from '../interfaces/exception-handler-config.interface';\nimport { PrismaExceptionFormatter } from '../formatters/prisma-exception.formatter';\nimport { DtoExceptionFormatter } from '../formatters/dto-exception.formatter';\nimport { HttpExceptionFormatter } from '../formatters/http-exception.formatter';\nimport { UnknownExceptionFormatter } from '../formatters/unknown-exception.formatter';\n\n@Module({})\nexport class ExceptionHandlerModule {\n static forRoot(config?: ExceptionHandlerConfig): DynamicModule {\n const providers = [\n ExceptionHandlerService,\n {\n provide: GlobalExceptionFilter,\n useFactory: (service: ExceptionHandlerService) => {\n return new GlobalExceptionFilter(service, config);\n },\n inject: [ExceptionHandlerService],\n },\n ];\n\n return {\n module: ExceptionHandlerModule,\n providers,\n exports: [ExceptionHandlerService, GlobalExceptionFilter],\n global: true,\n };\n }\n\n static forFeature(config?: ExceptionHandlerConfig): DynamicModule {\n return this.forRoot(config);\n }\n}\n\n// Initialize formatters\nexport function initializeFormatters(service: ExceptionHandlerService): void {\n service.registerFormatter(new PrismaExceptionFormatter());\n service.registerFormatter(new DtoExceptionFormatter());\n service.registerFormatter(new HttpExceptionFormatter());\n service.registerFormatter(new UnknownExceptionFormatter());\n}\n"],"mappings":"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","names":["import_common","import_common","import_common"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,354 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result)
9
+ __defProp(target, key, result);
10
+ return result;
11
+ };
12
+
13
+ // src/constants/default-messages.ts
14
+ var DEFAULT_ERROR_MESSAGES = {
15
+ UNKNOWN_ERROR: "An unexpected error occurred",
16
+ VALIDATION_ERROR: "Validation failed",
17
+ DATABASE_ERROR: "Database error",
18
+ NOT_FOUND: "Resource not found",
19
+ UNAUTHORIZED: "Unauthorized access",
20
+ FORBIDDEN: "Access forbidden",
21
+ CONFLICT: "Conflict occurred",
22
+ BAD_REQUEST: "Bad request"
23
+ };
24
+ var PRISMA_ERROR_MESSAGES = {
25
+ P2002: "A record with this {field} already exists.",
26
+ P2003: "This {field} does not exist.",
27
+ P2005: "Invalid value for {field}.",
28
+ P2006: "Invalid format for {field}.",
29
+ P2025: "Record not found."
30
+ };
31
+ var DEFAULT_PATH = "unknown";
32
+
33
+ // src/utils/is-prisma-error.ts
34
+ function isPrismaError(exception) {
35
+ if (!exception || typeof exception !== "object") {
36
+ return false;
37
+ }
38
+ const error = exception;
39
+ const hasErrorCode = typeof error.code === "string";
40
+ const hasClientVersion = typeof error.clientVersion === "string";
41
+ const hasMeta = typeof error.meta === "object";
42
+ return hasErrorCode && (hasClientVersion || hasMeta);
43
+ }
44
+
45
+ // src/formatters/prisma-exception.formatter.ts
46
+ var PrismaExceptionFormatter = class {
47
+ supports(exception) {
48
+ return isPrismaError(exception);
49
+ }
50
+ format(exception) {
51
+ const error = exception;
52
+ const code = error.code;
53
+ const meta = error.meta;
54
+ const target = error.target;
55
+ const messageTemplate = PRISMA_ERROR_MESSAGES[code] || "Database operation failed";
56
+ let path = "unknown";
57
+ let message = messageTemplate;
58
+ if (code === "P2002" && target && target.length > 0) {
59
+ path = target[0];
60
+ message = messageTemplate.replace("{field}", path);
61
+ } else if (code === "P2003" && meta?.field_name) {
62
+ path = meta.field_name;
63
+ message = messageTemplate.replace("{field}", path);
64
+ } else if (code === "P2005" && meta?.field_name) {
65
+ path = meta.field_name;
66
+ message = messageTemplate.replace("{field}", path);
67
+ } else if (code === "P2006" && meta?.field_name) {
68
+ path = meta.field_name;
69
+ message = messageTemplate.replace("{field}", path);
70
+ } else if (code === "P2025") {
71
+ path = "record";
72
+ message = messageTemplate;
73
+ }
74
+ return [{ path, message }];
75
+ }
76
+ message(exception) {
77
+ const error = exception;
78
+ const code = error.code;
79
+ return PRISMA_ERROR_MESSAGES[code] || "Database error";
80
+ }
81
+ };
82
+
83
+ // src/formatters/dto-exception.formatter.ts
84
+ var DtoExceptionFormatter = class {
85
+ supports(exception) {
86
+ if (!exception || typeof exception !== "object") {
87
+ return false;
88
+ }
89
+ const error = exception;
90
+ return Array.isArray(error.validationErrors) || Array.isArray(error.children) && error.constraints !== void 0;
91
+ }
92
+ format(exception) {
93
+ const error = exception;
94
+ const validationErrors = error.validationErrors;
95
+ const children = error.children;
96
+ if (validationErrors) {
97
+ return this.formatValidationErrors(validationErrors);
98
+ }
99
+ if (children) {
100
+ return this.formatChildrenErrors(children);
101
+ }
102
+ return [{ path: "unknown", message: "Validation failed" }];
103
+ }
104
+ message(exception) {
105
+ const error = exception;
106
+ const validationErrors = error.validationErrors;
107
+ const children = error.children;
108
+ if (validationErrors && validationErrors.length > 0) {
109
+ const firstError = validationErrors[0];
110
+ const constraints = firstError.constraints;
111
+ if (constraints) {
112
+ return Object.values(constraints)[0];
113
+ }
114
+ }
115
+ if (children && children.length > 0) {
116
+ return "Validation failed for nested fields";
117
+ }
118
+ return "Validation failed";
119
+ }
120
+ formatValidationErrors(errors) {
121
+ return errors.flatMap((error) => {
122
+ const constraints = error.constraints;
123
+ if (constraints) {
124
+ return Object.entries(constraints).map(([, value]) => ({
125
+ path: error.property,
126
+ message: value
127
+ }));
128
+ }
129
+ return [];
130
+ });
131
+ }
132
+ formatChildrenErrors(children) {
133
+ return children.flatMap((child) => {
134
+ const constraints = child.constraints;
135
+ if (constraints) {
136
+ return Object.entries(constraints).map(([, value]) => ({
137
+ path: child.property,
138
+ message: value
139
+ }));
140
+ }
141
+ return [];
142
+ });
143
+ }
144
+ };
145
+
146
+ // src/formatters/http-exception.formatter.ts
147
+ import { HttpException } from "@nestjs/common";
148
+ var HttpExceptionFormatter = class {
149
+ supports(exception) {
150
+ return exception instanceof HttpException;
151
+ }
152
+ format(exception) {
153
+ const httpException = exception;
154
+ const response = httpException.getResponse();
155
+ if (typeof response === "string") {
156
+ return [{ path: "unknown", message: response }];
157
+ }
158
+ if (typeof response === "object" && response !== null) {
159
+ const responseObj = response;
160
+ if (responseObj.message && Array.isArray(responseObj.message)) {
161
+ return responseObj.message.map((msg) => ({
162
+ path: "unknown",
163
+ message: msg
164
+ }));
165
+ }
166
+ if (responseObj.message && typeof responseObj.message === "string") {
167
+ return [{ path: "unknown", message: responseObj.message }];
168
+ }
169
+ if (responseObj.error && typeof responseObj.error === "string") {
170
+ return [{ path: "unknown", message: responseObj.error }];
171
+ }
172
+ }
173
+ return [{ path: "unknown", message: "An error occurred" }];
174
+ }
175
+ message(exception) {
176
+ const httpException = exception;
177
+ const response = httpException.getResponse();
178
+ if (typeof response === "string") {
179
+ return response;
180
+ }
181
+ if (typeof response === "object" && response !== null) {
182
+ const responseObj = response;
183
+ if (responseObj.message && typeof responseObj.message === "string") {
184
+ return responseObj.message;
185
+ }
186
+ if (responseObj.error && typeof responseObj.error === "string") {
187
+ return responseObj.error;
188
+ }
189
+ }
190
+ return "An error occurred";
191
+ }
192
+ };
193
+
194
+ // src/formatters/unknown-exception.formatter.ts
195
+ var UnknownExceptionFormatter = class {
196
+ supports(_exception) {
197
+ return true;
198
+ }
199
+ format(_exception) {
200
+ return [
201
+ {
202
+ path: DEFAULT_PATH,
203
+ message: "Internal server error"
204
+ }
205
+ ];
206
+ }
207
+ message(_exception) {
208
+ return "Internal server error";
209
+ }
210
+ };
211
+
212
+ // src/services/exception-handler.service.ts
213
+ import { Injectable } from "@nestjs/common";
214
+ var ExceptionHandlerService = class {
215
+ constructor() {
216
+ this.formatters = [];
217
+ this.defaultFormatter = new UnknownExceptionFormatter();
218
+ }
219
+ registerFormatter(formatter) {
220
+ this.formatters.push(formatter);
221
+ }
222
+ getFormatter(exception) {
223
+ for (const formatter of this.formatters) {
224
+ if (formatter.supports(exception)) {
225
+ return formatter;
226
+ }
227
+ }
228
+ return this.defaultFormatter;
229
+ }
230
+ formatException(exception) {
231
+ const formatter = this.getFormatter(exception);
232
+ const errors = formatter.format(exception);
233
+ const message = formatter.message(exception);
234
+ return { errors, message };
235
+ }
236
+ formatErrors(exception) {
237
+ const formatter = this.getFormatter(exception);
238
+ return formatter.format(exception);
239
+ }
240
+ getErrorMessage(exception) {
241
+ const formatter = this.getFormatter(exception);
242
+ return formatter.message(exception);
243
+ }
244
+ getAllFormatters() {
245
+ return [...this.formatters];
246
+ }
247
+ };
248
+ ExceptionHandlerService = __decorateClass([
249
+ Injectable()
250
+ ], ExceptionHandlerService);
251
+
252
+ // src/filter/global-exception.filter.ts
253
+ import {
254
+ Catch,
255
+ HttpException as HttpException2,
256
+ HttpStatus,
257
+ Logger
258
+ } from "@nestjs/common";
259
+ var GlobalExceptionFilter = class {
260
+ constructor(exceptionHandlerService, config) {
261
+ this.exceptionHandlerService = exceptionHandlerService;
262
+ this.logger = new Logger(GlobalExceptionFilter.name);
263
+ this.config = config || { enableLogging: true, hideStackTrace: false };
264
+ }
265
+ catch(exception, host) {
266
+ const ctx = host.switchToHttp();
267
+ const response = ctx.getResponse();
268
+ const request = ctx.getRequest();
269
+ const { errors, message } = this.exceptionHandlerService.formatException(exception);
270
+ const status = this.getStatusCode(exception);
271
+ const errorResponse = {
272
+ success: false,
273
+ message,
274
+ errorMessages: errors
275
+ };
276
+ if (this.config.enableLogging) {
277
+ this.logError(request, status, errors, exception);
278
+ }
279
+ response.status(status).json(errorResponse);
280
+ }
281
+ getStatusCode(exception) {
282
+ if (exception instanceof HttpException2) {
283
+ return exception.getStatus();
284
+ }
285
+ return HttpStatus.INTERNAL_SERVER_ERROR;
286
+ }
287
+ logError(request, status, errorMessages, exception) {
288
+ const method = request.method;
289
+ const url = request.url;
290
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
291
+ const logData = {
292
+ timestamp,
293
+ method,
294
+ url,
295
+ status,
296
+ errorMessages,
297
+ stack: this.config.hideStackTrace ? void 0 : exception?.stack
298
+ };
299
+ this.logger.error(`${method} ${url} - ${status}`, JSON.stringify(logData));
300
+ }
301
+ };
302
+ GlobalExceptionFilter = __decorateClass([
303
+ Catch()
304
+ ], GlobalExceptionFilter);
305
+
306
+ // src/module/exception-handler.module.ts
307
+ import { Module } from "@nestjs/common";
308
+ var ExceptionHandlerModule = class {
309
+ static forRoot(config) {
310
+ const providers = [
311
+ ExceptionHandlerService,
312
+ {
313
+ provide: GlobalExceptionFilter,
314
+ useFactory: (service) => {
315
+ return new GlobalExceptionFilter(service, config);
316
+ },
317
+ inject: [ExceptionHandlerService]
318
+ }
319
+ ];
320
+ return {
321
+ module: ExceptionHandlerModule,
322
+ providers,
323
+ exports: [ExceptionHandlerService, GlobalExceptionFilter],
324
+ global: true
325
+ };
326
+ }
327
+ static forFeature(config) {
328
+ return this.forRoot(config);
329
+ }
330
+ };
331
+ ExceptionHandlerModule = __decorateClass([
332
+ Module({})
333
+ ], ExceptionHandlerModule);
334
+ function initializeFormatters(service) {
335
+ service.registerFormatter(new PrismaExceptionFormatter());
336
+ service.registerFormatter(new DtoExceptionFormatter());
337
+ service.registerFormatter(new HttpExceptionFormatter());
338
+ service.registerFormatter(new UnknownExceptionFormatter());
339
+ }
340
+ export {
341
+ DEFAULT_ERROR_MESSAGES,
342
+ DEFAULT_PATH,
343
+ DtoExceptionFormatter,
344
+ ExceptionHandlerModule,
345
+ ExceptionHandlerService,
346
+ GlobalExceptionFilter,
347
+ HttpExceptionFormatter,
348
+ PRISMA_ERROR_MESSAGES,
349
+ PrismaExceptionFormatter,
350
+ UnknownExceptionFormatter,
351
+ initializeFormatters,
352
+ isPrismaError
353
+ };
354
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants/default-messages.ts","../src/utils/is-prisma-error.ts","../src/formatters/prisma-exception.formatter.ts","../src/formatters/dto-exception.formatter.ts","../src/formatters/http-exception.formatter.ts","../src/formatters/unknown-exception.formatter.ts","../src/services/exception-handler.service.ts","../src/filter/global-exception.filter.ts","../src/module/exception-handler.module.ts"],"sourcesContent":["export const DEFAULT_ERROR_MESSAGES = {\n UNKNOWN_ERROR: 'An unexpected error occurred',\n VALIDATION_ERROR: 'Validation failed',\n DATABASE_ERROR: 'Database error',\n NOT_FOUND: 'Resource not found',\n UNAUTHORIZED: 'Unauthorized access',\n FORBIDDEN: 'Access forbidden',\n CONFLICT: 'Conflict occurred',\n BAD_REQUEST: 'Bad request',\n};\n\nexport const PRISMA_ERROR_MESSAGES: Record<string, string> = {\n P2002: 'A record with this {field} already exists.',\n P2003: 'This {field} does not exist.',\n P2005: 'Invalid value for {field}.',\n P2006: 'Invalid format for {field}.',\n P2025: 'Record not found.',\n};\n\nexport const DEFAULT_PATH = 'unknown';\n","export function isPrismaError(exception: unknown): boolean {\n if (!exception || typeof exception !== 'object') {\n return false;\n }\n\n const error = exception as Record<string, unknown>;\n\n // Check for Prisma error characteristics\n const hasErrorCode = typeof error.code === 'string';\n const hasClientVersion = typeof error.clientVersion === 'string';\n const hasMeta = typeof error.meta === 'object';\n\n // Prisma errors typically have these properties\n return hasErrorCode && (hasClientVersion || hasMeta);\n}\n","import { ExceptionFormatter } from '../interfaces/exception-formatter.interface';\nimport { ErrorMessage } from '../interfaces/error-message.interface';\nimport { isPrismaError } from '../utils/is-prisma-error';\nimport { PRISMA_ERROR_MESSAGES } from '../constants/default-messages';\n\nexport class PrismaExceptionFormatter implements ExceptionFormatter {\n supports(exception: unknown): boolean {\n return isPrismaError(exception);\n }\n\n format(exception: unknown): ErrorMessage[] {\n const error = exception as Record<string, unknown>;\n const code = error.code as string;\n const meta = error.meta as Record<string, string> | undefined;\n const target = error.target as string[] | undefined;\n\n const messageTemplate = PRISMA_ERROR_MESSAGES[code] || 'Database operation failed';\n let path = 'unknown';\n let message = messageTemplate;\n\n if (code === 'P2002' && target && target.length > 0) {\n path = target[0];\n message = messageTemplate.replace('{field}', path);\n } else if (code === 'P2003' && meta?.field_name) {\n path = meta.field_name;\n message = messageTemplate.replace('{field}', path);\n } else if (code === 'P2005' && meta?.field_name) {\n path = meta.field_name;\n message = messageTemplate.replace('{field}', path);\n } else if (code === 'P2006' && meta?.field_name) {\n path = meta.field_name;\n message = messageTemplate.replace('{field}', path);\n } else if (code === 'P2025') {\n path = 'record';\n message = messageTemplate;\n }\n\n return [{ path, message }];\n }\n\n message(exception: unknown): string {\n const error = exception as Record<string, unknown>;\n const code = error.code as string;\n return PRISMA_ERROR_MESSAGES[code] || 'Database error';\n }\n}\n","import { ValidationError } from '@nestjs/common';\nimport { ExceptionFormatter } from '../interfaces/exception-formatter.interface';\nimport { ErrorMessage } from '../interfaces/error-message.interface';\n\nexport class DtoExceptionFormatter implements ExceptionFormatter {\n supports(exception: unknown): boolean {\n if (!exception || typeof exception !== 'object') {\n return false;\n }\n\n const error = exception as Record<string, unknown>;\n return (\n Array.isArray(error.validationErrors) ||\n (Array.isArray(error.children) && error.constraints !== undefined)\n );\n }\n\n format(exception: unknown): ErrorMessage[] {\n const error = exception as Record<string, unknown>;\n const validationErrors = error.validationErrors as ValidationError[] | undefined;\n const children = error.children as ValidationError[] | undefined;\n\n if (validationErrors) {\n return this.formatValidationErrors(validationErrors);\n }\n\n if (children) {\n return this.formatChildrenErrors(children);\n }\n\n return [{ path: 'unknown', message: 'Validation failed' }];\n }\n\n message(exception: unknown): string {\n const error = exception as Record<string, unknown>;\n const validationErrors = error.validationErrors as ValidationError[] | undefined;\n const children = error.children as ValidationError[] | undefined;\n\n if (validationErrors && validationErrors.length > 0) {\n const firstError = validationErrors[0];\n const constraints = firstError.constraints;\n if (constraints) {\n return Object.values(constraints)[0];\n }\n }\n\n if (children && children.length > 0) {\n return 'Validation failed for nested fields';\n }\n\n return 'Validation failed';\n }\n\n private formatValidationErrors(errors: ValidationError[]): ErrorMessage[] {\n return errors.flatMap((error) => {\n const constraints = error.constraints;\n if (constraints) {\n return Object.entries(constraints).map(([, value]) => ({\n path: error.property,\n message: value,\n }));\n }\n return [];\n });\n }\n\n private formatChildrenErrors(children: ValidationError[]): ErrorMessage[] {\n return children.flatMap((child) => {\n const constraints = child.constraints;\n if (constraints) {\n return Object.entries(constraints).map(([, value]) => ({\n path: child.property,\n message: value,\n }));\n }\n return [];\n });\n }\n}\n","import { HttpException } from '@nestjs/common';\nimport { ExceptionFormatter } from '../interfaces/exception-formatter.interface';\nimport { ErrorMessage } from '../interfaces/error-message.interface';\n\nexport class HttpExceptionFormatter implements ExceptionFormatter {\n supports(exception: unknown): boolean {\n return exception instanceof HttpException;\n }\n\n format(exception: unknown): ErrorMessage[] {\n const httpException = exception as HttpException;\n const response = httpException.getResponse();\n\n if (typeof response === 'string') {\n return [{ path: 'unknown', message: response }];\n }\n\n if (typeof response === 'object' && response !== null) {\n const responseObj = response as Record<string, unknown>;\n\n if (responseObj.message && Array.isArray(responseObj.message)) {\n // Handle validation errors from class-validator in HTTP exceptions\n return (responseObj.message as string[]).map((msg) => ({\n path: 'unknown',\n message: msg,\n }));\n }\n\n if (responseObj.message && typeof responseObj.message === 'string') {\n return [{ path: 'unknown', message: responseObj.message }];\n }\n\n if (responseObj.error && typeof responseObj.error === 'string') {\n return [{ path: 'unknown', message: responseObj.error }];\n }\n }\n\n return [{ path: 'unknown', message: 'An error occurred' }];\n }\n\n message(exception: unknown): string {\n const httpException = exception as HttpException;\n const response = httpException.getResponse();\n\n if (typeof response === 'string') {\n return response;\n }\n\n if (typeof response === 'object' && response !== null) {\n const responseObj = response as Record<string, unknown>;\n\n if (responseObj.message && typeof responseObj.message === 'string') {\n return responseObj.message;\n }\n\n if (responseObj.error && typeof responseObj.error === 'string') {\n return responseObj.error;\n }\n }\n\n return 'An error occurred';\n }\n}\n","import { ExceptionFormatter } from '../interfaces/exception-formatter.interface';\nimport { ErrorMessage } from '../interfaces/error-message.interface';\nimport { DEFAULT_PATH } from '../constants/default-messages';\n\nexport class UnknownExceptionFormatter implements ExceptionFormatter {\n supports(_exception: unknown): boolean {\n return true;\n }\n\n format(_exception: unknown): ErrorMessage[] {\n return [\n {\n path: DEFAULT_PATH,\n message: 'Internal server error',\n },\n ];\n }\n\n message(_exception: unknown): string {\n return 'Internal server error';\n }\n}\n","import { Injectable } from '@nestjs/common';\nimport { ExceptionFormatter } from '../interfaces/exception-formatter.interface';\nimport { ErrorMessage } from '../interfaces/error-message.interface';\nimport { UnknownExceptionFormatter } from '../formatters/unknown-exception.formatter';\n\n@Injectable()\nexport class ExceptionHandlerService {\n private formatters: ExceptionFormatter[] = [];\n private defaultFormatter: ExceptionFormatter;\n\n constructor() {\n this.defaultFormatter = new UnknownExceptionFormatter();\n }\n\n registerFormatter(formatter: ExceptionFormatter): void {\n this.formatters.push(formatter);\n }\n\n getFormatter(exception: unknown): ExceptionFormatter {\n for (const formatter of this.formatters) {\n if (formatter.supports(exception)) {\n return formatter;\n }\n }\n return this.defaultFormatter;\n }\n\n formatException(exception: unknown): { errors: ErrorMessage[]; message: string } {\n const formatter = this.getFormatter(exception);\n const errors = formatter.format(exception);\n const message = formatter.message(exception);\n\n return { errors, message };\n }\n\n formatErrors(exception: unknown): ErrorMessage[] {\n const formatter = this.getFormatter(exception);\n return formatter.format(exception);\n }\n\n getErrorMessage(exception: unknown): string {\n const formatter = this.getFormatter(exception);\n return formatter.message(exception);\n }\n\n getAllFormatters(): ExceptionFormatter[] {\n return [...this.formatters];\n }\n}\n","import {\n ExceptionFilter,\n Catch,\n ArgumentsHost,\n HttpException,\n HttpStatus,\n Logger,\n} from '@nestjs/common';\nimport { Request, Response } from 'express';\nimport { ExceptionHandlerService } from '../services/exception-handler.service';\nimport { StandardErrorResponse } from '../interfaces/error-message.interface';\nimport { ExceptionHandlerConfig } from '../interfaces/exception-handler-config.interface';\n\n@Catch()\nexport class GlobalExceptionFilter implements ExceptionFilter {\n private readonly logger = new Logger(GlobalExceptionFilter.name);\n private config: ExceptionHandlerConfig;\n\n constructor(\n private exceptionHandlerService: ExceptionHandlerService,\n config?: ExceptionHandlerConfig,\n ) {\n this.config = config || { enableLogging: true, hideStackTrace: false };\n }\n\n catch(exception: unknown, host: ArgumentsHost): void {\n const ctx = host.switchToHttp();\n const response = ctx.getResponse<Response>();\n const request = ctx.getRequest<Request>();\n\n const { errors, message } = this.exceptionHandlerService.formatException(exception);\n const status = this.getStatusCode(exception);\n\n const errorResponse: StandardErrorResponse = {\n success: false,\n message,\n errorMessages: errors,\n };\n\n if (this.config.enableLogging) {\n this.logError(request, status, errors, exception);\n }\n\n response.status(status).json(errorResponse);\n }\n\n private getStatusCode(exception: unknown): number {\n if (exception instanceof HttpException) {\n return exception.getStatus();\n }\n return HttpStatus.INTERNAL_SERVER_ERROR;\n }\n\n private logError(\n request: Request,\n status: number,\n errorMessages: { path: string; message: string }[],\n exception: unknown,\n ): void {\n const method = request.method;\n const url = request.url;\n const timestamp = new Date().toISOString();\n\n const logData = {\n timestamp,\n method,\n url,\n status,\n errorMessages,\n stack: this.config.hideStackTrace ? undefined : (exception as Error)?.stack,\n };\n\n this.logger.error(`${method} ${url} - ${status}`, JSON.stringify(logData));\n }\n}\n","import { DynamicModule, Module } from '@nestjs/common';\nimport { ExceptionHandlerService } from '../services/exception-handler.service';\nimport { GlobalExceptionFilter } from '../filter/global-exception.filter';\nimport { ExceptionHandlerConfig } from '../interfaces/exception-handler-config.interface';\nimport { PrismaExceptionFormatter } from '../formatters/prisma-exception.formatter';\nimport { DtoExceptionFormatter } from '../formatters/dto-exception.formatter';\nimport { HttpExceptionFormatter } from '../formatters/http-exception.formatter';\nimport { UnknownExceptionFormatter } from '../formatters/unknown-exception.formatter';\n\n@Module({})\nexport class ExceptionHandlerModule {\n static forRoot(config?: ExceptionHandlerConfig): DynamicModule {\n const providers = [\n ExceptionHandlerService,\n {\n provide: GlobalExceptionFilter,\n useFactory: (service: ExceptionHandlerService) => {\n return new GlobalExceptionFilter(service, config);\n },\n inject: [ExceptionHandlerService],\n },\n ];\n\n return {\n module: ExceptionHandlerModule,\n providers,\n exports: [ExceptionHandlerService, GlobalExceptionFilter],\n global: true,\n };\n }\n\n static forFeature(config?: ExceptionHandlerConfig): DynamicModule {\n return this.forRoot(config);\n }\n}\n\n// Initialize formatters\nexport function initializeFormatters(service: ExceptionHandlerService): void {\n service.registerFormatter(new PrismaExceptionFormatter());\n service.registerFormatter(new DtoExceptionFormatter());\n service.registerFormatter(new HttpExceptionFormatter());\n service.registerFormatter(new UnknownExceptionFormatter());\n}\n"],"mappings":"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","names":["HttpException","HttpException"]}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "nestjs-exception-handler",
3
+ "version": "1.0.0",
4
+ "description": "A production-grade global exception handling system for NestJS applications",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "lint": "eslint src --ext .ts",
21
+ "format": "prettier --write \"src/**/*.ts\"",
22
+ "test": "jest",
23
+ "test:watch": "jest --watch",
24
+ "test:cov": "jest --coverage",
25
+ "prepublishOnly": "npm run build"
26
+ },
27
+ "keywords": [
28
+ "nestjs",
29
+ "exception",
30
+ "handler",
31
+ "filter",
32
+ "error",
33
+ "prisma",
34
+ "validation"
35
+ ],
36
+ "author": "Nurul Islam Rimon",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/nurulislamrimon/nestjs-exception-handler.git"
41
+ },
42
+ "peerDependencies": {
43
+ "@nestjs/common": "^10.0.0",
44
+ "@nestjs/core": "^10.0.0",
45
+ "@prisma/client": "^5.0.0",
46
+ "reflect-metadata": "^0.1.13",
47
+ "rxjs": "^7.8.0"
48
+ },
49
+ "devDependencies": {
50
+ "@nestjs/common": "^10.0.0",
51
+ "@nestjs/core": "^10.0.0",
52
+ "@nestjs/testing": "^10.4.22",
53
+ "@prisma/client": "^5.0.0",
54
+ "@types/express": "^4.17.17",
55
+ "@types/jest": "^29.5.0",
56
+ "@types/node": "^20.0.0",
57
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
58
+ "@typescript-eslint/parser": "^6.0.0",
59
+ "eslint": "^8.0.0",
60
+ "eslint-config-prettier": "^10.1.8",
61
+ "eslint-plugin-prettier": "^5.5.5",
62
+ "jest": "^29.5.0",
63
+ "prettier": "^3.0.0",
64
+ "reflect-metadata": "^0.1.13",
65
+ "rxjs": "^7.8.0",
66
+ "ts-jest": "^29.1.0",
67
+ "ts-node": "^10.9.2",
68
+ "tsup": "^7.0.0",
69
+ "typescript": "^5.0.0"
70
+ },
71
+ "dependencies": {}
72
+ }