@openstage/monadyssey-fetch 3.0.0-beta.7 → 3.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +24 -0
- package/dist/monadyssey-fetch.d.ts +193 -96
- package/dist/monadyssey-fetch.mjs +151 -70
- package/dist/monadyssey-fetch.mjs.map +1 -1
- package/package.json +12 -8
- package/readme.md +27 -8
- package/dist/monadyssey-fetch.cjs +0 -8
- package/dist/monadyssey-fetch.cjs.map +0 -1
- package/dist/monadyssey-fetch.umd.js +0 -8
- package/dist/monadyssey-fetch.umd.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Gabriel Bornea
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
6
|
+
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
|
7
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
|
8
|
+
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
11
|
+
|
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
13
|
+
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
14
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
15
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
16
|
+
|
|
17
|
+
Inspiration Acknowledgment:
|
|
18
|
+
|
|
19
|
+
The monadyssey library's development and design approaches draw conceptual inspiration from the Haskell language,
|
|
20
|
+
the Arrow library for Kotlin, and the Cats library for Scala. This acknowledgment is to highlight the influence
|
|
21
|
+
these projects have had on monadyssey's API design and embrace of functional programming paradigms. It is crucial
|
|
22
|
+
to note that this inspiration pertains solely to API design and architecture principles; no direct code from these
|
|
23
|
+
projects has been used in monadyssey. This library stands as an independent work, and this section is included to
|
|
24
|
+
honor the spirit of shared knowledge and to contribute to community growth within the functional programming ecosystem.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IO } from '@openstage/monadyssey-core';
|
|
2
2
|
import { Option as Option_2 } from '@openstage/monadyssey-core';
|
|
3
|
-
import { Pipe } from '@openstage/monadyssey-core';
|
|
3
|
+
import type { Pipe } from '@openstage/monadyssey-core';
|
|
4
|
+
import type { Schedule } from '@openstage/monadyssey-core';
|
|
4
5
|
import { Stream } from '@openstage/monadyssey-core';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -21,24 +22,27 @@ export declare type Credentials = "omit" | "same-origin" | "include";
|
|
|
21
22
|
export declare const decodeEvents: <E>() => Pipe<E, Uint8Array, ServerSentEvent>;
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
|
-
* A composable HTTP client that wraps the native `fetch` API, returning `IO` instances instead of
|
|
25
|
+
* A composable HTTP client that wraps the native `fetch` API, returning `IO` instances instead of
|
|
26
|
+
* Promises. Each instance carries its own configuration (base URL, interceptors, default headers,
|
|
27
|
+
* timeout, credentials), so different parts of an application can use independently configured
|
|
28
|
+
* clients.
|
|
25
29
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
30
|
+
* Three kinds of call, by what you want back:
|
|
31
|
+
* - **the decoded body** — `get`, `post`, `put`, `patch`, `delete`, `fetch` return
|
|
32
|
+
* `IO<HttpError, A>`. A response with no body (`204`, an empty `200`) fails with
|
|
33
|
+
* `kind: "decode"`, since a value was expected; pass `{ empty: "option" }` when absence is
|
|
34
|
+
* legitimate, to get `IO<HttpError, Option<A>>`.
|
|
35
|
+
* - **nothing** — `send(method, uri, { body })` returns `IO<HttpError, void>` for actions whose
|
|
36
|
+
* response body you do not read (publish, archive, leave …); any body, or none, is fine.
|
|
37
|
+
* - **the `Response`** — `raw(method, uri, options?)` returns `IO<HttpError, Response>` for
|
|
38
|
+
* status codes, headers or streaming.
|
|
29
39
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
40
|
+
* Every non-2xx response fails with `kind: "response"`, whichever you use. Cancellation is
|
|
41
|
+
* supported: when the IO is cancelled (via a fiber or `timeout`), the underlying `fetch` is
|
|
42
|
+
* aborted through its `AbortSignal`.
|
|
33
43
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* protocol-level fact (the HTTP spec says these statuses have no body), distinct from a
|
|
37
|
-
* domain-level optionality. For that reason the methods return `IO<HttpError, A | null>` rather
|
|
38
|
-
* than `IO<HttpError, Option<A>>`. `Option` is the right tool when a value might be absent at
|
|
39
|
-
* the domain level; `| null` is honest when the absence is structural to the protocol. For the
|
|
40
|
-
* 95% case where you control the endpoint and never receive 204, the `| null` is a brief
|
|
41
|
-
* `?? defaultValue` away.
|
|
44
|
+
* `A` is what you claim the body is; the JSON is not checked unless you pass a `transform` that
|
|
45
|
+
* validates it (a schema's `parse`, say) — a throw there fails with `kind: "decode"`.
|
|
42
46
|
*
|
|
43
47
|
* **Default credentials:** `same-origin`, matching the platform `fetch` default. Set
|
|
44
48
|
* `credentials: "include"` explicitly per-client or per-request if you need cookies to flow
|
|
@@ -48,11 +52,12 @@ export declare const decodeEvents: <E>() => Pipe<E, Uint8Array, ServerSentEvent>
|
|
|
48
52
|
* const api = new HttpClient({
|
|
49
53
|
* baseUrl: "https://api.example.com",
|
|
50
54
|
* interceptors: [authInterceptor],
|
|
51
|
-
* defaultHeaders: { "Accept": "application/json" },
|
|
52
55
|
* timeout: 5000,
|
|
53
56
|
* });
|
|
54
57
|
*
|
|
55
|
-
* const users = api.get<User[]>("/users");
|
|
58
|
+
* const users = api.get<User[]>("/users"); // IO<HttpError, User[]>
|
|
59
|
+
* const avatar = api.get<Avatar>("/me/avatar", { empty: "option" }); // IO<HttpError, Option<Avatar>>
|
|
60
|
+
* const leave = api.send("POST", `/communities/${slug}/leave`); // IO<HttpError, void>
|
|
56
61
|
*/
|
|
57
62
|
export declare class HttpClient {
|
|
58
63
|
private readonly interceptors;
|
|
@@ -67,81 +72,102 @@ export declare class HttpClient {
|
|
|
67
72
|
*/
|
|
68
73
|
constructor(config?: HttpClientConfig);
|
|
69
74
|
/**
|
|
70
|
-
* Performs a GET request.
|
|
75
|
+
* Performs a GET request and decodes the body.
|
|
71
76
|
*
|
|
72
|
-
* @template A - The
|
|
77
|
+
* @template A - The type of the decoded body.
|
|
73
78
|
* @param {string} uri - The URL or path to request.
|
|
74
|
-
* @param {
|
|
75
|
-
* @returns {IO<HttpError, A
|
|
79
|
+
* @param {Options<A>} [options] - Request options; `{ empty: "option" }` yields `Option<A>`.
|
|
80
|
+
* @returns {IO<HttpError, A>} The decoded body.
|
|
76
81
|
*/
|
|
77
|
-
get(uri: string, options: Omit<
|
|
78
|
-
|
|
79
|
-
}): IO<HttpError, Response>;
|
|
80
|
-
get<A = unknown>(uri: string, options?: Omit<Options<A>, "body">): IO<HttpError, A | null>;
|
|
82
|
+
get<A = unknown>(uri: string, options: Omit<OptionalBody<A>, "body">): IO<HttpError, Option_2<NonNullable<A>>>;
|
|
83
|
+
get<A = unknown>(uri: string, options?: Omit<RequiredBody<A>, "body">): IO<HttpError, A>;
|
|
81
84
|
/**
|
|
82
|
-
* Performs a POST request.
|
|
85
|
+
* Performs a POST request and decodes the body.
|
|
83
86
|
*
|
|
84
|
-
* @template A - The
|
|
87
|
+
* @template A - The type of the decoded body.
|
|
85
88
|
* @param {string} uri - The URL or path to request.
|
|
86
89
|
* @param {unknown} [body] - The request payload.
|
|
87
|
-
* @param {Options<A>} [options] - Request options
|
|
88
|
-
* @returns {IO<HttpError, A
|
|
90
|
+
* @param {Options<A>} [options] - Request options; `{ empty: "option" }` yields `Option<A>`.
|
|
91
|
+
* @returns {IO<HttpError, A>} The decoded body.
|
|
89
92
|
*/
|
|
90
|
-
post(uri: string, body: unknown, options:
|
|
91
|
-
|
|
92
|
-
}): IO<HttpError, Response>;
|
|
93
|
-
post<A = unknown>(uri: string, body?: unknown, options?: Options<A>): IO<HttpError, A | null>;
|
|
93
|
+
post<A = unknown>(uri: string, body: unknown, options: OptionalBody<A>): IO<HttpError, Option_2<NonNullable<A>>>;
|
|
94
|
+
post<A = unknown>(uri: string, body?: unknown, options?: RequiredBody<A>): IO<HttpError, A>;
|
|
94
95
|
/**
|
|
95
|
-
* Performs a PUT request.
|
|
96
|
+
* Performs a PUT request and decodes the body.
|
|
96
97
|
*
|
|
97
|
-
* @template A - The
|
|
98
|
+
* @template A - The type of the decoded body.
|
|
98
99
|
* @param {string} uri - The URL or path to request.
|
|
99
100
|
* @param {unknown} [body] - The request payload.
|
|
100
|
-
* @param {Options<A>} [options] - Request options
|
|
101
|
-
* @returns {IO<HttpError, A
|
|
101
|
+
* @param {Options<A>} [options] - Request options; `{ empty: "option" }` yields `Option<A>`.
|
|
102
|
+
* @returns {IO<HttpError, A>} The decoded body.
|
|
102
103
|
*/
|
|
103
|
-
put(uri: string, body: unknown, options:
|
|
104
|
-
|
|
105
|
-
}): IO<HttpError, Response>;
|
|
106
|
-
put<A = unknown>(uri: string, body?: unknown, options?: Options<A>): IO<HttpError, A | null>;
|
|
104
|
+
put<A = unknown>(uri: string, body: unknown, options: OptionalBody<A>): IO<HttpError, Option_2<NonNullable<A>>>;
|
|
105
|
+
put<A = unknown>(uri: string, body?: unknown, options?: RequiredBody<A>): IO<HttpError, A>;
|
|
107
106
|
/**
|
|
108
|
-
* Performs a PATCH request.
|
|
107
|
+
* Performs a PATCH request and decodes the body.
|
|
109
108
|
*
|
|
110
|
-
* @template A - The
|
|
109
|
+
* @template A - The type of the decoded body.
|
|
111
110
|
* @param {string} uri - The URL or path to request.
|
|
112
111
|
* @param {unknown} [body] - The request payload.
|
|
113
|
-
* @param {Options<A>} [options] - Request options
|
|
114
|
-
* @returns {IO<HttpError, A
|
|
112
|
+
* @param {Options<A>} [options] - Request options; `{ empty: "option" }` yields `Option<A>`.
|
|
113
|
+
* @returns {IO<HttpError, A>} The decoded body.
|
|
115
114
|
*/
|
|
116
|
-
patch(uri: string, body: unknown, options:
|
|
117
|
-
|
|
118
|
-
}): IO<HttpError, Response>;
|
|
119
|
-
patch<A = unknown>(uri: string, body?: unknown, options?: Options<A>): IO<HttpError, A | null>;
|
|
115
|
+
patch<A = unknown>(uri: string, body: unknown, options: OptionalBody<A>): IO<HttpError, Option_2<NonNullable<A>>>;
|
|
116
|
+
patch<A = unknown>(uri: string, body?: unknown, options?: RequiredBody<A>): IO<HttpError, A>;
|
|
120
117
|
/**
|
|
121
|
-
* Performs a DELETE request.
|
|
118
|
+
* Performs a DELETE request and decodes the body. For a DELETE that answers `204 No Content`,
|
|
119
|
+
* use `send("DELETE", uri)` instead.
|
|
122
120
|
*
|
|
123
|
-
* @template A - The
|
|
121
|
+
* @template A - The type of the decoded body.
|
|
124
122
|
* @param {string} uri - The URL or path to request.
|
|
125
|
-
* @param {
|
|
126
|
-
* @returns {IO<HttpError, A
|
|
123
|
+
* @param {Options<A>} [options] - Request options; `{ empty: "option" }` yields `Option<A>`.
|
|
124
|
+
* @returns {IO<HttpError, A>} The decoded body.
|
|
127
125
|
*/
|
|
128
|
-
delete(uri: string, options: Omit<
|
|
129
|
-
|
|
130
|
-
}): IO<HttpError, Response>;
|
|
131
|
-
delete<A = unknown>(uri: string, options?: Omit<Options<A>, "body">): IO<HttpError, A | null>;
|
|
126
|
+
delete<A = unknown>(uri: string, options: Omit<OptionalBody<A>, "body">): IO<HttpError, Option_2<NonNullable<A>>>;
|
|
127
|
+
delete<A = unknown>(uri: string, options?: Omit<RequiredBody<A>, "body">): IO<HttpError, A>;
|
|
132
128
|
/**
|
|
133
|
-
* Performs a
|
|
129
|
+
* Performs a request with any method and decodes the body.
|
|
134
130
|
*
|
|
135
|
-
* @template A - The
|
|
131
|
+
* @template A - The type of the decoded body.
|
|
136
132
|
* @param {string} uri - The URL or path to request.
|
|
137
133
|
* @param {Method} method - The HTTP method.
|
|
138
|
-
* @param {Options<A>} [options] - Request options
|
|
139
|
-
* @returns {IO<HttpError, A
|
|
134
|
+
* @param {Options<A>} [options] - Request options, including `body`; `{ empty: "option" }` yields `Option<A>`.
|
|
135
|
+
* @returns {IO<HttpError, A>} The decoded body.
|
|
140
136
|
*/
|
|
141
|
-
fetch(uri: string, method: Method, options:
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
137
|
+
fetch<A = unknown>(uri: string, method: Method, options: OptionalBody<A>): IO<HttpError, Option_2<NonNullable<A>>>;
|
|
138
|
+
fetch<A = unknown>(uri: string, method: Method, options?: RequiredBody<A>): IO<HttpError, A>;
|
|
139
|
+
/**
|
|
140
|
+
* Performs a request whose response body you do not need — an action such as publish,
|
|
141
|
+
* archive or leave. Succeeds with `void` for any 2xx, with or without a body (which is
|
|
142
|
+
* discarded); a non-2xx response fails with `kind: "response"` and its body.
|
|
143
|
+
*
|
|
144
|
+
* @param {Method} method - The HTTP method.
|
|
145
|
+
* @param {string} uri - The URL or path to request.
|
|
146
|
+
* @param {SendOptions} [options] - Headers, credentials, timeout and body. A `GET` or `HEAD`
|
|
147
|
+
* request with a body throws `TypeError` where it is built.
|
|
148
|
+
* @returns {IO<HttpError, void>}
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* client.send("POST", `/api/v1/communities/${slug}/leave`);
|
|
152
|
+
* client.send("PUT", `/api/v1/articles/${id}`, { body: article });
|
|
153
|
+
* client.send("DELETE", `/api/v1/passkeys/${id}`, { headers: { "X-Step-Up": token } });
|
|
154
|
+
*/
|
|
155
|
+
send(method: Method, uri: string, options?: SendOptions): IO<HttpError, void>;
|
|
156
|
+
/**
|
|
157
|
+
* Performs a request and yields the `Response` itself, for status codes, headers or streaming.
|
|
158
|
+
* A non-2xx response still fails with `kind: "response"` (its body read into the error); a 2xx
|
|
159
|
+
* `Response` is returned unread. When you only need the status or headers, cancel the body
|
|
160
|
+
* (`response.body?.cancel()`) so the connection is released; `send` does this for you.
|
|
161
|
+
*
|
|
162
|
+
* @param {Method} method - The HTTP method.
|
|
163
|
+
* @param {string} uri - The URL or path to request.
|
|
164
|
+
* @param {SendOptions} [options] - Headers, credentials, timeout and body.
|
|
165
|
+
* @returns {IO<HttpError, Response>}
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* client.raw("POST", "/api/v1/communities", { body: input }).map((r) => r.headers.get("Location"));
|
|
169
|
+
*/
|
|
170
|
+
raw(method: Method, uri: string, options?: SendOptions): IO<HttpError, Response>;
|
|
145
171
|
/**
|
|
146
172
|
* Opens a server-sent-events stream and emits each {@link ServerSentEvent} as it arrives.
|
|
147
173
|
*
|
|
@@ -158,13 +184,17 @@ export declare class HttpClient {
|
|
|
158
184
|
* @param {string} uri - The URL or path to connect to.
|
|
159
185
|
* @param {SseOptions} [options] - Headers, credentials, and reconnection settings.
|
|
160
186
|
* @returns {Stream<HttpError, ServerSentEvent>} A stream of parsed events.
|
|
187
|
+
* @throws {RangeError} If `options.retry` is negative or `NaN`.
|
|
161
188
|
*
|
|
162
189
|
* @example
|
|
163
190
|
* const events = client.sse("/events", { headers: { Authorization: `Bearer ${token}` } });
|
|
164
|
-
* await events.runForEach((event) => IO.
|
|
191
|
+
* await events.runForEach((event) => IO.sync(() => handle(event))).unsafeRun();
|
|
165
192
|
*/
|
|
166
193
|
sse(uri: string, options?: SseOptions): Stream<HttpError, ServerSentEvent>;
|
|
167
194
|
private resolveUrl;
|
|
195
|
+
/** Prepares the request, runs it through the interceptors and `fetch`, and yields the `Response`. */
|
|
196
|
+
private exchange;
|
|
197
|
+
private withTimeout;
|
|
168
198
|
private request;
|
|
169
199
|
}
|
|
170
200
|
|
|
@@ -193,7 +223,8 @@ export declare type HttpClientConfig = {
|
|
|
193
223
|
*
|
|
194
224
|
* `kind` tells the two facts apart that `status` alone cannot: "the server said 500" is
|
|
195
225
|
* `kind: "response", status: 500`, while "nothing answered" is `kind: "network", status: 0`.
|
|
196
|
-
* For every kind other than `"response"`, `status` is `0
|
|
226
|
+
* For every kind other than `"response"` and `"decode"`, `status` is `0`; `body` is `null` except
|
|
227
|
+
* for `"response"`.
|
|
197
228
|
*
|
|
198
229
|
* @example
|
|
199
230
|
* client.post("/payments", payment).mapErr((error) =>
|
|
@@ -233,6 +264,16 @@ export declare class HttpError extends Error {
|
|
|
233
264
|
* @param {number} after The timeout in milliseconds.
|
|
234
265
|
*/
|
|
235
266
|
static timeout(url: string, after: number): HttpError;
|
|
267
|
+
/**
|
|
268
|
+
* An error for a 2xx response whose body could not be used: it failed to parse, a `transform`
|
|
269
|
+
* threw, or there was no body where one was expected. `status` is the real status, `body` is
|
|
270
|
+
* `null`, and `cause` carries the underlying error.
|
|
271
|
+
*
|
|
272
|
+
* @param {string} url The request URL.
|
|
273
|
+
* @param {Response} response The response that could not be decoded.
|
|
274
|
+
* @param {unknown} cause The parse error, the value a `transform` threw, or a description.
|
|
275
|
+
*/
|
|
276
|
+
static decode(url: string, response: Response, cause: unknown): HttpError;
|
|
236
277
|
/**
|
|
237
278
|
* An error for a request that could not be built, so nothing was sent — typically a body that
|
|
238
279
|
* could not be serialized. `status` is `0` and `body` is `null`.
|
|
@@ -269,75 +310,112 @@ export declare class HttpError extends Error {
|
|
|
269
310
|
* (e) => `${e.code}: ${e.message}`
|
|
270
311
|
* );
|
|
271
312
|
*/
|
|
272
|
-
bodyAs<T>(guard: (x: unknown) => x is T): Option_2<T
|
|
313
|
+
bodyAs<T>(guard: (x: unknown) => x is T): Option_2<NonNullable<T>>;
|
|
273
314
|
}
|
|
274
315
|
|
|
275
316
|
/**
|
|
276
317
|
* How a request failed.
|
|
277
318
|
* - `"request"`: the request could not be built — typically the body could not be serialized.
|
|
278
319
|
* Nothing was sent.
|
|
279
|
-
* - `"response"`: the server answered with a non-2xx status
|
|
320
|
+
* - `"response"`: the server answered with a non-2xx status. `body` carries what it sent.
|
|
321
|
+
* - `"decode"`: the server answered 2xx, but the body could not be used — it failed to parse, a
|
|
322
|
+
* `transform` threw, or there was no body where one was expected (a `204`, say). `status` is the
|
|
323
|
+
* real status and `cause` the underlying error.
|
|
280
324
|
* - `"network"`: no response arrived — DNS failure, offline, CORS block, or a rejected interceptor.
|
|
281
325
|
* - `"timeout"`: the client's `timeout` option fired before the response, or its body, completed.
|
|
282
326
|
* The request may have reached the server.
|
|
283
327
|
* - `"aborted"`: the request was aborted by something other than IO cancellation, such as an
|
|
284
328
|
* interceptor's own signal (an IO cancelled via `fiber.cancel()` or `IO.timeout` ends as
|
|
285
329
|
* `Cancelled`, not as an `HttpError`).
|
|
330
|
+
*
|
|
331
|
+
* New kinds may be added in a minor release, so give an exhaustive `switch` a `default` branch.
|
|
286
332
|
*/
|
|
287
|
-
export declare type HttpErrorKind = "request" | "response" | "network" | "timeout" | "aborted";
|
|
333
|
+
export declare type HttpErrorKind = "request" | "response" | "decode" | "network" | "timeout" | "aborted";
|
|
288
334
|
|
|
289
335
|
/**
|
|
290
|
-
* An HTTP interceptor that can modify or handle request and response
|
|
291
|
-
*
|
|
336
|
+
* An HTTP interceptor that can modify or handle a request before, and its response after, the
|
|
337
|
+
* outgoing `fetch` call.
|
|
292
338
|
*/
|
|
293
339
|
export declare interface HttpInterceptor {
|
|
294
340
|
/**
|
|
295
341
|
* Intercepts an outgoing HTTP request.
|
|
296
342
|
*
|
|
297
|
-
* Call `next(request)` to continue the chain with the (optionally modified) request.
|
|
298
|
-
*
|
|
343
|
+
* Call `next(request)` to continue the chain with the (optionally modified) request — e.g.
|
|
344
|
+
* `next({ url: request.url, init: { ...request.init, headers } })`. Return a
|
|
345
|
+
* `Promise<Response>` without calling `next` to short-circuit the request.
|
|
299
346
|
*
|
|
300
|
-
* @param request - The
|
|
347
|
+
* @param request - The resolved URL and `fetch` options of the pending request.
|
|
301
348
|
* @param next - Forwards the request to the next interceptor or to `fetch`.
|
|
302
349
|
* @returns A Promise of the resulting `Response`.
|
|
303
350
|
*/
|
|
304
|
-
intercept(request:
|
|
351
|
+
intercept(request: InterceptedRequest, next: (request: InterceptedRequest) => Promise<Response>): Promise<Response>;
|
|
305
352
|
}
|
|
306
353
|
|
|
354
|
+
/**
|
|
355
|
+
* A request as seen by an {@link HttpInterceptor}: the resolved URL and the `fetch` options.
|
|
356
|
+
* `init.headers` is always a `Headers` instance — copy it with `new Headers(request.init.headers)`
|
|
357
|
+
* (spreading a `Headers` object yields `{}`).
|
|
358
|
+
*/
|
|
359
|
+
export declare type InterceptedRequest = {
|
|
360
|
+
readonly url: string;
|
|
361
|
+
readonly init: Omit<RequestInit, "headers"> & {
|
|
362
|
+
readonly headers: Headers;
|
|
363
|
+
};
|
|
364
|
+
};
|
|
365
|
+
|
|
307
366
|
/**
|
|
308
367
|
* Represents the HTTP method for the request.
|
|
309
368
|
*/
|
|
310
369
|
export declare type Method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD";
|
|
311
370
|
|
|
371
|
+
/** Options for a request that expects no body back, or `Option` of one. */
|
|
372
|
+
declare type OptionalBody<A> = Options<A> & {
|
|
373
|
+
empty: "option";
|
|
374
|
+
};
|
|
375
|
+
|
|
312
376
|
/**
|
|
313
|
-
*
|
|
314
|
-
*
|
|
315
|
-
*
|
|
377
|
+
* Options for a request whose response body is decoded (`get`, `post`, `put`, `patch`, `delete`,
|
|
378
|
+
* `fetch`).
|
|
379
|
+
*
|
|
380
|
+
* @template A - The type of the decoded response body.
|
|
316
381
|
*/
|
|
317
|
-
export declare type
|
|
382
|
+
export declare type Options<A = unknown> = RequestOptions & {
|
|
383
|
+
/** The request payload (for `fetch`; the other methods take it as an argument). */
|
|
384
|
+
body?: unknown;
|
|
385
|
+
/** How the response body is read. Defaults to `"json"`. */
|
|
386
|
+
responseType?: ResponseType_2;
|
|
387
|
+
/**
|
|
388
|
+
* Turns the parsed body into an `A` — a decoder or validator. Called only when there is a body;
|
|
389
|
+
* a throw fails the request with `kind: "decode"`.
|
|
390
|
+
*/
|
|
391
|
+
transform?: (data: unknown) => A;
|
|
392
|
+
/**
|
|
393
|
+
* What a response without a body (`204`, `205`, an empty `200`) means:
|
|
394
|
+
* - `"error"` (default): a value was expected, so it fails with `kind: "decode"`;
|
|
395
|
+
* - `"option"`: absence is expected, so the request yields `Option<A>` — `None` for no body.
|
|
396
|
+
*
|
|
397
|
+
* For requests whose body you never read, use `send()`; to inspect the `Response`, use `raw()`.
|
|
398
|
+
*/
|
|
399
|
+
empty?: "error" | "option";
|
|
400
|
+
};
|
|
318
401
|
|
|
319
402
|
/**
|
|
320
|
-
* Options
|
|
321
|
-
*
|
|
322
|
-
* @template A - The expected type of the response body after transformation.
|
|
403
|
+
* Options shared by every request: headers, credentials and timeout.
|
|
323
404
|
*/
|
|
324
|
-
export declare type
|
|
405
|
+
export declare type RequestOptions = {
|
|
325
406
|
/** Custom headers for the request as key-value pairs. */
|
|
326
407
|
headers?: Record<string, string>;
|
|
327
|
-
/** The request payload. */
|
|
328
|
-
body?: unknown;
|
|
329
|
-
/** The expected type of the response body. Defaults to `"json"`. */
|
|
330
|
-
responseType?: ResponseType_2;
|
|
331
408
|
/** The credential policy for the request. Defaults to the client-level setting. */
|
|
332
409
|
credentials?: Credentials;
|
|
333
|
-
/** Specifies how the response should be observed. Defaults to `"body"`. */
|
|
334
|
-
observe?: Observe;
|
|
335
|
-
/** A function to transform the response body into the desired type. */
|
|
336
|
-
transform?: (data: unknown) => A;
|
|
337
410
|
/** Per-request timeout in milliseconds. Overrides the client-level timeout. */
|
|
338
411
|
timeout?: number;
|
|
339
412
|
};
|
|
340
413
|
|
|
414
|
+
/** Options for a request whose body is required (the default). */
|
|
415
|
+
declare type RequiredBody<A> = Options<A> & {
|
|
416
|
+
empty?: "error";
|
|
417
|
+
};
|
|
418
|
+
|
|
341
419
|
/**
|
|
342
420
|
* Specifies the expected response type.
|
|
343
421
|
* - `"json"`: Parse the response as JSON.
|
|
@@ -349,10 +427,20 @@ export declare type Options<A = unknown> = {
|
|
|
349
427
|
declare type ResponseType_2 = "json" | "text" | "blob" | "arrayBuffer" | "formData";
|
|
350
428
|
export { ResponseType_2 as ResponseType }
|
|
351
429
|
|
|
430
|
+
/**
|
|
431
|
+
* Options for `send` and `raw`: the shared request options plus the payload.
|
|
432
|
+
*/
|
|
433
|
+
export declare type SendOptions = RequestOptions & {
|
|
434
|
+
/** The request payload. */
|
|
435
|
+
body?: unknown;
|
|
436
|
+
};
|
|
437
|
+
|
|
352
438
|
/**
|
|
353
439
|
* A single server-sent event parsed from a text/event-stream response.
|
|
354
440
|
*
|
|
355
|
-
* @property id - The event id
|
|
441
|
+
* @property id - The last event id in effect when the event was dispatched — set by the event's
|
|
442
|
+
* own `id:` field or by an earlier one, as the spec's `MessageEvent.lastEventId`. Absent until
|
|
443
|
+
* the server sends an `id:`; the empty string after the server resets it. Used to resume a stream.
|
|
356
444
|
* @property event - The event type. Defaults to `"message"` when the server sends no `event:` field.
|
|
357
445
|
* @property data - The event payload. Multiple `data:` lines are joined with a newline.
|
|
358
446
|
* @property retry - The reconnection time in milliseconds, if the server sent a `retry:` field.
|
|
@@ -377,12 +465,21 @@ export declare type SseOptions = {
|
|
|
377
465
|
* (network error or a `5xx` status). Terminal `4xx` responses (including auth failures) are not
|
|
378
466
|
* retried. On reconnect the last received event id is sent as `Last-Event-ID`, and the request
|
|
379
467
|
* headers (including `Authorization`) and credentials are re-applied. Defaults to `true`.
|
|
468
|
+
*
|
|
469
|
+
* `true` waits `retry` ms (or the server's `retry:` value) before each reconnect, forever. Pass a
|
|
470
|
+
* `Schedule` for backoff, jitter or a limit on consecutive failed reconnects, e.g.
|
|
471
|
+
* `Schedule.exponential(1000).maxDelay(30_000).jittered()`; a server `retry:` value still
|
|
472
|
+
* takes precedence as the delay once received. `maxAttempts` counts connection attempts since the
|
|
473
|
+
* last delivered event, the connection that delivered it included — `maxAttempts(3)` allows two
|
|
474
|
+
* reconnects in a row that deliver nothing — and the count resets with every delivered event.
|
|
380
475
|
*/
|
|
381
|
-
reconnect?: boolean;
|
|
476
|
+
reconnect?: boolean | Schedule;
|
|
382
477
|
/**
|
|
383
478
|
* The delay in milliseconds before reconnecting, used until the server sends a `retry:` value.
|
|
384
479
|
* A server-sent value below 100 ms is raised to 100 ms so a misbehaving server cannot make the
|
|
385
|
-
* client reconnect in a tight loop.
|
|
480
|
+
* client reconnect in a tight loop. Delays above 2,147,483,647 ms (the `setTimeout` limit) are
|
|
481
|
+
* lowered to it. Must be a non-negative number: `sse()` throws `RangeError` otherwise.
|
|
482
|
+
* Defaults to `3000`.
|
|
386
483
|
*/
|
|
387
484
|
retry?: number;
|
|
388
485
|
};
|