@geekmidas/errors 1.0.2 → 10.0.0-alpha.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/src/index.ts DELETED
@@ -1,828 +0,0 @@
1
- // http-errors.ts - Core HTTP Error Classes and Types
2
-
3
- /**
4
- * Base HTTP Error class that extends the native Error.
5
- * Provides a foundation for all HTTP-specific errors with status codes and structured error responses.
6
- *
7
- * @extends Error
8
- *
9
- * @example
10
- * ```typescript
11
- * throw new HttpError(400, 'Bad Request', {
12
- * details: { field: 'email', message: 'Invalid format' }
13
- * });
14
- * ```
15
- */
16
- export class HttpError extends Error {
17
- /** The HTTP status code (e.g., 400, 404, 500) */
18
- public readonly statusCode: number;
19
- /** The standard HTTP status message (e.g., 'Bad Request', 'Not Found') */
20
- public readonly statusMessage: string;
21
- /** Type discriminator for runtime type checking */
22
- public readonly isHttpError = true;
23
- /** Additional error details for debugging or client information */
24
- public readonly details?: any;
25
- /** Application-specific error code for client-side handling */
26
- public readonly code?: string;
27
-
28
- /**
29
- * Creates a new HttpError instance.
30
- *
31
- * @param statusCode - The HTTP status code
32
- * @param message - Optional error message for the client
33
- * @param options - Optional configuration object
34
- * @param options.statusMessage - Override the default status message
35
- * @param options.details - Additional error details or context
36
- * @param options.code - Application-specific error code
37
- * @param options.cause - The underlying error that caused this error (ES2022)
38
- */
39
- constructor(
40
- statusCode: number,
41
- message?: string,
42
- options?: {
43
- statusMessage?: string;
44
- details?: any;
45
- code?: string;
46
- cause?: Error;
47
- },
48
- ) {
49
- super(message || options?.statusMessage || 'HTTP Error');
50
- this.name = this.constructor.name;
51
- this.statusCode = statusCode;
52
- this.statusMessage =
53
- options?.statusMessage || this.getDefaultStatusMessage(statusCode);
54
- this.details = options?.details;
55
- this.code = options?.code;
56
-
57
- // Set cause if provided (ES2022 feature)
58
- if (options?.cause) {
59
- this.cause = options.cause;
60
- }
61
- // Maintains proper stack trace for where our error was thrown
62
- Error.captureStackTrace(this, this.constructor);
63
- }
64
-
65
- /**
66
- * Gets the error response body as a JSON string.
67
- * Used for sending the error response to clients.
68
- *
69
- * @returns JSON string containing message, code, and error details
70
- */
71
- get body() {
72
- return JSON.stringify({
73
- message: this.message,
74
- code: this.code,
75
- error: this.details,
76
- });
77
- }
78
-
79
- /**
80
- * Gets the default HTTP status message for a given status code.
81
- *
82
- * @param statusCode - The HTTP status code
83
- * @returns The standard HTTP status message or 'Unknown Error' if not found
84
- * @private
85
- */
86
- private getDefaultStatusMessage(statusCode: number): string {
87
- const statusMessages: Record<number, string> = {
88
- 400: 'Bad Request',
89
- 401: 'Unauthorized',
90
- 403: 'Forbidden',
91
- 404: 'Not Found',
92
- 405: 'Method Not Allowed',
93
- 406: 'Not Acceptable',
94
- 408: 'Request Timeout',
95
- 409: 'Conflict',
96
- 410: 'Gone',
97
- 422: 'Unprocessable Entity',
98
- 429: 'Too Many Requests',
99
- 500: 'Internal Server Error',
100
- 501: 'Not Implemented',
101
- 502: 'Bad Gateway',
102
- 503: 'Service Unavailable',
103
- 504: 'Gateway Timeout',
104
- };
105
- return statusMessages[statusCode] || 'Unknown Error';
106
- }
107
-
108
- /**
109
- * Serializes the error to a JSON-compatible object.
110
- * Useful for logging and debugging purposes.
111
- *
112
- * @returns Object representation of the error including stack trace
113
- */
114
- toJSON() {
115
- return {
116
- name: this.name,
117
- message: this.message,
118
- statusCode: this.statusCode,
119
- statusMessage: this.statusMessage,
120
- code: this.code,
121
- details: this.details,
122
- stack: this.stack,
123
- };
124
- }
125
- }
126
-
127
- // Client Error Classes (4xx)
128
-
129
- /**
130
- * Represents a 400 Bad Request error.
131
- * Used when the client sends a malformed or invalid request.
132
- *
133
- * @extends HttpError
134
- *
135
- * @example
136
- * ```typescript
137
- * throw new BadRequestError('Invalid JSON', { line: 5, column: 12 });
138
- * ```
139
- */
140
- export class BadRequestError extends HttpError {
141
- constructor(message?: string, details?: any) {
142
- super(400, message, { details });
143
- }
144
- }
145
-
146
- /**
147
- * Represents a 401 Unauthorized error.
148
- * Used when authentication is required but not provided or invalid.
149
- *
150
- * @extends HttpError
151
- *
152
- * @example
153
- * ```typescript
154
- * throw new UnauthorizedError('Invalid token');
155
- * ```
156
- */
157
- export class UnauthorizedError extends HttpError {
158
- constructor(message?: string, details?: any) {
159
- super(401, message, { details });
160
- }
161
- }
162
-
163
- /**
164
- * Represents a 403 Forbidden error.
165
- * Used when the client is authenticated but lacks permission for the resource.
166
- *
167
- * @extends HttpError
168
- *
169
- * @example
170
- * ```typescript
171
- * throw new ForbiddenError('Insufficient permissions', { required: 'admin' });
172
- * ```
173
- */
174
- export class ForbiddenError extends HttpError {
175
- constructor(message?: string, details?: any) {
176
- super(403, message, { details });
177
- }
178
- }
179
-
180
- /**
181
- * Represents a 404 Not Found error.
182
- * Used when the requested resource doesn't exist.
183
- *
184
- * @extends HttpError
185
- *
186
- * @example
187
- * ```typescript
188
- * throw new NotFoundError('User not found', { userId: '123' });
189
- * ```
190
- */
191
- export class NotFoundError extends HttpError {
192
- constructor(message?: string, details?: any) {
193
- super(404, message, { details });
194
- }
195
- }
196
-
197
- /**
198
- * Represents a 405 Method Not Allowed error.
199
- * Used when the HTTP method is not supported for the requested resource.
200
- *
201
- * @extends HttpError
202
- *
203
- * @example
204
- * ```typescript
205
- * throw new MethodNotAllowedError('DELETE not supported', ['GET', 'POST', 'PUT']);
206
- * ```
207
- */
208
- export class MethodNotAllowedError extends HttpError {
209
- /**
210
- * @param message - Optional error message
211
- * @param allowedMethods - Array of allowed HTTP methods for this resource
212
- */
213
- constructor(message?: string, allowedMethods?: string[]) {
214
- super(405, message, {
215
- details: allowedMethods ? { allowedMethods } : undefined,
216
- });
217
- }
218
- }
219
-
220
- /**
221
- * Represents a 409 Conflict error.
222
- * Used when the request conflicts with the current state of the resource.
223
- *
224
- * @extends HttpError
225
- *
226
- * @example
227
- * ```typescript
228
- * throw new ConflictError('Email already exists', { email: 'user@example.com' });
229
- * ```
230
- */
231
- export class ConflictError extends HttpError {
232
- constructor(message?: string, details?: any) {
233
- super(409, message, { details });
234
- }
235
- }
236
-
237
- /**
238
- * Represents a 422 Unprocessable Entity error.
239
- * Used when the request is well-formed but contains semantic errors.
240
- *
241
- * @extends HttpError
242
- *
243
- * @example
244
- * ```typescript
245
- * throw new UnprocessableEntityError('Validation failed', {
246
- * email: 'Invalid format',
247
- * age: 'Must be 18 or older'
248
- * });
249
- * ```
250
- */
251
- export class UnprocessableEntityError extends HttpError {
252
- /**
253
- * @param message - Optional error message
254
- * @param validationErrors - Object containing field-specific validation errors
255
- */
256
- constructor(message?: string, validationErrors?: any) {
257
- super(422, message, {
258
- details: validationErrors ? { validationErrors } : undefined,
259
- });
260
- }
261
- }
262
-
263
- /**
264
- * Represents a 429 Too Many Requests error.
265
- * Used when the client has exceeded rate limits.
266
- *
267
- * @extends HttpError
268
- *
269
- * @example
270
- * ```typescript
271
- * throw new TooManyRequestsError('Rate limit exceeded', 60); // retry after 60 seconds
272
- * ```
273
- */
274
- export class TooManyRequestsError extends HttpError {
275
- /**
276
- * @param message - Optional error message
277
- * @param retryAfter - Number of seconds the client should wait before retrying
278
- */
279
- constructor(message?: string, retryAfter?: number) {
280
- super(429, message, {
281
- details: retryAfter ? { retryAfter } : undefined,
282
- });
283
- }
284
- }
285
-
286
- // Server Error Classes (5xx)
287
-
288
- /**
289
- * Represents a 500 Internal Server Error.
290
- * Used for unexpected server-side errors.
291
- *
292
- * @extends HttpError
293
- *
294
- * @example
295
- * ```typescript
296
- * throw new InternalServerError('Database connection failed');
297
- * ```
298
- */
299
- export class InternalServerError extends HttpError {
300
- constructor(message?: string, details?: any) {
301
- super(500, message, { details });
302
- }
303
- }
304
-
305
- /**
306
- * Represents a 501 Not Implemented error.
307
- * Used when the server doesn't support the requested functionality.
308
- *
309
- * @extends HttpError
310
- *
311
- * @example
312
- * ```typescript
313
- * throw new NotImplementedError('WebSocket support not implemented');
314
- * ```
315
- */
316
- export class NotImplementedError extends HttpError {
317
- constructor(message?: string, details?: any) {
318
- super(501, message, { details });
319
- }
320
- }
321
-
322
- /**
323
- * Represents a 502 Bad Gateway error.
324
- * Used when the server receives an invalid response from an upstream server.
325
- *
326
- * @extends HttpError
327
- *
328
- * @example
329
- * ```typescript
330
- * throw new BadGatewayError('Upstream server error');
331
- * ```
332
- */
333
- export class BadGatewayError extends HttpError {
334
- constructor(message?: string, details?: any) {
335
- super(502, message, { details });
336
- }
337
- }
338
-
339
- /**
340
- * Represents a 503 Service Unavailable error.
341
- * Used when the server is temporarily unable to handle requests.
342
- *
343
- * @extends HttpError
344
- *
345
- * @example
346
- * ```typescript
347
- * throw new ServiceUnavailableError('Maintenance in progress', 300); // retry after 5 minutes
348
- * ```
349
- */
350
- export class ServiceUnavailableError extends HttpError {
351
- /**
352
- * @param message - Optional error message
353
- * @param retryAfter - Number of seconds the client should wait before retrying
354
- */
355
- constructor(message?: string, retryAfter?: number) {
356
- super(503, message, {
357
- details: retryAfter ? { retryAfter } : undefined,
358
- });
359
- }
360
- }
361
-
362
- /**
363
- * Represents a 504 Gateway Timeout error.
364
- * Used when the server doesn't receive a timely response from an upstream server.
365
- *
366
- * @extends HttpError
367
- *
368
- * @example
369
- * ```typescript
370
- * throw new GatewayTimeoutError('Upstream server timeout');
371
- * ```
372
- */
373
- export class GatewayTimeoutError extends HttpError {
374
- constructor(message?: string, details?: any) {
375
- super(504, message, { details });
376
- }
377
- }
378
-
379
- // Type definitions for different error factory signatures
380
-
381
- /** Factory function for standard HTTP errors with optional details */
382
- type StandardErrorFactory = (message?: string, details?: any) => HttpError;
383
- /** Factory function for Method Not Allowed errors with allowed methods */
384
- type MethodNotAllowedFactory = (
385
- message?: string,
386
- allowedMethods?: string[],
387
- ) => MethodNotAllowedError;
388
- /** Factory function for errors that include retry-after information */
389
- type RetryAfterFactory = (message?: string, retryAfter?: number) => HttpError;
390
- /** Factory function for validation errors with field-specific errors */
391
- type ValidationErrorFactory = (
392
- message?: string,
393
- validationErrors?: any,
394
- ) => UnprocessableEntityError;
395
-
396
- /** Discriminated union for all factory types */
397
- type ErrorFactory =
398
- | { type: 'standard'; factory: StandardErrorFactory }
399
- | { type: 'methodNotAllowed'; factory: MethodNotAllowedFactory }
400
- | { type: 'retryAfter'; factory: RetryAfterFactory }
401
- | { type: 'validation'; factory: ValidationErrorFactory };
402
-
403
- /** Type-safe error registry mapping status codes to their factory functions */
404
- const errorRegistry = {
405
- 400: {
406
- type: 'standard',
407
- factory: (m: string, d: any) => new BadRequestError(m, d),
408
- },
409
- 401: {
410
- type: 'standard',
411
- factory: (m: string, d: any) => new UnauthorizedError(m, d),
412
- },
413
- 403: {
414
- type: 'standard',
415
- factory: (m: string, d: any) => new ForbiddenError(m, d),
416
- },
417
- 404: {
418
- type: 'standard',
419
- factory: (m: string, d: any) => new NotFoundError(m, d),
420
- },
421
- 405: {
422
- type: 'methodNotAllowed',
423
- factory: (m: string, am: string[]) => new MethodNotAllowedError(m, am),
424
- },
425
- 409: {
426
- type: 'standard',
427
- factory: (m: string, d: any) => new ConflictError(m, d),
428
- },
429
- 422: {
430
- type: 'validation',
431
- factory: (m: string, ve: any) => new UnprocessableEntityError(m, ve),
432
- },
433
- 429: {
434
- type: 'retryAfter',
435
- factory: (m: string, ra: number) => new TooManyRequestsError(m, ra),
436
- },
437
- 500: {
438
- type: 'standard',
439
- factory: (m: string, d: any) => new InternalServerError(m, d),
440
- },
441
- 501: {
442
- type: 'standard',
443
- factory: (m: string, d: any) => new NotImplementedError(m, d),
444
- },
445
- 502: {
446
- type: 'standard',
447
- factory: (m: string, d: any) => new BadGatewayError(m, d),
448
- },
449
- 503: {
450
- type: 'retryAfter',
451
- factory: (m: string, ra: number) => new ServiceUnavailableError(m, ra),
452
- },
453
- 504: {
454
- type: 'standard',
455
- factory: (m: string, d: any) => new GatewayTimeoutError(m, d),
456
- },
457
- } as const;
458
-
459
- /** Valid status codes that have registered error factories */
460
- type ValidStatusCode = keyof typeof errorRegistry;
461
-
462
- /** Type-safe options based on status code, ensuring correct parameters for each error type */
463
- type ErrorOptions<T extends number> = T extends 405
464
- ? { allowedMethods?: string[]; code?: string; cause?: Error }
465
- : T extends 422
466
- ? { validationErrors?: any; code?: string; cause?: Error }
467
- : T extends 429 | 503
468
- ? { retryAfter?: number; code?: string; cause?: Error }
469
- : { details?: any; code?: string; cause?: Error };
470
-
471
- /** Handler functions for each factory type */
472
- const factoryHandlers: Record<
473
- ErrorFactory['type'],
474
- (entry: any, message?: string, options?: any) => HttpError
475
- > = {
476
- standard: (entry, message, options) =>
477
- entry.factory(message, options?.details),
478
- methodNotAllowed: (entry, message, options) =>
479
- entry.factory(message, options?.allowedMethods),
480
- retryAfter: (entry, message, options) =>
481
- entry.factory(message, options?.retryAfter),
482
- validation: (entry, message, options) =>
483
- entry.factory(message, options?.validationErrors),
484
- };
485
-
486
- /**
487
- * Creates an HTTP error with type-safe options based on the status code.
488
- * Provides IntelliSense support for status-code-specific options.
489
- *
490
- * @overload For known status codes with specific options
491
- * @param statusCode - A valid HTTP status code from the registry
492
- * @param message - Optional error message
493
- * @param options - Status-code-specific options
494
- * @returns The appropriate HttpError subclass
495
- *
496
- * @example
497
- * ```typescript
498
- * // TypeScript knows allowedMethods is valid for 405
499
- * createHttpError(405, 'Method not allowed', { allowedMethods: ['GET', 'POST'] });
500
- *
501
- * // TypeScript knows retryAfter is valid for 429
502
- * createHttpError(429, 'Rate limited', { retryAfter: 60 });
503
- * ```
504
- */
505
- export function createHttpError<T extends ValidStatusCode>(
506
- statusCode: T,
507
- message?: string,
508
- options?: ErrorOptions<T>,
509
- ): HttpError;
510
- export function createHttpError(
511
- statusCode: number,
512
- message?: string,
513
- options?: HttpErrorOptions,
514
- ): HttpError;
515
- export function createHttpError(
516
- statusCode: number,
517
- message?: string,
518
- options?: any,
519
- ): HttpError {
520
- const entry = errorRegistry[statusCode as ValidStatusCode];
521
-
522
- if (entry) {
523
- const handler = factoryHandlers[entry.type];
524
- return handler(entry, message, options);
525
- }
526
-
527
- // Fallback to generic HttpError for unknown status codes
528
- return new HttpError(statusCode, message, options);
529
- }
530
-
531
- /**
532
- * Type-safe error creation utilities with descriptive method names.
533
- * Provides a fluent API for creating specific HTTP errors.
534
- *
535
- * @example
536
- * ```typescript
537
- * createError.notFound('User not found');
538
- * createError.badRequest('Invalid input', { field: 'email' });
539
- * createError.methodNotAllowed('DELETE not supported', ['GET', 'POST']);
540
- * ```
541
- */
542
- export const createError = {
543
- badRequest: (message?: string, details?: any) =>
544
- new BadRequestError(message, details),
545
-
546
- unauthorized: (message?: string, details?: any) =>
547
- new UnauthorizedError(message, details),
548
-
549
- forbidden: (message?: string, details?: any) =>
550
- new ForbiddenError(message, details),
551
-
552
- notFound: (message?: string, details?: any) =>
553
- new NotFoundError(message, details),
554
-
555
- methodNotAllowed: (message?: string, allowedMethods?: string[]) =>
556
- new MethodNotAllowedError(message, allowedMethods),
557
-
558
- conflict: (message?: string, details?: any) =>
559
- new ConflictError(message, details),
560
-
561
- unprocessableEntity: (message?: string, validationErrors?: any) =>
562
- new UnprocessableEntityError(message, validationErrors),
563
-
564
- tooManyRequests: (message?: string, retryAfter?: number) =>
565
- new TooManyRequestsError(message, retryAfter),
566
-
567
- internalServerError: (message?: string, details?: any) =>
568
- new InternalServerError(message, details),
569
-
570
- notImplemented: (message?: string, details?: any) =>
571
- new NotImplementedError(message, details),
572
-
573
- badGateway: (message?: string, details?: any) =>
574
- new BadGatewayError(message, details),
575
-
576
- serviceUnavailable: (message?: string, retryAfter?: number) =>
577
- new ServiceUnavailableError(message, retryAfter),
578
-
579
- gatewayTimeout: (message?: string, details?: any) =>
580
- new GatewayTimeoutError(message, details),
581
- } as const;
582
-
583
- // Type guards
584
-
585
- /**
586
- * Type guard to check if an error is an HttpError.
587
- * Works with both instanceof checks and duck typing.
588
- *
589
- * @param error - The error to check
590
- * @returns True if the error is an HttpError
591
- *
592
- * @example
593
- * ```typescript
594
- * try {
595
- * // some code
596
- * } catch (error) {
597
- * if (isHttpError(error)) {
598
- * console.log(`HTTP ${error.statusCode}: ${error.message}`);
599
- * }
600
- * }
601
- * ```
602
- */
603
- export function isHttpError(error: unknown): error is HttpError {
604
- return (
605
- error instanceof HttpError ||
606
- (error !== null &&
607
- typeof error === 'object' &&
608
- 'isHttpError' in error &&
609
- error.isHttpError === true)
610
- );
611
- }
612
-
613
- /**
614
- * Type guard to check if an error is a client error (4xx status code).
615
- *
616
- * @param error - The error to check
617
- * @returns True if the error is an HttpError with a 4xx status code
618
- *
619
- * @example
620
- * ```typescript
621
- * if (isClientError(error)) {
622
- * // Log client error metrics
623
- * }
624
- * ```
625
- */
626
- export function isClientError(error: unknown): error is HttpError {
627
- return (
628
- isHttpError(error) && error.statusCode >= 400 && error.statusCode < 500
629
- );
630
- }
631
-
632
- /**
633
- * Type guard to check if an error is a server error (5xx status code).
634
- *
635
- * @param error - The error to check
636
- * @returns True if the error is an HttpError with a 5xx status code
637
- *
638
- * @example
639
- * ```typescript
640
- * if (isServerError(error)) {
641
- * // Trigger alerts for server errors
642
- * }
643
- * ```
644
- */
645
- export function isServerError(error: unknown): error is HttpError {
646
- return (
647
- isHttpError(error) && error.statusCode >= 500 && error.statusCode < 600
648
- );
649
- }
650
-
651
- // Utility functions
652
-
653
- /**
654
- * Wraps an unknown error into an HttpError.
655
- * If the error is already an HttpError, returns it unchanged.
656
- *
657
- * @param error - The error to wrap
658
- * @param statusCode - The HTTP status code to use (defaults to 500)
659
- * @param message - Optional message to override the original error message
660
- * @returns An HttpError instance
661
- *
662
- * @example
663
- * ```typescript
664
- * try {
665
- * await someOperation();
666
- * } catch (error) {
667
- * throw wrapError(error, 503, 'Service temporarily unavailable');
668
- * }
669
- * ```
670
- */
671
- export function wrapError(
672
- error: unknown,
673
- statusCode = 500,
674
- message?: string,
675
- ): HttpError {
676
- if (isHttpError(error)) {
677
- return error;
678
- }
679
-
680
- if (error instanceof HttpError) {
681
- return error;
682
- }
683
-
684
- return new HttpError(statusCode, message || 'An unknown error occurred', {
685
- details: { originalError: error },
686
- });
687
- }
688
-
689
- // Types for better TypeScript support
690
-
691
- /**
692
- * Options for creating an HttpError.
693
- */
694
- export interface HttpErrorOptions {
695
- statusMessage?: string;
696
- details?: any;
697
- code?: string;
698
- cause?: Error;
699
- }
700
-
701
- /**
702
- * Constructor type for HttpError classes.
703
- * Useful for factory patterns and dependency injection.
704
- */
705
- export type HttpErrorConstructor = new (
706
- message?: string,
707
- options?: HttpErrorOptions,
708
- ) => HttpError;
709
-
710
- /**
711
- * HTTP status code enum for type-safe status code usage.
712
- * Includes common 2xx, 3xx, 4xx, and 5xx status codes.
713
- */
714
- export enum HttpStatusCode {
715
- // 2xx Success
716
- OK = 200,
717
- CREATED = 201,
718
- ACCEPTED = 202,
719
- NO_CONTENT = 204,
720
-
721
- // 3xx Redirection
722
- MOVED_PERMANENTLY = 301,
723
- FOUND = 302,
724
- NOT_MODIFIED = 304,
725
-
726
- // 4xx Client Error
727
- BAD_REQUEST = 400,
728
- UNAUTHORIZED = 401,
729
- FORBIDDEN = 403,
730
- NOT_FOUND = 404,
731
- METHOD_NOT_ALLOWED = 405,
732
- NOT_ACCEPTABLE = 406,
733
- REQUEST_TIMEOUT = 408,
734
- CONFLICT = 409,
735
- GONE = 410,
736
- UNPROCESSABLE_ENTITY = 422,
737
- TOO_MANY_REQUESTS = 429,
738
-
739
- // 5xx Server Error
740
- INTERNAL_SERVER_ERROR = 500,
741
- NOT_IMPLEMENTED = 501,
742
- BAD_GATEWAY = 502,
743
- SERVICE_UNAVAILABLE = 503,
744
- GATEWAY_TIMEOUT = 504,
745
- }
746
-
747
- /**
748
- * Namespace containing all HTTP error classes.
749
- * Useful for importing all error types at once.
750
- *
751
- * @example
752
- * ```typescript
753
- * import { HttpErrors } from '@geekmidas/errors';
754
- * throw new HttpErrors.NotFoundError('Resource not found');
755
- * ```
756
- */
757
- export const HttpErrors = {
758
- HttpError,
759
- BadRequestError,
760
- UnauthorizedError,
761
- ForbiddenError,
762
- NotFoundError,
763
- MethodNotAllowedError,
764
- ConflictError,
765
- UnprocessableEntityError,
766
- TooManyRequestsError,
767
- InternalServerError,
768
- NotImplementedError,
769
- BadGatewayError,
770
- ServiceUnavailableError,
771
- GatewayTimeoutError,
772
- };
773
-
774
- // Usage examples:
775
- /*
776
- // Basic usage
777
- throw new NotFoundError('User not found');
778
- throw new BadRequestError('Invalid email format', { field: 'email' });
779
-
780
- // With validation errors
781
- throw new UnprocessableEntityError('Validation failed', {
782
- email: 'Invalid email format',
783
- password: 'Password must be at least 8 characters',
784
- });
785
-
786
- // Type-safe factory function with IntelliSense support
787
- throw createHttpError(405, 'Method not allowed', {
788
- allowedMethods: ['GET', 'POST'] // TypeScript knows this is the correct option!
789
- });
790
-
791
- throw createHttpError(429, 'Too many requests', {
792
- retryAfter: 60 // TypeScript knows this needs retryAfter, not details!
793
- });
794
-
795
- throw createHttpError(422, 'Validation failed', {
796
- validationErrors: { // TypeScript knows this is for validation errors
797
- email: 'Invalid format',
798
- age: 'Must be 18+'
799
- }
800
- });
801
-
802
- // Using the type-safe createError object
803
- throw createError.methodNotAllowed('DELETE not supported', ['GET', 'POST']);
804
- throw createError.tooManyRequests('Rate limit exceeded', 60);
805
- throw createError.unprocessableEntity('Invalid input', {
806
- field: 'email',
807
- message: 'Invalid format'
808
- });
809
-
810
- // TypeScript will show errors for incorrect usage:
811
- // throw createHttpError(404, 'Not found', { retryAfter: 60 }); // ❌ Type error!
812
- // throw createError.notFound('User not found', 60); // ❌ Type error!
813
-
814
- // Wrapping unknown errors
815
- try {
816
- await someAsyncOperation();
817
- } catch (error) {
818
- throw wrapError(error, 500, 'Failed to process request');
819
- }
820
-
821
- // In Express middleware
822
- app.use(expressErrorHandler);
823
-
824
- // Type checking
825
- if (isClientError(error)) {
826
- console.log('Client made a bad request');
827
- }
828
- */