arthron 0.1.0 → 1.0.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/README.md +125 -48
- package/dist/index.cjs +752 -268
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +308 -83
- package/dist/index.d.mts +308 -83
- package/dist/index.mjs +752 -269
- package/dist/index.mjs.map +1 -1
- package/llms.txt +46 -30
- package/package.json +4 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,88 @@
|
|
|
1
|
-
//#region src/
|
|
2
|
-
|
|
1
|
+
//#region src/types/request.types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* What plugins see and return. `init.headers` is always a plain record with
|
|
4
|
+
* lowercased names — spread it, read it, add to it — and the pipeline puts
|
|
5
|
+
* it back into that shape after every request interceptor.
|
|
6
|
+
*/
|
|
7
|
+
interface RequestContext {
|
|
8
|
+
url: string;
|
|
9
|
+
init: Omit<RequestInit, "headers"> & {
|
|
10
|
+
headers: Record<string, string>;
|
|
11
|
+
};
|
|
12
|
+
/** Per-call settings for plugins (`RequestOptions.meta`); never sent. */
|
|
13
|
+
meta: ArthronMeta;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Per-call settings for plugins, passed as `api.get(path, { meta })` and
|
|
17
|
+
* carried next to `init` — never sent to fetch. The built-in plugins read
|
|
18
|
+
* `retry` and `timeout`; your own add keys by augmentation:
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* declare module "arthron" {
|
|
22
|
+
* interface ArthronMeta { skipAuth?: boolean }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
interface ArthronMeta {
|
|
27
|
+
/** `false` turns `retry()` off for this call; an object overrides its options. */
|
|
28
|
+
retry?: false | Omit<RetryOptions, "sleep">;
|
|
29
|
+
/** Deadline for this call in ms, overriding `timeout(ms)`. `Infinity` lifts it. */
|
|
30
|
+
timeout?: number;
|
|
31
|
+
}
|
|
32
|
+
type RetryOptions = {
|
|
33
|
+
/** Number of retries after the first attempt. Default 2 (3 requests total). */
|
|
34
|
+
retries?: number;
|
|
35
|
+
/** Statuses worth retrying. Network errors (status 0) always are. */
|
|
36
|
+
retryOn?: readonly number[];
|
|
37
|
+
/** Methods safe to repeat (QUERY is, per RFC 10008). Compared case-insensitively. */
|
|
38
|
+
methods?: readonly string[];
|
|
39
|
+
/**
|
|
40
|
+
* Backoff in ms for retry number `retry` (0-based). Default "full jitter":
|
|
41
|
+
* a random share of 300 · 2^retry, so clients that failed together do not
|
|
42
|
+
* retry together.
|
|
43
|
+
*/
|
|
44
|
+
delay?: (retry: number, error: unknown) => number;
|
|
45
|
+
/**
|
|
46
|
+
* Your own verdict on one failure: `true` retries, `false` stops,
|
|
47
|
+
* `undefined` leaves it to `retryOn`/`methods`. It sees every error — a
|
|
48
|
+
* TimeoutError from a `timeout()` placed after `retry()` included — but
|
|
49
|
+
* cannot exceed `retries`, resend a `ReadableStream` body, or retry a call
|
|
50
|
+
* the caller aborted.
|
|
51
|
+
*/
|
|
52
|
+
shouldRetry?: (error: unknown, attempt: number, ctx: RequestContext) => boolean | undefined;
|
|
53
|
+
/** Called before each wait, for logs and metrics. */
|
|
54
|
+
onRetry?: (error: unknown, attempt: number, waitMs: number) => void;
|
|
55
|
+
/** Injectable for tests. Default `setTimeout`; rejects with the abort reason. */
|
|
56
|
+
sleep?: (ms: number, signal?: AbortSignal | null) => Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Longest `Retry-After` (ms) worth honouring. Beyond it the request is not
|
|
59
|
+
* retried at all. Default 60 000.
|
|
60
|
+
*/
|
|
61
|
+
maxRetryAfter?: number;
|
|
62
|
+
};
|
|
63
|
+
type QueryValue = string | number | boolean | null | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Query parameters. `null`/`undefined` values are skipped, an array becomes
|
|
66
|
+
* repeated keys (`ids=1&ids=2`), and a `URLSearchParams` is used as is.
|
|
67
|
+
*/
|
|
68
|
+
type QueryParams = Record<string, QueryValue | readonly QueryValue[]> | URLSearchParams;
|
|
69
|
+
/**
|
|
70
|
+
* Headers as config and per-call options accept them: anything fetch's
|
|
71
|
+
* `headers` takes, or a plain object whose `null`/`undefined` values delete
|
|
72
|
+
* that header from the layer underneath (a client default, an inherited
|
|
73
|
+
* header). Not spelled `HeadersInit`: that name exists only in the DOM lib,
|
|
74
|
+
* and a Node project typed with `@types/node` alone does not have it.
|
|
75
|
+
*/
|
|
76
|
+
type HeadersOption = NonNullable<RequestInit["headers"]> | Record<string, string | null | undefined>;
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/error/arthron-error.d.ts
|
|
3
79
|
type ArthronErrorInit = {
|
|
4
80
|
message: string;
|
|
5
81
|
status: number;
|
|
6
82
|
statusText: string;
|
|
7
83
|
headers: Headers;
|
|
8
84
|
data: unknown;
|
|
85
|
+
detail?: string | undefined;
|
|
9
86
|
request: RequestContext;
|
|
10
87
|
response?: Response;
|
|
11
88
|
cause?: unknown;
|
|
@@ -20,42 +97,47 @@ export declare class ArthronError extends Error {
|
|
|
20
97
|
/** HTTP status of the failed response; `0` when fetch itself failed (network). */
|
|
21
98
|
readonly status: number;
|
|
22
99
|
readonly statusText: string;
|
|
23
|
-
/** Response headers; empty for network failures. */
|
|
100
|
+
/** Response headers; empty for network failures. Not enumerable — kept out of logs. */
|
|
24
101
|
readonly headers: Headers;
|
|
25
102
|
/** Parsed body: JSON if it parses, else the text, else `undefined`. */
|
|
26
103
|
readonly data: unknown;
|
|
27
|
-
/**
|
|
104
|
+
/**
|
|
105
|
+
* The server's own explanation, picked out of `data` (by default
|
|
106
|
+
* `message` → `error` → `error.message` → `detail`; see the `errorDetail`
|
|
107
|
+
* config). `undefined` when the body had none. Untrusted server text: show
|
|
108
|
+
* it to users as text, never as HTML. `message`, by contrast, is written by
|
|
109
|
+
* arthron — method, URL without query, status — and is meant for logs.
|
|
110
|
+
*/
|
|
111
|
+
readonly detail: string | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* The context that was sent — url and init after request interceptors.
|
|
114
|
+
* Not enumerable: it holds credentials, so `JSON.stringify`, `console.error`
|
|
115
|
+
* and error trackers leave it out. Read it directly when you need it.
|
|
116
|
+
*/
|
|
28
117
|
readonly request: RequestContext;
|
|
29
|
-
/** The
|
|
118
|
+
/** The failed Response, still readable — its body holds what arthron read (at most 64 KiB). Absent for network failures. Not enumerable. */
|
|
30
119
|
readonly response: Response | undefined;
|
|
31
120
|
/** The underlying error for network failures. */
|
|
32
121
|
readonly cause: unknown;
|
|
33
122
|
constructor(init: ArthronErrorInit);
|
|
123
|
+
/** `instanceof ArthronError` holds for an error from any copy of the package. */
|
|
124
|
+
static [Symbol.hasInstance](value: unknown): boolean;
|
|
125
|
+
/** What serializers see: no headers, no body, no query or userinfo. */
|
|
126
|
+
toJSON(): {
|
|
127
|
+
name: string;
|
|
128
|
+
message: string;
|
|
129
|
+
detail: string | undefined;
|
|
130
|
+
status: number;
|
|
131
|
+
statusText: string;
|
|
132
|
+
method: string;
|
|
133
|
+
url: string;
|
|
134
|
+
data: unknown;
|
|
135
|
+
};
|
|
34
136
|
}
|
|
35
137
|
/** `true` for errors arthron produced: a `!ok` response or a network failure. Cancellations and plugin bugs are not ArthronErrors. */
|
|
36
138
|
export declare function isArthronError(error: unknown): error is ArthronError;
|
|
37
139
|
//#endregion
|
|
38
|
-
//#region src/
|
|
39
|
-
/** One server-sent event, as described by the WHATWG EventSource spec. */
|
|
40
|
-
type SseEvent = {
|
|
41
|
-
/** The `event:` field, when the server sent one. */
|
|
42
|
-
event?: string;
|
|
43
|
-
/** All `data:` lines of the block, joined with `\n`. */
|
|
44
|
-
data: string;
|
|
45
|
-
/** The `id:` field, when present. */
|
|
46
|
-
id?: string;
|
|
47
|
-
/** The `retry:` field in ms, when present and numeric. */
|
|
48
|
-
retry?: number;
|
|
49
|
-
};
|
|
50
|
-
//#endregion
|
|
51
|
-
//#region src/url.d.ts
|
|
52
|
-
type QueryParams = Record<string, string | number | boolean | null | undefined>;
|
|
53
|
-
//#endregion
|
|
54
|
-
//#region src/types.d.ts
|
|
55
|
-
type RequestContext = {
|
|
56
|
-
url: string;
|
|
57
|
-
init: RequestInit;
|
|
58
|
-
};
|
|
140
|
+
//#region src/types/plugin.types.d.ts
|
|
59
141
|
/** Runs before each attempt. Returns the context to send (may be a new object). */
|
|
60
142
|
type RequestInterceptor = (ctx: RequestContext) => RequestContext | Promise<RequestContext>;
|
|
61
143
|
/** Runs after a successful attempt. The body is single-use — `clone()` to peek. */
|
|
@@ -69,67 +151,199 @@ type ErrorInterceptor = (err: ArthronError, ctx: RequestContext) => ArthronError
|
|
|
69
151
|
* failure was a cancellation or a bug in a plugin.
|
|
70
152
|
*/
|
|
71
153
|
type Middleware = (ctx: RequestContext, next: (ctx: RequestContext) => Promise<Response>) => Promise<Response>;
|
|
72
|
-
|
|
73
|
-
/**
|
|
154
|
+
interface Plugin {
|
|
155
|
+
/**
|
|
156
|
+
* Identity within a client: `use`/`extend` replace the plugin of the same
|
|
157
|
+
* name in place, `without(name)` removes it. The built-ins are named
|
|
158
|
+
* "retry", "timeout" and "logging". Leave it out to always append.
|
|
159
|
+
*/
|
|
74
160
|
name?: string;
|
|
75
161
|
middleware?: Middleware;
|
|
76
162
|
request?: RequestInterceptor;
|
|
77
163
|
response?: ResponseInterceptor;
|
|
78
164
|
error?: ErrorInterceptor;
|
|
165
|
+
}
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region src/types/response.types.d.ts
|
|
168
|
+
interface ArthronPromise extends Promise<Response> {
|
|
169
|
+
/** The body as JSON. `T` is a cast — nothing checks it. */
|
|
170
|
+
json<T = unknown>(): Promise<T>;
|
|
171
|
+
/**
|
|
172
|
+
* The body as JSON, validated by a Standard Schema (Zod, Valibot, ArkType…)
|
|
173
|
+
* and typed by it. A mismatch rejects with a `SchemaError`.
|
|
174
|
+
*/
|
|
175
|
+
json<S extends StandardSchemaV1>(schema: S): Promise<InferOutput<S>>;
|
|
176
|
+
text(): Promise<string>;
|
|
177
|
+
blob(): Promise<Blob>;
|
|
178
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
179
|
+
formData(): Promise<FormData>;
|
|
180
|
+
/** Iterate a `text/event-stream` body as events. */
|
|
181
|
+
sse(options?: SseOptions): AsyncIterable<SseEvent>;
|
|
182
|
+
/** Iterate a newline-delimited JSON body, one parsed value per line. */
|
|
183
|
+
ndjson<T = unknown>(options?: NdjsonOptions): AsyncIterable<T>;
|
|
184
|
+
}
|
|
185
|
+
/** One server-sent event, as described by the WHATWG EventSource spec. */
|
|
186
|
+
type SseEvent = {
|
|
187
|
+
/** The `event:` field, when the server sent one. */
|
|
188
|
+
event?: string;
|
|
189
|
+
/** All `data:` lines of the block, joined with `\n`. */
|
|
190
|
+
data: string;
|
|
191
|
+
/** The `id:` field of this event's own block, when it had one. */
|
|
192
|
+
id?: string;
|
|
193
|
+
/**
|
|
194
|
+
* The last event ID so far, as EventSource's `lastEventId`: it persists
|
|
195
|
+
* across events (a block with only `id:` updates it too) and is "" until
|
|
196
|
+
* the server sends one. Send it as `Last-Event-ID` to resume a stream.
|
|
197
|
+
*/
|
|
198
|
+
lastEventId: string;
|
|
199
|
+
/** The reconnection time in ms the server last set with `retry:`; carried on every event after it. */
|
|
200
|
+
retry?: number;
|
|
79
201
|
};
|
|
80
|
-
type
|
|
81
|
-
|
|
202
|
+
type NdjsonOptions = {
|
|
203
|
+
/**
|
|
204
|
+
* Longest line accepted, in characters. A longer one rejects the iteration
|
|
205
|
+
* with a RangeError and cancels the body. Default 8 Mi.
|
|
206
|
+
*/
|
|
207
|
+
maxLineLength?: number;
|
|
82
208
|
};
|
|
83
|
-
type
|
|
84
|
-
|
|
85
|
-
|
|
209
|
+
type SseOptions = NdjsonOptions & {
|
|
210
|
+
/**
|
|
211
|
+
* Most `data` one event may collect before its blank line, in characters.
|
|
212
|
+
* More rejects the iteration with a RangeError and cancels the body.
|
|
213
|
+
* Default 8 Mi.
|
|
214
|
+
*/
|
|
215
|
+
maxEventSize?: number;
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* The Standard Schema interface (https://standardschema.dev), vendored as
|
|
219
|
+
* types only so arthron keeps zero dependencies. Zod, Valibot, ArkType and
|
|
220
|
+
* others implement it, so their schemas can be passed to `.json(schema)`.
|
|
221
|
+
*/
|
|
222
|
+
interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
223
|
+
readonly "~standard": {
|
|
224
|
+
readonly version: 1;
|
|
225
|
+
readonly vendor: string;
|
|
226
|
+
readonly validate: (value: unknown) => SchemaResult<Output> | Promise<SchemaResult<Output>>;
|
|
227
|
+
readonly types?: {
|
|
228
|
+
readonly input: Input;
|
|
229
|
+
readonly output: Output;
|
|
230
|
+
} | undefined;
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
type SchemaResult<Output> = {
|
|
234
|
+
readonly value: Output;
|
|
235
|
+
readonly issues?: undefined;
|
|
236
|
+
} | {
|
|
237
|
+
readonly issues: readonly SchemaIssue[];
|
|
86
238
|
};
|
|
87
|
-
|
|
239
|
+
interface SchemaIssue {
|
|
240
|
+
readonly message: string;
|
|
241
|
+
readonly path?: readonly (PropertyKey | {
|
|
242
|
+
readonly key: PropertyKey;
|
|
243
|
+
})[] | undefined;
|
|
244
|
+
}
|
|
245
|
+
/** The type a schema produces. */
|
|
246
|
+
type InferOutput<S extends StandardSchemaV1> = NonNullable<S["~standard"]["types"]>["output"];
|
|
247
|
+
type ErrorDetailResolver = (data: unknown, response: Response) => string | undefined;
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region src/client/client.types.d.ts
|
|
250
|
+
/**
|
|
251
|
+
* The methods arthron knows by name; any other string is sent as written.
|
|
252
|
+
* The standard ones go out uppercased whatever their case — fetch itself
|
|
253
|
+
* only normalizes six of them, so a lowercase "patch" would draw a 405.
|
|
254
|
+
*/
|
|
255
|
+
type HttpMethod = "GET" | "HEAD" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "QUERY" | (string & {});
|
|
256
|
+
/**
|
|
257
|
+
* Per-call options. Public types are interfaces, so a plugin package can add
|
|
258
|
+
* its own options by augmentation (`declare module "arthron"`).
|
|
259
|
+
*/
|
|
260
|
+
interface RequestOptions extends Omit<RequestInit, "body" | "method" | "headers"> {
|
|
261
|
+
/** Per-call headers; a `null`/`undefined` value drops a client default. */
|
|
262
|
+
headers?: HeadersOption;
|
|
263
|
+
params?: QueryParams;
|
|
264
|
+
/**
|
|
265
|
+
* Values for `{name}` placeholders in the path, each encoded into its own
|
|
266
|
+
* segment: `get("/users/{id}", { path: { id } })`. Interpolating ids into
|
|
267
|
+
* the path string yourself lets "../" or "?" escape the segment.
|
|
268
|
+
*/
|
|
269
|
+
path?: Record<string, string | number>;
|
|
270
|
+
/** Settings for plugins on this call only (see `ArthronMeta`). Not sent. */
|
|
271
|
+
meta?: ArthronMeta;
|
|
272
|
+
/** Which non-ok responses reject on this call; overrides the client's `throwOn`. */
|
|
273
|
+
throwOn?: (res: Response) => boolean;
|
|
274
|
+
}
|
|
275
|
+
/** `request()`'s options: any method, with the same body rules as `post`. */
|
|
276
|
+
interface RequestInitWithBody extends RequestOptions {
|
|
277
|
+
method: HttpMethod;
|
|
278
|
+
body?: unknown;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* The fetch options a client can set as defaults: the same `RequestInit`
|
|
282
|
+
* fields per-call options take, minus what only makes sense per call —
|
|
283
|
+
* `body`, `method`, `signal` (one client-wide signal, once aborted, would
|
|
284
|
+
* fail every later call) and `window`. `headers` has its own merge rules.
|
|
285
|
+
*/
|
|
286
|
+
type FetchDefaults = Omit<RequestInit, "body" | "method" | "headers" | "signal" | "window">;
|
|
287
|
+
/**
|
|
288
|
+
* Client config. Besides arthron's own keys it takes any fetch option as a
|
|
289
|
+
* default (`credentials`, `cache`, `redirect`, `mode`, …), flat like per-call
|
|
290
|
+
* options; a per-call value wins.
|
|
291
|
+
*/
|
|
292
|
+
interface ArthronConfig extends FetchDefaults {
|
|
88
293
|
/** Prefix for relative paths. Without it only absolute URLs are accepted. */
|
|
89
294
|
baseURL?: string;
|
|
90
|
-
/**
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
295
|
+
/**
|
|
296
|
+
* Let an absolute URL on another origin than `baseURL` through. Off by
|
|
297
|
+
* default, so a path from user input or an API response cannot send the
|
|
298
|
+
* client's headers elsewhere; config `headers` are never sent to another
|
|
299
|
+
* origin even when this is on.
|
|
300
|
+
*/
|
|
301
|
+
allowAbsoluteUrls?: boolean;
|
|
302
|
+
/** Default headers. Per-call headers win, compared case-insensitively; `extend` can drop one with `null`. */
|
|
303
|
+
headers?: HeadersOption;
|
|
94
304
|
/** Injection point for tests and polyfills. Defaults to `globalThis.fetch`. */
|
|
95
305
|
fetch?: typeof fetch;
|
|
96
306
|
use?: Plugin[];
|
|
97
307
|
/** How to pick a message out of an error body. */
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
/** Iterate a newline-delimited JSON body, one parsed value per line. */
|
|
109
|
-
ndjson<T = unknown>(): AsyncIterable<T>;
|
|
110
|
-
};
|
|
111
|
-
type Arthron = {
|
|
308
|
+
errorDetail?: ErrorDetailResolver;
|
|
309
|
+
/**
|
|
310
|
+
* Which non-ok responses reject with an ArthronError — return `false` to
|
|
311
|
+
* get the Response instead (a 404 that is data, say). An ok response never
|
|
312
|
+
* rejects. Default: every non-ok response except an opaque one
|
|
313
|
+
* (`mode: "no-cors"`) and the 3xx of `redirect: "manual"`.
|
|
314
|
+
*/
|
|
315
|
+
throwOn?: (res: Response) => boolean;
|
|
316
|
+
}
|
|
317
|
+
interface Arthron {
|
|
112
318
|
get(path: string, init?: RequestOptions): ArthronPromise;
|
|
113
319
|
delete(path: string, init?: RequestOptions): ArthronPromise;
|
|
114
320
|
head(path: string, init?: RequestOptions): ArthronPromise;
|
|
115
321
|
post(path: string, body?: unknown, init?: RequestOptions): ArthronPromise;
|
|
116
322
|
put(path: string, body?: unknown, init?: RequestOptions): ArthronPromise;
|
|
117
323
|
patch(path: string, body?: unknown, init?: RequestOptions): ArthronPromise;
|
|
324
|
+
/** RFC 10008 QUERY: safe and idempotent like GET, but the query travels in the body. */
|
|
325
|
+
query(path: string, body?: unknown, init?: RequestOptions): ArthronPromise;
|
|
326
|
+
/** Any method — the extension point for verbs without their own helper. */
|
|
118
327
|
request(path: string, init: RequestInitWithBody): ArthronPromise;
|
|
119
|
-
/**
|
|
328
|
+
/**
|
|
329
|
+
* New client with these plugins added: a named one replaces the plugin of
|
|
330
|
+
* that name in place, an unnamed one appends. The receiver is untouched.
|
|
331
|
+
*/
|
|
120
332
|
use(...plugins: Plugin[]): Arthron;
|
|
121
|
-
/** New client with config shallow-merged, headers merged, plugins
|
|
333
|
+
/** New client with config shallow-merged, headers merged, plugins added as `use` adds them. */
|
|
122
334
|
extend(config: Partial<ArthronConfig>): Arthron;
|
|
123
|
-
|
|
335
|
+
/** New client without the plugins of these names. The receiver is untouched. */
|
|
336
|
+
without(...names: string[]): Arthron;
|
|
337
|
+
}
|
|
124
338
|
//#endregion
|
|
125
|
-
//#region src/client.d.ts
|
|
339
|
+
//#region src/client/client.d.ts
|
|
126
340
|
/**
|
|
127
341
|
* Build a client from config. The result is immutable — `use` and `extend`
|
|
128
342
|
* return new clients and never touch the one they were called on.
|
|
129
343
|
*/
|
|
130
344
|
export declare function arthron(config?: ArthronConfig): Arthron;
|
|
131
345
|
//#endregion
|
|
132
|
-
//#region src/define.d.ts
|
|
346
|
+
//#region src/pipeline/define-plugin.d.ts
|
|
133
347
|
/** Identity helper: gives a middleware written in its own file the right parameter types. */
|
|
134
348
|
export declare const defineMiddleware: (middleware: Middleware) => Middleware;
|
|
135
349
|
/** Identity helpers for each interceptor kind — `defineInterceptor.request(fn)` etc. */
|
|
@@ -141,7 +355,7 @@ export declare const defineInterceptor: {
|
|
|
141
355
|
/** Identity helper: type-checks a plugin object literal without an annotation. */
|
|
142
356
|
export declare const definePlugin: (plugin: Plugin) => Plugin;
|
|
143
357
|
//#endregion
|
|
144
|
-
//#region src/plugins/logging.d.ts
|
|
358
|
+
//#region src/plugins/logging/logging.types.d.ts
|
|
145
359
|
type LogEventBase = {
|
|
146
360
|
method: string;
|
|
147
361
|
path: string;
|
|
@@ -168,6 +382,8 @@ type LoggingOptions = {
|
|
|
168
382
|
/** Clock in ms. Injectable for tests. */
|
|
169
383
|
now?: () => number;
|
|
170
384
|
};
|
|
385
|
+
//#endregion
|
|
386
|
+
//#region src/plugins/logging/logging.d.ts
|
|
171
387
|
/**
|
|
172
388
|
* One event when a request starts, one when it settles, with status and
|
|
173
389
|
* elapsed time. Wraps the whole call, so retries are included in the time.
|
|
@@ -176,44 +392,53 @@ type LoggingOptions = {
|
|
|
176
392
|
*/
|
|
177
393
|
export declare function logging(options?: LoggingOptions): Plugin;
|
|
178
394
|
//#endregion
|
|
179
|
-
//#region src/plugins/retry.d.ts
|
|
180
|
-
type RetryOptions = {
|
|
181
|
-
/** Number of retries after the first attempt. Default 2 (3 requests total). */
|
|
182
|
-
retries?: number;
|
|
183
|
-
/** Statuses worth retrying. Network errors (status 0) always are. */
|
|
184
|
-
retryOn?: readonly number[];
|
|
185
|
-
/** Methods safe to repeat. Compared case-insensitively. */
|
|
186
|
-
methods?: readonly string[];
|
|
187
|
-
/** Backoff in ms for retry number `retry` (0-based). Default 300 · 2^retry. */
|
|
188
|
-
delay?: (retry: number, error: ArthronError) => number;
|
|
189
|
-
/** Injectable for tests. Default `setTimeout`; rejects with the abort reason. */
|
|
190
|
-
sleep?: (ms: number, signal?: AbortSignal | null) => Promise<void>;
|
|
191
|
-
/**
|
|
192
|
-
* Longest `Retry-After` (ms) worth honouring. Beyond it the request is not
|
|
193
|
-
* retried at all. Default 60 000. Also guards `setTimeout`'s 2^31-1 ms cap,
|
|
194
|
-
* past which timers fire immediately.
|
|
195
|
-
*/
|
|
196
|
-
maxRetryAfter?: number;
|
|
197
|
-
};
|
|
395
|
+
//#region src/plugins/retry/retry.d.ts
|
|
198
396
|
/**
|
|
199
397
|
* Retry on network errors and the configured statuses by calling `next`
|
|
200
398
|
* again — the whole attempt (request interceptors included) is re-run.
|
|
201
399
|
* Only `ArthronError` is considered; cancellation and plugin bugs pass through.
|
|
400
|
+
* A call can turn it off or override its options with `meta.retry`.
|
|
202
401
|
*/
|
|
203
402
|
export declare function retry(options?: RetryOptions): Plugin;
|
|
204
403
|
//#endregion
|
|
205
|
-
//#region src/plugins/timeout.d.ts
|
|
404
|
+
//#region src/plugins/timeout/timeout.types.d.ts
|
|
405
|
+
type TimeoutOptions = {
|
|
406
|
+
/**
|
|
407
|
+
* Also abort when no data has arrived for this many ms — while waiting for
|
|
408
|
+
* the headers and between body chunks. Unlike the total deadline, a stream
|
|
409
|
+
* that keeps flowing is never cut off: `timeout(Infinity, { idle: 30_000 })`.
|
|
410
|
+
*/
|
|
411
|
+
idle?: number;
|
|
412
|
+
};
|
|
413
|
+
//#endregion
|
|
414
|
+
//#region src/plugins/timeout/timeout.d.ts
|
|
206
415
|
/**
|
|
207
416
|
* Abort the request when it takes longer than `ms` — counted from the start
|
|
208
417
|
* of the attempt until the body has been fully read, so a server that sends
|
|
209
|
-
* headers and then stalls still trips it.
|
|
418
|
+
* headers and then stalls still trips it. With `idle`, also abort once no
|
|
419
|
+
* data has arrived for that long. Rejects with a `TimeoutError` (a
|
|
210
420
|
* `DOMException`, like `AbortSignal.timeout()` would give); it is not an
|
|
211
421
|
* `ArthronError`, so error interceptors and `retry` leave it alone.
|
|
212
422
|
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
423
|
+
* A call can change the total deadline with `meta.timeout`.
|
|
424
|
+
*
|
|
425
|
+
* Deadlines are timers on an AbortController — not `AbortSignal.timeout`,
|
|
426
|
+
* since the idle one restarts — joined to the caller's signal with
|
|
427
|
+
* `AbortSignal.any`.
|
|
215
428
|
*/
|
|
216
|
-
export declare function timeout(ms: number): Plugin;
|
|
429
|
+
export declare function timeout(ms: number, options?: TimeoutOptions): Plugin;
|
|
430
|
+
//#endregion
|
|
431
|
+
//#region src/response/schema-validation.d.ts
|
|
432
|
+
/**
|
|
433
|
+
* `.json(schema)` got a body that does not match. Not an ArthronError: the
|
|
434
|
+
* request succeeded — the data is what is wrong.
|
|
435
|
+
*/
|
|
436
|
+
export declare class SchemaError extends Error {
|
|
437
|
+
readonly name = "SchemaError";
|
|
438
|
+
/** Every problem the validator reported, with the path to it. */
|
|
439
|
+
readonly issues: readonly SchemaIssue[];
|
|
440
|
+
constructor(issues: readonly SchemaIssue[]);
|
|
441
|
+
}
|
|
217
442
|
//#endregion
|
|
218
|
-
export type { Arthron, ArthronConfig, ArthronPromise, ErrorInterceptor,
|
|
443
|
+
export type { Arthron, ArthronConfig, ArthronMeta, ArthronPromise, ErrorDetailResolver, ErrorInterceptor, HeadersOption, HttpMethod, InferOutput, LogEvent, LoggingOptions, Middleware, NdjsonOptions, Plugin, QueryParams, RequestContext, RequestInitWithBody, RequestInterceptor, RequestOptions, ResponseInterceptor, RetryOptions, SchemaIssue, SseEvent, SseOptions, StandardSchemaV1, TimeoutOptions };
|
|
219
444
|
//# sourceMappingURL=index.d.mts.map
|