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.
- package/LICENSE +21 -0
- package/README.md +293 -0
- package/dist/chunk-2TAKYP6Q.mjs +213 -0
- package/dist/index.d.mts +842 -0
- package/dist/index.d.ts +842 -0
- package/dist/index.js +1553 -0
- package/dist/index.mjs +1254 -0
- package/dist/predefined-FHOIIQHS.mjs +26 -0
- package/package.json +65 -0
package/dist/index.d.mts
ADDED
|
@@ -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 };
|