@tongei/express-response-envelop 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +480 -0
  2. package/dist/builder/envelope.builder.d.ts +30 -0
  3. package/dist/builder/envelope.builder.js +33 -0
  4. package/dist/builder/envelope.builder.js.map +1 -0
  5. package/dist/error-handler/envelop-error-handler.d.ts +7 -0
  6. package/dist/error-handler/envelop-error-handler.js +41 -0
  7. package/dist/error-handler/envelop-error-handler.js.map +1 -0
  8. package/dist/exceptions/built-in.exceptions.d.ts +58 -0
  9. package/dist/exceptions/built-in.exceptions.js +119 -0
  10. package/dist/exceptions/built-in.exceptions.js.map +1 -0
  11. package/dist/exceptions/http.exception.d.ts +5 -0
  12. package/dist/exceptions/http.exception.js +18 -0
  13. package/dist/exceptions/http.exception.js.map +1 -0
  14. package/dist/exceptions/index.d.ts +2 -0
  15. package/dist/exceptions/index.js +19 -0
  16. package/dist/exceptions/index.js.map +1 -0
  17. package/dist/filters/exception-filter.type.d.ts +5 -0
  18. package/dist/filters/exception-filter.type.js +3 -0
  19. package/dist/filters/exception-filter.type.js.map +1 -0
  20. package/dist/helpers/send-envelop.d.ts +8 -0
  21. package/dist/helpers/send-envelop.js +27 -0
  22. package/dist/helpers/send-envelop.js.map +1 -0
  23. package/dist/index.d.ts +8 -0
  24. package/dist/index.js +25 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/middleware/response-envelop.middleware.d.ts +3 -0
  27. package/dist/middleware/response-envelop.middleware.js +26 -0
  28. package/dist/middleware/response-envelop.middleware.js.map +1 -0
  29. package/dist/tsconfig.build.tsbuildinfo +1 -0
  30. package/dist/types/response-envelop-option.type.d.ts +10 -0
  31. package/dist/types/response-envelop-option.type.js +3 -0
  32. package/dist/types/response-envelop-option.type.js.map +1 -0
  33. package/package.json +73 -0
