@web-ts-toolkit/http-errors 0.32.0 → 0.33.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/README.md +99 -1
- package/index.d.mts +163 -22
- package/index.d.ts +163 -22
- package/index.js +298 -58
- package/index.mjs +283 -57
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -15,10 +15,23 @@ pnpm add @web-ts-toolkit/http-errors
|
|
|
15
15
|
- machine-readable error metadata
|
|
16
16
|
- helpers for AIP-193 and RFC 9457 payloads
|
|
17
17
|
|
|
18
|
+
## Constructor Status Contract
|
|
19
|
+
|
|
20
|
+
`HttpError` accepts only finite integer HTTP error status codes from `400` through `599`.
|
|
21
|
+
`ClientError` narrows that to `400` through `499`, and `ServerError` narrows it to `500` through `599`.
|
|
22
|
+
Invalid or category-mismatched statuses throw synchronously before an error instance is created.
|
|
23
|
+
|
|
18
24
|
## Quick Start
|
|
19
25
|
|
|
20
26
|
```ts
|
|
21
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
HttpError,
|
|
29
|
+
ServiceUnavailableError,
|
|
30
|
+
UnauthorizedError,
|
|
31
|
+
toAip193ErrorPayload,
|
|
32
|
+
toRfc9457ErrorPayload,
|
|
33
|
+
toRfc9457ValidationErrorPayload,
|
|
34
|
+
} from '@web-ts-toolkit/http-errors';
|
|
22
35
|
|
|
23
36
|
throw new UnauthorizedError();
|
|
24
37
|
throw new UnauthorizedError('missing bearer token');
|
|
@@ -27,15 +40,100 @@ throw new HttpError(503);
|
|
|
27
40
|
throw new HttpError(503, 'please try again later');
|
|
28
41
|
|
|
29
42
|
throw new ServiceUnavailableError();
|
|
43
|
+
|
|
44
|
+
const error = new HttpError(400, 'Email must be a valid address.', {
|
|
45
|
+
reason: 'INVALID_EMAIL',
|
|
46
|
+
domain: 'api.example.com',
|
|
47
|
+
type: 'https://api.example.com/problems/invalid-email',
|
|
48
|
+
title: 'Invalid email address',
|
|
49
|
+
instance: '/problems/invalid-email/123',
|
|
50
|
+
metadata: { field: 'email' },
|
|
51
|
+
errors: [{ detail: 'must be a valid email address', pointer: '#/email' }],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const aip193 = toAip193ErrorPayload(error);
|
|
55
|
+
const rfc9457 = toRfc9457ErrorPayload(error);
|
|
56
|
+
const validation = toRfc9457ValidationErrorPayload(error);
|
|
57
|
+
void [aip193, rfc9457, validation];
|
|
30
58
|
```
|
|
31
59
|
|
|
32
60
|
## Main Exports
|
|
33
61
|
|
|
34
62
|
- `HttpError`
|
|
63
|
+
- `ClientError` and `ServerError`
|
|
35
64
|
- specific error classes such as `BadRequestError`, `ForbiddenError`, `NotFoundError`
|
|
36
65
|
- `toAip193ErrorPayload(...)`
|
|
37
66
|
- `toRfc9457ErrorPayload(...)`
|
|
38
67
|
- `toRfc9457ValidationErrorPayload(...)`
|
|
68
|
+
- types including `HttpErrorOptions`, `HttpErrorShape`, `HttpErrorProblemFields`, `HttpErrorMetadataValue`, `Aip193ErrorInfoDetail`, `Aip193ErrorPayload`, `Rfc9457ErrorPayload`, and `Rfc9457ValidationError`
|
|
69
|
+
|
|
70
|
+
## AIP-193 Serializer Contract
|
|
71
|
+
|
|
72
|
+
`toAip193ErrorPayload(...)` returns a Google-style `{ error }` envelope. It emits `code`, `status`, `message`, and `details` on every payload. The first detail is always an `error_info` entry whose `reason` defaults to the error `reason` or canonical status, whose `domain` defaults to the error `domain` or the serializer fallback domain, and whose `metadata` is copied when present.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { BadRequestError, toAip193ErrorPayload } from '@web-ts-toolkit/http-errors';
|
|
76
|
+
|
|
77
|
+
const payload = toAip193ErrorPayload(
|
|
78
|
+
new BadRequestError('Email must be a valid address.', {
|
|
79
|
+
reason: 'INVALID_EMAIL',
|
|
80
|
+
domain: 'api.example.com',
|
|
81
|
+
metadata: { field: 'email' },
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// payload.error.details[0] is:
|
|
86
|
+
// { type: 'error_info', reason: 'INVALID_EMAIL', domain: 'api.example.com', metadata: { field: 'email' } }
|
|
87
|
+
void payload;
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## RFC 9457 Serializer Contract
|
|
91
|
+
|
|
92
|
+
`toRfc9457ErrorPayload(...)` emits required RFC 9457 problem members (`type`, `title`, `status`, and `detail`) on every payload. If the input shape has `errors` typed as an array, the returned payload preserves that entry type for custom extension errors.
|
|
93
|
+
|
|
94
|
+
When `type` is missing it falls back to `about:blank`. When `title` is missing it falls back to the canonical HTTP status title, or `Unknown` for unmapped status codes. `instance` is emitted only when present.
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { BadRequestError, toRfc9457ErrorPayload } from '@web-ts-toolkit/http-errors';
|
|
98
|
+
|
|
99
|
+
const payload = toRfc9457ErrorPayload(
|
|
100
|
+
new BadRequestError('Email must be a valid address.', {
|
|
101
|
+
type: 'https://api.example.com/problems/invalid-email',
|
|
102
|
+
title: 'Invalid email address',
|
|
103
|
+
instance: '/problems/invalid-email/123',
|
|
104
|
+
errors: [{ detail: 'must be a valid email address', pointer: '#/email' }],
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// payload is:
|
|
109
|
+
// { type, title, status: 400, detail: 'Email must be a valid address.', instance, errors }
|
|
110
|
+
void payload;
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`toRfc9457ValidationErrorPayload(...)` is the validation-specific helper. It accepts JavaScript input defensively and only emits `errors` entries that have an own string `detail` plus optional own string `pointer`, `parameter`, and `header` fields. Non-arrays, empty arrays, inherited validation fields, and invalid entries are omitted from the returned `errors` array; if no valid entries remain, `errors` is omitted.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { BadRequestError, toRfc9457ValidationErrorPayload } from '@web-ts-toolkit/http-errors';
|
|
117
|
+
|
|
118
|
+
const payload = toRfc9457ValidationErrorPayload(
|
|
119
|
+
new BadRequestError('Email must be a valid address.', {
|
|
120
|
+
errors: [{ detail: 'must be a valid email address', pointer: '#/email', debug: 'omitted' }, { pointer: '#/name' }],
|
|
121
|
+
}),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// payload.errors is [{ detail: 'must be a valid email address', pointer: '#/email' }]
|
|
125
|
+
void payload;
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## External Payload Disclosure
|
|
129
|
+
|
|
130
|
+
Serializers emit public payload fields verbatim. Treat `message`, `details`, `errors`, `metadata`, `type`, `title`, and `instance` as externally visible API response data. Do not put secrets, stack traces, raw upstream errors, tokens, credentials, or internal diagnostics in these fields unless you intentionally want clients to receive them.
|
|
131
|
+
|
|
132
|
+
## Structured Value Ownership
|
|
133
|
+
|
|
134
|
+
`HttpError` snapshots supported top-level collections at construction. `metadata` is normalized into an error-owned frozen string record, and array-valued `details` and `errors` are copied into error-owned frozen arrays. Mutating the source objects after construction cannot add, remove, reorder, or rename error-owned top-level entries.
|
|
135
|
+
|
|
136
|
+
Serializers also return fresh top-level arrays and metadata records, so mutating one payload does not change the source error or later payloads. This is a shallow boundary: nested detail and error entry objects remain shared, and `ErrorOptions.cause` identity is preserved.
|
|
39
137
|
|
|
40
138
|
## Documentation
|
|
41
139
|
|
package/index.d.mts
CHANGED
|
@@ -1,57 +1,108 @@
|
|
|
1
|
+
/** Scalar values accepted in `HttpErrorOptions.metadata` before string normalization. */
|
|
1
2
|
type HttpErrorMetadataValue = string | number | boolean | bigint | null | undefined;
|
|
3
|
+
/** RFC 9457 problem fields stored on an HTTP error and emitted by RFC serializers. */
|
|
2
4
|
type HttpErrorProblemFields = {
|
|
5
|
+
/** Problem type URI. Falls back to `about:blank` when serialized if absent. */
|
|
3
6
|
type?: string;
|
|
7
|
+
/** Public problem title. Falls back to the status title when serialized if absent. */
|
|
4
8
|
title?: string;
|
|
9
|
+
/** Problem instance URI emitted only when present. */
|
|
5
10
|
instance?: string;
|
|
6
11
|
};
|
|
7
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Constructor options for `HttpError`, `ClientError`, `ServerError`, and specific subclasses.
|
|
14
|
+
*
|
|
15
|
+
* `message`, `details`, `errors`, `metadata`, `type`, `title`, and `instance` can
|
|
16
|
+
* be emitted verbatim by serializers. Do not place secrets or log-only diagnostics
|
|
17
|
+
* in these fields. Top-level `metadata`, `details`, and array-valued `errors` are
|
|
18
|
+
* shallow-snapshotted by `HttpError` construction.
|
|
19
|
+
*/
|
|
20
|
+
type HttpErrorOptions<TErrors = unknown> = ErrorOptions & HttpErrorProblemFields & {
|
|
21
|
+
/** Override canonical status text for serializers such as AIP-193. */
|
|
8
22
|
status?: string;
|
|
23
|
+
/** Machine-readable application reason, such as `INVALID_EMAIL`. */
|
|
9
24
|
reason?: string;
|
|
25
|
+
/** Logical application domain, such as `api.example.com`. */
|
|
10
26
|
domain?: string;
|
|
11
|
-
metadata
|
|
12
|
-
|
|
13
|
-
|
|
27
|
+
/** Key-value metadata normalized to strings and copied into serialized payloads. */
|
|
28
|
+
metadata?: Readonly<Record<string, HttpErrorMetadataValue>>;
|
|
29
|
+
/** Additional structured details emitted by AIP-193 payloads. */
|
|
30
|
+
details?: readonly unknown[];
|
|
31
|
+
/** Extension or validation errors emitted by RFC 9457 helpers when array-valued. */
|
|
32
|
+
errors?: TErrors;
|
|
14
33
|
};
|
|
15
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Minimal error-like input accepted by serializers.
|
|
36
|
+
*
|
|
37
|
+
* This shape allows using real `HttpError` instances or compatible plain objects.
|
|
38
|
+
* Serializers treat `message` and structured fields as public response data.
|
|
39
|
+
*/
|
|
40
|
+
type HttpErrorShape<TErrors = unknown> = HttpErrorProblemFields & {
|
|
41
|
+
/** HTTP error status code used as the response code/status. */
|
|
16
42
|
statusCode: number;
|
|
43
|
+
/** Canonical or custom status string used by AIP-193 payloads. */
|
|
17
44
|
status?: string;
|
|
45
|
+
/** Public error detail/message emitted verbatim. */
|
|
18
46
|
message: string;
|
|
47
|
+
/** Machine-readable application reason used by AIP-193 `error_info`. */
|
|
19
48
|
reason?: string;
|
|
49
|
+
/** Domain used by AIP-193 `error_info`. */
|
|
20
50
|
domain?: string;
|
|
21
|
-
metadata
|
|
22
|
-
|
|
23
|
-
|
|
51
|
+
/** String metadata copied into AIP-193 `error_info`. */
|
|
52
|
+
metadata?: Readonly<Record<string, string>>;
|
|
53
|
+
/** Additional AIP-193 detail entries. */
|
|
54
|
+
details?: readonly unknown[];
|
|
55
|
+
/** RFC 9457 extension or validation errors. Array-valued entries are shallow-copied. */
|
|
56
|
+
errors?: TErrors;
|
|
24
57
|
};
|
|
58
|
+
/** AIP-193 `error_info` detail entry emitted as the first AIP-193 detail. */
|
|
25
59
|
type Aip193ErrorInfoDetail = {
|
|
26
60
|
type: 'error_info';
|
|
27
61
|
reason: string;
|
|
28
62
|
domain: string;
|
|
29
|
-
metadata?: Record<string, string
|
|
63
|
+
metadata?: Readonly<Record<string, string>>;
|
|
30
64
|
};
|
|
65
|
+
/** Google/AIP-193-style error response envelope. */
|
|
31
66
|
type Aip193ErrorPayload = {
|
|
32
67
|
error: {
|
|
68
|
+
/** HTTP status code. */
|
|
33
69
|
code: number;
|
|
70
|
+
/** Canonical or custom status string. */
|
|
34
71
|
status: string;
|
|
72
|
+
/** Public error message emitted verbatim from the input error. */
|
|
35
73
|
message: string;
|
|
36
|
-
details
|
|
74
|
+
/** Structured details, beginning with an `error_info` entry. */
|
|
75
|
+
details?: readonly unknown[];
|
|
37
76
|
};
|
|
38
77
|
};
|
|
78
|
+
/** RFC 9457 problem-details payload with optional typed `errors` extension entries. */
|
|
39
79
|
type Rfc9457ErrorPayload<TError = unknown> = {
|
|
40
|
-
type
|
|
41
|
-
|
|
42
|
-
status
|
|
43
|
-
|
|
80
|
+
/** Problem type URI, defaulting to `about:blank` when absent on the input. */
|
|
81
|
+
type: string;
|
|
82
|
+
/** Public problem title, defaulting to the status title or `Unknown`. */
|
|
83
|
+
title: string;
|
|
84
|
+
/** HTTP status code. */
|
|
85
|
+
status: number;
|
|
86
|
+
/** Public problem detail emitted verbatim from the input error message. */
|
|
87
|
+
detail: string;
|
|
88
|
+
/** Problem instance URI, emitted only when present on the input. */
|
|
44
89
|
instance?: string;
|
|
45
|
-
errors
|
|
90
|
+
/** Optional extension errors. Validation helpers emit only validated entries. */
|
|
91
|
+
errors?: readonly TError[];
|
|
46
92
|
};
|
|
93
|
+
/** RFC 9457 validation error entry accepted by `toRfc9457ValidationErrorPayload`. */
|
|
47
94
|
type Rfc9457ValidationError = {
|
|
95
|
+
/** Human-readable validation detail. Required and must be an own string field. */
|
|
48
96
|
detail: string;
|
|
97
|
+
/** JSON Pointer to the invalid field, when available. */
|
|
49
98
|
pointer?: string;
|
|
99
|
+
/** Query/path/header parameter name, when available. */
|
|
50
100
|
parameter?: string;
|
|
101
|
+
/** Header name, when available. */
|
|
51
102
|
header?: string;
|
|
52
103
|
};
|
|
53
104
|
|
|
54
|
-
declare const
|
|
105
|
+
declare const canonicalStatusLookup: Readonly<{
|
|
55
106
|
readonly 400: "INVALID_ARGUMENT";
|
|
56
107
|
readonly 401: "UNAUTHENTICATED";
|
|
57
108
|
readonly 403: "PERMISSION_DENIED";
|
|
@@ -63,18 +114,88 @@ declare const canonicalStatusByHttpStatus: {
|
|
|
63
114
|
readonly 501: "UNIMPLEMENTED";
|
|
64
115
|
readonly 503: "UNAVAILABLE";
|
|
65
116
|
readonly 504: "DEADLINE_EXCEEDED";
|
|
66
|
-
}
|
|
117
|
+
}>;
|
|
118
|
+
declare const canonicalStatusByHttpStatus: Readonly<typeof canonicalStatusLookup>;
|
|
67
119
|
declare const getCanonicalStatus: (statusCode: number) => string;
|
|
68
120
|
declare const getStatusTitle: (statusCode: number) => string;
|
|
121
|
+
declare const isHttpErrorStatusCode: (statusCode: unknown) => statusCode is number;
|
|
122
|
+
declare const validateHttpErrorStatusCode: (statusCode: unknown, source?: string) => number;
|
|
123
|
+
declare const validateClientErrorStatusCode: (statusCode: unknown, source?: string) => number;
|
|
124
|
+
declare const validateServerErrorStatusCode: (statusCode: unknown, source?: string) => number;
|
|
69
125
|
|
|
70
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Creates an AIP-193 `error_info` detail entry.
|
|
128
|
+
*
|
|
129
|
+
* The returned `metadata` record is a shallow copy so payload mutation does not
|
|
130
|
+
* mutate the source error metadata.
|
|
131
|
+
*
|
|
132
|
+
* @param reason Machine-readable reason, usually an application code or canonical status.
|
|
133
|
+
* @param domain Logical error domain, such as `api.example.com`.
|
|
134
|
+
* @param metadata Optional string metadata copied into the returned detail.
|
|
135
|
+
* @returns A serializable AIP-193 `error_info` detail.
|
|
136
|
+
*/
|
|
137
|
+
declare const createAip193ErrorInfoDetail: (reason: string, domain: string, metadata?: Readonly<Record<string, string>>) => Aip193ErrorInfoDetail;
|
|
138
|
+
/**
|
|
139
|
+
* Converts an HTTP error shape into an AIP-193-style `{ error }` envelope.
|
|
140
|
+
*
|
|
141
|
+
* Emits `error.message` verbatim as the public payload message. The first detail
|
|
142
|
+
* is always an `error_info` entry. Additional `errors` and `details` entries are
|
|
143
|
+
* shallow-copied at the top level only.
|
|
144
|
+
*
|
|
145
|
+
* @param error Error-like shape with status, message, and optional structured fields.
|
|
146
|
+
* @param fallbackDomain Domain used for `error_info` when `error.domain` is absent.
|
|
147
|
+
* @returns A payload containing `code`, `status`, `message`, and `details`.
|
|
148
|
+
*/
|
|
71
149
|
declare const toAip193ErrorPayload: (error: HttpErrorShape, fallbackDomain?: string) => Aip193ErrorPayload;
|
|
72
|
-
|
|
150
|
+
/**
|
|
151
|
+
* Converts an HTTP error shape with typed extension errors into an RFC 9457 problem payload.
|
|
152
|
+
*
|
|
153
|
+
* Emits `message` as `detail` and passes `type`, `title`, `instance`, and array
|
|
154
|
+
* `errors` through as public response data. Array-valued `errors` are shallow-copied.
|
|
155
|
+
*
|
|
156
|
+
* @param error Error-like shape whose `errors` field is a typed array.
|
|
157
|
+
* @returns RFC 9457 problem details preserving the typed extension error entries.
|
|
158
|
+
*/
|
|
159
|
+
declare function toRfc9457ErrorPayload<TError>(error: HttpErrorShape<readonly TError[]>): Rfc9457ErrorPayload<TError>;
|
|
160
|
+
/**
|
|
161
|
+
* Converts an HTTP error shape into an RFC 9457 problem payload.
|
|
162
|
+
*
|
|
163
|
+
* Missing `type` falls back to `about:blank`; missing `title` falls back to the
|
|
164
|
+
* canonical status title, or `Unknown` for unmapped status codes. `message` is
|
|
165
|
+
* emitted verbatim as `detail`; `instance` and array-valued `errors` are emitted
|
|
166
|
+
* when present.
|
|
167
|
+
*
|
|
168
|
+
* @param error Error-like shape with status, message, and optional problem fields.
|
|
169
|
+
* @returns RFC 9457 problem details.
|
|
170
|
+
*/
|
|
171
|
+
declare function toRfc9457ErrorPayload(error: HttpErrorShape): Rfc9457ErrorPayload;
|
|
172
|
+
/**
|
|
173
|
+
* Converts an HTTP error shape into an RFC 9457 validation problem payload.
|
|
174
|
+
*
|
|
175
|
+
* Runtime-narrows `errors` before typing the result as validation entries. Keeps
|
|
176
|
+
* only own string `detail` plus optional own string `pointer`, `parameter`, and
|
|
177
|
+
* `header`; extra fields are omitted. If no valid entries remain, `errors` is omitted.
|
|
178
|
+
*
|
|
179
|
+
* @param error Error-like shape with optional validation-style `errors` entries.
|
|
180
|
+
* @returns RFC 9457 problem details with validated `errors` entries when available.
|
|
181
|
+
*/
|
|
73
182
|
declare const toRfc9457ValidationErrorPayload: (error: HttpErrorShape) => Rfc9457ErrorPayload<Rfc9457ValidationError>;
|
|
74
183
|
|
|
75
184
|
/**
|
|
76
185
|
* Base typed HTTP error with a numeric `statusCode` and machine-readable metadata.
|
|
77
186
|
*
|
|
187
|
+
* Accepts only finite integer status codes from 400 through 599. Structured options
|
|
188
|
+
* are intended for external API payloads: serializers emit `message`, `details`,
|
|
189
|
+
* `errors`, `metadata`, `type`, `title`, and `instance` verbatim, so do not store
|
|
190
|
+
* secrets or log-only diagnostics in those fields.
|
|
191
|
+
*
|
|
192
|
+
* Top-level `metadata`, `details`, and array-valued `errors` are shallow snapshots:
|
|
193
|
+
* the error owns frozen top-level records/arrays, but nested objects remain shared.
|
|
194
|
+
*
|
|
195
|
+
* @param statusCode HTTP error status code from 400 through 599. Defaults to 500.
|
|
196
|
+
* @param message Public error message. Defaults to the package's status message.
|
|
197
|
+
* @param options Optional cause and structured fields used by payload serializers.
|
|
198
|
+
*
|
|
78
199
|
* @example
|
|
79
200
|
* throw new HttpError(503, 'please try again later');
|
|
80
201
|
*/
|
|
@@ -84,17 +205,37 @@ declare class HttpError extends Error {
|
|
|
84
205
|
readonly date: Date;
|
|
85
206
|
readonly reason?: string;
|
|
86
207
|
readonly domain?: string;
|
|
87
|
-
readonly metadata?: Record<string, string
|
|
88
|
-
readonly details?: unknown[];
|
|
208
|
+
readonly metadata?: Readonly<Record<string, string>>;
|
|
209
|
+
readonly details?: readonly unknown[];
|
|
89
210
|
readonly errors?: unknown;
|
|
90
211
|
readonly type?: string;
|
|
91
212
|
readonly title?: string;
|
|
92
213
|
readonly instance?: string;
|
|
93
214
|
constructor(statusCode?: number, message?: string, options?: HttpErrorOptions);
|
|
94
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Base class for 4xx client errors.
|
|
218
|
+
*
|
|
219
|
+
* Accepts only finite integer status codes from 400 through 499 and otherwise has
|
|
220
|
+
* the same payload, disclosure, and shallow ownership semantics as `HttpError`.
|
|
221
|
+
*
|
|
222
|
+
* @param statusCode HTTP client error status code from 400 through 499. Defaults to 400.
|
|
223
|
+
* @param message Public error message. Defaults to the package's status message.
|
|
224
|
+
* @param options Optional cause and structured fields used by payload serializers.
|
|
225
|
+
*/
|
|
95
226
|
declare class ClientError extends HttpError {
|
|
96
227
|
constructor(statusCode?: number, message?: string, options?: HttpErrorOptions);
|
|
97
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Base class for 5xx server errors.
|
|
231
|
+
*
|
|
232
|
+
* Accepts only finite integer status codes from 500 through 599 and otherwise has
|
|
233
|
+
* the same payload, disclosure, and shallow ownership semantics as `HttpError`.
|
|
234
|
+
*
|
|
235
|
+
* @param statusCode HTTP server error status code from 500 through 599. Defaults to 500.
|
|
236
|
+
* @param message Public error message. Defaults to the package's status message.
|
|
237
|
+
* @param options Optional cause and structured fields used by payload serializers.
|
|
238
|
+
*/
|
|
98
239
|
declare class ServerError extends HttpError {
|
|
99
240
|
constructor(statusCode?: number, message?: string, options?: HttpErrorOptions);
|
|
100
241
|
}
|
|
@@ -215,4 +356,4 @@ declare class NetworkAuthenticationRequiredError extends ServerError {
|
|
|
215
356
|
constructor(message?: string, options?: HttpErrorOptions);
|
|
216
357
|
}
|
|
217
358
|
|
|
218
|
-
export { type Aip193ErrorInfoDetail, type Aip193ErrorPayload, BadGatewayError, BadRequestError, ClientError, ConflictError, ExpectationFailedError, FailedDependencyError, ForbiddenError, GatewayTimeoutError, GoneError, HttpError, type HttpErrorMetadataValue, type HttpErrorOptions, type HttpErrorProblemFields, type HttpErrorShape, HttpVersionNotSupportedError, InsufficientStorageError, InternalServerError, LengthRequiredError, LockedError, LoopDetectedError, MethodNotAllowedError, MisdirectedRequestError, NetworkAuthenticationRequiredError, NotAcceptableError, NotExtendedError, NotFoundError, NotImplementedError, PayloadTooLargeError, PreconditionFailedError, PreconditionRequiredError, ProxyAuthRequiredError, RequestHeaderFieldsTooLargeError, RequestTimeoutError, RequestedRangeNotSatisfiableError, type Rfc9457ErrorPayload, type Rfc9457ValidationError, ServerError, ServiceUnavailableError, TeapotError, TooManyRequestsError, UnauthorizedError, UnavailableForLegalReasonsError, UnprocessableEntityError, UnsupportedMediaTypeError, UpgradeRequiredError, UriTooLongError, VariantAlsoNegotiatesError, canonicalStatusByHttpStatus, createAip193ErrorInfoDetail, getCanonicalStatus, getStatusTitle, toAip193ErrorPayload, toRfc9457ErrorPayload, toRfc9457ValidationErrorPayload };
|
|
359
|
+
export { type Aip193ErrorInfoDetail, type Aip193ErrorPayload, BadGatewayError, BadRequestError, ClientError, ConflictError, ExpectationFailedError, FailedDependencyError, ForbiddenError, GatewayTimeoutError, GoneError, HttpError, type HttpErrorMetadataValue, type HttpErrorOptions, type HttpErrorProblemFields, type HttpErrorShape, HttpVersionNotSupportedError, InsufficientStorageError, InternalServerError, LengthRequiredError, LockedError, LoopDetectedError, MethodNotAllowedError, MisdirectedRequestError, NetworkAuthenticationRequiredError, NotAcceptableError, NotExtendedError, NotFoundError, NotImplementedError, PayloadTooLargeError, PreconditionFailedError, PreconditionRequiredError, ProxyAuthRequiredError, RequestHeaderFieldsTooLargeError, RequestTimeoutError, RequestedRangeNotSatisfiableError, type Rfc9457ErrorPayload, type Rfc9457ValidationError, ServerError, ServiceUnavailableError, TeapotError, TooManyRequestsError, UnauthorizedError, UnavailableForLegalReasonsError, UnprocessableEntityError, UnsupportedMediaTypeError, UpgradeRequiredError, UriTooLongError, VariantAlsoNegotiatesError, canonicalStatusByHttpStatus, createAip193ErrorInfoDetail, getCanonicalStatus, getStatusTitle, isHttpErrorStatusCode, toAip193ErrorPayload, toRfc9457ErrorPayload, toRfc9457ValidationErrorPayload, validateClientErrorStatusCode, validateHttpErrorStatusCode, validateServerErrorStatusCode };
|
package/index.d.ts
CHANGED
|
@@ -1,57 +1,108 @@
|
|
|
1
|
+
/** Scalar values accepted in `HttpErrorOptions.metadata` before string normalization. */
|
|
1
2
|
type HttpErrorMetadataValue = string | number | boolean | bigint | null | undefined;
|
|
3
|
+
/** RFC 9457 problem fields stored on an HTTP error and emitted by RFC serializers. */
|
|
2
4
|
type HttpErrorProblemFields = {
|
|
5
|
+
/** Problem type URI. Falls back to `about:blank` when serialized if absent. */
|
|
3
6
|
type?: string;
|
|
7
|
+
/** Public problem title. Falls back to the status title when serialized if absent. */
|
|
4
8
|
title?: string;
|
|
9
|
+
/** Problem instance URI emitted only when present. */
|
|
5
10
|
instance?: string;
|
|
6
11
|
};
|
|
7
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Constructor options for `HttpError`, `ClientError`, `ServerError`, and specific subclasses.
|
|
14
|
+
*
|
|
15
|
+
* `message`, `details`, `errors`, `metadata`, `type`, `title`, and `instance` can
|
|
16
|
+
* be emitted verbatim by serializers. Do not place secrets or log-only diagnostics
|
|
17
|
+
* in these fields. Top-level `metadata`, `details`, and array-valued `errors` are
|
|
18
|
+
* shallow-snapshotted by `HttpError` construction.
|
|
19
|
+
*/
|
|
20
|
+
type HttpErrorOptions<TErrors = unknown> = ErrorOptions & HttpErrorProblemFields & {
|
|
21
|
+
/** Override canonical status text for serializers such as AIP-193. */
|
|
8
22
|
status?: string;
|
|
23
|
+
/** Machine-readable application reason, such as `INVALID_EMAIL`. */
|
|
9
24
|
reason?: string;
|
|
25
|
+
/** Logical application domain, such as `api.example.com`. */
|
|
10
26
|
domain?: string;
|
|
11
|
-
metadata
|
|
12
|
-
|
|
13
|
-
|
|
27
|
+
/** Key-value metadata normalized to strings and copied into serialized payloads. */
|
|
28
|
+
metadata?: Readonly<Record<string, HttpErrorMetadataValue>>;
|
|
29
|
+
/** Additional structured details emitted by AIP-193 payloads. */
|
|
30
|
+
details?: readonly unknown[];
|
|
31
|
+
/** Extension or validation errors emitted by RFC 9457 helpers when array-valued. */
|
|
32
|
+
errors?: TErrors;
|
|
14
33
|
};
|
|
15
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Minimal error-like input accepted by serializers.
|
|
36
|
+
*
|
|
37
|
+
* This shape allows using real `HttpError` instances or compatible plain objects.
|
|
38
|
+
* Serializers treat `message` and structured fields as public response data.
|
|
39
|
+
*/
|
|
40
|
+
type HttpErrorShape<TErrors = unknown> = HttpErrorProblemFields & {
|
|
41
|
+
/** HTTP error status code used as the response code/status. */
|
|
16
42
|
statusCode: number;
|
|
43
|
+
/** Canonical or custom status string used by AIP-193 payloads. */
|
|
17
44
|
status?: string;
|
|
45
|
+
/** Public error detail/message emitted verbatim. */
|
|
18
46
|
message: string;
|
|
47
|
+
/** Machine-readable application reason used by AIP-193 `error_info`. */
|
|
19
48
|
reason?: string;
|
|
49
|
+
/** Domain used by AIP-193 `error_info`. */
|
|
20
50
|
domain?: string;
|
|
21
|
-
metadata
|
|
22
|
-
|
|
23
|
-
|
|
51
|
+
/** String metadata copied into AIP-193 `error_info`. */
|
|
52
|
+
metadata?: Readonly<Record<string, string>>;
|
|
53
|
+
/** Additional AIP-193 detail entries. */
|
|
54
|
+
details?: readonly unknown[];
|
|
55
|
+
/** RFC 9457 extension or validation errors. Array-valued entries are shallow-copied. */
|
|
56
|
+
errors?: TErrors;
|
|
24
57
|
};
|
|
58
|
+
/** AIP-193 `error_info` detail entry emitted as the first AIP-193 detail. */
|
|
25
59
|
type Aip193ErrorInfoDetail = {
|
|
26
60
|
type: 'error_info';
|
|
27
61
|
reason: string;
|
|
28
62
|
domain: string;
|
|
29
|
-
metadata?: Record<string, string
|
|
63
|
+
metadata?: Readonly<Record<string, string>>;
|
|
30
64
|
};
|
|
65
|
+
/** Google/AIP-193-style error response envelope. */
|
|
31
66
|
type Aip193ErrorPayload = {
|
|
32
67
|
error: {
|
|
68
|
+
/** HTTP status code. */
|
|
33
69
|
code: number;
|
|
70
|
+
/** Canonical or custom status string. */
|
|
34
71
|
status: string;
|
|
72
|
+
/** Public error message emitted verbatim from the input error. */
|
|
35
73
|
message: string;
|
|
36
|
-
details
|
|
74
|
+
/** Structured details, beginning with an `error_info` entry. */
|
|
75
|
+
details?: readonly unknown[];
|
|
37
76
|
};
|
|
38
77
|
};
|
|
78
|
+
/** RFC 9457 problem-details payload with optional typed `errors` extension entries. */
|
|
39
79
|
type Rfc9457ErrorPayload<TError = unknown> = {
|
|
40
|
-
type
|
|
41
|
-
|
|
42
|
-
status
|
|
43
|
-
|
|
80
|
+
/** Problem type URI, defaulting to `about:blank` when absent on the input. */
|
|
81
|
+
type: string;
|
|
82
|
+
/** Public problem title, defaulting to the status title or `Unknown`. */
|
|
83
|
+
title: string;
|
|
84
|
+
/** HTTP status code. */
|
|
85
|
+
status: number;
|
|
86
|
+
/** Public problem detail emitted verbatim from the input error message. */
|
|
87
|
+
detail: string;
|
|
88
|
+
/** Problem instance URI, emitted only when present on the input. */
|
|
44
89
|
instance?: string;
|
|
45
|
-
errors
|
|
90
|
+
/** Optional extension errors. Validation helpers emit only validated entries. */
|
|
91
|
+
errors?: readonly TError[];
|
|
46
92
|
};
|
|
93
|
+
/** RFC 9457 validation error entry accepted by `toRfc9457ValidationErrorPayload`. */
|
|
47
94
|
type Rfc9457ValidationError = {
|
|
95
|
+
/** Human-readable validation detail. Required and must be an own string field. */
|
|
48
96
|
detail: string;
|
|
97
|
+
/** JSON Pointer to the invalid field, when available. */
|
|
49
98
|
pointer?: string;
|
|
99
|
+
/** Query/path/header parameter name, when available. */
|
|
50
100
|
parameter?: string;
|
|
101
|
+
/** Header name, when available. */
|
|
51
102
|
header?: string;
|
|
52
103
|
};
|
|
53
104
|
|
|
54
|
-
declare const
|
|
105
|
+
declare const canonicalStatusLookup: Readonly<{
|
|
55
106
|
readonly 400: "INVALID_ARGUMENT";
|
|
56
107
|
readonly 401: "UNAUTHENTICATED";
|
|
57
108
|
readonly 403: "PERMISSION_DENIED";
|
|
@@ -63,18 +114,88 @@ declare const canonicalStatusByHttpStatus: {
|
|
|
63
114
|
readonly 501: "UNIMPLEMENTED";
|
|
64
115
|
readonly 503: "UNAVAILABLE";
|
|
65
116
|
readonly 504: "DEADLINE_EXCEEDED";
|
|
66
|
-
}
|
|
117
|
+
}>;
|
|
118
|
+
declare const canonicalStatusByHttpStatus: Readonly<typeof canonicalStatusLookup>;
|
|
67
119
|
declare const getCanonicalStatus: (statusCode: number) => string;
|
|
68
120
|
declare const getStatusTitle: (statusCode: number) => string;
|
|
121
|
+
declare const isHttpErrorStatusCode: (statusCode: unknown) => statusCode is number;
|
|
122
|
+
declare const validateHttpErrorStatusCode: (statusCode: unknown, source?: string) => number;
|
|
123
|
+
declare const validateClientErrorStatusCode: (statusCode: unknown, source?: string) => number;
|
|
124
|
+
declare const validateServerErrorStatusCode: (statusCode: unknown, source?: string) => number;
|
|
69
125
|
|
|
70
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Creates an AIP-193 `error_info` detail entry.
|
|
128
|
+
*
|
|
129
|
+
* The returned `metadata` record is a shallow copy so payload mutation does not
|
|
130
|
+
* mutate the source error metadata.
|
|
131
|
+
*
|
|
132
|
+
* @param reason Machine-readable reason, usually an application code or canonical status.
|
|
133
|
+
* @param domain Logical error domain, such as `api.example.com`.
|
|
134
|
+
* @param metadata Optional string metadata copied into the returned detail.
|
|
135
|
+
* @returns A serializable AIP-193 `error_info` detail.
|
|
136
|
+
*/
|
|
137
|
+
declare const createAip193ErrorInfoDetail: (reason: string, domain: string, metadata?: Readonly<Record<string, string>>) => Aip193ErrorInfoDetail;
|
|
138
|
+
/**
|
|
139
|
+
* Converts an HTTP error shape into an AIP-193-style `{ error }` envelope.
|
|
140
|
+
*
|
|
141
|
+
* Emits `error.message` verbatim as the public payload message. The first detail
|
|
142
|
+
* is always an `error_info` entry. Additional `errors` and `details` entries are
|
|
143
|
+
* shallow-copied at the top level only.
|
|
144
|
+
*
|
|
145
|
+
* @param error Error-like shape with status, message, and optional structured fields.
|
|
146
|
+
* @param fallbackDomain Domain used for `error_info` when `error.domain` is absent.
|
|
147
|
+
* @returns A payload containing `code`, `status`, `message`, and `details`.
|
|
148
|
+
*/
|
|
71
149
|
declare const toAip193ErrorPayload: (error: HttpErrorShape, fallbackDomain?: string) => Aip193ErrorPayload;
|
|
72
|
-
|
|
150
|
+
/**
|
|
151
|
+
* Converts an HTTP error shape with typed extension errors into an RFC 9457 problem payload.
|
|
152
|
+
*
|
|
153
|
+
* Emits `message` as `detail` and passes `type`, `title`, `instance`, and array
|
|
154
|
+
* `errors` through as public response data. Array-valued `errors` are shallow-copied.
|
|
155
|
+
*
|
|
156
|
+
* @param error Error-like shape whose `errors` field is a typed array.
|
|
157
|
+
* @returns RFC 9457 problem details preserving the typed extension error entries.
|
|
158
|
+
*/
|
|
159
|
+
declare function toRfc9457ErrorPayload<TError>(error: HttpErrorShape<readonly TError[]>): Rfc9457ErrorPayload<TError>;
|
|
160
|
+
/**
|
|
161
|
+
* Converts an HTTP error shape into an RFC 9457 problem payload.
|
|
162
|
+
*
|
|
163
|
+
* Missing `type` falls back to `about:blank`; missing `title` falls back to the
|
|
164
|
+
* canonical status title, or `Unknown` for unmapped status codes. `message` is
|
|
165
|
+
* emitted verbatim as `detail`; `instance` and array-valued `errors` are emitted
|
|
166
|
+
* when present.
|
|
167
|
+
*
|
|
168
|
+
* @param error Error-like shape with status, message, and optional problem fields.
|
|
169
|
+
* @returns RFC 9457 problem details.
|
|
170
|
+
*/
|
|
171
|
+
declare function toRfc9457ErrorPayload(error: HttpErrorShape): Rfc9457ErrorPayload;
|
|
172
|
+
/**
|
|
173
|
+
* Converts an HTTP error shape into an RFC 9457 validation problem payload.
|
|
174
|
+
*
|
|
175
|
+
* Runtime-narrows `errors` before typing the result as validation entries. Keeps
|
|
176
|
+
* only own string `detail` plus optional own string `pointer`, `parameter`, and
|
|
177
|
+
* `header`; extra fields are omitted. If no valid entries remain, `errors` is omitted.
|
|
178
|
+
*
|
|
179
|
+
* @param error Error-like shape with optional validation-style `errors` entries.
|
|
180
|
+
* @returns RFC 9457 problem details with validated `errors` entries when available.
|
|
181
|
+
*/
|
|
73
182
|
declare const toRfc9457ValidationErrorPayload: (error: HttpErrorShape) => Rfc9457ErrorPayload<Rfc9457ValidationError>;
|
|
74
183
|
|
|
75
184
|
/**
|
|
76
185
|
* Base typed HTTP error with a numeric `statusCode` and machine-readable metadata.
|
|
77
186
|
*
|
|
187
|
+
* Accepts only finite integer status codes from 400 through 599. Structured options
|
|
188
|
+
* are intended for external API payloads: serializers emit `message`, `details`,
|
|
189
|
+
* `errors`, `metadata`, `type`, `title`, and `instance` verbatim, so do not store
|
|
190
|
+
* secrets or log-only diagnostics in those fields.
|
|
191
|
+
*
|
|
192
|
+
* Top-level `metadata`, `details`, and array-valued `errors` are shallow snapshots:
|
|
193
|
+
* the error owns frozen top-level records/arrays, but nested objects remain shared.
|
|
194
|
+
*
|
|
195
|
+
* @param statusCode HTTP error status code from 400 through 599. Defaults to 500.
|
|
196
|
+
* @param message Public error message. Defaults to the package's status message.
|
|
197
|
+
* @param options Optional cause and structured fields used by payload serializers.
|
|
198
|
+
*
|
|
78
199
|
* @example
|
|
79
200
|
* throw new HttpError(503, 'please try again later');
|
|
80
201
|
*/
|
|
@@ -84,17 +205,37 @@ declare class HttpError extends Error {
|
|
|
84
205
|
readonly date: Date;
|
|
85
206
|
readonly reason?: string;
|
|
86
207
|
readonly domain?: string;
|
|
87
|
-
readonly metadata?: Record<string, string
|
|
88
|
-
readonly details?: unknown[];
|
|
208
|
+
readonly metadata?: Readonly<Record<string, string>>;
|
|
209
|
+
readonly details?: readonly unknown[];
|
|
89
210
|
readonly errors?: unknown;
|
|
90
211
|
readonly type?: string;
|
|
91
212
|
readonly title?: string;
|
|
92
213
|
readonly instance?: string;
|
|
93
214
|
constructor(statusCode?: number, message?: string, options?: HttpErrorOptions);
|
|
94
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Base class for 4xx client errors.
|
|
218
|
+
*
|
|
219
|
+
* Accepts only finite integer status codes from 400 through 499 and otherwise has
|
|
220
|
+
* the same payload, disclosure, and shallow ownership semantics as `HttpError`.
|
|
221
|
+
*
|
|
222
|
+
* @param statusCode HTTP client error status code from 400 through 499. Defaults to 400.
|
|
223
|
+
* @param message Public error message. Defaults to the package's status message.
|
|
224
|
+
* @param options Optional cause and structured fields used by payload serializers.
|
|
225
|
+
*/
|
|
95
226
|
declare class ClientError extends HttpError {
|
|
96
227
|
constructor(statusCode?: number, message?: string, options?: HttpErrorOptions);
|
|
97
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Base class for 5xx server errors.
|
|
231
|
+
*
|
|
232
|
+
* Accepts only finite integer status codes from 500 through 599 and otherwise has
|
|
233
|
+
* the same payload, disclosure, and shallow ownership semantics as `HttpError`.
|
|
234
|
+
*
|
|
235
|
+
* @param statusCode HTTP server error status code from 500 through 599. Defaults to 500.
|
|
236
|
+
* @param message Public error message. Defaults to the package's status message.
|
|
237
|
+
* @param options Optional cause and structured fields used by payload serializers.
|
|
238
|
+
*/
|
|
98
239
|
declare class ServerError extends HttpError {
|
|
99
240
|
constructor(statusCode?: number, message?: string, options?: HttpErrorOptions);
|
|
100
241
|
}
|
|
@@ -215,4 +356,4 @@ declare class NetworkAuthenticationRequiredError extends ServerError {
|
|
|
215
356
|
constructor(message?: string, options?: HttpErrorOptions);
|
|
216
357
|
}
|
|
217
358
|
|
|
218
|
-
export { type Aip193ErrorInfoDetail, type Aip193ErrorPayload, BadGatewayError, BadRequestError, ClientError, ConflictError, ExpectationFailedError, FailedDependencyError, ForbiddenError, GatewayTimeoutError, GoneError, HttpError, type HttpErrorMetadataValue, type HttpErrorOptions, type HttpErrorProblemFields, type HttpErrorShape, HttpVersionNotSupportedError, InsufficientStorageError, InternalServerError, LengthRequiredError, LockedError, LoopDetectedError, MethodNotAllowedError, MisdirectedRequestError, NetworkAuthenticationRequiredError, NotAcceptableError, NotExtendedError, NotFoundError, NotImplementedError, PayloadTooLargeError, PreconditionFailedError, PreconditionRequiredError, ProxyAuthRequiredError, RequestHeaderFieldsTooLargeError, RequestTimeoutError, RequestedRangeNotSatisfiableError, type Rfc9457ErrorPayload, type Rfc9457ValidationError, ServerError, ServiceUnavailableError, TeapotError, TooManyRequestsError, UnauthorizedError, UnavailableForLegalReasonsError, UnprocessableEntityError, UnsupportedMediaTypeError, UpgradeRequiredError, UriTooLongError, VariantAlsoNegotiatesError, canonicalStatusByHttpStatus, createAip193ErrorInfoDetail, getCanonicalStatus, getStatusTitle, toAip193ErrorPayload, toRfc9457ErrorPayload, toRfc9457ValidationErrorPayload };
|
|
359
|
+
export { type Aip193ErrorInfoDetail, type Aip193ErrorPayload, BadGatewayError, BadRequestError, ClientError, ConflictError, ExpectationFailedError, FailedDependencyError, ForbiddenError, GatewayTimeoutError, GoneError, HttpError, type HttpErrorMetadataValue, type HttpErrorOptions, type HttpErrorProblemFields, type HttpErrorShape, HttpVersionNotSupportedError, InsufficientStorageError, InternalServerError, LengthRequiredError, LockedError, LoopDetectedError, MethodNotAllowedError, MisdirectedRequestError, NetworkAuthenticationRequiredError, NotAcceptableError, NotExtendedError, NotFoundError, NotImplementedError, PayloadTooLargeError, PreconditionFailedError, PreconditionRequiredError, ProxyAuthRequiredError, RequestHeaderFieldsTooLargeError, RequestTimeoutError, RequestedRangeNotSatisfiableError, type Rfc9457ErrorPayload, type Rfc9457ValidationError, ServerError, ServiceUnavailableError, TeapotError, TooManyRequestsError, UnauthorizedError, UnavailableForLegalReasonsError, UnprocessableEntityError, UnsupportedMediaTypeError, UpgradeRequiredError, UriTooLongError, VariantAlsoNegotiatesError, canonicalStatusByHttpStatus, createAip193ErrorInfoDetail, getCanonicalStatus, getStatusTitle, isHttpErrorStatusCode, toAip193ErrorPayload, toRfc9457ErrorPayload, toRfc9457ValidationErrorPayload, validateClientErrorStatusCode, validateHttpErrorStatusCode, validateServerErrorStatusCode };
|