apienvelope 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.
@@ -0,0 +1,842 @@
1
+ import { Request, Response, NextFunction, RequestHandler, ErrorRequestHandler } from 'express';
2
+
3
+ /**
4
+ * Base response interface with common fields
5
+ */
6
+ interface BaseResponse {
7
+ timestamp: string;
8
+ meta?: ResponseMeta;
9
+ }
10
+ /**
11
+ * Metadata that can be attached to any response
12
+ */
13
+ interface ResponseMeta {
14
+ requestId?: string;
15
+ correlationId?: string;
16
+ userId?: string;
17
+ [key: string]: unknown;
18
+ }
19
+ /**
20
+ * Successful response structure
21
+ * @template T - The type of the data payload
22
+ */
23
+ interface SuccessResponse<T = unknown> extends BaseResponse {
24
+ success: true;
25
+ data: T;
26
+ }
27
+ /**
28
+ * Error details structure
29
+ */
30
+ interface ErrorDetails {
31
+ code: string;
32
+ message: string;
33
+ details?: Record<string, unknown>;
34
+ stack?: string;
35
+ fields?: FieldErrors;
36
+ }
37
+ /**
38
+ * Field-level validation errors
39
+ */
40
+ interface FieldErrors {
41
+ [field: string]: string | string[];
42
+ }
43
+ /**
44
+ * Error response structure
45
+ */
46
+ interface ErrorResponse extends BaseResponse {
47
+ success: false;
48
+ error: ErrorDetails;
49
+ }
50
+ /**
51
+ * Pagination metadata
52
+ */
53
+ interface PaginationMeta {
54
+ page: number;
55
+ limit: number;
56
+ total: number;
57
+ totalPages: number;
58
+ hasNextPage: boolean;
59
+ hasPreviousPage: boolean;
60
+ links?: PaginationLinks;
61
+ }
62
+ /**
63
+ * HATEOAS-style pagination links
64
+ */
65
+ interface PaginationLinks {
66
+ self?: string;
67
+ first?: string;
68
+ last?: string;
69
+ next?: string;
70
+ previous?: string;
71
+ }
72
+ /**
73
+ * Cursor-based pagination metadata
74
+ */
75
+ interface CursorPaginationMeta {
76
+ limit: number;
77
+ cursor?: string;
78
+ nextCursor?: string;
79
+ previousCursor?: string;
80
+ hasMore: boolean;
81
+ links?: PaginationLinks;
82
+ }
83
+ /**
84
+ * Paginated response structure (offset-based)
85
+ * @template T - The type of items in the data array
86
+ */
87
+ interface PaginatedResponse<T = unknown> extends BaseResponse {
88
+ success: true;
89
+ data: T[];
90
+ pagination: PaginationMeta;
91
+ }
92
+ /**
93
+ * Cursor-paginated response structure
94
+ * @template T - The type of items in the data array
95
+ */
96
+ interface CursorPaginatedResponse<T = unknown> extends BaseResponse {
97
+ success: true;
98
+ data: T[];
99
+ pagination: CursorPaginationMeta;
100
+ }
101
+ /**
102
+ * Discriminated union for type-safe response handling
103
+ * @template T - The type of the data payload for success responses
104
+ */
105
+ type ApiResponse<T = unknown> = SuccessResponse<T> | ErrorResponse;
106
+ /**
107
+ * Discriminated union for paginated responses
108
+ * @template T - The type of items in the data array
109
+ */
110
+ type PaginatedApiResponse<T = unknown> = PaginatedResponse<T> | ErrorResponse;
111
+ /**
112
+ * Type guard for success responses
113
+ */
114
+ declare function isSuccessResponse<T>(response: ApiResponse<T>): response is SuccessResponse<T>;
115
+ /**
116
+ * Type guard for error responses
117
+ */
118
+ declare function isErrorResponse(response: ApiResponse<unknown>): response is ErrorResponse;
119
+ /**
120
+ * Type guard for paginated responses
121
+ */
122
+ declare function isPaginatedResponse<T>(response: PaginatedApiResponse<T>): response is PaginatedResponse<T>;
123
+
124
+ /**
125
+ * Error constructor type for mapping
126
+ */
127
+ type ErrorConstructor = new (...args: any[]) => Error;
128
+ /**
129
+ * Error serializer function type
130
+ */
131
+ type ErrorSerializer = (error: Error) => Record<string, unknown>;
132
+ /**
133
+ * Error context for traceability
134
+ */
135
+ interface ErrorContext {
136
+ requestId?: string;
137
+ correlationId?: string;
138
+ userId?: string;
139
+ path?: string;
140
+ method?: string;
141
+ timestamp?: string;
142
+ [key: string]: unknown;
143
+ }
144
+ /**
145
+ * API Error options
146
+ */
147
+ interface ApiErrorOptions {
148
+ code?: string;
149
+ statusCode?: number;
150
+ details?: Record<string, unknown>;
151
+ fields?: FieldErrors;
152
+ cause?: Error;
153
+ context?: ErrorContext;
154
+ isOperational?: boolean;
155
+ }
156
+ /**
157
+ * Serialized error structure
158
+ */
159
+ interface SerializedError {
160
+ code: string;
161
+ message: string;
162
+ statusCode: number;
163
+ details?: Record<string, unknown>;
164
+ fields?: FieldErrors;
165
+ stack?: string;
166
+ context?: ErrorContext;
167
+ }
168
+ /**
169
+ * Error chain item for nested errors
170
+ */
171
+ interface ErrorChainItem {
172
+ name: string;
173
+ message: string;
174
+ code?: string;
175
+ stack?: string;
176
+ }
177
+ /**
178
+ * Default error codes
179
+ */
180
+ declare const ErrorCodes: {
181
+ readonly VALIDATION_ERROR: "VALIDATION_ERROR";
182
+ readonly NOT_FOUND: "NOT_FOUND";
183
+ readonly UNAUTHORIZED: "UNAUTHORIZED";
184
+ readonly FORBIDDEN: "FORBIDDEN";
185
+ readonly CONFLICT: "CONFLICT";
186
+ readonly INTERNAL_ERROR: "INTERNAL_ERROR";
187
+ readonly BAD_REQUEST: "BAD_REQUEST";
188
+ readonly RATE_LIMIT_EXCEEDED: "RATE_LIMIT_EXCEEDED";
189
+ readonly SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE";
190
+ readonly UNPROCESSABLE_ENTITY: "UNPROCESSABLE_ENTITY";
191
+ };
192
+ type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
193
+
194
+ /**
195
+ * Environment types
196
+ */
197
+ type Environment = 'development' | 'staging' | 'production' | 'test';
198
+ /**
199
+ * Response hook function types
200
+ */
201
+ type PreResponseHook = (data: unknown, meta?: ResponseMeta) => {
202
+ data: unknown;
203
+ meta?: ResponseMeta;
204
+ };
205
+ type PostResponseHook = (response: SuccessResponse<unknown> | ErrorResponse) => SuccessResponse<unknown> | ErrorResponse;
206
+ /**
207
+ * Custom formatter function type
208
+ */
209
+ type CustomFormatter = (response: SuccessResponse<unknown> | ErrorResponse) => Record<string, unknown>;
210
+ /**
211
+ * Pagination configuration
212
+ */
213
+ interface PaginationConfig {
214
+ defaultLimit: number;
215
+ maxLimit: number;
216
+ includeLinks: boolean;
217
+ baseUrl?: string;
218
+ }
219
+ /**
220
+ * Main formatter configuration
221
+ */
222
+ interface FormatterConfig {
223
+ /** Include stack traces in error responses */
224
+ includeStackTraces: boolean;
225
+ /** Current environment */
226
+ environment: Environment;
227
+ /** Custom error to status code mappings */
228
+ customErrorMappers?: Map<ErrorConstructor, number>;
229
+ /** Custom error serializers */
230
+ customSerializers?: Map<ErrorConstructor, ErrorSerializer>;
231
+ /** Include timestamp in responses */
232
+ includeTimestamp: boolean;
233
+ /** Mask sensitive data in errors */
234
+ maskSensitiveData: boolean;
235
+ /** Header name for request ID */
236
+ requestIdHeader: string;
237
+ /** Header name for correlation ID */
238
+ correlationIdHeader: string;
239
+ /** Pagination configuration */
240
+ pagination: PaginationConfig;
241
+ /** Pre-response processing hooks */
242
+ preResponseHooks: PreResponseHook[];
243
+ /** Post-response processing hooks */
244
+ postResponseHooks: PostResponseHook[];
245
+ /** Custom response formatter (passthrough mode) */
246
+ customFormatter?: CustomFormatter;
247
+ /** Enable passthrough mode for backward compatibility */
248
+ passthroughMode: boolean;
249
+ /** Sensitive fields to mask in error details */
250
+ sensitiveFields: string[];
251
+ /** Generate request ID if not present */
252
+ generateRequestId: boolean;
253
+ }
254
+ /**
255
+ * Partial configuration for user input
256
+ */
257
+ type FormatterConfigInput = Partial<FormatterConfig>;
258
+ /**
259
+ * Default configuration values
260
+ */
261
+ declare const defaultConfig: FormatterConfig;
262
+
263
+ /**
264
+ * Pagination input for offset-based pagination
265
+ */
266
+ interface PaginationInput {
267
+ page: number;
268
+ limit: number;
269
+ total: number;
270
+ }
271
+ /**
272
+ * Cursor pagination input
273
+ */
274
+ interface CursorPaginationInput {
275
+ limit: number;
276
+ cursor?: string;
277
+ nextCursor?: string;
278
+ previousCursor?: string;
279
+ hasMore: boolean;
280
+ }
281
+ /**
282
+ * Validate and normalize pagination input
283
+ */
284
+ declare function validatePaginationInput(input: Partial<PaginationInput>, config: PaginationConfig): PaginationInput;
285
+ /**
286
+ * Calculate pagination metadata
287
+ */
288
+ declare function calculatePaginationMeta(input: PaginationInput, baseUrl?: string): PaginationMeta;
289
+ /**
290
+ * Generate HATEOAS-style pagination links
291
+ */
292
+ declare function generatePaginationLinks(page: number, totalPages: number, limit: number, baseUrl: string): PaginationMeta['links'];
293
+ /**
294
+ * Calculate cursor pagination metadata
295
+ */
296
+ declare function calculateCursorPaginationMeta(input: CursorPaginationInput, baseUrl?: string): CursorPaginationMeta;
297
+ /**
298
+ * Generate cursor pagination links
299
+ */
300
+ declare function generateCursorPaginationLinks(input: CursorPaginationInput, baseUrl: string): CursorPaginationMeta['links'];
301
+ /**
302
+ * Validate configuration input
303
+ */
304
+ declare function validateConfig(input: FormatterConfigInput): string[];
305
+ /**
306
+ * Check if value is a plain object
307
+ */
308
+ declare function isPlainObject(value: unknown): value is Record<string, unknown>;
309
+ /**
310
+ * Generate a unique request ID
311
+ */
312
+ declare function generateRequestId(): string;
313
+
314
+ /**
315
+ * Core response formatter class
316
+ * Handles formatting of success, error, and paginated responses
317
+ */
318
+ declare class ResponseFormatter {
319
+ private config;
320
+ private statusCodeMapper;
321
+ constructor(config?: FormatterConfigInput);
322
+ /**
323
+ * Merge user config with defaults
324
+ */
325
+ private mergeConfig;
326
+ /**
327
+ * Get current configuration
328
+ */
329
+ getConfig(): Readonly<FormatterConfig>;
330
+ /**
331
+ * Update configuration
332
+ */
333
+ updateConfig(config: FormatterConfigInput): void;
334
+ /**
335
+ * Generate timestamp
336
+ */
337
+ private getTimestamp;
338
+ /**
339
+ * Apply pre-response hooks
340
+ */
341
+ private applyPreHooks;
342
+ /**
343
+ * Apply post-response hooks
344
+ */
345
+ private applyPostHooks;
346
+ /**
347
+ * Format a success response
348
+ */
349
+ formatSuccess<T>(data: T, meta?: ResponseMeta): SuccessResponse<T>;
350
+ /**
351
+ * Format an error response
352
+ */
353
+ formatError(error: Error, meta?: ResponseMeta): ErrorResponse;
354
+ /**
355
+ * Format a paginated response (offset-based)
356
+ */
357
+ formatPaginated<T>(data: T[], paginationInput: Partial<PaginationInput>, meta?: ResponseMeta, baseUrl?: string): PaginatedResponse<T>;
358
+ /**
359
+ * Format a cursor-paginated response
360
+ */
361
+ formatCursorPaginated<T>(data: T[], cursorInput: CursorPaginationInput, meta?: ResponseMeta, baseUrl?: string): CursorPaginatedResponse<T>;
362
+ /**
363
+ * Get status code for an error
364
+ */
365
+ getErrorStatusCode(error: Error): number;
366
+ /**
367
+ * Get success status code based on HTTP method
368
+ */
369
+ getSuccessStatusCode(method: string, hasData: boolean): number;
370
+ /**
371
+ * Generate or extract request ID
372
+ */
373
+ getRequestId(existingId?: string): string;
374
+ }
375
+ /**
376
+ * Create a response formatter instance
377
+ */
378
+ declare function createResponseFormatter(config?: FormatterConfigInput): ResponseFormatter;
379
+
380
+ /**
381
+ * Error handler options
382
+ */
383
+ interface ErrorHandlerOptions {
384
+ /** Log errors to console */
385
+ logErrors: boolean;
386
+ /** Custom error logger */
387
+ errorLogger?: (error: Error, req: Request) => void;
388
+ /** Transform error before formatting */
389
+ transformError?: (error: Error) => Error;
390
+ /** Handle non-operational errors differently */
391
+ handleNonOperational?: (error: Error, req: Request, res: Response) => void;
392
+ }
393
+ /**
394
+ * Error handler class for Express applications
395
+ */
396
+ declare class ErrorHandler {
397
+ private formatter;
398
+ private options;
399
+ private config;
400
+ constructor(formatter: ResponseFormatter, options?: Partial<ErrorHandlerOptions>);
401
+ /**
402
+ * Extract request metadata for error context
403
+ */
404
+ private extractMeta;
405
+ /**
406
+ * Log error if enabled
407
+ */
408
+ private logError;
409
+ /**
410
+ * Check if error is operational (expected)
411
+ */
412
+ private isOperationalError;
413
+ /**
414
+ * Handle the error and send response
415
+ */
416
+ handle(error: Error, req: Request, res: Response, _next: NextFunction): void;
417
+ /**
418
+ * Create Express error handling middleware
419
+ */
420
+ middleware(): (error: Error, req: Request, res: Response, next: NextFunction) => void;
421
+ }
422
+ /**
423
+ * Create an error handler instance
424
+ */
425
+ declare function createErrorHandler(formatter: ResponseFormatter, options?: Partial<ErrorHandlerOptions>): ErrorHandler;
426
+ /**
427
+ * Create error handling middleware directly
428
+ */
429
+ declare function errorHandlerMiddleware(formatter: ResponseFormatter, options?: Partial<ErrorHandlerOptions>): (error: Error, req: Request, res: Response, next: NextFunction) => void;
430
+
431
+ /**
432
+ * Pagination helper class for handling pagination logic
433
+ */
434
+ declare class PaginationHelper {
435
+ private config;
436
+ constructor(config?: Partial<PaginationConfig>);
437
+ /**
438
+ * Extract pagination parameters from request
439
+ */
440
+ extractFromRequest(req: Request): {
441
+ page: number;
442
+ limit: number;
443
+ };
444
+ /**
445
+ * Extract cursor pagination parameters from request
446
+ */
447
+ extractCursorFromRequest(req: Request): {
448
+ cursor?: string;
449
+ limit: number;
450
+ };
451
+ /**
452
+ * Calculate offset for database queries
453
+ */
454
+ calculateOffset(page: number, limit: number): number;
455
+ /**
456
+ * Build pagination metadata
457
+ */
458
+ buildMeta(input: PaginationInput, baseUrl?: string): PaginationMeta;
459
+ /**
460
+ * Build cursor pagination metadata
461
+ */
462
+ buildCursorMeta(input: CursorPaginationInput, baseUrl?: string): CursorPaginationMeta;
463
+ /**
464
+ * Create pagination info from data array and total count
465
+ */
466
+ fromArray<T>(data: T[], page: number, limit: number, total: number): {
467
+ data: T[];
468
+ pagination: PaginationMeta;
469
+ };
470
+ /**
471
+ * Paginate an in-memory array
472
+ */
473
+ paginateArray<T>(items: T[], page: number, limit: number): {
474
+ data: T[];
475
+ pagination: PaginationMeta;
476
+ };
477
+ /**
478
+ * Check if there are more pages
479
+ */
480
+ hasNextPage(page: number, limit: number, total: number): boolean;
481
+ /**
482
+ * Check if there are previous pages
483
+ */
484
+ hasPreviousPage(page: number): boolean;
485
+ /**
486
+ * Get total pages count
487
+ */
488
+ getTotalPages(total: number, limit: number): number;
489
+ /**
490
+ * Validate page number is within bounds
491
+ */
492
+ isValidPage(page: number, total: number, limit: number): boolean;
493
+ /**
494
+ * Get configuration
495
+ */
496
+ getConfig(): Readonly<PaginationConfig>;
497
+ /**
498
+ * Update configuration
499
+ */
500
+ updateConfig(config: Partial<PaginationConfig>): void;
501
+ }
502
+ /**
503
+ * Create a pagination helper instance
504
+ */
505
+ declare function createPaginationHelper(config?: Partial<PaginationConfig>): PaginationHelper;
506
+
507
+ /**
508
+ * Base API Error class for all application errors
509
+ * Provides structured error information for consistent API responses
510
+ */
511
+ declare class ApiError extends Error {
512
+ readonly code: string;
513
+ readonly statusCode: number;
514
+ readonly details?: Record<string, unknown>;
515
+ readonly fields?: FieldErrors;
516
+ readonly context?: ErrorContext;
517
+ readonly isOperational: boolean;
518
+ readonly timestamp: string;
519
+ constructor(message: string, options?: ApiErrorOptions);
520
+ /**
521
+ * Serialize error for response
522
+ */
523
+ serialize(includeStack?: boolean): SerializedError;
524
+ /**
525
+ * Get error chain for nested errors
526
+ */
527
+ getErrorChain(): Array<{
528
+ name: string;
529
+ message: string;
530
+ code?: string;
531
+ }>;
532
+ /**
533
+ * Create a new error with additional context
534
+ */
535
+ withContext(context: ErrorContext): ApiError;
536
+ /**
537
+ * Convert to JSON for logging
538
+ */
539
+ toJSON(): Record<string, unknown>;
540
+ }
541
+
542
+ /**
543
+ * Validation Error - 400 Bad Request
544
+ * Used for input validation failures
545
+ */
546
+ declare class ValidationError extends ApiError {
547
+ constructor(message?: string, fields?: FieldErrors, options?: Omit<ApiErrorOptions, 'code' | 'statusCode' | 'fields'>);
548
+ }
549
+ /**
550
+ * Not Found Error - 404
551
+ * Used when a requested resource doesn't exist
552
+ */
553
+ declare class NotFoundError extends ApiError {
554
+ constructor(message?: string, options?: Omit<ApiErrorOptions, 'code' | 'statusCode'>);
555
+ }
556
+ /**
557
+ * Unauthorized Error - 401
558
+ * Used when authentication is required but not provided or invalid
559
+ */
560
+ declare class UnauthorizedError extends ApiError {
561
+ constructor(message?: string, options?: Omit<ApiErrorOptions, 'code' | 'statusCode'>);
562
+ }
563
+ /**
564
+ * Forbidden Error - 403
565
+ * Used when user is authenticated but lacks permission
566
+ */
567
+ declare class ForbiddenError extends ApiError {
568
+ constructor(message?: string, options?: Omit<ApiErrorOptions, 'code' | 'statusCode'>);
569
+ }
570
+ /**
571
+ * Conflict Error - 409
572
+ * Used for resource conflicts (e.g., duplicate entries)
573
+ */
574
+ declare class ConflictError extends ApiError {
575
+ constructor(message?: string, options?: Omit<ApiErrorOptions, 'code' | 'statusCode'>);
576
+ }
577
+ /**
578
+ * Internal Server Error - 500
579
+ * Used for unexpected server errors
580
+ */
581
+ declare class InternalServerError extends ApiError {
582
+ constructor(message?: string, options?: Omit<ApiErrorOptions, 'code' | 'statusCode'>);
583
+ }
584
+ /**
585
+ * Bad Request Error - 400
586
+ * Used for malformed requests
587
+ */
588
+ declare class BadRequestError extends ApiError {
589
+ constructor(message?: string, options?: Omit<ApiErrorOptions, 'code' | 'statusCode'>);
590
+ }
591
+ /**
592
+ * Rate Limit Error - 429
593
+ * Used when rate limiting is triggered
594
+ */
595
+ declare class RateLimitError extends ApiError {
596
+ readonly retryAfter?: number;
597
+ constructor(message?: string, retryAfter?: number, options?: Omit<ApiErrorOptions, 'code' | 'statusCode'>);
598
+ }
599
+ /**
600
+ * Service Unavailable Error - 503
601
+ * Used when service is temporarily unavailable
602
+ */
603
+ declare class ServiceUnavailableError extends ApiError {
604
+ constructor(message?: string, options?: Omit<ApiErrorOptions, 'code' | 'statusCode'>);
605
+ }
606
+ /**
607
+ * Unprocessable Entity Error - 422
608
+ * Used when request is valid but cannot be processed
609
+ */
610
+ declare class UnprocessableEntityError extends ApiError {
611
+ constructor(message?: string, options?: Omit<ApiErrorOptions, 'code' | 'statusCode'>);
612
+ }
613
+ /**
614
+ * Factory function to create ApiError with context
615
+ */
616
+ declare function createError(ErrorClass: new (message: string, ...args: unknown[]) => ApiError, message: string, context?: ErrorContext): ApiError;
617
+
618
+ /**
619
+ * Extended Express Response with formatter methods
620
+ */
621
+ interface FormattedResponse extends Response {
622
+ /** Send a formatted success response */
623
+ respond: <T>(data: T, meta?: ResponseMeta, statusCode?: number) => void;
624
+ /** Send a formatted paginated response */
625
+ respondPaginated: <T>(data: T[], pagination: Partial<PaginationInput>, meta?: ResponseMeta) => void;
626
+ /** Send a formatted cursor-paginated response */
627
+ respondCursorPaginated: <T>(data: T[], pagination: CursorPaginationInput, meta?: ResponseMeta) => void;
628
+ /** Send a formatted error response */
629
+ respondError: (error: Error, meta?: ResponseMeta) => void;
630
+ /** Get the response formatter instance */
631
+ formatter: ResponseFormatter;
632
+ }
633
+ /**
634
+ * Extended Express Request with formatter context
635
+ */
636
+ interface FormattedRequest extends Request {
637
+ /** Request ID for tracing */
638
+ requestId: string;
639
+ /** Correlation ID for distributed tracing */
640
+ correlationId?: string;
641
+ }
642
+ /**
643
+ * Middleware options
644
+ */
645
+ interface ResponseWrapperOptions extends FormatterConfigInput {
646
+ /** Skip wrapping for specific paths */
647
+ skipPaths?: string[];
648
+ /** Skip wrapping based on custom condition */
649
+ skipCondition?: (req: Request) => boolean;
650
+ }
651
+ /**
652
+ * Create response wrapper middleware
653
+ */
654
+ declare function responseWrapper(options?: ResponseWrapperOptions): RequestHandler;
655
+ /**
656
+ * Create response wrapper with custom formatter
657
+ */
658
+ declare function createResponseWrapper(formatter: ResponseFormatter, options?: Omit<ResponseWrapperOptions, keyof FormatterConfigInput>): RequestHandler;
659
+
660
+ /**
661
+ * Error catcher options
662
+ */
663
+ interface ErrorCatcherOptions extends FormatterConfigInput {
664
+ /** Log errors to console */
665
+ logErrors?: boolean;
666
+ /** Custom error logger */
667
+ errorLogger?: (error: Error, req: Request) => void;
668
+ /** Transform error before formatting */
669
+ transformError?: (error: Error) => Error;
670
+ /** Custom response handler */
671
+ customHandler?: (error: Error, req: Request, res: Response) => boolean;
672
+ }
673
+ /**
674
+ * Create error catching middleware
675
+ */
676
+ declare function errorCatcher(options?: ErrorCatcherOptions): ErrorRequestHandler;
677
+ /**
678
+ * Create error catcher with existing formatter
679
+ */
680
+ declare function createErrorCatcher(formatter: ResponseFormatter, options?: Omit<ErrorCatcherOptions, keyof FormatterConfigInput>): ErrorRequestHandler;
681
+ /**
682
+ * Async handler wrapper to catch errors in async route handlers
683
+ */
684
+ declare function asyncHandler<T>(fn: (req: Request, res: Response, next: NextFunction) => Promise<T>): (req: Request, res: Response, next: NextFunction) => void;
685
+ /**
686
+ * Create a try-catch wrapper for route handlers
687
+ */
688
+ declare function catchErrors<T>(fn: (req: Request, res: Response) => Promise<T>): (req: Request, res: Response, next: NextFunction) => void;
689
+
690
+ /**
691
+ * Decorator options
692
+ */
693
+ interface ResponseDecoratorOptions {
694
+ /** Status code to use for success response */
695
+ statusCode?: number;
696
+ /** Additional metadata to include */
697
+ meta?: ResponseMeta;
698
+ /** Skip formatting and return raw response */
699
+ raw?: boolean;
700
+ }
701
+ /**
702
+ * Create a response decorator factory
703
+ */
704
+ declare function createResponseDecorator(formatter: ResponseFormatter): (options?: ResponseDecoratorOptions) => MethodDecorator;
705
+ /**
706
+ * Handle errors decorator
707
+ * Wraps method in try-catch and passes errors to next()
708
+ */
709
+ declare function HandleErrors(): MethodDecorator;
710
+ /**
711
+ * API Route decorator factory
712
+ * Creates a decorator that handles response formatting and error catching
713
+ */
714
+ declare function ApiRoute(formatter: ResponseFormatter, options?: ResponseDecoratorOptions): MethodDecorator;
715
+ /**
716
+ * Validate decorator
717
+ * Validates request body/params/query before executing handler
718
+ */
719
+ declare function Validate(validator: (data: unknown) => {
720
+ valid: boolean;
721
+ errors?: Record<string, string[]>;
722
+ }, source?: 'body' | 'params' | 'query'): MethodDecorator;
723
+
724
+ /**
725
+ * Pagination decorator options
726
+ */
727
+ interface PaginateDecoratorOptions {
728
+ /** Default page size */
729
+ defaultLimit?: number;
730
+ /** Maximum page size */
731
+ maxLimit?: number;
732
+ /** Include HATEOAS links */
733
+ includeLinks?: boolean;
734
+ /** Additional metadata */
735
+ meta?: ResponseMeta;
736
+ }
737
+ /**
738
+ * Result type for paginated handlers
739
+ */
740
+ interface PaginatedResult<T> {
741
+ data: T[];
742
+ total: number;
743
+ }
744
+ /**
745
+ * Cursor paginated result type
746
+ */
747
+ interface CursorPaginatedResult<T> {
748
+ data: T[];
749
+ nextCursor?: string;
750
+ previousCursor?: string;
751
+ hasMore: boolean;
752
+ }
753
+ /**
754
+ * Paginate decorator factory
755
+ * Automatically handles pagination for route handlers
756
+ */
757
+ declare function Paginate(formatter: ResponseFormatter, options?: PaginateDecoratorOptions): MethodDecorator;
758
+ /**
759
+ * Cursor paginate decorator factory
760
+ */
761
+ declare function CursorPaginate(formatter: ResponseFormatter, options?: PaginateDecoratorOptions): MethodDecorator;
762
+
763
+ /**
764
+ * Status code mapper class
765
+ */
766
+ declare class StatusCodeMapper {
767
+ private customMappings;
768
+ constructor(customMappings?: Map<ErrorConstructor, number>);
769
+ /**
770
+ * Get status code for an error
771
+ */
772
+ getStatusCode(error: Error): number;
773
+ /**
774
+ * Get success status code based on HTTP method
775
+ */
776
+ getSuccessStatusCode(method: string, hasData: boolean): number;
777
+ /**
778
+ * Add custom error mapping
779
+ */
780
+ addMapping(ErrorClass: ErrorConstructor, statusCode: number): void;
781
+ /**
782
+ * Remove custom error mapping
783
+ */
784
+ removeMapping(ErrorClass: ErrorConstructor): boolean;
785
+ /**
786
+ * Check if status code indicates success
787
+ */
788
+ static isSuccessCode(statusCode: number): boolean;
789
+ /**
790
+ * Check if status code indicates client error
791
+ */
792
+ static isClientError(statusCode: number): boolean;
793
+ /**
794
+ * Check if status code indicates server error
795
+ */
796
+ static isServerError(statusCode: number): boolean;
797
+ }
798
+ /**
799
+ * Create a status code mapper with custom mappings
800
+ */
801
+ declare function createStatusCodeMapper(customMappings?: Map<ErrorConstructor, number>): StatusCodeMapper;
802
+
803
+ /**
804
+ * Options for error serialization
805
+ */
806
+ interface SerializationOptions {
807
+ includeStack: boolean;
808
+ maskSensitiveData: boolean;
809
+ sensitiveFields: string[];
810
+ customSerializers?: Map<ErrorConstructor, ErrorSerializer>;
811
+ }
812
+ /**
813
+ * Serialize an error to ErrorDetails format
814
+ */
815
+ declare function serializeError(error: Error, options?: Partial<SerializationOptions>): ErrorDetails;
816
+ /**
817
+ * Extract field errors from validation error
818
+ */
819
+ declare function extractFieldErrors(error: Error): FieldErrors | undefined;
820
+ /**
821
+ * Extract error context
822
+ */
823
+ declare function extractErrorContext(error: Error): ErrorContext | undefined;
824
+ /**
825
+ * Create error serializer with options
826
+ */
827
+ declare function createErrorSerializer(options?: Partial<SerializationOptions>): (error: Error) => ErrorDetails;
828
+
829
+ /**
830
+ * Quick setup function that returns both middleware
831
+ * @example
832
+ * const { wrapper, errorHandler } = responseFormatter({ environment: 'production' });
833
+ * app.use(wrapper);
834
+ * // ... routes
835
+ * app.use(errorHandler);
836
+ */
837
+ declare function responseFormatter(options?: ResponseWrapperOptions & ErrorCatcherOptions): {
838
+ wrapper: RequestHandler;
839
+ errorHandler: ErrorRequestHandler;
840
+ };
841
+
842
+ export { ApiError, type ApiErrorOptions, type ApiResponse, ApiRoute, BadRequestError, ConflictError, CursorPaginate, type CursorPaginatedResponse, type CursorPaginatedResult, type CursorPaginationInput, type CursorPaginationMeta, type CustomFormatter, type Environment, type ErrorCatcherOptions, type ErrorChainItem, type ErrorCode, ErrorCodes, type ErrorConstructor, type ErrorContext, type ErrorDetails, ErrorHandler, type ErrorHandlerOptions, type ErrorResponse, type ErrorSerializer, type FieldErrors, ForbiddenError, type FormattedRequest, type FormattedResponse, type FormatterConfig, type FormatterConfigInput, HandleErrors, InternalServerError, NotFoundError, Paginate, type PaginateDecoratorOptions, type PaginatedApiResponse, type PaginatedResponse, type PaginatedResult, type PaginationConfig, PaginationHelper, type PaginationInput, type PaginationLinks, type PaginationMeta, type PostResponseHook, type PreResponseHook, RateLimitError, type ResponseDecoratorOptions, ResponseFormatter, type ResponseMeta, type ResponseWrapperOptions, type SerializationOptions, type SerializedError, ServiceUnavailableError, StatusCodeMapper, type SuccessResponse, UnauthorizedError, UnprocessableEntityError, Validate, ValidationError, asyncHandler, calculateCursorPaginationMeta, calculatePaginationMeta, catchErrors, createError, createErrorCatcher, createErrorHandler, createErrorSerializer, createPaginationHelper, createResponseDecorator, createResponseFormatter, createResponseWrapper, createStatusCodeMapper, responseFormatter as default, defaultConfig, errorCatcher, errorHandlerMiddleware, extractErrorContext, extractFieldErrors, generateCursorPaginationLinks, generatePaginationLinks, generateRequestId, isErrorResponse, isPaginatedResponse, isPlainObject, isSuccessResponse, responseFormatter, responseWrapper, serializeError, validateConfig, validatePaginationInput };