http-response-kit 1.0.0 → 2.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.
Files changed (47) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +357 -272
  3. package/dist/chunk-373JVXMN.mjs +1199 -0
  4. package/dist/chunk-373JVXMN.mjs.map +1 -0
  5. package/dist/chunk-FFRB2EUE.mjs +36 -0
  6. package/dist/chunk-FFRB2EUE.mjs.map +1 -0
  7. package/dist/express.d.mts +50 -0
  8. package/dist/express.d.ts +50 -0
  9. package/dist/express.js +1155 -0
  10. package/dist/express.js.map +1 -0
  11. package/dist/express.mjs +28 -0
  12. package/dist/express.mjs.map +1 -0
  13. package/dist/fastify.d.mts +45 -0
  14. package/dist/fastify.d.ts +45 -0
  15. package/dist/fastify.js +1170 -0
  16. package/dist/fastify.js.map +1 -0
  17. package/dist/fastify.mjs +43 -0
  18. package/dist/fastify.mjs.map +1 -0
  19. package/dist/hono.d.mts +33 -0
  20. package/dist/hono.d.ts +33 -0
  21. package/dist/hono.js +1139 -0
  22. package/dist/hono.js.map +1 -0
  23. package/dist/hono.mjs +18 -0
  24. package/dist/hono.mjs.map +1 -0
  25. package/dist/index.d.mts +75 -493
  26. package/dist/index.d.ts +75 -493
  27. package/dist/index.js +480 -180
  28. package/dist/index.js.map +1 -0
  29. package/dist/index.mjs +18 -891
  30. package/dist/index.mjs.map +1 -0
  31. package/dist/kit-nHfihlKE.d.mts +753 -0
  32. package/dist/kit-nHfihlKE.d.ts +753 -0
  33. package/dist/koa.d.mts +38 -0
  34. package/dist/koa.d.ts +38 -0
  35. package/dist/koa.js +1150 -0
  36. package/dist/koa.js.map +1 -0
  37. package/dist/koa.mjs +24 -0
  38. package/dist/koa.mjs.map +1 -0
  39. package/dist/schemas.d.mts +452 -0
  40. package/dist/schemas.d.ts +452 -0
  41. package/dist/schemas.js +124 -0
  42. package/dist/schemas.js.map +1 -0
  43. package/dist/schemas.mjs +119 -0
  44. package/dist/schemas.mjs.map +1 -0
  45. package/dist/shared-Czwmz6Xa.d.ts +22 -0
  46. package/dist/shared-DYq1Fic4.d.mts +22 -0
  47. package/package.json +104 -49
