openapi-typesafe-fetch 1.0.0-rc.4 → 1.0.0-rc.6
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/CHANGELOG.md +59 -0
- package/README.md +3 -3
- package/dist/helpers.d.cts +35 -12
- package/dist/helpers.d.mts +35 -12
- package/dist/helpers.d.ts +35 -12
- package/dist/index.cjs +137 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -9
- package/dist/index.d.mts +32 -9
- package/dist/index.d.ts +32 -9
- package/dist/index.mjs +137 -53
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/helpers.ts +51 -12
- package/src/index.d.ts +32 -9
- package/src/index.js +247 -72
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,65 @@
|
|
|
2
2
|
|
|
3
3
|
This package is a fork of `openapi-fetch`. The entries above `0.17.0` are releases of openapi-typesafe-fetch; `0.17.0` and the entries below it are the upstream history up to the fork point (upstream commit `d46a319a`), with `openapi-fetch` versions.
|
|
4
4
|
|
|
5
|
+
## 1.0.0-rc.6
|
|
6
|
+
|
|
7
|
+
### Patch Changes
|
|
8
|
+
|
|
9
|
+
- [#87](https://github.com/openapi-typesafe/openapi-typesafe/pull/87) [`dfb0fe3`](https://github.com/openapi-typesafe/openapi-typesafe/commit/dfb0fe3c61a75d2b8ca512577f4b699049171a64) Thanks [@fedorello](https://github.com/fedorello)! - Leave out `null` and `undefined` items and members of arrays and objects in every parameter style, also in the path and headers (`ids=1,null`, `filter=owner,undefined` and `x-p: a,,b,1` were sent before), and default `explode` to `true` for the `form` query style only, as OpenAPI does, so `{ array: { style: "pipeDelimited" } }` sends `id=3|4|5`. A nested value in a header parameter now fails with an error that names header parameters, not `querySerializer()`.
|
|
10
|
+
|
|
11
|
+
## 1.0.0-rc.5
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- [#68](https://github.com/openapi-typesafe/openapi-typesafe/pull/68) [`0f0792b`](https://github.com/openapi-typesafe/openapi-typesafe/commit/0f0792b8efa4f5139653cd285455f7d6165ddb95) Thanks [@fedorello](https://github.com/fedorello)! - A `FormData`, `Blob`, `File` or `ReadableStream` body from `undici` or another realm (an iframe) is
|
|
16
|
+
sent as it is: the client told a body by `instanceof`, so it JSON-encoded one of another class as
|
|
17
|
+
`{}`. `createClient` takes a `FormData` class next to `Request`: a multipart body is built with it,
|
|
18
|
+
and a FormData body of another class is copied into one of it, since undici's `Request` read the
|
|
19
|
+
platform's FormData as the text `[object FormData]`. With undici, pass
|
|
20
|
+
`createClient({ fetch, Request, FormData })` from the package. An instance of the platform's own
|
|
21
|
+
global class is still sent as it is, so the FormData, Blob and URLSearchParams of React Native and
|
|
22
|
+
the Blob and File of jsdom 20 (Jest 29), which have no type tag or no `arrayBuffer`, keep working.
|
|
23
|
+
|
|
24
|
+
- [#67](https://github.com/openapi-typesafe/openapi-typesafe/pull/67) [`fbaded2`](https://github.com/openapi-typesafe/openapi-typesafe/commit/fbaded241385d032d5b28d2c93d5e0a7d6ae292b) Thanks [@fedorello](https://github.com/fedorello)! - The client has a read-only `baseUrl`: the `baseUrl` option without its trailing slash, or `""`.
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- [#68](https://github.com/openapi-typesafe/openapi-typesafe/pull/68) [`0f0792b`](https://github.com/openapi-typesafe/openapi-typesafe/commit/0f0792b8efa4f5139653cd285455f7d6165ddb95) Thanks [@fedorello](https://github.com/fedorello)! - An empty success body read with `parseAs: "text"`, `"blob"`, `"arrayBuffer"` or `"stream"` gives
|
|
29
|
+
`""`, an empty `Blob` or `ArrayBuffer`, or `response.body`, as its type says. A 204, an answer to
|
|
30
|
+
HEAD or a `Content-Length: 0` gave `undefined`, while the same empty body without a length gave
|
|
31
|
+
`""`. With the default `parseAs: "json"` an empty body is still `undefined`.
|
|
32
|
+
|
|
33
|
+
- [#68](https://github.com/openapi-typesafe/openapi-typesafe/pull/68) [`0f0792b`](https://github.com/openapi-typesafe/openapi-typesafe/commit/0f0792b8efa4f5139653cd285455f7d6165ddb95) Thanks [@fedorello](https://github.com/fedorello)! - `params.header` values are written in the `simple` style, the only style OpenAPI has for headers:
|
|
34
|
+
a `Date` as ISO 8601 (it was local time), an array as `a,b` (it was `a, b`) and an object as
|
|
35
|
+
`role,admin` (it was `[object Object]`), not percent-encoded, also in the names. A nested object or
|
|
36
|
+
array inside one throws, as in the query. An empty array or object sends no header, and `null`
|
|
37
|
+
still removes one.
|
|
38
|
+
|
|
39
|
+
- [#68](https://github.com/openapi-typesafe/openapi-typesafe/pull/68) [`0f0792b`](https://github.com/openapi-typesafe/openapi-typesafe/commit/0f0792b8efa4f5139653cd285455f7d6165ddb95) Thanks [@fedorello](https://github.com/fedorello)! - A form or multipart `Content-Type` with spaces or tabs before its parameters
|
|
40
|
+
(`application/x-www-form-urlencoded ; charset=utf-8`, RFC 9110 OWS) gives form data or `FormData`
|
|
41
|
+
again, in the runtime and in the result type of `defaultBodySerializer`; the object was sent as
|
|
42
|
+
JSON. The JSON check already took them.
|
|
43
|
+
|
|
44
|
+
- [#68](https://github.com/openapi-typesafe/openapi-typesafe/pull/68) [`0f0792b`](https://github.com/openapi-typesafe/openapi-typesafe/commit/0f0792b8efa4f5139653cd285455f7d6165ddb95) Thanks [@fedorello](https://github.com/fedorello)! - `style` and `explode` of the `array` and `object` options of `QuerySerializerOptions` are optional,
|
|
45
|
+
and one left out takes the client's value, else its default (`form` or `deepObject`, exploded): a
|
|
46
|
+
request's `{ array: { explode: false } }` keeps the client's `style`. `onError` may return an
|
|
47
|
+
`Error` of another realm (an iframe, `node:vm`); it was rejected as not an error.
|
|
48
|
+
|
|
49
|
+
- [#68](https://github.com/openapi-typesafe/openapi-typesafe/pull/68) [`0f0792b`](https://github.com/openapi-typesafe/openapi-typesafe/commit/0f0792b8efa4f5139653cd285455f7d6165ddb95) Thanks [@fedorello](https://github.com/fedorello)! - The query of a request whose path template has a fragment (`/docs#intro`) goes before the
|
|
50
|
+
fragment, joined with a query the template already has. It was added after the `#`, where it is
|
|
51
|
+
part of the fragment, so `fetch` never sent it.
|
|
52
|
+
|
|
53
|
+
- [#75](https://github.com/openapi-typesafe/openapi-typesafe/pull/75) [`a74608e`](https://github.com/openapi-typesafe/openapi-typesafe/commit/a74608ec36b0a938594e0d0fac10c9fb222c1742) Thanks [@fedorello](https://github.com/fedorello)! - `Readable` and `Writable` find the `$Read` and `$Write` properties of an object with an index
|
|
54
|
+
signature (`additionalProperties`). The keys were read through the index signature, so no
|
|
55
|
+
property was marked: a request body required the `readOnly` `id`, and a response kept the
|
|
56
|
+
`writeOnly` password. The helper types that `--read-write-markers` writes are fixed the same way.
|
|
57
|
+
|
|
58
|
+
- [#68](https://github.com/openapi-typesafe/openapi-typesafe/pull/68) [`0f0792b`](https://github.com/openapi-typesafe/openapi-typesafe/commit/0f0792b8efa4f5139653cd285455f7d6165ddb95) Thanks [@fedorello](https://github.com/fedorello)! - A response is typed as data or an error by the first digit of its status, as `response.ok` reads
|
|
59
|
+
it: a declared 205, 208 or 226 types `data` with its body, and a 419, a 3XX (read with
|
|
60
|
+
`redirect: "manual"`) or a 1XX types `error` with its body.
|
|
61
|
+
The types classified by two closed lists of statuses, `OkStatus` and `ErrorStatus`, which stay
|
|
62
|
+
exported. New helper types `SuccessStatusKey` and `ErrorStatusKey` name the statuses of each kind.
|
|
63
|
+
|
|
5
64
|
## 1.0.0-rc.4
|
|
6
65
|
|
|
7
66
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# openapi-typesafe-fetch
|
|
2
2
|
|
|
3
|
-
A type-safe `fetch` client for types generated by [`openapi-typesafe`](../openapi-typesafe). About
|
|
4
|
-
(
|
|
3
|
+
A type-safe `fetch` client for types generated by [`openapi-typesafe`](../openapi-typesafe). About 11 kB minified
|
|
4
|
+
(4 kB gzipped), no runtime dependencies, works in browsers, Node.js, Bun and Deno, and with React, Vue, Svelte or plain JavaScript.
|
|
5
5
|
|
|
6
6
|
A maintained, drop-in successor to `openapi-fetch` (see the [repository README](../../README.md)).
|
|
7
7
|
|
|
@@ -26,7 +26,7 @@ const client = createClient<paths>({ baseUrl: "https://api.example.com/v1/" });
|
|
|
26
26
|
|
|
27
27
|
const {
|
|
28
28
|
data, // present on a 2xx response
|
|
29
|
-
error, // present on a
|
|
29
|
+
error, // present on a response that is not 2xx
|
|
30
30
|
} = await client.GET("/posts/{post_id}", {
|
|
31
31
|
params: { path: { post_id: "123" } },
|
|
32
32
|
});
|
package/dist/helpers.d.cts
CHANGED
|
@@ -2,12 +2,32 @@
|
|
|
2
2
|
type HttpMethod = "get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace"
|
|
3
3
|
/** OpenAPI 3.2: a safe, idempotent request with a body. */
|
|
4
4
|
| "query";
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Some 2XX statuses, kept for code that names them. The client does not classify by this list: a
|
|
7
|
+
* status is a success or an error by its first digit (`SuccessStatusKey`, `ErrorStatusKey`).
|
|
8
|
+
*/
|
|
6
9
|
type OkStatus = 200 | 201 | 202 | 203 | 204 | 206 | 207 | "2XX";
|
|
7
|
-
/** 4XX and 5XX statuses */
|
|
10
|
+
/** Some 4XX and 5XX statuses and `default`, kept like `OkStatus`. */
|
|
8
11
|
type ErrorStatus = 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 | "5XX" | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 444 | 450 | 451 | 497 | 498 | 499 | "4XX" | "default";
|
|
12
|
+
type StatusDigit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
|
13
|
+
/**
|
|
14
|
+
* The keys of a Response Object Map whose text matches a pattern. A generated map has numeric keys
|
|
15
|
+
* (`200`) and string ones (`"2XX"`, `"default"`), and a numeric literal matches no template
|
|
16
|
+
* literal type, so each key is matched by its text.
|
|
17
|
+
*/
|
|
18
|
+
type StatusKeysMatching<Keys, Pattern extends string> = Keys extends string | number ? `${Keys}` extends Pattern ? Keys : never : never;
|
|
19
|
+
/**
|
|
20
|
+
* The success statuses of a Response Object Map: every 2XX one. A closed list of statuses left out
|
|
21
|
+
* the ones it did not name (205, 208, 226), and their bodies were typed as no data.
|
|
22
|
+
*/
|
|
23
|
+
type SuccessStatusKey<T> = StatusKeysMatching<keyof T, `2${StatusDigit}${StatusDigit}` | "2XX">;
|
|
24
|
+
/**
|
|
25
|
+
* The error statuses of a Response Object Map: every 1XX, 3XX, 4XX and 5XX one, and `default`. The
|
|
26
|
+
* client returns each response that is not `ok` as `error`, also a 3XX with `redirect: "manual"`.
|
|
27
|
+
*/
|
|
28
|
+
type ErrorStatusKey<T> = StatusKeysMatching<keyof T, `${1 | 3 | 4 | 5}${StatusDigit}${StatusDigit}` | `${1 | 3 | 4 | 5}XX` | "default">;
|
|
9
29
|
/** Get a union of OK Statuses */
|
|
10
|
-
type OKStatusUnion<T> = FilterKeys<T,
|
|
30
|
+
type OKStatusUnion<T> = FilterKeys<T, SuccessStatusKey<T>>;
|
|
11
31
|
/** Get first error status, in order */
|
|
12
32
|
type FirstErrorStatus<T> = T extends {
|
|
13
33
|
500: unknown;
|
|
@@ -178,7 +198,7 @@ type OperationRequestBodyContent<T> = FilterKeys<OperationRequestBodyMediaConten
|
|
|
178
198
|
* Responses Object), so then it covers every success (upstream #1862). With a 2XX status declared,
|
|
179
199
|
* `default` is left to the errors, as before.
|
|
180
200
|
*/
|
|
181
|
-
type SuccessStatus<T> = [
|
|
201
|
+
type SuccessStatus<T> = [SuccessStatusKey<T>] extends [never] ? Extract<keyof T, "default"> : SuccessStatusKey<T>;
|
|
182
202
|
/**
|
|
183
203
|
* Return all 2XX responses from a Response Object Map, or `default` if it declares no 2XX one. For
|
|
184
204
|
* a union of maps (a call with a union of paths), the union of each map's responses: `keyof` of a
|
|
@@ -190,13 +210,13 @@ type GetResponseContent<T extends Record<string | number, any>, Media extends Me
|
|
|
190
210
|
[K in ResponseCode]: T[K]["content"] extends Record<string, any> ? FilterKeys<T[K]["content"], Media> extends never ? T[K]["content"] : FilterKeys<T[K]["content"], Media> : K extends keyof T ? T[K]["content"] : never;
|
|
191
211
|
}[ResponseCode] : never;
|
|
192
212
|
/**
|
|
193
|
-
* Return all
|
|
194
|
-
* the union of each map's responses, as `SuccessResponse`.
|
|
213
|
+
* Return all 1XX, 3XX, 4XX, 5XX and `default` responses from a Response Object Map; for a union
|
|
214
|
+
* of maps, the union of each map's responses, as `SuccessResponse`.
|
|
195
215
|
*/
|
|
196
|
-
type ErrorResponse<T extends Record<string | number, any>, Media extends MediaType = MediaType> = T extends unknown ? GetResponseContent<T, Media,
|
|
216
|
+
type ErrorResponse<T extends Record<string | number, any>, Media extends MediaType = MediaType> = T extends unknown ? GetResponseContent<T, Media, ErrorStatusKey<T>> : never;
|
|
197
217
|
/** Return first JSON-like 2XX response from a path + HTTP method */
|
|
198
218
|
type SuccessResponseJSON<PathMethod extends Record<string | number, any>> = SuccessResponse<ResponseObjectMap<PathMethod>, `${string}/json`>;
|
|
199
|
-
/** Return
|
|
219
|
+
/** Return JSON-like 1XX, 3XX, 4XX, 5XX and `default` responses from a path + HTTP method */
|
|
200
220
|
type ErrorResponseJSON<PathMethod extends Record<string | number, any>> = ErrorResponse<ResponseObjectMap<PathMethod>, `${string}/json`>;
|
|
201
221
|
/** Return JSON-like request body from a path + HTTP method */
|
|
202
222
|
type RequestBodyJSON<PathMethod> = JSONLike<FilterKeys<OperationRequestBody<PathMethod>, "content">>;
|
|
@@ -258,10 +278,13 @@ type ReadWriteLeaf = ReadWritePrimitive | ((...args: never) => unknown);
|
|
|
258
278
|
* `any` key is not marked either (`0 extends 1 & T[K]` is true only for `any`): a check on `any`
|
|
259
279
|
* takes both branches, so `Readable` dropped the key and `Writable` typed it `undefined`. The
|
|
260
280
|
* checks are not distributive (their check types are not type parameters), so `never` is seen.
|
|
281
|
+
* The keys are read by remapping, not as `{ ... }[keyof T]`: with an index signature (from
|
|
282
|
+
* `additionalProperties`) `keyof T` is `string`, which indexes the signature only, so no property
|
|
283
|
+
* was marked and `Writable` made a readOnly property a required `never`.
|
|
261
284
|
*/
|
|
262
|
-
type ReadWriteMarkedKeys<T, Marker> = {
|
|
263
|
-
[K in keyof T
|
|
264
|
-
}
|
|
285
|
+
type ReadWriteMarkedKeys<T, Marker> = keyof {
|
|
286
|
+
[K in keyof T as 0 extends 1 & T[K] ? never : NonNullable<T[K]> extends never ? never : NonNullable<T[K]> extends Marker ? K : never]: never;
|
|
287
|
+
};
|
|
265
288
|
/**
|
|
266
289
|
* Resolve an array or a tuple element by element. An array uses `T[number]`, not `infer E`: for an
|
|
267
290
|
* intersection of arrays (`allOf`) inference keeps one member and narrowing breaks (upstream
|
|
@@ -296,4 +319,4 @@ type Writable<T> = T extends $Read<any> ? never : T extends $Write<infer U> ? Wr
|
|
|
296
319
|
[K in ReadWriteMarkedKeys<T, $Read<any>>]?: never;
|
|
297
320
|
} : T;
|
|
298
321
|
|
|
299
|
-
export type { $Read, $Write, ErrorResponse, ErrorResponseJSON, ErrorStatus, FilterKeys, FindRequiredKeys, FirstErrorStatus, GetResponseContent, GetValueWithDefault, HasRequiredKeys, HttpMethod, IsOperationRequestBodyOptional, JSONLike, MediaType, OKStatusUnion, OkStatus, OperationObject, OperationRequestBody, OperationRequestBodyContent, OperationRequestBodyMediaContent, PathItemObject, PathsWithMethod, Readable, RequestBodyJSON, RequiredKeysOf, ResponseContent, ResponseObjectMap, SuccessResponse, SuccessResponseJSON, Writable };
|
|
322
|
+
export type { $Read, $Write, ErrorResponse, ErrorResponseJSON, ErrorStatus, ErrorStatusKey, FilterKeys, FindRequiredKeys, FirstErrorStatus, GetResponseContent, GetValueWithDefault, HasRequiredKeys, HttpMethod, IsOperationRequestBodyOptional, JSONLike, MediaType, OKStatusUnion, OkStatus, OperationObject, OperationRequestBody, OperationRequestBodyContent, OperationRequestBodyMediaContent, PathItemObject, PathsWithMethod, Readable, RequestBodyJSON, RequiredKeysOf, ResponseContent, ResponseObjectMap, SuccessResponse, SuccessResponseJSON, SuccessStatusKey, Writable };
|
package/dist/helpers.d.mts
CHANGED
|
@@ -2,12 +2,32 @@
|
|
|
2
2
|
type HttpMethod = "get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace"
|
|
3
3
|
/** OpenAPI 3.2: a safe, idempotent request with a body. */
|
|
4
4
|
| "query";
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Some 2XX statuses, kept for code that names them. The client does not classify by this list: a
|
|
7
|
+
* status is a success or an error by its first digit (`SuccessStatusKey`, `ErrorStatusKey`).
|
|
8
|
+
*/
|
|
6
9
|
type OkStatus = 200 | 201 | 202 | 203 | 204 | 206 | 207 | "2XX";
|
|
7
|
-
/** 4XX and 5XX statuses */
|
|
10
|
+
/** Some 4XX and 5XX statuses and `default`, kept like `OkStatus`. */
|
|
8
11
|
type ErrorStatus = 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 | "5XX" | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 444 | 450 | 451 | 497 | 498 | 499 | "4XX" | "default";
|
|
12
|
+
type StatusDigit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
|
13
|
+
/**
|
|
14
|
+
* The keys of a Response Object Map whose text matches a pattern. A generated map has numeric keys
|
|
15
|
+
* (`200`) and string ones (`"2XX"`, `"default"`), and a numeric literal matches no template
|
|
16
|
+
* literal type, so each key is matched by its text.
|
|
17
|
+
*/
|
|
18
|
+
type StatusKeysMatching<Keys, Pattern extends string> = Keys extends string | number ? `${Keys}` extends Pattern ? Keys : never : never;
|
|
19
|
+
/**
|
|
20
|
+
* The success statuses of a Response Object Map: every 2XX one. A closed list of statuses left out
|
|
21
|
+
* the ones it did not name (205, 208, 226), and their bodies were typed as no data.
|
|
22
|
+
*/
|
|
23
|
+
type SuccessStatusKey<T> = StatusKeysMatching<keyof T, `2${StatusDigit}${StatusDigit}` | "2XX">;
|
|
24
|
+
/**
|
|
25
|
+
* The error statuses of a Response Object Map: every 1XX, 3XX, 4XX and 5XX one, and `default`. The
|
|
26
|
+
* client returns each response that is not `ok` as `error`, also a 3XX with `redirect: "manual"`.
|
|
27
|
+
*/
|
|
28
|
+
type ErrorStatusKey<T> = StatusKeysMatching<keyof T, `${1 | 3 | 4 | 5}${StatusDigit}${StatusDigit}` | `${1 | 3 | 4 | 5}XX` | "default">;
|
|
9
29
|
/** Get a union of OK Statuses */
|
|
10
|
-
type OKStatusUnion<T> = FilterKeys<T,
|
|
30
|
+
type OKStatusUnion<T> = FilterKeys<T, SuccessStatusKey<T>>;
|
|
11
31
|
/** Get first error status, in order */
|
|
12
32
|
type FirstErrorStatus<T> = T extends {
|
|
13
33
|
500: unknown;
|
|
@@ -178,7 +198,7 @@ type OperationRequestBodyContent<T> = FilterKeys<OperationRequestBodyMediaConten
|
|
|
178
198
|
* Responses Object), so then it covers every success (upstream #1862). With a 2XX status declared,
|
|
179
199
|
* `default` is left to the errors, as before.
|
|
180
200
|
*/
|
|
181
|
-
type SuccessStatus<T> = [
|
|
201
|
+
type SuccessStatus<T> = [SuccessStatusKey<T>] extends [never] ? Extract<keyof T, "default"> : SuccessStatusKey<T>;
|
|
182
202
|
/**
|
|
183
203
|
* Return all 2XX responses from a Response Object Map, or `default` if it declares no 2XX one. For
|
|
184
204
|
* a union of maps (a call with a union of paths), the union of each map's responses: `keyof` of a
|
|
@@ -190,13 +210,13 @@ type GetResponseContent<T extends Record<string | number, any>, Media extends Me
|
|
|
190
210
|
[K in ResponseCode]: T[K]["content"] extends Record<string, any> ? FilterKeys<T[K]["content"], Media> extends never ? T[K]["content"] : FilterKeys<T[K]["content"], Media> : K extends keyof T ? T[K]["content"] : never;
|
|
191
211
|
}[ResponseCode] : never;
|
|
192
212
|
/**
|
|
193
|
-
* Return all
|
|
194
|
-
* the union of each map's responses, as `SuccessResponse`.
|
|
213
|
+
* Return all 1XX, 3XX, 4XX, 5XX and `default` responses from a Response Object Map; for a union
|
|
214
|
+
* of maps, the union of each map's responses, as `SuccessResponse`.
|
|
195
215
|
*/
|
|
196
|
-
type ErrorResponse<T extends Record<string | number, any>, Media extends MediaType = MediaType> = T extends unknown ? GetResponseContent<T, Media,
|
|
216
|
+
type ErrorResponse<T extends Record<string | number, any>, Media extends MediaType = MediaType> = T extends unknown ? GetResponseContent<T, Media, ErrorStatusKey<T>> : never;
|
|
197
217
|
/** Return first JSON-like 2XX response from a path + HTTP method */
|
|
198
218
|
type SuccessResponseJSON<PathMethod extends Record<string | number, any>> = SuccessResponse<ResponseObjectMap<PathMethod>, `${string}/json`>;
|
|
199
|
-
/** Return
|
|
219
|
+
/** Return JSON-like 1XX, 3XX, 4XX, 5XX and `default` responses from a path + HTTP method */
|
|
200
220
|
type ErrorResponseJSON<PathMethod extends Record<string | number, any>> = ErrorResponse<ResponseObjectMap<PathMethod>, `${string}/json`>;
|
|
201
221
|
/** Return JSON-like request body from a path + HTTP method */
|
|
202
222
|
type RequestBodyJSON<PathMethod> = JSONLike<FilterKeys<OperationRequestBody<PathMethod>, "content">>;
|
|
@@ -258,10 +278,13 @@ type ReadWriteLeaf = ReadWritePrimitive | ((...args: never) => unknown);
|
|
|
258
278
|
* `any` key is not marked either (`0 extends 1 & T[K]` is true only for `any`): a check on `any`
|
|
259
279
|
* takes both branches, so `Readable` dropped the key and `Writable` typed it `undefined`. The
|
|
260
280
|
* checks are not distributive (their check types are not type parameters), so `never` is seen.
|
|
281
|
+
* The keys are read by remapping, not as `{ ... }[keyof T]`: with an index signature (from
|
|
282
|
+
* `additionalProperties`) `keyof T` is `string`, which indexes the signature only, so no property
|
|
283
|
+
* was marked and `Writable` made a readOnly property a required `never`.
|
|
261
284
|
*/
|
|
262
|
-
type ReadWriteMarkedKeys<T, Marker> = {
|
|
263
|
-
[K in keyof T
|
|
264
|
-
}
|
|
285
|
+
type ReadWriteMarkedKeys<T, Marker> = keyof {
|
|
286
|
+
[K in keyof T as 0 extends 1 & T[K] ? never : NonNullable<T[K]> extends never ? never : NonNullable<T[K]> extends Marker ? K : never]: never;
|
|
287
|
+
};
|
|
265
288
|
/**
|
|
266
289
|
* Resolve an array or a tuple element by element. An array uses `T[number]`, not `infer E`: for an
|
|
267
290
|
* intersection of arrays (`allOf`) inference keeps one member and narrowing breaks (upstream
|
|
@@ -296,4 +319,4 @@ type Writable<T> = T extends $Read<any> ? never : T extends $Write<infer U> ? Wr
|
|
|
296
319
|
[K in ReadWriteMarkedKeys<T, $Read<any>>]?: never;
|
|
297
320
|
} : T;
|
|
298
321
|
|
|
299
|
-
export type { $Read, $Write, ErrorResponse, ErrorResponseJSON, ErrorStatus, FilterKeys, FindRequiredKeys, FirstErrorStatus, GetResponseContent, GetValueWithDefault, HasRequiredKeys, HttpMethod, IsOperationRequestBodyOptional, JSONLike, MediaType, OKStatusUnion, OkStatus, OperationObject, OperationRequestBody, OperationRequestBodyContent, OperationRequestBodyMediaContent, PathItemObject, PathsWithMethod, Readable, RequestBodyJSON, RequiredKeysOf, ResponseContent, ResponseObjectMap, SuccessResponse, SuccessResponseJSON, Writable };
|
|
322
|
+
export type { $Read, $Write, ErrorResponse, ErrorResponseJSON, ErrorStatus, ErrorStatusKey, FilterKeys, FindRequiredKeys, FirstErrorStatus, GetResponseContent, GetValueWithDefault, HasRequiredKeys, HttpMethod, IsOperationRequestBodyOptional, JSONLike, MediaType, OKStatusUnion, OkStatus, OperationObject, OperationRequestBody, OperationRequestBodyContent, OperationRequestBodyMediaContent, PathItemObject, PathsWithMethod, Readable, RequestBodyJSON, RequiredKeysOf, ResponseContent, ResponseObjectMap, SuccessResponse, SuccessResponseJSON, SuccessStatusKey, Writable };
|
package/dist/helpers.d.ts
CHANGED
|
@@ -2,12 +2,32 @@
|
|
|
2
2
|
type HttpMethod = "get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace"
|
|
3
3
|
/** OpenAPI 3.2: a safe, idempotent request with a body. */
|
|
4
4
|
| "query";
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Some 2XX statuses, kept for code that names them. The client does not classify by this list: a
|
|
7
|
+
* status is a success or an error by its first digit (`SuccessStatusKey`, `ErrorStatusKey`).
|
|
8
|
+
*/
|
|
6
9
|
type OkStatus = 200 | 201 | 202 | 203 | 204 | 206 | 207 | "2XX";
|
|
7
|
-
/** 4XX and 5XX statuses */
|
|
10
|
+
/** Some 4XX and 5XX statuses and `default`, kept like `OkStatus`. */
|
|
8
11
|
type ErrorStatus = 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 | "5XX" | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 444 | 450 | 451 | 497 | 498 | 499 | "4XX" | "default";
|
|
12
|
+
type StatusDigit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
|
13
|
+
/**
|
|
14
|
+
* The keys of a Response Object Map whose text matches a pattern. A generated map has numeric keys
|
|
15
|
+
* (`200`) and string ones (`"2XX"`, `"default"`), and a numeric literal matches no template
|
|
16
|
+
* literal type, so each key is matched by its text.
|
|
17
|
+
*/
|
|
18
|
+
type StatusKeysMatching<Keys, Pattern extends string> = Keys extends string | number ? `${Keys}` extends Pattern ? Keys : never : never;
|
|
19
|
+
/**
|
|
20
|
+
* The success statuses of a Response Object Map: every 2XX one. A closed list of statuses left out
|
|
21
|
+
* the ones it did not name (205, 208, 226), and their bodies were typed as no data.
|
|
22
|
+
*/
|
|
23
|
+
type SuccessStatusKey<T> = StatusKeysMatching<keyof T, `2${StatusDigit}${StatusDigit}` | "2XX">;
|
|
24
|
+
/**
|
|
25
|
+
* The error statuses of a Response Object Map: every 1XX, 3XX, 4XX and 5XX one, and `default`. The
|
|
26
|
+
* client returns each response that is not `ok` as `error`, also a 3XX with `redirect: "manual"`.
|
|
27
|
+
*/
|
|
28
|
+
type ErrorStatusKey<T> = StatusKeysMatching<keyof T, `${1 | 3 | 4 | 5}${StatusDigit}${StatusDigit}` | `${1 | 3 | 4 | 5}XX` | "default">;
|
|
9
29
|
/** Get a union of OK Statuses */
|
|
10
|
-
type OKStatusUnion<T> = FilterKeys<T,
|
|
30
|
+
type OKStatusUnion<T> = FilterKeys<T, SuccessStatusKey<T>>;
|
|
11
31
|
/** Get first error status, in order */
|
|
12
32
|
type FirstErrorStatus<T> = T extends {
|
|
13
33
|
500: unknown;
|
|
@@ -178,7 +198,7 @@ type OperationRequestBodyContent<T> = FilterKeys<OperationRequestBodyMediaConten
|
|
|
178
198
|
* Responses Object), so then it covers every success (upstream #1862). With a 2XX status declared,
|
|
179
199
|
* `default` is left to the errors, as before.
|
|
180
200
|
*/
|
|
181
|
-
type SuccessStatus<T> = [
|
|
201
|
+
type SuccessStatus<T> = [SuccessStatusKey<T>] extends [never] ? Extract<keyof T, "default"> : SuccessStatusKey<T>;
|
|
182
202
|
/**
|
|
183
203
|
* Return all 2XX responses from a Response Object Map, or `default` if it declares no 2XX one. For
|
|
184
204
|
* a union of maps (a call with a union of paths), the union of each map's responses: `keyof` of a
|
|
@@ -190,13 +210,13 @@ type GetResponseContent<T extends Record<string | number, any>, Media extends Me
|
|
|
190
210
|
[K in ResponseCode]: T[K]["content"] extends Record<string, any> ? FilterKeys<T[K]["content"], Media> extends never ? T[K]["content"] : FilterKeys<T[K]["content"], Media> : K extends keyof T ? T[K]["content"] : never;
|
|
191
211
|
}[ResponseCode] : never;
|
|
192
212
|
/**
|
|
193
|
-
* Return all
|
|
194
|
-
* the union of each map's responses, as `SuccessResponse`.
|
|
213
|
+
* Return all 1XX, 3XX, 4XX, 5XX and `default` responses from a Response Object Map; for a union
|
|
214
|
+
* of maps, the union of each map's responses, as `SuccessResponse`.
|
|
195
215
|
*/
|
|
196
|
-
type ErrorResponse<T extends Record<string | number, any>, Media extends MediaType = MediaType> = T extends unknown ? GetResponseContent<T, Media,
|
|
216
|
+
type ErrorResponse<T extends Record<string | number, any>, Media extends MediaType = MediaType> = T extends unknown ? GetResponseContent<T, Media, ErrorStatusKey<T>> : never;
|
|
197
217
|
/** Return first JSON-like 2XX response from a path + HTTP method */
|
|
198
218
|
type SuccessResponseJSON<PathMethod extends Record<string | number, any>> = SuccessResponse<ResponseObjectMap<PathMethod>, `${string}/json`>;
|
|
199
|
-
/** Return
|
|
219
|
+
/** Return JSON-like 1XX, 3XX, 4XX, 5XX and `default` responses from a path + HTTP method */
|
|
200
220
|
type ErrorResponseJSON<PathMethod extends Record<string | number, any>> = ErrorResponse<ResponseObjectMap<PathMethod>, `${string}/json`>;
|
|
201
221
|
/** Return JSON-like request body from a path + HTTP method */
|
|
202
222
|
type RequestBodyJSON<PathMethod> = JSONLike<FilterKeys<OperationRequestBody<PathMethod>, "content">>;
|
|
@@ -258,10 +278,13 @@ type ReadWriteLeaf = ReadWritePrimitive | ((...args: never) => unknown);
|
|
|
258
278
|
* `any` key is not marked either (`0 extends 1 & T[K]` is true only for `any`): a check on `any`
|
|
259
279
|
* takes both branches, so `Readable` dropped the key and `Writable` typed it `undefined`. The
|
|
260
280
|
* checks are not distributive (their check types are not type parameters), so `never` is seen.
|
|
281
|
+
* The keys are read by remapping, not as `{ ... }[keyof T]`: with an index signature (from
|
|
282
|
+
* `additionalProperties`) `keyof T` is `string`, which indexes the signature only, so no property
|
|
283
|
+
* was marked and `Writable` made a readOnly property a required `never`.
|
|
261
284
|
*/
|
|
262
|
-
type ReadWriteMarkedKeys<T, Marker> = {
|
|
263
|
-
[K in keyof T
|
|
264
|
-
}
|
|
285
|
+
type ReadWriteMarkedKeys<T, Marker> = keyof {
|
|
286
|
+
[K in keyof T as 0 extends 1 & T[K] ? never : NonNullable<T[K]> extends never ? never : NonNullable<T[K]> extends Marker ? K : never]: never;
|
|
287
|
+
};
|
|
265
288
|
/**
|
|
266
289
|
* Resolve an array or a tuple element by element. An array uses `T[number]`, not `infer E`: for an
|
|
267
290
|
* intersection of arrays (`allOf`) inference keeps one member and narrowing breaks (upstream
|
|
@@ -296,4 +319,4 @@ type Writable<T> = T extends $Read<any> ? never : T extends $Write<infer U> ? Wr
|
|
|
296
319
|
[K in ReadWriteMarkedKeys<T, $Read<any>>]?: never;
|
|
297
320
|
} : T;
|
|
298
321
|
|
|
299
|
-
export type { $Read, $Write, ErrorResponse, ErrorResponseJSON, ErrorStatus, FilterKeys, FindRequiredKeys, FirstErrorStatus, GetResponseContent, GetValueWithDefault, HasRequiredKeys, HttpMethod, IsOperationRequestBodyOptional, JSONLike, MediaType, OKStatusUnion, OkStatus, OperationObject, OperationRequestBody, OperationRequestBodyContent, OperationRequestBodyMediaContent, PathItemObject, PathsWithMethod, Readable, RequestBodyJSON, RequiredKeysOf, ResponseContent, ResponseObjectMap, SuccessResponse, SuccessResponseJSON, Writable };
|
|
322
|
+
export type { $Read, $Write, ErrorResponse, ErrorResponseJSON, ErrorStatus, ErrorStatusKey, FilterKeys, FindRequiredKeys, FirstErrorStatus, GetResponseContent, GetValueWithDefault, HasRequiredKeys, HttpMethod, IsOperationRequestBodyOptional, JSONLike, MediaType, OKStatusUnion, OkStatus, OperationObject, OperationRequestBody, OperationRequestBodyContent, OperationRequestBodyMediaContent, PathItemObject, PathsWithMethod, Readable, RequestBodyJSON, RequiredKeysOf, ResponseContent, ResponseObjectMap, SuccessResponse, SuccessResponseJSON, SuccessStatusKey, Writable };
|