@nxgt/httpyz 0.3.0 → 0.3.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/dist/chunks/index-52w12dh5.js +1051 -0
- package/dist/chunks/index-52w12dh5.js.map +25 -0
- package/dist/index.js +21 -1056
- package/dist/index.js.map +3 -19
- package/dist/integration/index.js +17 -1054
- package/dist/integration/index.js.map +3 -19
- package/package.json +1 -1
|
@@ -1,1058 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (!signal)
|
|
11
|
-
return promise;
|
|
12
|
-
if (signal.aborted)
|
|
13
|
-
return Promise.reject(signal.reason);
|
|
14
|
-
return new Promise((resolve, reject) => {
|
|
15
|
-
const stop = () => reject(signal.reason);
|
|
16
|
-
signal.addEventListener("abort", stop, { once: true });
|
|
17
|
-
promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", stop));
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
function joinSignals(...signals) {
|
|
21
|
-
const present = signals.filter((signal) => signal != null);
|
|
22
|
-
return present.length > 1 ? AbortSignal.any(present) : present[0];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// src/cancel/latest.ts
|
|
26
|
-
function createLatest() {
|
|
27
|
-
const running = new Map;
|
|
28
|
-
return (key) => {
|
|
29
|
-
running.get(key)?.abort(cancelled(`A later call with latest: '${key}' replaced this one`));
|
|
30
|
-
const controller = new AbortController;
|
|
31
|
-
running.set(key, controller);
|
|
32
|
-
return controller.signal;
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// src/errors/errors.ts
|
|
37
|
-
class ClientError extends Error {
|
|
38
|
-
constructor(context, message, options) {
|
|
39
|
-
const route = `${context.method.toUpperCase()} ${context.path}`;
|
|
40
|
-
const call = context.operationId === undefined ? route : `${context.operationId} (${route})`;
|
|
41
|
-
super(`${call}: ${message}`, options);
|
|
42
|
-
this.name = "ClientError";
|
|
43
|
-
this.operationId = context.operationId;
|
|
44
|
-
this.method = context.method;
|
|
45
|
-
this.path = context.path;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
class NetworkError extends ClientError {
|
|
50
|
-
constructor(context, options) {
|
|
51
|
-
super(context, "no reply came back", options);
|
|
52
|
-
this.name = "NetworkError";
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
class TimeoutError extends ClientError {
|
|
57
|
-
constructor(context, timeout, options) {
|
|
58
|
-
super(context, `no reply within ${timeout} ms`, options);
|
|
59
|
-
this.name = "TimeoutError";
|
|
60
|
-
this.timeout = timeout;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
class UndeclaredStatusError extends ClientError {
|
|
65
|
-
constructor(context, response) {
|
|
66
|
-
super(context, `no ${response.status} reply is declared`);
|
|
67
|
-
this.name = "UndeclaredStatusError";
|
|
68
|
-
this.status = response.status;
|
|
69
|
-
this.response = response;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
class ValidationError extends ClientError {
|
|
74
|
-
constructor(context, failure) {
|
|
75
|
-
super(context, failure.issues.map((issue) => issue.message).join("; "));
|
|
76
|
-
this.name = "ValidationError";
|
|
77
|
-
this.failure = failure;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
class ReplyStatusError extends Error {
|
|
82
|
-
constructor(reply, expected) {
|
|
83
|
-
const wanted = expected.length > 0 ? expected.join(" or ") : "2xx";
|
|
84
|
-
super(`Expected a ${wanted} reply, got ${reply.status}`);
|
|
85
|
-
this.name = "ReplyStatusError";
|
|
86
|
-
this.status = reply.status;
|
|
87
|
-
this.data = reply.data;
|
|
88
|
-
this.response = reply.response;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// src/middleware/auth.ts
|
|
93
|
-
function auth({
|
|
94
|
-
token,
|
|
95
|
-
refresh,
|
|
96
|
-
scheme = "Bearer"
|
|
97
|
-
}) {
|
|
98
|
-
let refreshing;
|
|
99
|
-
const sign = (request, value) => {
|
|
100
|
-
if (value)
|
|
101
|
-
request.headers.set("authorization", `${scheme} ${value}`);
|
|
102
|
-
return request;
|
|
103
|
-
};
|
|
104
|
-
return async (request, next) => {
|
|
105
|
-
const used = await token();
|
|
106
|
-
const replay = refresh ? request.clone() : undefined;
|
|
107
|
-
const response = await next(sign(request, used));
|
|
108
|
-
if (response.status !== 401 || !replay || !refresh)
|
|
109
|
-
return response;
|
|
110
|
-
try {
|
|
111
|
-
if (await token() === used) {
|
|
112
|
-
refreshing ??= Promise.resolve().then(refresh).finally(() => {
|
|
113
|
-
refreshing = undefined;
|
|
114
|
-
});
|
|
115
|
-
await abortable(refreshing, request.signal);
|
|
116
|
-
}
|
|
117
|
-
} catch (error) {
|
|
118
|
-
if (request.signal.aborted) {
|
|
119
|
-
await response.body?.cancel();
|
|
120
|
-
throw error;
|
|
121
|
-
}
|
|
122
|
-
return response;
|
|
123
|
-
}
|
|
124
|
-
const fresh = await token();
|
|
125
|
-
if (!fresh || fresh === used)
|
|
126
|
-
return response;
|
|
127
|
-
await response.body?.cancel();
|
|
128
|
-
return next(sign(replay, fresh));
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// src/middleware/compose.ts
|
|
133
|
-
var compose = (middlewares, send, call) => middlewares.reduceRight((next, middleware) => (request) => middleware(request, next, call), send);
|
|
134
|
-
|
|
135
|
-
// src/middleware/retry.ts
|
|
136
|
-
var REPEATABLE = [
|
|
137
|
-
"get",
|
|
138
|
-
"head",
|
|
139
|
-
"options",
|
|
140
|
-
"put",
|
|
141
|
-
"delete",
|
|
142
|
-
"trace",
|
|
143
|
-
"query"
|
|
144
|
-
];
|
|
145
|
-
var TRANSIENT = [408, 429, 502, 503, 504];
|
|
146
|
-
var backoff = (attempt) => Math.random() * 300 * 2 ** (attempt - 1);
|
|
147
|
-
function retrySettings(retry) {
|
|
148
|
-
if (retry === undefined || retry === false)
|
|
149
|
-
return;
|
|
150
|
-
const options = typeof retry === "number" ? { attempts: retry } : retry;
|
|
151
|
-
const attempts = options.attempts ?? 2;
|
|
152
|
-
if (attempts <= 0)
|
|
153
|
-
return;
|
|
154
|
-
return {
|
|
155
|
-
attempts,
|
|
156
|
-
methods: options.methods ?? REPEATABLE,
|
|
157
|
-
statuses: options.statuses ?? TRANSIENT,
|
|
158
|
-
delay: options.delay ?? backoff,
|
|
159
|
-
maxDelay: options.maxDelay ?? 1e4
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
function retryDelay(response, attempt, settings) {
|
|
163
|
-
const header = response?.headers.get("retry-after")?.trim();
|
|
164
|
-
if (header) {
|
|
165
|
-
const wait = /^\d+(?:\.\d+)?$/.test(header) ? Number(header) * 1000 : Date.parse(header) - Date.now();
|
|
166
|
-
if (!Number.isNaN(wait)) {
|
|
167
|
-
return wait > settings.maxDelay ? undefined : Math.max(0, wait);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return Math.min(Math.max(0, settings.delay(attempt)), settings.maxDelay);
|
|
171
|
-
}
|
|
172
|
-
var sleep = (ms, signal) => new Promise((resolve, reject) => {
|
|
173
|
-
if (signal.aborted)
|
|
174
|
-
return reject(signal.reason);
|
|
175
|
-
const stop = () => {
|
|
176
|
-
clearTimeout(timer);
|
|
177
|
-
reject(signal.reason);
|
|
178
|
-
};
|
|
179
|
-
const timer = setTimeout(() => {
|
|
180
|
-
signal.removeEventListener("abort", stop);
|
|
181
|
-
resolve();
|
|
182
|
-
}, ms);
|
|
183
|
-
signal.addEventListener("abort", stop, { once: true });
|
|
184
|
-
});
|
|
185
|
-
function retrying(settings) {
|
|
186
|
-
return async (request, next) => {
|
|
187
|
-
const method = request.method.toLowerCase();
|
|
188
|
-
if (!settings.methods.includes(method))
|
|
189
|
-
return next(request);
|
|
190
|
-
for (let attempt = 1;; attempt++) {
|
|
191
|
-
const last = attempt > settings.attempts;
|
|
192
|
-
const sent = last ? request : request.clone();
|
|
193
|
-
let wait;
|
|
194
|
-
try {
|
|
195
|
-
const response = await next(sent);
|
|
196
|
-
if (last || !settings.statuses.includes(response.status)) {
|
|
197
|
-
return response;
|
|
198
|
-
}
|
|
199
|
-
wait = retryDelay(response, attempt, settings);
|
|
200
|
-
if (wait === undefined)
|
|
201
|
-
return response;
|
|
202
|
-
await response.body?.cancel();
|
|
203
|
-
} catch (error) {
|
|
204
|
-
if (last || !(error instanceof NetworkError))
|
|
205
|
-
throw error;
|
|
206
|
-
wait = retryDelay(undefined, attempt, settings) ?? 0;
|
|
207
|
-
}
|
|
208
|
-
await sleep(wait, request.signal);
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// src/schema/standard-schema.ts
|
|
214
|
-
async function check(schema, value, target) {
|
|
215
|
-
const result = await schema["~standard"].validate(value);
|
|
216
|
-
if (result.issues === undefined)
|
|
217
|
-
return { ok: true, value: result.value };
|
|
218
|
-
return {
|
|
219
|
-
ok: false,
|
|
220
|
-
issues: result.issues.map((issue) => {
|
|
221
|
-
const { code } = issue;
|
|
222
|
-
return {
|
|
223
|
-
target,
|
|
224
|
-
path: (issue.path ?? []).map((key) => typeof key === "object" ? key.key : key).filter((key) => typeof key !== "symbol"),
|
|
225
|
-
code: typeof code === "string" ? code : "custom",
|
|
226
|
-
message: issue.message
|
|
227
|
-
};
|
|
228
|
-
})
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// src/reply/media-type.ts
|
|
233
|
-
var mediaType = (header) => (header.split(";")[0] ?? "").trim().toLowerCase();
|
|
234
|
-
function mediaKind(type) {
|
|
235
|
-
if (type === "application/json" || /^application\/[\w.-]+\+json$/.test(type)) {
|
|
236
|
-
return "json";
|
|
237
|
-
}
|
|
238
|
-
if (type === "application/x-www-form-urlencoded" || type === "multipart/form-data") {
|
|
239
|
-
return "form";
|
|
240
|
-
}
|
|
241
|
-
return type.startsWith("text/") ? "text" : "binary";
|
|
242
|
-
}
|
|
243
|
-
function declaredType(content, type) {
|
|
244
|
-
const types = Object.keys(content);
|
|
245
|
-
const exact = types.find((key) => key.toLowerCase() === type);
|
|
246
|
-
if (exact !== undefined)
|
|
247
|
-
return exact;
|
|
248
|
-
const range = `${type.split("/")[0]}/*`;
|
|
249
|
-
if (content[range])
|
|
250
|
-
return range;
|
|
251
|
-
if (content["*/*"])
|
|
252
|
-
return "*/*";
|
|
253
|
-
const kind = mediaKind(type);
|
|
254
|
-
if (kind !== "json" && kind !== "text")
|
|
255
|
-
return;
|
|
256
|
-
return types.find((key) => content[key]?.kind === kind);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// src/reply/read-reply.ts
|
|
260
|
-
var isSchema = (value) => typeof value === "object" && value !== null && ("~standard" in value);
|
|
261
|
-
function toSpec(responses) {
|
|
262
|
-
const spec = {};
|
|
263
|
-
for (const [status, declared] of Object.entries(responses)) {
|
|
264
|
-
const content = {};
|
|
265
|
-
if (isSchema(declared)) {
|
|
266
|
-
content["application/json"] = { kind: "json", schema: declared };
|
|
267
|
-
} else if (declared !== null) {
|
|
268
|
-
for (const [type, schema] of Object.entries(declared)) {
|
|
269
|
-
content[type] = {
|
|
270
|
-
kind: mediaKind(type.toLowerCase()),
|
|
271
|
-
...schema === null ? {} : { schema }
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
spec[Number(status)] = content;
|
|
276
|
-
}
|
|
277
|
-
return spec;
|
|
278
|
-
}
|
|
279
|
-
async function readReply(context, spec, response, settings) {
|
|
280
|
-
const { status } = response;
|
|
281
|
-
const header = response.headers.get("content-type");
|
|
282
|
-
const refused = (issues) => new ValidationError(context, {
|
|
283
|
-
kind: "response",
|
|
284
|
-
...context,
|
|
285
|
-
status,
|
|
286
|
-
issues
|
|
287
|
-
});
|
|
288
|
-
const failure = (code, message) => refused([{ target: "response", path: [], code, message }]);
|
|
289
|
-
const parse = (text) => {
|
|
290
|
-
try {
|
|
291
|
-
return JSON.parse(text);
|
|
292
|
-
} catch {
|
|
293
|
-
throw failure("invalid_json", `the ${status} reply is not valid JSON`);
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
if (!spec) {
|
|
297
|
-
const type = header === null ? undefined : mediaType(header);
|
|
298
|
-
const reply = (data) => ({ status, type, data, response });
|
|
299
|
-
if (response.body === null)
|
|
300
|
-
return reply(undefined);
|
|
301
|
-
switch (type === undefined ? undefined : mediaKind(type)) {
|
|
302
|
-
case "json": {
|
|
303
|
-
const text = await response.text();
|
|
304
|
-
return reply(text === "" ? undefined : parse(text));
|
|
305
|
-
}
|
|
306
|
-
case "form":
|
|
307
|
-
return reply(await response.formData());
|
|
308
|
-
case "binary":
|
|
309
|
-
return reply(await response.blob());
|
|
310
|
-
default: {
|
|
311
|
-
const text = await response.text();
|
|
312
|
-
return reply(type === undefined && text === "" ? undefined : text);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
const declared = spec[status];
|
|
317
|
-
if (!declared)
|
|
318
|
-
throw new UndeclaredStatusError(context, response);
|
|
319
|
-
const types = Object.keys(declared);
|
|
320
|
-
if (types.length === 0) {
|
|
321
|
-
return { status, type: undefined, data: undefined, response };
|
|
322
|
-
}
|
|
323
|
-
const type = header === null ? types.length === 1 ? types[0] : undefined : declaredType(declared, mediaType(header));
|
|
324
|
-
const media = type === undefined ? undefined : declared[type];
|
|
325
|
-
if (type === undefined || media === undefined) {
|
|
326
|
-
throw failure("invalid_content_type", `a ${status} reply is ${types.join(" or ")}, not ${header ?? "untyped"}`);
|
|
327
|
-
}
|
|
328
|
-
const reply = (data) => ({ status, type, data, response });
|
|
329
|
-
const settle = async (data) => {
|
|
330
|
-
if (!settings.validate || !media.schema)
|
|
331
|
-
return reply(data);
|
|
332
|
-
const result = await check(media.schema, data, "response");
|
|
333
|
-
if (!result.ok)
|
|
334
|
-
throw refused(result.issues);
|
|
335
|
-
return reply(settings.decode ? result.value : data);
|
|
336
|
-
};
|
|
337
|
-
switch (media.kind) {
|
|
338
|
-
case "json": {
|
|
339
|
-
const text = await response.text();
|
|
340
|
-
if (text === "" && !(settings.validate && media.schema)) {
|
|
341
|
-
return reply(undefined);
|
|
342
|
-
}
|
|
343
|
-
return settle(parse(text));
|
|
344
|
-
}
|
|
345
|
-
case "text":
|
|
346
|
-
return settle(await response.text());
|
|
347
|
-
case "form":
|
|
348
|
-
return reply(await response.formData());
|
|
349
|
-
default:
|
|
350
|
-
return reply(await response.blob());
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// src/request/encode.ts
|
|
355
|
-
var text = (value) => value instanceof Date ? value.toISOString() : String(value);
|
|
356
|
-
var absent = (value) => value === undefined || value === null;
|
|
357
|
-
function fillPath(context, param) {
|
|
358
|
-
return context.path.replace(/\{([^}]+)\}/g, (_, name) => {
|
|
359
|
-
const value = param?.[name];
|
|
360
|
-
if (absent(value)) {
|
|
361
|
-
throw new TypeError(`${context.method.toUpperCase()} ${context.path}: the path parameter ${name} is missing`);
|
|
362
|
-
}
|
|
363
|
-
return encodeURIComponent(text(value));
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
function writeQuery(query) {
|
|
367
|
-
if (query === undefined)
|
|
368
|
-
return "";
|
|
369
|
-
if (query instanceof URLSearchParams)
|
|
370
|
-
return query.toString();
|
|
371
|
-
const search = new URLSearchParams;
|
|
372
|
-
for (const [name, value] of Object.entries(query)) {
|
|
373
|
-
for (const item of Array.isArray(value) ? value : [value]) {
|
|
374
|
-
if (!absent(item))
|
|
375
|
-
search.append(name, text(item));
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
return search.toString();
|
|
379
|
-
}
|
|
380
|
-
function joinUrl(baseUrl, path, query) {
|
|
381
|
-
const root = baseUrl === undefined ? "" : String(baseUrl).replace(/\/+$/, "");
|
|
382
|
-
return `${root}${path}${query === "" ? "" : `?${query}`}`;
|
|
383
|
-
}
|
|
384
|
-
function writeBody(input, headers, own) {
|
|
385
|
-
const type = (fallback) => headers.set("content-type", own ?? fallback);
|
|
386
|
-
if (input.json !== undefined) {
|
|
387
|
-
type("application/json");
|
|
388
|
-
return JSON.stringify(input.json);
|
|
389
|
-
}
|
|
390
|
-
if (input.form !== undefined) {
|
|
391
|
-
headers.delete("content-type");
|
|
392
|
-
const { form } = input;
|
|
393
|
-
if (form instanceof FormData || form instanceof URLSearchParams) {
|
|
394
|
-
return form;
|
|
395
|
-
}
|
|
396
|
-
return [...fields(form)].some(([, value]) => value instanceof Blob) ? toFormData(form) : toSearchParams(form);
|
|
397
|
-
}
|
|
398
|
-
if (input.text !== undefined) {
|
|
399
|
-
type("text/plain");
|
|
400
|
-
return input.text;
|
|
401
|
-
}
|
|
402
|
-
if (input.body !== undefined) {
|
|
403
|
-
const { body } = input;
|
|
404
|
-
type(body instanceof Blob && body.type !== "" ? body.type : "application/octet-stream");
|
|
405
|
-
return body;
|
|
406
|
-
}
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
function* fields(form) {
|
|
410
|
-
for (const [name, value] of Object.entries(form)) {
|
|
411
|
-
for (const item of Array.isArray(value) ? value : [value]) {
|
|
412
|
-
if (absent(item))
|
|
413
|
-
continue;
|
|
414
|
-
if (item instanceof Blob)
|
|
415
|
-
yield [name, item];
|
|
416
|
-
else if (typeof item === "object" && !(item instanceof Date)) {
|
|
417
|
-
yield [name, JSON.stringify(item)];
|
|
418
|
-
} else
|
|
419
|
-
yield [name, text(item)];
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
function toFormData(form) {
|
|
424
|
-
const data = new FormData;
|
|
425
|
-
for (const [name, value] of fields(form))
|
|
426
|
-
data.append(name, value);
|
|
427
|
-
return data;
|
|
428
|
-
}
|
|
429
|
-
function toSearchParams(form) {
|
|
430
|
-
const data = new URLSearchParams;
|
|
431
|
-
for (const [name, value] of fields(form)) {
|
|
432
|
-
if (value instanceof Blob) {
|
|
433
|
-
throw new TypeError(`${name} is a file: an application/x-www-form-urlencoded body cannot carry one`);
|
|
434
|
-
}
|
|
435
|
-
data.append(name, value);
|
|
436
|
-
}
|
|
437
|
-
return data;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// src/stream/connection.ts
|
|
441
|
-
var failure = (context, status, issues) => new ValidationError(context, {
|
|
442
|
-
kind: "response",
|
|
443
|
-
...context,
|
|
444
|
-
status,
|
|
445
|
-
issues
|
|
446
|
-
});
|
|
447
|
-
async function opened(settings, response, types) {
|
|
448
|
-
const { status } = response;
|
|
449
|
-
if (status === 204) {
|
|
450
|
-
await response.body?.cancel();
|
|
451
|
-
return false;
|
|
452
|
-
}
|
|
453
|
-
if (!response.ok)
|
|
454
|
-
throw new UndeclaredStatusError(settings.context, response);
|
|
455
|
-
const header = response.headers.get("content-type");
|
|
456
|
-
if (header === null || !types.includes(mediaType(header)) || !response.body) {
|
|
457
|
-
await response.body?.cancel();
|
|
458
|
-
throw failure(settings.context, status, [
|
|
459
|
-
{
|
|
460
|
-
target: "response",
|
|
461
|
-
path: [],
|
|
462
|
-
code: "invalid_content_type",
|
|
463
|
-
message: `a ${status} reply is ${types.join(" or ")}, not ${header ?? "untyped"}`
|
|
464
|
-
}
|
|
465
|
-
]);
|
|
466
|
-
}
|
|
467
|
-
return true;
|
|
468
|
-
}
|
|
469
|
-
async function settle(settings, status, text, schema, what) {
|
|
470
|
-
let value;
|
|
471
|
-
try {
|
|
472
|
-
value = JSON.parse(text);
|
|
473
|
-
} catch {
|
|
474
|
-
throw failure(settings.context, status, [
|
|
475
|
-
{
|
|
476
|
-
target: "response",
|
|
477
|
-
path: [],
|
|
478
|
-
code: "invalid_json",
|
|
479
|
-
message: `${what} is not valid JSON`
|
|
480
|
-
}
|
|
481
|
-
]);
|
|
482
|
-
}
|
|
483
|
-
if (!schema || !settings.validate)
|
|
484
|
-
return value;
|
|
485
|
-
const result = await check(schema, value, "response");
|
|
486
|
-
if (!result.ok)
|
|
487
|
-
throw failure(settings.context, status, result.issues);
|
|
488
|
-
return settings.decode ? result.value : value;
|
|
489
|
-
}
|
|
490
|
-
function pause(ms, ...signals) {
|
|
491
|
-
const live = signals.filter((each) => !!each);
|
|
492
|
-
return new Promise((resolve) => {
|
|
493
|
-
const done = () => {
|
|
494
|
-
clearTimeout(timer);
|
|
495
|
-
for (const each of live)
|
|
496
|
-
each.removeEventListener("abort", done);
|
|
497
|
-
resolve();
|
|
498
|
-
};
|
|
499
|
-
const timer = setTimeout(done, ms);
|
|
500
|
-
for (const each of live) {
|
|
501
|
-
if (each.aborted)
|
|
502
|
-
return done();
|
|
503
|
-
each.addEventListener("abort", done, { once: true });
|
|
504
|
-
}
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
class Reading {
|
|
509
|
-
#reader;
|
|
510
|
-
#signal;
|
|
511
|
-
#halt;
|
|
512
|
-
constructor(signal) {
|
|
513
|
-
this.closer = new AbortController;
|
|
514
|
-
this.#halt = () => {
|
|
515
|
-
this.#reader?.cancel().catch(() => {});
|
|
516
|
-
};
|
|
517
|
-
this.#signal = signal;
|
|
518
|
-
this.closer.signal.addEventListener("abort", this.#halt);
|
|
519
|
-
signal?.addEventListener("abort", this.#halt);
|
|
520
|
-
}
|
|
521
|
-
read(response) {
|
|
522
|
-
const body = response.body;
|
|
523
|
-
this.#reader = body.pipeThrough(new TextDecoderStream).getReader();
|
|
524
|
-
return this.#reader;
|
|
525
|
-
}
|
|
526
|
-
stopped() {
|
|
527
|
-
this.#signal?.throwIfAborted();
|
|
528
|
-
return this.closer.signal.aborted;
|
|
529
|
-
}
|
|
530
|
-
release() {
|
|
531
|
-
this.#reader?.cancel().catch(() => {});
|
|
532
|
-
this.#reader = undefined;
|
|
533
|
-
this.#signal?.removeEventListener("abort", this.#halt);
|
|
534
|
-
}
|
|
535
|
-
close() {
|
|
536
|
-
this.closer.abort();
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
// src/stream/sse-parser.ts
|
|
541
|
-
var LINE_END = /\r\n|\r|\n/g;
|
|
542
|
-
function createSseParser(lastEventId) {
|
|
543
|
-
let buffer = "";
|
|
544
|
-
let started = false;
|
|
545
|
-
let afterCr = false;
|
|
546
|
-
let data = "";
|
|
547
|
-
let type = "";
|
|
548
|
-
let id = lastEventId ?? "";
|
|
549
|
-
let dispatchedId = lastEventId;
|
|
550
|
-
let retry;
|
|
551
|
-
const dispatch = (events) => {
|
|
552
|
-
dispatchedId = id === "" ? undefined : id;
|
|
553
|
-
if (data === "") {
|
|
554
|
-
type = "";
|
|
555
|
-
return;
|
|
556
|
-
}
|
|
557
|
-
events.push({
|
|
558
|
-
event: type === "" ? "message" : type,
|
|
559
|
-
data: data.endsWith(`
|
|
560
|
-
`) ? data.slice(0, -1) : data,
|
|
561
|
-
id: dispatchedId
|
|
562
|
-
});
|
|
563
|
-
data = "";
|
|
564
|
-
type = "";
|
|
565
|
-
};
|
|
566
|
-
const line = (text, events) => {
|
|
567
|
-
if (text === "")
|
|
568
|
-
return dispatch(events);
|
|
569
|
-
if (text.startsWith(":"))
|
|
570
|
-
return;
|
|
571
|
-
const colon = text.indexOf(":");
|
|
572
|
-
const field = colon === -1 ? text : text.slice(0, colon);
|
|
573
|
-
let value = colon === -1 ? "" : text.slice(colon + 1);
|
|
574
|
-
if (value.startsWith(" "))
|
|
575
|
-
value = value.slice(1);
|
|
576
|
-
switch (field) {
|
|
577
|
-
case "event":
|
|
578
|
-
type = value;
|
|
579
|
-
break;
|
|
580
|
-
case "data":
|
|
581
|
-
data += `${value}
|
|
582
|
-
`;
|
|
583
|
-
break;
|
|
584
|
-
case "id":
|
|
585
|
-
if (!value.includes("\x00"))
|
|
586
|
-
id = value;
|
|
587
|
-
break;
|
|
588
|
-
case "retry":
|
|
589
|
-
if (/^\d+$/.test(value))
|
|
590
|
-
retry = Number(value);
|
|
591
|
-
break;
|
|
592
|
-
}
|
|
593
|
-
};
|
|
594
|
-
return {
|
|
595
|
-
push(chunk) {
|
|
596
|
-
let text = chunk;
|
|
597
|
-
if (!started && text !== "") {
|
|
598
|
-
started = true;
|
|
599
|
-
if (text.startsWith("\uFEFF"))
|
|
600
|
-
text = text.slice(1);
|
|
601
|
-
}
|
|
602
|
-
if (afterCr && text !== "") {
|
|
603
|
-
afterCr = false;
|
|
604
|
-
if (text.startsWith(`
|
|
605
|
-
`))
|
|
606
|
-
text = text.slice(1);
|
|
607
|
-
}
|
|
608
|
-
buffer += text;
|
|
609
|
-
const events = [];
|
|
610
|
-
let start = 0;
|
|
611
|
-
LINE_END.lastIndex = 0;
|
|
612
|
-
for (let end = LINE_END.exec(buffer);end !== null; end = LINE_END.exec(buffer)) {
|
|
613
|
-
if (end[0] === "\r" && end.index === buffer.length - 1) {
|
|
614
|
-
afterCr = true;
|
|
615
|
-
}
|
|
616
|
-
line(buffer.slice(start, end.index), events);
|
|
617
|
-
start = end.index + end[0].length;
|
|
618
|
-
}
|
|
619
|
-
buffer = buffer.slice(start);
|
|
620
|
-
return events;
|
|
621
|
-
},
|
|
622
|
-
get retry() {
|
|
623
|
-
return retry;
|
|
624
|
-
},
|
|
625
|
-
get lastEventId() {
|
|
626
|
-
return dispatchedId;
|
|
627
|
-
}
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
// src/stream/event-stream.ts
|
|
632
|
-
function eventStream(settings) {
|
|
633
|
-
const reading = new Reading(settings.signal);
|
|
634
|
-
let lastEventId = settings.lastEventId;
|
|
635
|
-
let delay = settings.reconnect ? settings.reconnect.delay : 0;
|
|
636
|
-
let started = false;
|
|
637
|
-
const declared = async (raw, status) => {
|
|
638
|
-
const { events } = settings;
|
|
639
|
-
if (!events)
|
|
640
|
-
return raw;
|
|
641
|
-
if (!Object.hasOwn(events, raw.event)) {
|
|
642
|
-
settings.onUnknownEvent?.(raw);
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
|
-
const schema = events[raw.event];
|
|
646
|
-
if (!schema)
|
|
647
|
-
return raw;
|
|
648
|
-
const what = `the ${raw.event} event's data`;
|
|
649
|
-
const data = await settle(settings, status, raw.data, schema, what);
|
|
650
|
-
return { event: raw.event, data, id: raw.id };
|
|
651
|
-
};
|
|
652
|
-
const again = async (failures) => {
|
|
653
|
-
const { reconnect } = settings;
|
|
654
|
-
if (!reconnect || failures >= reconnect.attempts)
|
|
655
|
-
return false;
|
|
656
|
-
await pause(delay, reading.closer.signal, settings.signal);
|
|
657
|
-
return !reading.stopped();
|
|
658
|
-
};
|
|
659
|
-
async function* run() {
|
|
660
|
-
let failures = 0;
|
|
661
|
-
try {
|
|
662
|
-
for (;; ) {
|
|
663
|
-
let response;
|
|
664
|
-
try {
|
|
665
|
-
response = await settings.open(reading.closer.signal, lastEventId);
|
|
666
|
-
} catch (error) {
|
|
667
|
-
if (reading.closer.signal.aborted)
|
|
668
|
-
return;
|
|
669
|
-
if (error instanceof NetworkError && await again(failures++)) {
|
|
670
|
-
continue;
|
|
671
|
-
}
|
|
672
|
-
throw error;
|
|
673
|
-
}
|
|
674
|
-
if (!await opened(settings, response, ["text/event-stream"])) {
|
|
675
|
-
return;
|
|
676
|
-
}
|
|
677
|
-
const parser = createSseParser(lastEventId);
|
|
678
|
-
const reader = reading.read(response);
|
|
679
|
-
let dropped;
|
|
680
|
-
for (;; ) {
|
|
681
|
-
let chunk;
|
|
682
|
-
try {
|
|
683
|
-
chunk = await reader.read();
|
|
684
|
-
} catch (error) {
|
|
685
|
-
if (reading.stopped())
|
|
686
|
-
return;
|
|
687
|
-
dropped = error;
|
|
688
|
-
break;
|
|
689
|
-
}
|
|
690
|
-
if (reading.stopped())
|
|
691
|
-
return;
|
|
692
|
-
if (chunk.done)
|
|
693
|
-
break;
|
|
694
|
-
const events = parser.push(chunk.value);
|
|
695
|
-
lastEventId = parser.lastEventId;
|
|
696
|
-
delay = parser.retry ?? delay;
|
|
697
|
-
for (const raw of events) {
|
|
698
|
-
failures = 0;
|
|
699
|
-
const event = await declared(raw, response.status);
|
|
700
|
-
if (event !== undefined)
|
|
701
|
-
yield event;
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
if (!await again(failures++)) {
|
|
705
|
-
if (dropped === undefined)
|
|
706
|
-
return;
|
|
707
|
-
throw new NetworkError(settings.context, { cause: dropped });
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
} finally {
|
|
711
|
-
reading.release();
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
return {
|
|
715
|
-
[Symbol.asyncIterator]() {
|
|
716
|
-
if (started)
|
|
717
|
-
throw new TypeError("A stream is read once");
|
|
718
|
-
started = true;
|
|
719
|
-
return run();
|
|
720
|
-
},
|
|
721
|
-
close: () => reading.close(),
|
|
722
|
-
get lastEventId() {
|
|
723
|
-
return lastEventId;
|
|
724
|
-
}
|
|
725
|
-
};
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
// src/stream/line-parser.ts
|
|
729
|
-
var RS = String.fromCharCode(30);
|
|
730
|
-
function createLineParser() {
|
|
731
|
-
let buffer = "";
|
|
732
|
-
const records = (texts) => texts.map((text) => text.trim()).filter((text) => text !== "");
|
|
733
|
-
return {
|
|
734
|
-
push(chunk) {
|
|
735
|
-
const parts = (buffer + chunk).replaceAll(RS, `
|
|
736
|
-
`).split(/\r?\n/);
|
|
737
|
-
buffer = parts.pop() ?? "";
|
|
738
|
-
return records(parts);
|
|
739
|
-
},
|
|
740
|
-
end() {
|
|
741
|
-
const rest = buffer;
|
|
742
|
-
buffer = "";
|
|
743
|
-
return records([rest]);
|
|
744
|
-
}
|
|
745
|
-
};
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
// src/stream/line-stream.ts
|
|
749
|
-
var LINE_TYPES = [
|
|
750
|
-
"application/jsonl",
|
|
751
|
-
"application/x-ndjson",
|
|
752
|
-
"application/ndjson",
|
|
753
|
-
"application/jsonlines",
|
|
754
|
-
"application/x-jsonlines",
|
|
755
|
-
"application/json-seq"
|
|
756
|
-
];
|
|
757
|
-
function lineStream(settings) {
|
|
758
|
-
const reading = new Reading(settings.signal);
|
|
759
|
-
let started = false;
|
|
760
|
-
async function* run() {
|
|
761
|
-
try {
|
|
762
|
-
let response;
|
|
763
|
-
try {
|
|
764
|
-
response = await settings.open(reading.closer.signal, undefined);
|
|
765
|
-
} catch (error) {
|
|
766
|
-
if (reading.closer.signal.aborted)
|
|
767
|
-
return;
|
|
768
|
-
throw error;
|
|
769
|
-
}
|
|
770
|
-
if (!await opened(settings, response, LINE_TYPES))
|
|
771
|
-
return;
|
|
772
|
-
const parser = createLineParser();
|
|
773
|
-
const reader = reading.read(response);
|
|
774
|
-
for (;; ) {
|
|
775
|
-
let chunk;
|
|
776
|
-
try {
|
|
777
|
-
chunk = await reader.read();
|
|
778
|
-
} catch (error) {
|
|
779
|
-
if (reading.stopped())
|
|
780
|
-
return;
|
|
781
|
-
throw new NetworkError(settings.context, { cause: error });
|
|
782
|
-
}
|
|
783
|
-
if (reading.stopped())
|
|
784
|
-
return;
|
|
785
|
-
const texts = chunk.done ? parser.end() : parser.push(chunk.value);
|
|
786
|
-
for (const text of texts) {
|
|
787
|
-
yield await settle(settings, response.status, text, settings.item, "a line");
|
|
788
|
-
}
|
|
789
|
-
if (chunk.done)
|
|
790
|
-
return;
|
|
791
|
-
}
|
|
792
|
-
} finally {
|
|
793
|
-
reading.release();
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
return {
|
|
797
|
-
[Symbol.asyncIterator]() {
|
|
798
|
-
if (started)
|
|
799
|
-
throw new TypeError("A stream is read once");
|
|
800
|
-
started = true;
|
|
801
|
-
return run();
|
|
802
|
-
},
|
|
803
|
-
close: () => reading.close()
|
|
804
|
-
};
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
// src/client/create-http-client.ts
|
|
808
|
-
var METHODS = [
|
|
809
|
-
"get",
|
|
810
|
-
"put",
|
|
811
|
-
"post",
|
|
812
|
-
"delete",
|
|
813
|
-
"options",
|
|
814
|
-
"head",
|
|
815
|
-
"patch",
|
|
816
|
-
"trace",
|
|
817
|
-
"query"
|
|
818
|
-
];
|
|
819
|
-
var RECONNECT_DELAY = 3000;
|
|
820
|
-
var contextOf = (method, path, operationId) => operationId === undefined ? { method, path } : { method, path, operationId };
|
|
821
|
-
function createHttpClient(options = {}) {
|
|
822
|
-
const signer = options.auth ? auth(options.auth) : undefined;
|
|
823
|
-
const claim = createLatest();
|
|
824
|
-
const latestSignal = (key) => key === undefined ? undefined : claim(key);
|
|
825
|
-
const sharedHeaders = async () => new Headers(typeof options.headers === "function" ? await options.headers() : options.headers);
|
|
826
|
-
const withDeadline = (timeout, signal) => {
|
|
827
|
-
const deadline = timeout === undefined ? undefined : AbortSignal.timeout(timeout);
|
|
828
|
-
const signals = [signal, deadline].filter((each) => each != null);
|
|
829
|
-
return {
|
|
830
|
-
deadline,
|
|
831
|
-
signal: signals.length > 1 ? AbortSignal.any(signals) : signals[0]
|
|
832
|
-
};
|
|
833
|
-
};
|
|
834
|
-
const dispatch = async (request, context, timeout, deadline, retry, added) => {
|
|
835
|
-
const fetch = options.fetch ?? ((sent) => globalThis.fetch(sent));
|
|
836
|
-
const send = async (sent) => {
|
|
837
|
-
try {
|
|
838
|
-
sent.signal.throwIfAborted();
|
|
839
|
-
return await fetch(sent);
|
|
840
|
-
} catch (error) {
|
|
841
|
-
if (request.signal.aborted)
|
|
842
|
-
throw error;
|
|
843
|
-
throw new NetworkError(context, { cause: error });
|
|
844
|
-
}
|
|
845
|
-
};
|
|
846
|
-
const again = retrySettings(retry);
|
|
847
|
-
const layers = [
|
|
848
|
-
...again ? [retrying(again)] : [],
|
|
849
|
-
...signer ? [signer] : [],
|
|
850
|
-
...options.use ?? [],
|
|
851
|
-
...added
|
|
852
|
-
];
|
|
853
|
-
try {
|
|
854
|
-
return await compose(layers, send, context)(request);
|
|
855
|
-
} catch (error) {
|
|
856
|
-
if (deadline?.aborted && timeout !== undefined) {
|
|
857
|
-
throw new TimeoutError(context, timeout, { cause: error });
|
|
858
|
-
}
|
|
859
|
-
throw error;
|
|
860
|
-
}
|
|
861
|
-
};
|
|
862
|
-
const build = async (method, path, given, adjust) => {
|
|
863
|
-
const {
|
|
864
|
-
param,
|
|
865
|
-
query,
|
|
866
|
-
json,
|
|
867
|
-
form,
|
|
868
|
-
text,
|
|
869
|
-
body,
|
|
870
|
-
operationId,
|
|
871
|
-
timeout = options.timeout,
|
|
872
|
-
retry = options.retry,
|
|
873
|
-
headers: own,
|
|
874
|
-
signal,
|
|
875
|
-
...rest
|
|
876
|
-
} = given;
|
|
877
|
-
const context = contextOf(method, path, operationId);
|
|
878
|
-
const headers = await sharedHeaders();
|
|
879
|
-
const callHeaders = new Headers(own);
|
|
880
|
-
callHeaders.forEach((value, name) => {
|
|
881
|
-
headers.set(name, value);
|
|
882
|
-
});
|
|
883
|
-
adjust?.(headers);
|
|
884
|
-
const url = joinUrl(options.baseUrl, fillPath(context, param), writeQuery(query));
|
|
885
|
-
const payload = writeBody({ json, form, text, body }, headers, callHeaders.get("content-type"));
|
|
886
|
-
const init = {
|
|
887
|
-
...options.init,
|
|
888
|
-
...rest,
|
|
889
|
-
method: method.toUpperCase(),
|
|
890
|
-
headers,
|
|
891
|
-
body: payload,
|
|
892
|
-
...payload instanceof ReadableStream ? { duplex: "half" } : {}
|
|
893
|
-
};
|
|
894
|
-
return { context, url, init, timeout, retry, signal: signal ?? undefined };
|
|
895
|
-
};
|
|
896
|
-
const request = async (method, path, given, added) => {
|
|
897
|
-
const {
|
|
898
|
-
responses,
|
|
899
|
-
validate = true,
|
|
900
|
-
decode = true,
|
|
901
|
-
latest,
|
|
902
|
-
...call
|
|
903
|
-
} = given;
|
|
904
|
-
const replaced = latestSignal(latest);
|
|
905
|
-
const built = await build(method, path, call);
|
|
906
|
-
const { deadline, signal } = withDeadline(built.timeout, joinSignals(built.signal, replaced));
|
|
907
|
-
const response = await dispatch(new Request(built.url, { ...built.init, signal }), built.context, built.timeout, deadline, built.retry, added);
|
|
908
|
-
return readReply(built.context, responses === undefined ? undefined : toSpec(responses), response, { validate, decode });
|
|
909
|
-
};
|
|
910
|
-
const opener = (method, path, call, accept, added) => async (stream, lastEventId) => {
|
|
911
|
-
const built = await build(method, path, call, (headers) => {
|
|
912
|
-
if (!headers.has("accept"))
|
|
913
|
-
headers.set("accept", accept);
|
|
914
|
-
if (lastEventId !== undefined) {
|
|
915
|
-
headers.set("last-event-id", lastEventId);
|
|
916
|
-
}
|
|
917
|
-
});
|
|
918
|
-
const deadline = new AbortController;
|
|
919
|
-
const clock = built.timeout === undefined ? undefined : setTimeout(() => deadline.abort(new DOMException("The stream did not open", "TimeoutError")), built.timeout);
|
|
920
|
-
const signals = [stream, deadline.signal];
|
|
921
|
-
if (built.signal)
|
|
922
|
-
signals.push(built.signal);
|
|
923
|
-
try {
|
|
924
|
-
return await dispatch(new Request(built.url, {
|
|
925
|
-
...built.init,
|
|
926
|
-
signal: AbortSignal.any(signals)
|
|
927
|
-
}), built.context, built.timeout, deadline.signal, built.retry, added);
|
|
928
|
-
} finally {
|
|
929
|
-
clearTimeout(clock);
|
|
930
|
-
}
|
|
931
|
-
};
|
|
932
|
-
const events = (path, given, added) => {
|
|
933
|
-
const {
|
|
934
|
-
events,
|
|
935
|
-
onUnknownEvent,
|
|
936
|
-
reconnect,
|
|
937
|
-
lastEventId,
|
|
938
|
-
validate = true,
|
|
939
|
-
decode = true,
|
|
940
|
-
method = "get",
|
|
941
|
-
latest,
|
|
942
|
-
...own
|
|
943
|
-
} = given;
|
|
944
|
-
const call = {
|
|
945
|
-
...own,
|
|
946
|
-
signal: joinSignals(own.signal, latestSignal(latest))
|
|
947
|
-
};
|
|
948
|
-
const reconnects = reconnect === undefined ? method !== "post" && method !== "patch" : reconnect !== false;
|
|
949
|
-
const settings = typeof reconnect === "object" ? reconnect : {};
|
|
950
|
-
return eventStream({
|
|
951
|
-
context: contextOf(method, path, call.operationId),
|
|
952
|
-
open: opener(method, path, call, "text/event-stream", added),
|
|
953
|
-
signal: call.signal ?? undefined,
|
|
954
|
-
validate,
|
|
955
|
-
decode,
|
|
956
|
-
events,
|
|
957
|
-
onUnknownEvent,
|
|
958
|
-
reconnect: reconnects && {
|
|
959
|
-
attempts: settings.attempts ?? Number.POSITIVE_INFINITY,
|
|
960
|
-
delay: settings.delay ?? RECONNECT_DELAY
|
|
961
|
-
},
|
|
962
|
-
lastEventId
|
|
963
|
-
});
|
|
964
|
-
};
|
|
965
|
-
const lines = (path, given, added) => {
|
|
966
|
-
const {
|
|
967
|
-
item,
|
|
968
|
-
validate = true,
|
|
969
|
-
decode = true,
|
|
970
|
-
method = "get",
|
|
971
|
-
latest,
|
|
972
|
-
...own
|
|
973
|
-
} = given;
|
|
974
|
-
const call = {
|
|
975
|
-
...own,
|
|
976
|
-
signal: joinSignals(own.signal, latestSignal(latest))
|
|
977
|
-
};
|
|
978
|
-
return lineStream({
|
|
979
|
-
context: contextOf(method, path, call.operationId),
|
|
980
|
-
open: opener(method, path, call, LINE_TYPES.slice(0, 2).join(", "), added),
|
|
981
|
-
signal: call.signal ?? undefined,
|
|
982
|
-
validate,
|
|
983
|
-
decode,
|
|
984
|
-
item
|
|
985
|
-
});
|
|
986
|
-
};
|
|
987
|
-
const send = async (request, {
|
|
988
|
-
timeout = options.timeout,
|
|
989
|
-
retry = options.retry,
|
|
990
|
-
operationId,
|
|
991
|
-
latest
|
|
992
|
-
}, added) => {
|
|
993
|
-
const replaced = latestSignal(latest);
|
|
994
|
-
const method = request.method.toLowerCase();
|
|
995
|
-
const context = contextOf(method, new URL(request.url).pathname, operationId);
|
|
996
|
-
const headers = await sharedHeaders();
|
|
997
|
-
request.headers.forEach((value, name) => {
|
|
998
|
-
headers.set(name, value);
|
|
999
|
-
});
|
|
1000
|
-
const { deadline, signal } = withDeadline(timeout, joinSignals(request.signal, replaced));
|
|
1001
|
-
const sent = new Request(request, { headers, signal });
|
|
1002
|
-
return dispatch(sent, context, timeout, deadline, retry, added);
|
|
1003
|
-
};
|
|
1004
|
-
const surface = (scope, inherited) => {
|
|
1005
|
-
const own = [];
|
|
1006
|
-
const layers = () => [...inherited(), ...own];
|
|
1007
|
-
const scoped = (given) => {
|
|
1008
|
-
const extra = scope();
|
|
1009
|
-
const own = given ?? {};
|
|
1010
|
-
return extra ? { ...own, signal: joinSignals(own.signal, extra) } : own;
|
|
1011
|
-
};
|
|
1012
|
-
const client = {
|
|
1013
|
-
request: (method, path, given) => request(method, path, scoped(given), layers()),
|
|
1014
|
-
send: (sent, given) => {
|
|
1015
|
-
const extra = scope();
|
|
1016
|
-
return send(extra ? new Request(sent, { signal: joinSignals(sent.signal, extra) }) : sent, given ?? {}, layers());
|
|
1017
|
-
},
|
|
1018
|
-
events: (path, given) => events(path, scoped(given), layers()),
|
|
1019
|
-
lines: (path, given) => lines(path, scoped(given), layers()),
|
|
1020
|
-
use: (...middlewares) => {
|
|
1021
|
-
own.push(...middlewares);
|
|
1022
|
-
return client;
|
|
1023
|
-
},
|
|
1024
|
-
group: () => {
|
|
1025
|
-
let controller = new AbortController;
|
|
1026
|
-
const group = surface(() => joinSignals(scope(), controller.signal), layers);
|
|
1027
|
-
group.cancel = (reason) => {
|
|
1028
|
-
controller.abort(reason ?? cancelled("The group was cancelled"));
|
|
1029
|
-
controller = new AbortController;
|
|
1030
|
-
};
|
|
1031
|
-
Object.defineProperty(group, "signal", {
|
|
1032
|
-
enumerable: true,
|
|
1033
|
-
get: () => controller.signal
|
|
1034
|
-
});
|
|
1035
|
-
return group;
|
|
1036
|
-
}
|
|
1037
|
-
};
|
|
1038
|
-
for (const method of METHODS) {
|
|
1039
|
-
client[method] = (path, given) => request(method, path, scoped(given), layers());
|
|
1040
|
-
}
|
|
1041
|
-
return client;
|
|
1042
|
-
};
|
|
1043
|
-
return surface(() => {
|
|
1044
|
-
return;
|
|
1045
|
-
}, () => []);
|
|
1046
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
check2,
|
|
3
|
+
text2,
|
|
4
|
+
absent2,
|
|
5
|
+
fields2,
|
|
6
|
+
toFormData2,
|
|
7
|
+
toSearchParams2,
|
|
8
|
+
METHODS2
|
|
9
|
+
} from "../chunks/index-52w12dh5.js";
|
|
1047
10
|
export {
|
|
1048
|
-
METHODS,
|
|
1049
|
-
absent,
|
|
1050
|
-
check,
|
|
1051
|
-
fields,
|
|
1052
|
-
text,
|
|
1053
|
-
toFormData,
|
|
1054
|
-
toSearchParams
|
|
11
|
+
METHODS2 as METHODS,
|
|
12
|
+
absent2 as absent,
|
|
13
|
+
check2 as check,
|
|
14
|
+
fields2 as fields,
|
|
15
|
+
text2 as text,
|
|
16
|
+
toFormData2 as toFormData,
|
|
17
|
+
toSearchParams2 as toSearchParams
|
|
1055
18
|
};
|
|
1056
19
|
|
|
1057
|
-
//# debugId=
|
|
20
|
+
//# debugId=A418B0FBE97D892D64756E2164756E21
|
|
1058
21
|
//# sourceMappingURL=index.js.map
|