package/README.md ADDED
@@ -0,0 +1,480 @@
1
+ # @tongei/express-response-envelop
2
+
3
+ A lightweight Express.js library for centralizing and standardizing API responses with a consistent envelope structure.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @tongei/express-response-envelop
9
+ ```
10
+
11
+ ## Response Shape
12
+
13
+ **Success:**
14
+ ```json
15
+ {
16
+ "success": true,
17
+ "message": "Users fetched successfully",
18
+ "data": [...],
19
+ "optional": {
20
+ "apiVersion": "1.0.0",
21
+ "timestamp": "2025-01-01T00:00:00.000Z"
22
+ }
23
+ }
24
+ ```
25
+
26
+ **Error:**
27
+ ```json
28
+ {
29
+ "success": false,
30
+ "message": null,
31
+ "error": {
32
+ "status": 404,
33
+ "message": "User not found",
34
+ "details": { "field": "id" }
35
+ },
36
+ "optional": {
37
+ "apiVersion": "1.0.0",
38
+ "timestamp": "2025-01-01T00:00:00.000Z"
39
+ }
40
+ }
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Usage
46
+
47
+ There are two ways to use this library. You can use them together or independently.
48
+
49
+ ---
50
+
51
+ ### Option A — Global Middleware (Opt-out model)
52
+
53
+ Register the middleware once and **every `res.json()` call** is automatically wrapped in a success envelope.
54
+
55
+ ```ts
56
+ import express from 'express';
57
+ import {
58
+ responseEnvelopMiddleware,
59
+ envelopErrorHandler,
60
+ } from '@tongei/express-response-envelop';
61
+
62
+ const app = express();
63
+ app.use(express.json());
64
+
65
+ // 1. Register the global response middleware
66
+ app.use(
67
+ responseEnvelopMiddleware({
68
+ defaultApiVersion: '1.0.0', // optional
69
+ includeTimestamp: true, // default: true
70
+ }),
71
+ );
72
+
73
+ // Your routes — no changes needed
74
+ app.get('/users', (req, res) => {
75
+ res.json([{ id: 1, name: 'Alice' }]);
76
+ // Response: { success: true, message: null, data: [...], optional: { ... } }
77
+ });
78
+
79
+ // 2. Register the error handler LAST (after all routes)
80
+ app.use(
81
+ envelopErrorHandler({
82
+ defaultApiVersion: '1.0.0',
83
+ }),
84
+ );
85
+
86
+ app.listen(3000);
87
+ ```
88
+
89
+ #### Opt-out per route
90
+
91
+ If a specific route should skip the envelope (e.g., a health-check or file download), set `res.locals.skipEnvelop = true` before calling `res.json()`:
92
+
93
+ ```ts
94
+ app.get('/health', (req, res) => {
95
+ res.locals.skipEnvelop = true;
96
+ res.json({ status: 'ok' }); // returned as-is, not wrapped
97
+ });
98
+ ```
99
+
100
+ ---
101
+
102
+ ### Option B — Route-level Helpers (Explicit / Opt-in model)
103
+
104
+ Use the `sendEnvelop` and `sendErrorEnvelop` helpers for fine-grained control on specific routes, without using the global middleware.
105
+
106
+ ```ts
107
+ import express from 'express';
108
+ import {
109
+ sendEnvelop,
110
+ sendErrorEnvelop,
111
+ envelopErrorHandler,
112
+ } from '@tongei/express-response-envelop';
113
+
114
+ const app = express();
115
+ app.use(express.json());
116
+
117
+ // Success — static message
118
+ app.get('/users', (req, res) => {
119
+ const users = [{ id: 1, name: 'Alice' }];
120
+ sendEnvelop(res, users, { message: 'Users fetched successfully' });
121
+ });
122
+
123
+ // Success — dynamic message based on the data
124
+ app.get('/users/:id', (req, res) => {
125
+ const user = { id: 1, name: 'Alice' };
126
+ sendEnvelop(res, user, {
127
+ message: (data) => `User ${data.name} retrieved`,
128
+ });
129
+ });
130
+
131
+ // Success — with custom status and API version
132
+ app.post('/users', (req, res) => {
133
+ const newUser = { id: 2, name: 'Bob' };
134
+ sendEnvelop(res, newUser, {
135
+ status: 201,
136
+ message: 'User created',
137
+ apiVersion: '1.0.0',
138
+ });
139
+ });
140
+
141
+ // Error — explicit
142
+ app.get('/users/:id', (req, res) => {
143
+ sendErrorEnvelop(res, 404, 'User not found');
144
+ });
145
+
146
+ // Error — with details (e.g. validation)
147
+ app.post('/users', (req, res) => {
148
+ sendErrorEnvelop(res, 400, 'Validation failed', {
149
+ details: [{ field: 'email', message: 'Required' }],
150
+ });
151
+ });
152
+
153
+ // Register error handler last
154
+ app.use(envelopErrorHandler());
155
+
156
+ app.listen(3000);
157
+ ```
158
+
159
+ ---
160
+
161
+ ### Mixing Both Approaches
162
+
163
+ You can use the global middleware AND the route-level helpers together. The helpers automatically set `res.locals.skipEnvelop = true` to prevent double-wrapping.
164
+
165
+ ```ts
166
+ app.use(responseEnvelopMiddleware({ defaultApiVersion: '1.0.0' }));
167
+
168
+ // This route uses the global middleware — res.json is auto-wrapped
169
+ app.get('/products', (req, res) => {
170
+ res.json([{ id: 1 }]);
171
+ });
172
+
173
+ // This route uses explicit helpers — no double-wrap
174
+ app.post('/products', (req, res) => {
175
+ sendEnvelop(res, { id: 2 }, { status: 201, message: 'Created' });
176
+ });
177
+
178
+ app.use(envelopErrorHandler({ defaultApiVersion: '1.0.0' }));
179
+ ```
180
+
181
+ ---
182
+
183
+ ## API Reference
184
+
185
+ ### `responseEnvelopMiddleware(options?)`
186
+
187
+ | Option | Type | Default | Description |
188
+ |---|---|---|---|
189
+ | `defaultApiVersion` | `string` | `undefined` | Included in `optional.apiVersion` of every response |
190
+ | `includeTimestamp` | `boolean` | `true` | Whether to include `optional.timestamp` |
191
+
192
+ ### `envelopErrorHandler(options?)`
193
+
194
+ Same options as `responseEnvelopMiddleware`. Must be the **last** middleware registered.
195
+
196
+ Automatically detects `err.status`, `err.statusCode`, `err.errors`, and `err.details`.
197
+
198
+ ### `sendEnvelop(res, data, options?)`
199
+
200
+ | Option | Type | Description |
201
+ |---|---|---|
202
+ | `message` | `string \| (data) => string` | Static or dynamic message |
203
+ | `status` | `number` | HTTP status code (default: `200`) |
204
+ | `apiVersion` | `string` | Overrides the `optional.apiVersion` |
205
+ | `includeTimestamp` | `boolean` | Whether to include timestamp |
206
+
207
+ ### `sendErrorEnvelop(res, status, message, options?)`
208
+
209
+ | Option | Type | Description |
210
+ |---|---|---|
211
+ | `details` | `unknown` | Additional error details (e.g. validation errors) |
212
+ | `apiVersion` | `string` | Overrides the `optional.apiVersion` |
213
+ | `includeTimestamp` | `boolean` | Whether to include timestamp |
214
+
215
+ ### Builder utilities (low-level)
216
+
217
+ ```ts
218
+ import {
219
+ buildSuccessEnvelope,
220
+ buildErrorEnvelope,
221
+ } from '@tongei/express-response-envelop';
222
+
223
+ const success = buildSuccessEnvelope(data, { message: 'Done', apiVersion: '1.0' });
224
+ const error = buildErrorEnvelope(500, 'Internal error', { details: { ... } });
225
+ ```
226
+
227
+ ---
228
+
229
+ ## NestJS-style Exceptions
230
+
231
+ The package ships typed HTTP exception classes — exactly like NestJS — so you can `throw` them directly from any route handler, service, or middleware. The `envelopErrorHandler` catches them automatically.
232
+
233
+ ### Available exceptions
234
+
235
+ ```ts
236
+ import {
237
+ // 4xx
238
+ BadRequestException, // 400
239
+ UnauthorizedException, // 401
240
+ PaymentRequiredException, // 402
241
+ ForbiddenException, // 403
242
+ NotFoundException, // 404
243
+ MethodNotAllowedException, // 405
244
+ NotAcceptableException, // 406
245
+ RequestTimeoutException, // 408
246
+ ConflictException, // 409
247
+ GoneException, // 410
248
+ PayloadTooLargeException, // 413
249
+ UnsupportedMediaTypeException, // 415
250
+ UnprocessableEntityException,// 422
251
+ TooManyRequestsException, // 429
252
+ // 5xx
253
+ InternalServerErrorException,// 500
254
+ NotImplementedException, // 501
255
+ BadGatewayException, // 502
256
+ ServiceUnavailableException, // 503
257
+ GatewayTimeoutException, // 504
258
+ } from '@tongei/express-response-envelop';
259
+ ```
260
+
261
+ ### Throwing exceptions
262
+
263
+ ```ts
264
+ import express from 'express';
265
+ import {
266
+ responseEnvelopMiddleware,
267
+ envelopErrorHandler,
268
+ NotFoundException,
269
+ ConflictException,
270
+ ForbiddenException,
271
+ UnprocessableEntityException,
272
+ } from '@tongei/express-response-envelop';
273
+
274
+ const app = express();
275
+ app.use(express.json());
276
+ app.use(responseEnvelopMiddleware({ defaultApiVersion: '1.0.0' }));
277
+
278
+ app.get('/users/:id', (req, res) => {
279
+ const user = db.findUser(req.params.id);
280
+
281
+ if (!user) {
282
+ throw new NotFoundException(`User ${req.params.id} not found`);
283
+ // { success: false, error: { status: 404, message: 'User 42 not found' } }
284
+ }
285
+
286
+ res.json(user);
287
+ });
288
+
289
+ app.post('/users', (req, res) => {
290
+ if (db.emailExists(req.body.email)) {
291
+ throw new ConflictException('Email is already in use');
292
+ // { success: false, error: { status: 409, message: 'Email is already in use' } }
293
+ }
294
+
295
+ if (!req.user?.isAdmin) {
296
+ throw new ForbiddenException('Admin access required');
297
+ // { success: false, error: { status: 403, message: 'Admin access required' } }
298
+ }
299
+
300
+ res.json(db.createUser(req.body));
301
+ });
302
+
303
+ // Register the error handler LAST — it catches all thrown exceptions
304
+ app.use(envelopErrorHandler({ defaultApiVersion: '1.0.0' }));
305
+ app.listen(3000);
306
+ ```
307
+
308
+ > [!NOTE]
309
+ > The exceptions work with both `throw` and `next(err)`. You can throw them synchronously or pass them to `next()` in async routes.
310
+
311
+ ### Throwing with validation details
312
+
313
+ Pass a second argument to attach structured detail to the error response:
314
+
315
+ ```ts
316
+ app.post('/register', (req, res) => {
317
+ const errors = validate(req.body);
318
+
319
+ if (errors.length > 0) {
320
+ throw new UnprocessableEntityException('Validation failed', errors);
321
+ // {
322
+ // "success": false,
323
+ // "error": {
324
+ // "status": 422,
325
+ // "message": "Validation failed",
326
+ // "details": [{ "field": "email", "message": "Required" }]
327
+ // }
328
+ // }
329
+ }
330
+
331
+ res.json(db.register(req.body));
332
+ });
333
+ ```
334
+
335
+ ### Custom domain exceptions
336
+
337
+ Extend `HttpException` for domain-specific errors:
338
+
339
+ ```ts
340
+ import { HttpException } from '@tongei/express-response-envelop';
341
+
342
+ export class EntityNotFoundException extends HttpException {
343
+ constructor(entity: string, id: string | number) {
344
+ super(404, `${entity} with id "${id}" was not found`);
345
+ }
346
+ }
347
+
348
+ export class SubscriptionExpiredException extends HttpException {
349
+ constructor() {
350
+ super(402, 'Your subscription has expired');
351
+ }
352
+ }
353
+
354
+ // Usage:
355
+ throw new EntityNotFoundException('Product', req.params.id);
356
+ throw new SubscriptionExpiredException();
357
+ ```
358
+
359
+ ---
360
+
361
+ ## Custom Exception Filters
362
+
363
+ Register class-specific handlers in `envelopErrorHandler` — just like NestJS's `@Catch()` decorator. Filters are evaluated in order; the first match wins. Unmatched errors fall through to the default handler.
364
+
365
+ ```ts
366
+ import {
367
+ envelopErrorHandler,
368
+ sendErrorEnvelop,
369
+ EnvelopExceptionFilter,
370
+ } from '@tongei/express-response-envelop';
371
+
372
+ // 1. Define your domain exception
373
+ class DatabaseException extends Error {
374
+ constructor(message = 'Database error') {
375
+ super(message);
376
+ this.name = 'DatabaseException';
377
+ }
378
+ }
379
+
380
+ class RateLimitException extends Error {
381
+ retryAfter: number;
382
+ constructor(retryAfter = 60) {
383
+ super('Too many requests');
384
+ this.retryAfter = retryAfter;
385
+ }
386
+ }
387
+
388
+ // 2. Create filters
389
+ const dbFilter: EnvelopExceptionFilter<DatabaseException> = {
390
+ exceptionType: DatabaseException,
391
+ handle(err, req, res) {
392
+ sendErrorEnvelop(res, 503, 'Database unavailable', {
393
+ details: { reason: err.message },
394
+ });
395
+ },
396
+ };
397
+
398
+ const rateLimitFilter: EnvelopExceptionFilter<RateLimitException> = {
399
+ exceptionType: RateLimitException,
400
+ handle(err, req, res) {
401
+ res.setHeader('Retry-After', err.retryAfter);
402
+ sendErrorEnvelop(res, 429, 'Too many requests', {
403
+ details: { retryAfter: err.retryAfter },
404
+ });
405
+ },
406
+ };
407
+
408
+ // 3. Register filters — first match wins
409
+ app.use(
410
+ envelopErrorHandler({
411
+ defaultApiVersion: '1.0.0',
412
+ filters: [dbFilter, rateLimitFilter],
413
+ }),
414
+ );
415
+ ```
416
+
417
+ ---
418
+
419
+ ## Throwing Errors (plain Express style)
420
+
421
+ If you prefer not to use the typed exceptions, you can still use the classic Express pattern of attaching `status` to a plain error and passing it to `next()`:
422
+
423
+ ```ts
424
+ app.get('/users/:id', (req, res, next) => {
425
+ const user = db.findUser(req.params.id);
426
+
427
+ if (!user) {
428
+ const err: any = new Error('User not found');
429
+ err.status = 404;
430
+ return next(err);
431
+ }
432
+
433
+ res.json(user);
434
+ });
435
+ ```
436
+
437
+ Works seamlessly with [`http-errors`](https://github.com/jshttp/http-errors):
438
+
439
+ ```bash
440
+ npm install http-errors && npm install -D @types/http-errors
441
+ ```
442
+
443
+ ```ts
444
+ import createError from 'http-errors';
445
+
446
+ app.get('/protected', (req, res, next) => {
447
+ if (!req.headers.authorization) {
448
+ return next(createError(401, 'Authorization header missing'));
449
+ }
450
+ res.json({ secret: 'data' });
451
+ });
452
+ ```
453
+
454
+ ### Global 500 fallback
455
+
456
+ Any error without a `status` property (including uncaught `throw new Error(...)`) defaults to `500 Internal Server Error`:
457
+
458
+ ```ts
459
+ app.get('/risky', async (req, res, next) => {
460
+ try {
461
+ const data = await someFlakyOperation();
462
+ res.json(data);
463
+ } catch (err) {
464
+ next(err);
465
+ // { success: false, error: { status: 500, message: '...' } }
466
+ }
467
+ });
468
+
469
+ // Or with the typed exception:
470
+ app.get('/risky2', (req, res) => {
471
+ throw new InternalServerErrorException('Something went wrong internally');
472
+ });
473
+ ```
474
+
475
+ ---
476
+
477
+ ## License
478
+
479
+ MIT
480
+
@@ -0,0 +1,30 @@
1
+ export interface EnvelopeOptionalMeta {
2
+ apiVersion?: string;
3
+ timestamp?: string;
4
+ }
5
+ export interface SuccessEnvelope<T> {
6
+ success: true;
7
+ message: string | null;
8
+ data: T;
9
+ optional?: EnvelopeOptionalMeta;
10
+ }
11
+ export interface ErrorEnvelope {
12
+ success: false;
13
+ message: string | null;
14
+ error?: {
15
+ status: number;
16
+ message: string;
17
+ details?: unknown;
18
+ };
19
+ optional?: EnvelopeOptionalMeta;
20
+ }
21
+ export declare function buildSuccessEnvelope<T>(data: T, opts?: {
22
+ message?: string | null;
23
+ apiVersion?: string;
24
+ includeTimestamp?: boolean;
25
+ }): SuccessEnvelope<T>;
26
+ export declare function buildErrorEnvelope(status: number, message: string, opts?: {
27
+ apiVersion?: string;
28
+ includeTimestamp?: boolean;
29
+ details?: unknown;
30
+ }): ErrorEnvelope;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildSuccessEnvelope = buildSuccessEnvelope;
4
+ exports.buildErrorEnvelope = buildErrorEnvelope;
5
+ function buildOptional(apiVersion, includeTimestamp = true) {
6
+ const optional = {};
7
+ if (apiVersion !== undefined)
8
+ optional.apiVersion = apiVersion;
9
+ if (includeTimestamp)
10
+ optional.timestamp = new Date().toISOString();
11
+ return Object.keys(optional).length > 0 ? optional : undefined;
12
+ }
13
+ function buildSuccessEnvelope(data, opts = {}) {
14
+ return {
15
+ success: true,
16
+ message: opts.message ?? null,
17
+ data,
18
+ optional: buildOptional(opts.apiVersion, opts.includeTimestamp ?? true),
19
+ };
20
+ }
21
+ function buildErrorEnvelope(status, message, opts = {}) {
22
+ return {
23
+ success: false,
24
+ message: null,
25
+ error: {
26
+ status,
27
+ message,
28
+ ...(opts.details ? { details: opts.details } : {}),
29
+ },
30
+ optional: buildOptional(opts.apiVersion, opts.includeTimestamp ?? true),
31
+ };
32
+ }
33
+ //# sourceMappingURL=envelope.builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.builder.js","sourceRoot":"","sources":["../../src/builder/envelope.builder.ts"],"names":[],"mappings":";;AA8BA,oDAcC;AAED,gDAmBC;AA7CD,SAAS,aAAa,CACpB,UAAmB,EACnB,gBAAgB,GAAG,IAAI;IAEvB,MAAM,QAAQ,GAAyB,EAAE,CAAC;IAC1C,IAAI,UAAU,KAAK,SAAS;QAAE,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/D,IAAI,gBAAgB;QAAE,QAAQ,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpE,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;AACjE,CAAC;AAED,SAAgB,oBAAoB,CAClC,IAAO,EACP,OAII,EAAE;IAEN,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI;QAC7B,IAAI;QACJ,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC;KACxE,CAAC;AACJ,CAAC;AAED,SAAgB,kBAAkB,CAChC,MAAc,EACd,OAAe,EACf,OAII,EAAE;IAEN,OAAO;QACL,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,IAAI;QACb,KAAK,EAAE;YACL,MAAM;YACN,OAAO;YACP,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD;QACD,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC;KACxE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { ErrorRequestHandler } from 'express';
2
+ import { EnvelopExceptionFilter } from '../filters/exception-filter.type';
3
+ import { EnvelopMiddlewareOptions } from '../types/response-envelop-option.type';
4
+ export interface EnvelopErrorHandlerOptions extends EnvelopMiddlewareOptions {
5
+ filters?: EnvelopExceptionFilter[];
6
+ }
7
+ export declare function envelopErrorHandler(options?: EnvelopErrorHandlerOptions): ErrorRequestHandler;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.envelopErrorHandler = envelopErrorHandler;
4
+ const envelope_builder_1 = require("../builder/envelope.builder");
5
+ const http_exception_1 = require("../exceptions/http.exception");
6
+ function envelopErrorHandler(options = {}) {
7
+ const { defaultApiVersion, includeTimestamp, filters = [] } = options;
8
+ return function errorHandler(err, req, res, next) {
9
+ for (const filter of filters) {
10
+ if (err instanceof filter.exceptionType) {
11
+ filter.handle(err, req, res, next);
12
+ return;
13
+ }
14
+ }
15
+ if (err instanceof http_exception_1.HttpException) {
16
+ const envelope = (0, envelope_builder_1.buildErrorEnvelope)(err.status, err.message, {
17
+ apiVersion: defaultApiVersion,
18
+ includeTimestamp,
19
+ details: err.details,
20
+ });
21
+ res.status(err.status).json(envelope);
22
+ return;
23
+ }
24
+ const status = typeof err?.status === 'number'
25
+ ? err.status
26
+ : typeof err?.statusCode === 'number'
27
+ ? err.statusCode
28
+ : 500;
29
+ const message = typeof err?.message === 'string' && err.message
30
+ ? err.message
31
+ : 'Internal Server Error';
32
+ const details = err?.errors ?? err?.details ?? (err instanceof Error ? undefined : err);
33
+ const envelope = (0, envelope_builder_1.buildErrorEnvelope)(status, message, {
34
+ apiVersion: defaultApiVersion,
35
+ includeTimestamp,
36
+ details,
37
+ });
38
+ res.status(status).json(envelope);
39
+ };
40
+ }
41
+ //# sourceMappingURL=envelop-error-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelop-error-handler.js","sourceRoot":"","sources":["../../src/error-handler/envelop-error-handler.ts"],"names":[],"mappings":";;AAyDA,kDAwDC;AA/GD,kEAAiE;AACjE,iEAA6D;AAsD7D,SAAgB,mBAAmB,CACjC,UAAsC,EAAE;IAExC,MAAM,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAGtE,OAAO,SAAS,YAAY,CAC1B,GAAQ,EACR,GAAY,EACZ,GAAa,EACb,IAAkB;QAGlB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,GAAG,YAAY,MAAM,CAAC,aAAa,EAAE,CAAC;gBACxC,MAAM,CAAC,MAAM,CAAC,GAAU,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBAC1C,OAAO;YACT,CAAC;QACH,CAAC;QAGD,IAAI,GAAG,YAAY,8BAAa,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,IAAA,qCAAkB,EAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE;gBAC3D,UAAU,EAAE,iBAAiB;gBAC7B,gBAAgB;gBAChB,OAAO,EAAE,GAAG,CAAC,OAAO;aACrB,CAAC,CAAC;YACH,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACtC,OAAO;QACT,CAAC;QAGD,MAAM,MAAM,GACV,OAAO,GAAG,EAAE,MAAM,KAAK,QAAQ;YAC7B,CAAC,CAAC,GAAG,CAAC,MAAM;YACZ,CAAC,CAAC,OAAO,GAAG,EAAE,UAAU,KAAK,QAAQ;gBACnC,CAAC,CAAC,GAAG,CAAC,UAAU;gBAChB,CAAC,CAAC,GAAG,CAAC;QAEZ,MAAM,OAAO,GACX,OAAO,GAAG,EAAE,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO;YAC7C,CAAC,CAAC,GAAG,CAAC,OAAO;YACb,CAAC,CAAC,uBAAuB,CAAC;QAE9B,MAAM,OAAO,GACX,GAAG,EAAE,MAAM,IAAI,GAAG,EAAE,OAAO,IAAI,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAG1E,MAAM,QAAQ,GAAG,IAAA,qCAAkB,EAAC,MAAM,EAAE,OAAO,EAAE;YACnD,UAAU,EAAE,iBAAiB;YAC7B,gBAAgB;YAChB,OAAO;SACR,CAAC,CAAC;QAEH,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { HttpException } from './http.exception';
2
+ export declare class BadRequestException extends HttpException {
3
+ constructor(message?: string, details?: unknown);
4
+ }
5
+ export declare class UnauthorizedException extends HttpException {
6
+ constructor(message?: string, details?: unknown);
7
+ }
8
+ export declare class PaymentRequiredException extends HttpException {
9
+ constructor(message?: string, details?: unknown);
10
+ }
11
+ export declare class ForbiddenException extends HttpException {
12
+ constructor(message?: string, details?: unknown);
13
+ }
14
+ export declare class NotFoundException extends HttpException {
15
+ constructor(message?: string, details?: unknown);
16
+ }
17
+ export declare class MethodNotAllowedException extends HttpException {
18
+ constructor(message?: string, details?: unknown);
19
+ }
20
+ export declare class NotAcceptableException extends HttpException {
21
+ constructor(message?: string, details?: unknown);
22
+ }
23
+ export declare class RequestTimeoutException extends HttpException {
24
+ constructor(message?: string, details?: unknown);
25
+ }
26
+ export declare class ConflictException extends HttpException {
27
+ constructor(message?: string, details?: unknown);
28
+ }
29
+ export declare class GoneException extends HttpException {
30
+ constructor(message?: string, details?: unknown);
31
+ }
32
+ export declare class PayloadTooLargeException extends HttpException {
33
+ constructor(message?: string, details?: unknown);
34
+ }
35
+ export declare class UnsupportedMediaTypeException extends HttpException {
36
+ constructor(message?: string, details?: unknown);
37
+ }
38
+ export declare class UnprocessableEntityException extends HttpException {
39
+ constructor(message?: string, details?: unknown);
40
+ }
41
+ export declare class TooManyRequestsException extends HttpException {
42
+ constructor(message?: string, details?: unknown);
43
+ }
44
+ export declare class InternalServerErrorException extends HttpException {
45
+ constructor(message?: string, details?: unknown);
46
+ }
47
+ export declare class NotImplementedException extends HttpException {
48
+ constructor(message?: string, details?: unknown);
49
+ }
50
+ export declare class BadGatewayException extends HttpException {
51
+ constructor(message?: string, details?: unknown);
52
+ }
53
+ export declare class ServiceUnavailableException extends HttpException {
54
+ constructor(message?: string, details?: unknown);
55
+ }
56
+ export declare class GatewayTimeoutException extends HttpException {
57
+ constructor(message?: string, details?: unknown);
58
+ }