@@ -0,0 +1,753 @@
1
+ /**
2
+ * HTTP Response Kit - Type Definitions
3
+ * @module types
4
+ */
5
+ /**
6
+ * Information structure for HTTP errors
7
+ */
8
+ interface HttpErrorInfo {
9
+ /** Lowercase identifier for the error type */
10
+ type: string;
11
+ /** Human-readable title */
12
+ title: string;
13
+ /** HTTP status code */
14
+ code: number;
15
+ /** Default error description */
16
+ details: string;
17
+ /** Optional retry-after time in seconds */
18
+ retryAfter?: number;
19
+ /** Optional resolution suggestion */
20
+ resolution?: string;
21
+ }
22
+ /**
23
+ * A single validation issue, used for structured 422/400 responses.
24
+ * Mirrors the common `errors[]` extension of RFC 9457.
25
+ */
26
+ interface ValidationIssue {
27
+ /** The field/path that failed validation (e.g. "email", "items[0].qty") */
28
+ field: string;
29
+ /** Human-readable description of the issue */
30
+ message: string;
31
+ /** Optional stable machine-readable code (e.g. "too_short") */
32
+ code?: string;
33
+ }
34
+ /**
35
+ * Configuration options for HttpError
36
+ */
37
+ interface HttpErrorOptions {
38
+ /** Custom error message */
39
+ message?: string;
40
+ /** Additional metadata */
41
+ metadata?: Record<string, unknown>;
42
+ /** Original error cause (also set as the native ES2022 `Error.cause`) */
43
+ cause?: Error;
44
+ /** Retry-after time in seconds */
45
+ retryAfter?: number;
46
+ /**
47
+ * Whether the error message is safe to expose to clients.
48
+ * Defaults to `true` for 4xx and `false` for 5xx (security best practice:
49
+ * internal server error messages are never leaked unless explicitly allowed).
50
+ */
51
+ expose?: boolean;
52
+ /**
53
+ * Stable application-level error code, independent from the HTTP status
54
+ * (e.g. "USER_NOT_FOUND", "ERR-1042"). Serialized as `error.code`.
55
+ */
56
+ errorCode?: string;
57
+ /** Structured validation issues (serialized as `error.errors`) */
58
+ validationErrors?: ValidationIssue[];
59
+ /** Extra HTTP headers to send with the error (merged into `getHeaders()`) */
60
+ headers?: Record<string, string>;
61
+ /** RFC 9457 `instance`: URI identifying this specific occurrence */
62
+ instance?: string;
63
+ }
64
+ /**
65
+ * Information structure for HTTP success responses
66
+ */
67
+ interface HttpSuccessInfo {
68
+ /** HTTP status code */
69
+ code: number;
70
+ /** Description of the status */
71
+ description: string;
72
+ }
73
+ /**
74
+ * Configuration for success responses
75
+ */
76
+ interface SuccessResponseConfig<T = unknown> {
77
+ /** Response data payload */
78
+ data?: T;
79
+ /** Custom success message */
80
+ message?: string;
81
+ /** HTTP status code (default: 200) */
82
+ statusCode?: number;
83
+ /** Additional metadata */
84
+ metadata?: Record<string, unknown>;
85
+ /** Correlation/request id echoed as `request_id` */
86
+ requestId?: string;
87
+ }
88
+ /**
89
+ * Configuration for error responses
90
+ */
91
+ interface ErrorResponseConfig {
92
+ /** Include stack trace in response (overrides dev-mode default) */
93
+ includeStack?: boolean;
94
+ /** Additional fields to include */
95
+ additionalFields?: Record<string, unknown>;
96
+ /** Fallback status code for unknown errors */
97
+ fallbackCode?: number;
98
+ /** Correlation/request id echoed as `request_id` */
99
+ requestId?: string;
100
+ /** RFC 9457 `instance` override for this response */
101
+ instance?: string;
102
+ /** Force-expose (or hide) the error message regardless of `error.expose` */
103
+ expose?: boolean;
104
+ }
105
+ /** Output key casing for generated responses */
106
+ type ResponseCasing = 'snake' | 'camel';
107
+ /** Output format: proprietary envelope or RFC 9457 Problem Details */
108
+ type ResponseFormat = 'standard' | 'problem';
109
+ /**
110
+ * Per-instance kit configuration (there is no global configuration:
111
+ * every `createResponseKit()` call owns an isolated copy of this).
112
+ */
113
+ interface KitConfig {
114
+ /** Enable development mode (includes stack traces) */
115
+ isDevelopment?: boolean;
116
+ /** Include timestamp in responses (default: true) */
117
+ includeTimestamp?: boolean;
118
+ /** Custom default messages per error code */
119
+ customMessages?: Partial<Record<number, string>>;
120
+ /** Custom response transformer (applied last) */
121
+ responseTransformer?: (response: Record<string, unknown>) => Record<string, unknown>;
122
+ /**
123
+ * Error output format (default: 'standard').
124
+ * 'problem' emits RFC 9457 Problem Details bodies from `error()`.
125
+ */
126
+ format?: ResponseFormat;
127
+ /** Key casing of generated responses (default: 'snake') */
128
+ casing?: ResponseCasing;
129
+ /**
130
+ * Base URI used to build RFC 9457 `type` URIs
131
+ * (e.g. "https://errors.example.com" -> "https://errors.example.com/not_found").
132
+ * Defaults to "about:blank" semantics when unset.
133
+ */
134
+ problemTypeBase?: string;
135
+ /**
136
+ * Message resolver hook (i18n / localization).
137
+ * Return a string to override the outgoing message, or undefined to keep it.
138
+ */
139
+ messageResolver?: (error: HttpErrorLike) => string | undefined;
140
+ /**
141
+ * Sanitizer applied to metadata before serialization
142
+ * (strip PII, secrets, internal fields...).
143
+ */
144
+ metadataSanitizer?: (metadata: Record<string, unknown>) => Record<string, unknown>;
145
+ /**
146
+ * Expose 5xx error messages to clients by default (default: false).
147
+ * Strongly discouraged in production.
148
+ */
149
+ exposeServerErrors?: boolean;
150
+ }
151
+ /**
152
+ * Minimal structural view of HttpError used in config hooks
153
+ * (avoids circular type imports).
154
+ */
155
+ interface HttpErrorLike {
156
+ code: number;
157
+ type: string;
158
+ title: string;
159
+ message: string;
160
+ errorCode?: string;
161
+ metadata?: Record<string, unknown>;
162
+ }
163
+ /**
164
+ * Standard success response structure.
165
+ * The index signature `[key: string]: unknown` allows additional fields via
166
+ * `additionalFields`, but extra properties will be typed as `unknown` at compile time.
167
+ */
168
+ interface SuccessResponse<T = unknown> {
169
+ success: true;
170
+ status_code: number;
171
+ timestamp?: string;
172
+ request_id?: string;
173
+ data?: T;
174
+ message?: string;
175
+ metadata?: Record<string, unknown>;
176
+ [key: string]: unknown;
177
+ }
178
+ /**
179
+ * Standard error response structure.
180
+ * The index signature `[key: string]: unknown` allows additional fields via
181
+ * `additionalFields`, but extra properties will be typed as `unknown` at compile time.
182
+ */
183
+ interface ErrorResponse {
184
+ success: false;
185
+ status_code: number;
186
+ timestamp?: string;
187
+ request_id?: string;
188
+ retry_after?: number;
189
+ error: {
190
+ type: string;
191
+ title: string;
192
+ message: string;
193
+ code?: string;
194
+ details?: string;
195
+ errors?: ValidationIssue[];
196
+ stack?: string;
197
+ causes?: string[];
198
+ };
199
+ metadata?: Record<string, unknown>;
200
+ [key: string]: unknown;
201
+ }
202
+ /**
203
+ * RFC 9457 (obsoletes RFC 7807) Problem Details object.
204
+ * Serve with `Content-Type: application/problem+json`.
205
+ */
206
+ interface ProblemDetails {
207
+ /** URI reference identifying the problem type (default "about:blank") */
208
+ type: string;
209
+ /** Short human-readable summary of the problem type */
210
+ title: string;
211
+ /** HTTP status code */
212
+ status: number;
213
+ /** Human-readable explanation specific to this occurrence */
214
+ detail?: string;
215
+ /** URI reference identifying this specific occurrence */
216
+ instance?: string;
217
+ /** Extension: stable application error code */
218
+ code?: string;
219
+ /** Extension: validation issues */
220
+ errors?: ValidationIssue[];
221
+ /** Extension: correlation/request id */
222
+ request_id?: string;
223
+ /** Extension members */
224
+ [key: string]: unknown;
225
+ }
226
+ /** Options for building a Problem Details object */
227
+ interface ProblemOptions {
228
+ /** Base URI for the `type` member (overrides config) */
229
+ typeBase?: string;
230
+ /** `instance` member */
231
+ instance?: string;
232
+ /** Correlation/request id */
233
+ requestId?: string;
234
+ /** Extra extension members */
235
+ extensions?: Record<string, unknown>;
236
+ /** Force-expose (or hide) the error message */
237
+ expose?: boolean;
238
+ }
239
+ /**
240
+ * Input parameters for offset-based paginated responses
241
+ */
242
+ interface PaginationInput {
243
+ /** Current page number */
244
+ page: number;
245
+ /** Items per page */
246
+ limit: number;
247
+ /** Total number of items */
248
+ total: number;
249
+ /** Optional pre-computed total pages (overrides auto-calculation) */
250
+ totalPages?: number;
251
+ }
252
+ /**
253
+ * Pagination metadata included in paginated responses
254
+ */
255
+ interface PaginationMeta {
256
+ page: number;
257
+ limit: number;
258
+ total: number;
259
+ total_pages: number;
260
+ has_next: boolean;
261
+ has_prev: boolean;
262
+ }
263
+ /**
264
+ * Input parameters for cursor-based paginated responses
265
+ */
266
+ interface CursorPaginationInput {
267
+ /** Cursor pointing to the next page (absent/undefined = no next page) */
268
+ nextCursor?: string;
269
+ /** Cursor pointing to the previous page */
270
+ prevCursor?: string;
271
+ /** Items per page */
272
+ limit?: number;
273
+ /** Optional total count, when known */
274
+ total?: number;
275
+ }
276
+ /** Definition of a single domain error in a catalog */
277
+ interface CatalogEntry {
278
+ /** HTTP status code (e.g. 404) */
279
+ status: number;
280
+ /** Default client-facing message */
281
+ message?: string;
282
+ /** Optional title override */
283
+ title?: string;
284
+ /** Whether the message is exposable (defaults to status < 500) */
285
+ expose?: boolean;
286
+ /** Default metadata */
287
+ metadata?: Record<string, unknown>;
288
+ }
289
+
290
+ /**
291
+ * HTTP Response Kit - Status Code Enums
292
+ * @module constants/status-codes
293
+ */
294
+ /**
295
+ * HTTP 4xx Client Error codes
296
+ */
297
+ declare enum HttpClientErrorCode {
298
+ BAD_REQUEST = 400,
299
+ UNAUTHORIZED = 401,
300
+ PAYMENT_REQUIRED = 402,
301
+ FORBIDDEN = 403,
302
+ NOT_FOUND = 404,
303
+ METHOD_NOT_ALLOWED = 405,
304
+ NOT_ACCEPTABLE = 406,
305
+ PROXY_AUTHENTICATION_REQUIRED = 407,
306
+ REQUEST_TIMEOUT = 408,
307
+ CONFLICT = 409,
308
+ GONE = 410,
309
+ LENGTH_REQUIRED = 411,
310
+ PRECONDITION_FAILED = 412,
311
+ PAYLOAD_TOO_LARGE = 413,
312
+ URI_TOO_LONG = 414,
313
+ UNSUPPORTED_MEDIA_TYPE = 415,
314
+ RANGE_NOT_SATISFIABLE = 416,
315
+ EXPECTATION_FAILED = 417,
316
+ IM_A_TEAPOT = 418,
317
+ MISDIRECTED_REQUEST = 421,
318
+ UNPROCESSABLE_ENTITY = 422,
319
+ LOCKED = 423,
320
+ FAILED_DEPENDENCY = 424,
321
+ TOO_EARLY = 425,
322
+ UPGRADE_REQUIRED = 426,
323
+ PRECONDITION_REQUIRED = 428,
324
+ TOO_MANY_REQUESTS = 429,
325
+ REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
326
+ UNAVAILABLE_FOR_LEGAL_REASONS = 451
327
+ }
328
+ /**
329
+ * HTTP 5xx Server Error codes
330
+ */
331
+ declare enum HttpServerErrorCode {
332
+ INTERNAL_SERVER_ERROR = 500,
333
+ NOT_IMPLEMENTED = 501,
334
+ BAD_GATEWAY = 502,
335
+ SERVICE_UNAVAILABLE = 503,
336
+ GATEWAY_TIMEOUT = 504,
337
+ HTTP_VERSION_NOT_SUPPORTED = 505,
338
+ VARIANT_ALSO_NEGOTIATES = 506,
339
+ INSUFFICIENT_STORAGE = 507,
340
+ LOOP_DETECTED = 508,
341
+ BANDWIDTH_LIMIT_EXCEEDED = 509,
342
+ NOT_EXTENDED = 510,
343
+ NETWORK_AUTHENTICATION_REQUIRED = 511
344
+ }
345
+ /**
346
+ * All HTTP Error codes (4xx + 5xx)
347
+ */
348
+ declare const HttpErrorCode: {
349
+ readonly [x: number]: string;
350
+ readonly INTERNAL_SERVER_ERROR: HttpServerErrorCode.INTERNAL_SERVER_ERROR;
351
+ readonly NOT_IMPLEMENTED: HttpServerErrorCode.NOT_IMPLEMENTED;
352
+ readonly BAD_GATEWAY: HttpServerErrorCode.BAD_GATEWAY;
353
+ readonly SERVICE_UNAVAILABLE: HttpServerErrorCode.SERVICE_UNAVAILABLE;
354
+ readonly GATEWAY_TIMEOUT: HttpServerErrorCode.GATEWAY_TIMEOUT;
355
+ readonly HTTP_VERSION_NOT_SUPPORTED: HttpServerErrorCode.HTTP_VERSION_NOT_SUPPORTED;
356
+ readonly VARIANT_ALSO_NEGOTIATES: HttpServerErrorCode.VARIANT_ALSO_NEGOTIATES;
357
+ readonly INSUFFICIENT_STORAGE: HttpServerErrorCode.INSUFFICIENT_STORAGE;
358
+ readonly LOOP_DETECTED: HttpServerErrorCode.LOOP_DETECTED;
359
+ readonly BANDWIDTH_LIMIT_EXCEEDED: HttpServerErrorCode.BANDWIDTH_LIMIT_EXCEEDED;
360
+ readonly NOT_EXTENDED: HttpServerErrorCode.NOT_EXTENDED;
361
+ readonly NETWORK_AUTHENTICATION_REQUIRED: HttpServerErrorCode.NETWORK_AUTHENTICATION_REQUIRED;
362
+ readonly BAD_REQUEST: HttpClientErrorCode.BAD_REQUEST;
363
+ readonly UNAUTHORIZED: HttpClientErrorCode.UNAUTHORIZED;
364
+ readonly PAYMENT_REQUIRED: HttpClientErrorCode.PAYMENT_REQUIRED;
365
+ readonly FORBIDDEN: HttpClientErrorCode.FORBIDDEN;
366
+ readonly NOT_FOUND: HttpClientErrorCode.NOT_FOUND;
367
+ readonly METHOD_NOT_ALLOWED: HttpClientErrorCode.METHOD_NOT_ALLOWED;
368
+ readonly NOT_ACCEPTABLE: HttpClientErrorCode.NOT_ACCEPTABLE;
369
+ readonly PROXY_AUTHENTICATION_REQUIRED: HttpClientErrorCode.PROXY_AUTHENTICATION_REQUIRED;
370
+ readonly REQUEST_TIMEOUT: HttpClientErrorCode.REQUEST_TIMEOUT;
371
+ readonly CONFLICT: HttpClientErrorCode.CONFLICT;
372
+ readonly GONE: HttpClientErrorCode.GONE;
373
+ readonly LENGTH_REQUIRED: HttpClientErrorCode.LENGTH_REQUIRED;
374
+ readonly PRECONDITION_FAILED: HttpClientErrorCode.PRECONDITION_FAILED;
375
+ readonly PAYLOAD_TOO_LARGE: HttpClientErrorCode.PAYLOAD_TOO_LARGE;
376
+ readonly URI_TOO_LONG: HttpClientErrorCode.URI_TOO_LONG;
377
+ readonly UNSUPPORTED_MEDIA_TYPE: HttpClientErrorCode.UNSUPPORTED_MEDIA_TYPE;
378
+ readonly RANGE_NOT_SATISFIABLE: HttpClientErrorCode.RANGE_NOT_SATISFIABLE;
379
+ readonly EXPECTATION_FAILED: HttpClientErrorCode.EXPECTATION_FAILED;
380
+ readonly IM_A_TEAPOT: HttpClientErrorCode.IM_A_TEAPOT;
381
+ readonly MISDIRECTED_REQUEST: HttpClientErrorCode.MISDIRECTED_REQUEST;
382
+ readonly UNPROCESSABLE_ENTITY: HttpClientErrorCode.UNPROCESSABLE_ENTITY;
383
+ readonly LOCKED: HttpClientErrorCode.LOCKED;
384
+ readonly FAILED_DEPENDENCY: HttpClientErrorCode.FAILED_DEPENDENCY;
385
+ readonly TOO_EARLY: HttpClientErrorCode.TOO_EARLY;
386
+ readonly UPGRADE_REQUIRED: HttpClientErrorCode.UPGRADE_REQUIRED;
387
+ readonly PRECONDITION_REQUIRED: HttpClientErrorCode.PRECONDITION_REQUIRED;
388
+ readonly TOO_MANY_REQUESTS: HttpClientErrorCode.TOO_MANY_REQUESTS;
389
+ readonly REQUEST_HEADER_FIELDS_TOO_LARGE: HttpClientErrorCode.REQUEST_HEADER_FIELDS_TOO_LARGE;
390
+ readonly UNAVAILABLE_FOR_LEGAL_REASONS: HttpClientErrorCode.UNAVAILABLE_FOR_LEGAL_REASONS;
391
+ };
392
+ type HttpErrorCode = HttpClientErrorCode | HttpServerErrorCode;
393
+ /**
394
+ * HTTP 2xx Success codes
395
+ */
396
+ declare enum HttpSuccessCode {
397
+ OK = 200,
398
+ CREATED = 201,
399
+ ACCEPTED = 202,
400
+ NON_AUTHORITATIVE_INFORMATION = 203,
401
+ NO_CONTENT = 204,
402
+ RESET_CONTENT = 205,
403
+ PARTIAL_CONTENT = 206,
404
+ MULTI_STATUS = 207,
405
+ ALREADY_REPORTED = 208,
406
+ IM_USED = 226
407
+ }
408
+ /**
409
+ * HTTP 3xx Redirect codes
410
+ */
411
+ declare enum HttpRedirectCode {
412
+ MULTIPLE_CHOICES = 300,
413
+ MOVED_PERMANENTLY = 301,
414
+ FOUND = 302,
415
+ SEE_OTHER = 303,
416
+ NOT_MODIFIED = 304,
417
+ USE_PROXY = 305,
418
+ TEMPORARY_REDIRECT = 307,
419
+ PERMANENT_REDIRECT = 308
420
+ }
421
+ /**
422
+ * HTTP 1xx Informational codes
423
+ */
424
+ declare enum HttpInfoCode {
425
+ CONTINUE = 100,
426
+ SWITCHING_PROTOCOLS = 101,
427
+ PROCESSING = 102,
428
+ EARLY_HINTS = 103
429
+ }
430
+
431
+ /**
432
+ * HTTP Response Kit - HttpError Class
433
+ * @module errors/HttpError
434
+ */
435
+
436
+ /**
437
+ * Custom HTTP Error class that extends the native Error class.
438
+ * Provides structured error information for HTTP responses.
439
+ *
440
+ * Security model: `expose` controls whether `message` may be sent to clients.
441
+ * It defaults to `true` for 4xx and `false` for 5xx, so internal server error
442
+ * messages are never leaked unless explicitly allowed. The full message is
443
+ * always available on the instance for logging.
444
+ *
445
+ * @example
446
+ * ```ts
447
+ * // Basic usage with status code
448
+ * throw new HttpError(404);
449
+ * throw new HttpError(HttpErrorCode.NOT_FOUND);
450
+ *
451
+ * // With custom message
452
+ * throw new HttpError(404, { message: 'User not found' });
453
+ *
454
+ * // With metadata + stable application code
455
+ * throw new HttpError(400, {
456
+ * message: 'Validation failed',
457
+ * errorCode: 'VALIDATION_FAILED',
458
+ * metadata: { fields: ['email', 'password'] }
459
+ * });
460
+ *
461
+ * // Using factory methods
462
+ * throw HttpError.notFound('Resource not found');
463
+ * throw HttpError.validation([{ field: 'email', message: 'Invalid email' }]);
464
+ * ```
465
+ */
466
+ declare class HttpError extends Error {
467
+ /** HTTP status code */
468
+ readonly code: number;
469
+ /** Lowercase error type identifier */
470
+ readonly type: string;
471
+ /** Human-readable error title */
472
+ readonly title: string;
473
+ /** Default error description from definition */
474
+ readonly details: string;
475
+ /** Additional error metadata */
476
+ readonly metadata?: Record<string, unknown>;
477
+ /** Original error cause (also available as native `Error.cause`) */
478
+ readonly cause?: Error;
479
+ /** Retry-after time in seconds (if applicable) */
480
+ readonly retryAfter?: number;
481
+ /** Whether `message` is safe to send to clients (4xx: true, 5xx: false by default) */
482
+ readonly expose: boolean;
483
+ /** Stable application-level error code (e.g. "USER_NOT_FOUND") */
484
+ readonly errorCode?: string;
485
+ /** Structured validation issues */
486
+ readonly validationErrors?: ValidationIssue[];
487
+ /** Extra HTTP headers associated with this error */
488
+ readonly headers?: Record<string, string>;
489
+ /** RFC 9457 `instance` URI for this specific occurrence */
490
+ readonly instance?: string;
491
+ /**
492
+ * Creates a new HttpError instance
493
+ *
494
+ * @param code - HTTP status code (e.g., 404, 500)
495
+ * @param options - Optional configuration
496
+ */
497
+ constructor(code: HttpClientErrorCode | HttpServerErrorCode | number, options?: HttpErrorOptions);
498
+ /**
499
+ * The message that is safe to send to clients.
500
+ * Falls back to the generic definition message when `expose` is false.
501
+ */
502
+ get safeMessage(): string;
503
+ /**
504
+ * HTTP headers that should accompany this error response
505
+ * (e.g. `Retry-After` for 429/503, plus any custom headers).
506
+ */
507
+ getHeaders(): Record<string, string>;
508
+ /**
509
+ * Convert error to plain object for JSON serialization.
510
+ * Note: contains the full (non-sanitized) message - intended for logging.
511
+ * Use `kit.error()` / `toProblemDetails()` for client output.
512
+ */
513
+ toJSON(): Record<string, unknown>;
514
+ /**
515
+ * Build an RFC 9457 Problem Details object for this error.
516
+ * Serve it with `Content-Type: application/problem+json`.
517
+ *
518
+ * @example
519
+ * ```ts
520
+ * const problem = HttpError.notFound('User not found').toProblemDetails({
521
+ * typeBase: 'https://errors.example.com',
522
+ * instance: '/users/42',
523
+ * });
524
+ * // { type: 'https://errors.example.com/not_found', title: 'Not Found',
525
+ * // status: 404, detail: 'User not found', instance: '/users/42' }
526
+ * ```
527
+ */
528
+ toProblemDetails(options?: ProblemOptions): ProblemDetails;
529
+ /** 400 Bad Request */
530
+ static badRequest(message?: string, metadata?: Record<string, unknown>): HttpError;
531
+ /** 401 Unauthorized */
532
+ static unauthorized(message?: string, metadata?: Record<string, unknown>): HttpError;
533
+ /** 402 Payment Required */
534
+ static paymentRequired(message?: string, metadata?: Record<string, unknown>): HttpError;
535
+ /** 403 Forbidden */
536
+ static forbidden(message?: string, metadata?: Record<string, unknown>): HttpError;
537
+ /** 404 Not Found */
538
+ static notFound(message?: string, metadata?: Record<string, unknown>): HttpError;
539
+ /** 405 Method Not Allowed */
540
+ static methodNotAllowed(message?: string, metadata?: Record<string, unknown>): HttpError;
541
+ /** 406 Not Acceptable */
542
+ static notAcceptable(message?: string, metadata?: Record<string, unknown>): HttpError;
543
+ /** 407 Proxy Authentication Required */
544
+ static proxyAuthenticationRequired(message?: string, metadata?: Record<string, unknown>): HttpError;
545
+ /** 408 Request Timeout */
546
+ static requestTimeout(message?: string, metadata?: Record<string, unknown>): HttpError;
547
+ /** 409 Conflict */
548
+ static conflict(message?: string, metadata?: Record<string, unknown>): HttpError;
549
+ /** 410 Gone */
550
+ static gone(message?: string, metadata?: Record<string, unknown>): HttpError;
551
+ /** 411 Length Required */
552
+ static lengthRequired(message?: string, metadata?: Record<string, unknown>): HttpError;
553
+ /** 412 Precondition Failed */
554
+ static preconditionFailed(message?: string, metadata?: Record<string, unknown>): HttpError;
555
+ /** 413 Payload Too Large */
556
+ static payloadTooLarge(message?: string, metadata?: Record<string, unknown>): HttpError;
557
+ /** 414 URI Too Long */
558
+ static uriTooLong(message?: string, metadata?: Record<string, unknown>): HttpError;
559
+ /** 415 Unsupported Media Type */
560
+ static unsupportedMediaType(message?: string, metadata?: Record<string, unknown>): HttpError;
561
+ /** 416 Range Not Satisfiable */
562
+ static rangeNotSatisfiable(message?: string, metadata?: Record<string, unknown>): HttpError;
563
+ /** 417 Expectation Failed */
564
+ static expectationFailed(message?: string, metadata?: Record<string, unknown>): HttpError;
565
+ /** 418 I'm a Teapot */
566
+ static imATeapot(message?: string, metadata?: Record<string, unknown>): HttpError;
567
+ /** 421 Misdirected Request */
568
+ static misdirectedRequest(message?: string, metadata?: Record<string, unknown>): HttpError;
569
+ /** 422 Unprocessable Entity */
570
+ static unprocessableEntity(message?: string, metadata?: Record<string, unknown>): HttpError;
571
+ /**
572
+ * 422 Unprocessable Entity with structured validation issues.
573
+ *
574
+ * @example
575
+ * ```ts
576
+ * throw HttpError.validation([
577
+ * { field: 'email', message: 'Invalid email format', code: 'invalid_format' },
578
+ * { field: 'age', message: 'Must be >= 18', code: 'too_small' },
579
+ * ]);
580
+ * ```
581
+ */
582
+ static validation(errors: ValidationIssue[], message?: string, code?: number): HttpError;
583
+ /** 423 Locked */
584
+ static locked(message?: string, metadata?: Record<string, unknown>): HttpError;
585
+ /** 424 Failed Dependency */
586
+ static failedDependency(message?: string, metadata?: Record<string, unknown>): HttpError;
587
+ /** 425 Too Early */
588
+ static tooEarly(message?: string, metadata?: Record<string, unknown>): HttpError;
589
+ /** 426 Upgrade Required */
590
+ static upgradeRequired(message?: string, metadata?: Record<string, unknown>): HttpError;
591
+ /** 428 Precondition Required */
592
+ static preconditionRequired(message?: string, metadata?: Record<string, unknown>): HttpError;
593
+ /** 429 Too Many Requests */
594
+ static tooManyRequests(message?: string, retryAfter?: number, metadata?: Record<string, unknown>): HttpError;
595
+ /** 431 Request Header Fields Too Large */
596
+ static requestHeaderFieldsTooLarge(message?: string, metadata?: Record<string, unknown>): HttpError;
597
+ /** 451 Unavailable For Legal Reasons */
598
+ static unavailableForLegalReasons(message?: string, metadata?: Record<string, unknown>): HttpError;
599
+ /** 500 Internal Server Error */
600
+ static internalServerError(message?: string, metadata?: Record<string, unknown>): HttpError;
601
+ /** 501 Not Implemented */
602
+ static notImplemented(message?: string, metadata?: Record<string, unknown>): HttpError;
603
+ /** 502 Bad Gateway */
604
+ static badGateway(message?: string, metadata?: Record<string, unknown>): HttpError;
605
+ /** 503 Service Unavailable */
606
+ static serviceUnavailable(message?: string, retryAfter?: number, metadata?: Record<string, unknown>): HttpError;
607
+ /** 504 Gateway Timeout */
608
+ static gatewayTimeout(message?: string, metadata?: Record<string, unknown>): HttpError;
609
+ /** 505 HTTP Version Not Supported */
610
+ static httpVersionNotSupported(message?: string, metadata?: Record<string, unknown>): HttpError;
611
+ /** 506 Variant Also Negotiates */
612
+ static variantAlsoNegotiates(message?: string, metadata?: Record<string, unknown>): HttpError;
613
+ /** 507 Insufficient Storage */
614
+ static insufficientStorage(message?: string, metadata?: Record<string, unknown>): HttpError;
615
+ /** 508 Loop Detected */
616
+ static loopDetected(message?: string, metadata?: Record<string, unknown>): HttpError;
617
+ /** 509 Bandwidth Limit Exceeded */
618
+ static bandwidthLimitExceeded(message?: string, metadata?: Record<string, unknown>): HttpError;
619
+ /** 510 Not Extended */
620
+ static notExtended(message?: string, metadata?: Record<string, unknown>): HttpError;
621
+ /** 511 Network Authentication Required */
622
+ static networkAuthenticationRequired(message?: string, metadata?: Record<string, unknown>): HttpError;
623
+ /**
624
+ * Create an HttpError from an unknown error.
625
+ *
626
+ * Security: wrapped errors are marked `expose: false` when the resulting
627
+ * status is 5xx, so unexpected internal messages (DB errors, stack info,
628
+ * connection strings...) are never sent to clients. The original message
629
+ * and cause are preserved on the instance for logging.
630
+ *
631
+ * System/socket errors (ECONNREFUSED, ETIMEDOUT, undici fetch codes...)
632
+ * are automatically mapped to the semantically correct 502/503/504 -
633
+ * including codes buried in the `cause` chain (e.g. Node's
634
+ * `fetch failed` TypeError) - with the syscall code as `errorCode`.
635
+ */
636
+ static fromError(error: unknown, fallbackCode?: number): HttpError;
637
+ /**
638
+ * Check if an error is an HttpError
639
+ */
640
+ static isHttpError(error: unknown): error is HttpError;
641
+ /**
642
+ * Check if error is a client error (4xx)
643
+ */
644
+ isClientError(): boolean;
645
+ /**
646
+ * Check if error is a server error (5xx)
647
+ */
648
+ isServerError(): boolean;
649
+ /**
650
+ * Flattened chain of cause messages (most recent first).
651
+ * Useful for structured logging; never serialized to clients in production.
652
+ */
653
+ getCauseChain(): string[];
654
+ }
655
+
656
+ /**
657
+ * HTTP Response Kit - ResponseKit
658
+ *
659
+ * The single, definitive way to format responses: create an isolated kit
660
+ * with `createResponseKit()`. Every kit owns its configuration - there is
661
+ * no global mutable state anywhere in this library.
662
+ *
663
+ * @module kit
664
+ */
665
+
666
+ /** Type guard: is this a success response? */
667
+ declare function isSuccessResponse(response: SuccessResponse | ErrorResponse): response is SuccessResponse;
668
+ /** Type guard: is this an error response? */
669
+ declare function isErrorResponse(response: SuccessResponse | ErrorResponse): response is ErrorResponse;
670
+ /**
671
+ * An isolated response formatter with its own configuration.
672
+ * Create one with {@link createResponseKit}.
673
+ */
674
+ declare class ResponseKit {
675
+ private readonly config;
676
+ constructor(config?: KitConfig);
677
+ /** Merge partial configuration into this instance */
678
+ configure(config: Partial<KitConfig>): void;
679
+ /** Snapshot of the current configuration */
680
+ getConfig(): Readonly<KitConfig>;
681
+ /** Whether dev mode is active (stack traces, cause chains) */
682
+ isDevelopment(): boolean;
683
+ private finalize;
684
+ /**
685
+ * Resolve the outgoing client-facing message for an error.
686
+ *
687
+ * Priority: messageResolver > explicit message (if exposed)
688
+ * > customMessages[code] > generic status description.
689
+ */
690
+ private resolveMessage;
691
+ /** Format a success response */
692
+ success<T = unknown>(config?: SuccessResponseConfig<T>): SuccessResponse<T>;
693
+ /**
694
+ * Format an error response.
695
+ *
696
+ * Security: when the error is not exposable (5xx by default), the outgoing
697
+ * message falls back to the generic status description (or the configured
698
+ * custom message for that code) and `metadata` is omitted. The original
699
+ * message stays available on the error instance for logging.
700
+ */
701
+ error(error: HttpError, config?: ErrorResponseConfig): ErrorResponse;
702
+ /** Format a response from any error (converts to HttpError first) */
703
+ fromError(error: unknown, config?: ErrorResponseConfig): ErrorResponse;
704
+ /**
705
+ * Build an RFC 9457 Problem Details body from any error.
706
+ * Serve it with `Content-Type: application/problem+json`
707
+ * (see `PROBLEM_CONTENT_TYPE`).
708
+ */
709
+ problem(error: unknown, options?: ProblemOptions): ProblemDetails;
710
+ /** 200 OK */
711
+ ok<T = unknown>(data?: T, message?: string): SuccessResponse<T>;
712
+ /** 201 Created */
713
+ created<T = unknown>(data?: T, message?: string): SuccessResponse<T>;
714
+ /** 202 Accepted */
715
+ accepted<T = unknown>(data?: T, message?: string): SuccessResponse<T>;
716
+ /** 204 No Content */
717
+ noContent(): SuccessResponse<never>;
718
+ /** 206 Partial Content */
719
+ partialContent<T = unknown>(data?: T, message?: string): SuccessResponse<T>;
720
+ /** 304 Not Modified */
721
+ notModified(): SuccessResponse<never>;
722
+ /** Create an offset-based paginated success response */
723
+ paginated<T = unknown>(data: T[], pagination: PaginationInput, message?: string): SuccessResponse<T[]>;
724
+ /**
725
+ * Create a cursor-based paginated success response.
726
+ *
727
+ * @example
728
+ * ```ts
729
+ * kit.paginatedCursor(items, { nextCursor: 'eyJpZCI6NDJ9', limit: 20 });
730
+ * // metadata.pagination: { next_cursor, limit, has_next: true, has_prev: false }
731
+ * ```
732
+ */
733
+ paginatedCursor<T = unknown>(data: T[], cursor: CursorPaginationInput, message?: string): SuccessResponse<T[]>;
734
+ }
735
+ /**
736
+ * Create an isolated ResponseKit instance with its own configuration.
737
+ * This is the entry point of the library.
738
+ *
739
+ * @example
740
+ * ```ts
741
+ * const api = createResponseKit({
742
+ * isDevelopment: process.env.NODE_ENV === 'development',
743
+ * format: 'problem',
744
+ * problemTypeBase: 'https://errors.example.com',
745
+ * });
746
+ *
747
+ * api.ok(user);
748
+ * api.error(HttpError.notFound('No such user'), { requestId: req.id });
749
+ * ```
750
+ */
751
+ declare function createResponseKit(config?: KitConfig): ResponseKit;
752
+
753
+ export { type CatalogEntry as C, type ErrorResponse as E, HttpError as H, type KitConfig as K, type ProblemDetails as P, ResponseKit as R, type SuccessResponse as S, type ValidationIssue as V, type HttpErrorInfo as a, type HttpSuccessInfo as b, type HttpErrorOptions as c, type ProblemOptions as d, type CursorPaginationInput as e, type ErrorResponseConfig as f, HttpClientErrorCode as g, HttpErrorCode as h, type HttpErrorLike as i, HttpInfoCode as j, HttpRedirectCode as k, HttpServerErrorCode as l, HttpSuccessCode as m, type PaginationInput as n, type PaginationMeta as o, type ResponseCasing as p, type ResponseFormat as q, type SuccessResponseConfig as r, createResponseKit as s, isErrorResponse as t, isSuccessResponse as u };