@autometa/http 1.4.20 → 2.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.
Files changed (55) hide show
  1. package/README.md +107 -2
  2. package/dist/assertions/http-adapters.d.ts +35 -0
  3. package/dist/assertions/http-assertions-plugin.d.ts +16 -0
  4. package/dist/assertions/http-ensure.d.ts +42 -0
  5. package/dist/axios-transport.d.ts +22 -0
  6. package/dist/default-schema.d.ts +8 -0
  7. package/dist/fetch-transport.d.ts +21 -0
  8. package/dist/http-request.d.ts +109 -0
  9. package/dist/http-response.d.ts +77 -0
  10. package/dist/http.d.ts +300 -0
  11. package/dist/index.cjs +2076 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.d.ts +15 -1116
  14. package/dist/index.js +1727 -845
  15. package/dist/index.js.map +1 -1
  16. package/dist/plugins.d.ts +43 -0
  17. package/dist/request-meta.config.d.ts +56 -0
  18. package/dist/schema.map.d.ts +11 -0
  19. package/dist/transform-response.d.ts +1 -0
  20. package/dist/transport.d.ts +11 -0
  21. package/dist/types.d.ts +39 -0
  22. package/package.json +30 -30
  23. package/.eslintignore +0 -3
  24. package/.eslintrc.cjs +0 -4
  25. package/.turbo/turbo-lint$colon$fix.log +0 -4
  26. package/.turbo/turbo-prettify.log +0 -5
  27. package/.turbo/turbo-test.log +0 -120
  28. package/CHANGELOG.md +0 -335
  29. package/dist/esm/index.js +0 -1117
  30. package/dist/esm/index.js.map +0 -1
  31. package/dist/index.d.cts +0 -1116
  32. package/src/axios-client.ts +0 -35
  33. package/src/default-client-factory.axios.spec.ts +0 -9
  34. package/src/default-client-factory.other.spec.ts +0 -13
  35. package/src/default-client-factory.ts +0 -7
  36. package/src/default-schema.spec.ts +0 -74
  37. package/src/default-schema.ts +0 -127
  38. package/src/http-client.ts +0 -20
  39. package/src/http-request.spec.ts +0 -172
  40. package/src/http-request.ts +0 -201
  41. package/src/http-response.ts +0 -107
  42. package/src/http.spec.ts +0 -189
  43. package/src/http.ts +0 -907
  44. package/src/index.ts +0 -13
  45. package/src/node_modules/.vitest/deps/_metadata.json +0 -8
  46. package/src/node_modules/.vitest/deps/package.json +0 -3
  47. package/src/node_modules/.vitest/results.json +0 -1
  48. package/src/request-meta.config.spec.ts +0 -81
  49. package/src/request-meta.config.ts +0 -134
  50. package/src/request.config.ts +0 -34
  51. package/src/schema.map.spec.ts +0 -50
  52. package/src/schema.map.ts +0 -68
  53. package/src/transform-response.ts +0 -43
  54. package/src/types.ts +0 -37
  55. package/tsup.config.ts +0 -14
package/dist/index.cjs ADDED
@@ -0,0 +1,2076 @@
1
+ 'use strict';
2
+
3
+ var errors = require('@autometa/errors');
4
+ var cliHighlight = require('cli-highlight');
5
+ var assertions = require('@autometa/assertions');
6
+
7
+ // src/http.ts
8
+
9
+ // src/fetch-transport.ts
10
+ function createFetchTransport(fetchImpl = globalThis.fetch) {
11
+ if (!fetchImpl) {
12
+ throw new Error(
13
+ "No fetch implementation available. Provide one via createFetchTransport(fetchImpl)."
14
+ );
15
+ }
16
+ return {
17
+ async send(request, options = {}) {
18
+ const {
19
+ headers: optionHeaders,
20
+ body: optionBody,
21
+ signal: optionSignal,
22
+ streamResponse,
23
+ ...restOptions
24
+ } = options;
25
+ const headers = mergeHeaders(request.headers, optionHeaders);
26
+ const body = optionBody ?? createBody(request, headers);
27
+ const url = request.fullUrl ?? "";
28
+ const fetchOptions = {
29
+ ...restOptions,
30
+ method: request.method ?? "GET",
31
+ headers,
32
+ body
33
+ };
34
+ if (optionSignal !== void 0) {
35
+ fetchOptions.signal = optionSignal;
36
+ }
37
+ const response = await fetchImpl(url, fetchOptions);
38
+ const data = streamResponse ? response.body ?? null : await readBody(response);
39
+ return {
40
+ status: response.status,
41
+ statusText: response.statusText,
42
+ headers: headersToRecord(response.headers),
43
+ data
44
+ };
45
+ }
46
+ };
47
+ }
48
+ function mergeHeaders(base, additional) {
49
+ const next = { ...base };
50
+ if (!additional) {
51
+ return next;
52
+ }
53
+ for (const [key, value] of Object.entries(additional)) {
54
+ if (value === void 0 || value === null) {
55
+ delete next[key];
56
+ } else {
57
+ next[key] = String(value);
58
+ }
59
+ }
60
+ return next;
61
+ }
62
+ function createBody(request, headers) {
63
+ const { data } = request;
64
+ if (data === void 0 || data === null) {
65
+ return void 0;
66
+ }
67
+ if (isBodyInit(data)) {
68
+ return data;
69
+ }
70
+ if (typeof data === "string") {
71
+ return data;
72
+ }
73
+ if (typeof data === "object") {
74
+ if (!hasHeader(headers, "content-type")) {
75
+ headers["content-type"] = "application/json";
76
+ }
77
+ return JSON.stringify(data);
78
+ }
79
+ return String(data);
80
+ }
81
+ async function readBody(response) {
82
+ if (response.status === 204 || response.status === 205) {
83
+ return null;
84
+ }
85
+ const text = await response.text();
86
+ return text.length === 0 ? null : text;
87
+ }
88
+ function headersToRecord(headers) {
89
+ const record = {};
90
+ headers.forEach((value, key) => {
91
+ record[key] = value;
92
+ });
93
+ return record;
94
+ }
95
+ function hasHeader(headers, name) {
96
+ const lower = name.toLowerCase();
97
+ return Object.keys(headers).some((key) => key.toLowerCase() === lower);
98
+ }
99
+ function isBodyInit(value) {
100
+ if (typeof value === "string") {
101
+ return true;
102
+ }
103
+ if (typeof ArrayBuffer !== "undefined" && value instanceof ArrayBuffer) {
104
+ return true;
105
+ }
106
+ if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(value)) {
107
+ return true;
108
+ }
109
+ return false;
110
+ }
111
+
112
+ // src/http-request.ts
113
+ var HTTPRequest = class _HTTPRequest {
114
+ constructor(config) {
115
+ /**
116
+ * Normalised header collection that will be sent with the request.
117
+ */
118
+ this.headers = {};
119
+ this.params = {};
120
+ this.route = [];
121
+ this.queryOptions = {};
122
+ if (config) {
123
+ Object.assign(this, config);
124
+ if (config.queryOptions) {
125
+ this.queryOptions = { ...config.queryOptions };
126
+ }
127
+ }
128
+ }
129
+ /**
130
+ * Full request URL derived from {@link baseUrl}, {@link route} and {@link params}.
131
+ */
132
+ get fullUrl() {
133
+ return buildFullUrl(
134
+ this.baseUrl,
135
+ this.route,
136
+ this.params,
137
+ this.queryOptions
138
+ );
139
+ }
140
+ /**
141
+ * Creates a deep copy of an existing request instance.
142
+ */
143
+ static derive(original) {
144
+ const request = new _HTTPRequest();
145
+ request.headers = { ...original.headers };
146
+ request.params = cloneParams(original.params);
147
+ request.baseUrl = original.baseUrl;
148
+ request.route = [...original.route];
149
+ request.method = original.method;
150
+ request.data = original.data;
151
+ request.queryOptions = { ...original.queryOptions };
152
+ return request;
153
+ }
154
+ };
155
+ var HTTPRequestBuilder = class _HTTPRequestBuilder {
156
+ constructor(request = () => new HTTPRequest()) {
157
+ this.dynamicHeaders = /* @__PURE__ */ new Map();
158
+ this.requestInstance = typeof request === "function" ? request() : request;
159
+ this.queryOptions = { ...this.requestInstance.queryOptions };
160
+ }
161
+ /**
162
+ * Initializes a new builder for the default {@link HTTPRequest} type.
163
+ */
164
+ static create() {
165
+ return new _HTTPRequestBuilder();
166
+ }
167
+ /**
168
+ * Exposes the underlying request without defensive cloning.
169
+ */
170
+ get request() {
171
+ return this.requestInstance;
172
+ }
173
+ /**
174
+ * Resolves asynchronous header factories into concrete header values on demand.
175
+ */
176
+ async resolveDynamicHeaders(request = this.requestInstance) {
177
+ for (const [name, factory] of this.dynamicHeaders) {
178
+ if (!factory) {
179
+ continue;
180
+ }
181
+ try {
182
+ const result = await factory();
183
+ if (result === void 0 || result === null) {
184
+ delete request.headers[name];
185
+ continue;
186
+ }
187
+ request.headers[name] = String(result);
188
+ } catch (error) {
189
+ const cause = error;
190
+ throw new Error(
191
+ `Failed to resolve dynamic header "${name}": ${cause.message}`
192
+ );
193
+ }
194
+ }
195
+ return this;
196
+ }
197
+ /**
198
+ * Sets the root URL (protocol, host and optional base path).
199
+ */
200
+ url(url) {
201
+ this.requestInstance.baseUrl = url;
202
+ return this;
203
+ }
204
+ /**
205
+ * Appends one or more path segments to the current request route.
206
+ */
207
+ route(...segments) {
208
+ const mapped = segments.map((segment) => String(segment)).filter((segment) => segment.length > 0);
209
+ this.requestInstance.route.push(...mapped);
210
+ return this;
211
+ }
212
+ /**
213
+ * Adds or removes a query parameter value.
214
+ */
215
+ param(name, value) {
216
+ if (value === void 0) {
217
+ delete this.requestInstance.params[name];
218
+ return this;
219
+ }
220
+ if (Array.isArray(value)) {
221
+ const list = value.filter(
222
+ (item) => item !== void 0 && item !== null
223
+ );
224
+ const existing = this.requestInstance.params[name];
225
+ if (Array.isArray(existing)) {
226
+ this.requestInstance.params[name] = [
227
+ ...existing,
228
+ ...list
229
+ ];
230
+ } else {
231
+ this.requestInstance.params[name] = list;
232
+ }
233
+ return this;
234
+ }
235
+ if (value && typeof value === "object") {
236
+ const dictEntries = Object.entries(
237
+ value
238
+ ).reduce((acc, [key, paramValue]) => {
239
+ if (paramValue !== void 0) {
240
+ acc[key] = paramValue;
241
+ }
242
+ return acc;
243
+ }, {});
244
+ const existing = this.requestInstance.params[name];
245
+ if (isPlainObject(existing)) {
246
+ this.requestInstance.params[name] = {
247
+ ...existing,
248
+ ...dictEntries
249
+ };
250
+ } else {
251
+ this.requestInstance.params[name] = dictEntries;
252
+ }
253
+ return this;
254
+ }
255
+ this.requestInstance.params[name] = value;
256
+ return this;
257
+ }
258
+ /**
259
+ * Merges a dictionary of query parameters into the request.
260
+ */
261
+ params(dict) {
262
+ for (const [key, value] of Object.entries(dict)) {
263
+ this.param(key, value);
264
+ }
265
+ return this;
266
+ }
267
+ queryFormat(options) {
268
+ if (options.arrayFormat !== void 0) {
269
+ this.queryOptions.arrayFormat = options.arrayFormat;
270
+ }
271
+ if (options.objectFormat !== void 0) {
272
+ this.queryOptions.objectFormat = options.objectFormat;
273
+ }
274
+ if (Object.prototype.hasOwnProperty.call(options, "serializer")) {
275
+ const serializer = options.serializer ?? void 0;
276
+ if (serializer) {
277
+ this.queryOptions.serializer = serializer;
278
+ } else {
279
+ delete this.queryOptions.serializer;
280
+ }
281
+ }
282
+ this.requestInstance.queryOptions = { ...this.queryOptions };
283
+ return this;
284
+ }
285
+ /**
286
+ * Sets the request body payload. Passing `undefined` removes the body.
287
+ */
288
+ data(data) {
289
+ if (data === void 0) {
290
+ delete this.requestInstance.data;
291
+ return this;
292
+ }
293
+ this.requestInstance.data = data;
294
+ return this;
295
+ }
296
+ /**
297
+ * Sets a single header using direct values or a lazy factory.
298
+ */
299
+ header(name, value) {
300
+ if (typeof value === "function") {
301
+ this.dynamicHeaders.set(name, value);
302
+ delete this.requestInstance.headers[name];
303
+ return this;
304
+ }
305
+ this.dynamicHeaders.delete(name);
306
+ if (value === void 0 || value === null) {
307
+ delete this.requestInstance.headers[name];
308
+ return this;
309
+ }
310
+ if (Array.isArray(value)) {
311
+ const filtered = value.filter(
312
+ (item) => item !== void 0 && item !== null
313
+ );
314
+ this.requestInstance.headers[name] = filtered.map(String).join(",");
315
+ return this;
316
+ }
317
+ this.requestInstance.headers[name] = String(value);
318
+ return this;
319
+ }
320
+ /**
321
+ * Replaces or merges multiple headers in one call.
322
+ */
323
+ headers(dict) {
324
+ for (const [key, value] of Object.entries(dict)) {
325
+ this.header(key, value);
326
+ }
327
+ return this;
328
+ }
329
+ /**
330
+ * Stores the HTTP verb ensuring consistent casing.
331
+ */
332
+ method(method) {
333
+ this.requestInstance.method = method.toUpperCase();
334
+ return this;
335
+ }
336
+ /**
337
+ * Returns a copy-on-write builder pointing at the same request state.
338
+ */
339
+ derive() {
340
+ return this.clone();
341
+ }
342
+ /**
343
+ * Produces a deep copy of the builder and the underlying request.
344
+ */
345
+ clone() {
346
+ const request = HTTPRequest.derive(this.requestInstance);
347
+ const builder = new _HTTPRequestBuilder(request);
348
+ builder.dynamicHeaders = new Map(this.dynamicHeaders);
349
+ builder.queryOptions = { ...this.queryOptions };
350
+ builder.requestInstance.queryOptions = { ...this.queryOptions };
351
+ return builder;
352
+ }
353
+ /**
354
+ * Returns the current request without resolving header factories.
355
+ */
356
+ build() {
357
+ this.requestInstance.queryOptions = { ...this.queryOptions };
358
+ return this.requestInstance;
359
+ }
360
+ /**
361
+ * Resolves lazy headers before returning the request.
362
+ */
363
+ async buildAsync() {
364
+ await this.resolveDynamicHeaders();
365
+ this.requestInstance.queryOptions = { ...this.queryOptions };
366
+ return this.requestInstance;
367
+ }
368
+ };
369
+ function cloneParams(params) {
370
+ return Object.entries(params).reduce((acc, [key, value]) => {
371
+ if (Array.isArray(value)) {
372
+ acc[key] = [...value];
373
+ return acc;
374
+ }
375
+ if (isPlainObject(value)) {
376
+ acc[key] = { ...value };
377
+ return acc;
378
+ }
379
+ acc[key] = value;
380
+ return acc;
381
+ }, {});
382
+ }
383
+ function buildFullUrl(baseUrl, route, params, options) {
384
+ const pathSegments = route.map((segment) => String(segment)).filter((segment) => segment.length > 0).map((segment) => segment.replace(/^\/+|\/+$/g, ""));
385
+ const query = buildQueryString(params, options);
386
+ if (baseUrl && /^https?:\/\//i.test(baseUrl)) {
387
+ const url = new URL(baseUrl);
388
+ if (pathSegments.length > 0) {
389
+ const basePath = url.pathname.replace(/^\/+|\/+$/g, "");
390
+ const combined = [basePath, ...pathSegments].filter(Boolean).join("/");
391
+ url.pathname = `/${combined}`;
392
+ }
393
+ url.search = query ? `?${query}` : "";
394
+ return url.toString();
395
+ }
396
+ const trimmedBase = (baseUrl ?? "").replace(/\/+$/g, "");
397
+ const joinedPath = pathSegments.join("/");
398
+ const path = [trimmedBase, joinedPath].filter((segment) => segment && segment.length > 0).join(trimmedBase && joinedPath ? "/" : "");
399
+ if (!path && !query) {
400
+ return "";
401
+ }
402
+ if (!path) {
403
+ return query ? `?${query}` : "";
404
+ }
405
+ return query ? `${path}?${query}` : path;
406
+ }
407
+ function buildQueryString(params, options) {
408
+ if (!params || Object.keys(params).length === 0) {
409
+ return "";
410
+ }
411
+ const serializer = options?.serializer ?? void 0;
412
+ if (serializer) {
413
+ return serializer(params);
414
+ }
415
+ const arrayFormat = options?.arrayFormat ?? "repeat";
416
+ const objectFormat = options?.objectFormat ?? "brackets";
417
+ const search = new URLSearchParams();
418
+ const append = (key, value) => {
419
+ if (value === void 0 || value === null) {
420
+ return;
421
+ }
422
+ search.append(key, String(value));
423
+ };
424
+ const encode = (key, value) => {
425
+ if (value === void 0 || value === null) {
426
+ return;
427
+ }
428
+ if (Array.isArray(value)) {
429
+ const filtered = value.filter(
430
+ (item) => item !== void 0 && item !== null
431
+ );
432
+ if (filtered.length === 0) {
433
+ return;
434
+ }
435
+ switch (arrayFormat) {
436
+ case "json": {
437
+ append(key, JSON.stringify(filtered));
438
+ return;
439
+ }
440
+ case "comma": {
441
+ const joined = filtered.map((item) => String(item)).join(",");
442
+ append(key, joined);
443
+ return;
444
+ }
445
+ case "indices": {
446
+ filtered.forEach((item, index) => {
447
+ encode(`${key}[${index}]`, item);
448
+ });
449
+ return;
450
+ }
451
+ case "brackets": {
452
+ filtered.forEach((item) => {
453
+ encode(`${key}[]`, item);
454
+ });
455
+ return;
456
+ }
457
+ default: {
458
+ filtered.forEach((item) => {
459
+ encode(key, item);
460
+ });
461
+ return;
462
+ }
463
+ }
464
+ }
465
+ if (isPlainObject(value)) {
466
+ if (objectFormat === "json") {
467
+ append(key, JSON.stringify(value));
468
+ return;
469
+ }
470
+ for (const [childKey, childValue] of Object.entries(
471
+ value
472
+ )) {
473
+ const nextKey = objectFormat === "dot" ? `${key}.${childKey}` : `${key}[${childKey}]`;
474
+ encode(nextKey, childValue);
475
+ }
476
+ return;
477
+ }
478
+ append(key, value);
479
+ };
480
+ for (const [key, value] of Object.entries(params)) {
481
+ encode(key, value);
482
+ }
483
+ return search.toString();
484
+ }
485
+ function isPlainObject(value) {
486
+ if (value === null || typeof value !== "object") {
487
+ return false;
488
+ }
489
+ const proto = Object.getPrototypeOf(value);
490
+ return proto === Object.prototype || proto === null;
491
+ }
492
+
493
+ // src/http-response.ts
494
+ var HTTPResponse = class _HTTPResponse {
495
+ constructor() {
496
+ /**
497
+ * Human-readable text accompanying {@link status}.
498
+ */
499
+ this.statusText = "";
500
+ /**
501
+ * Normalised response headers keyed by lowercase header names.
502
+ */
503
+ this.headers = {};
504
+ }
505
+ /**
506
+ * Creates a shallow clone from an existing response instance.
507
+ */
508
+ static fromRaw(response) {
509
+ const next = new _HTTPResponse();
510
+ next.status = response.status;
511
+ next.statusText = response.statusText;
512
+ next.data = response.data;
513
+ next.headers = { ...response.headers };
514
+ next.request = response.request;
515
+ return next;
516
+ }
517
+ /**
518
+ * Returns a new response with identical metadata but a transformed payload.
519
+ *
520
+ * @example
521
+ * const productResponse = await http.route("products", 1).get<Product>()
522
+ * const simplified = productResponse.mapData((product) => product.name)
523
+ */
524
+ mapData(transform) {
525
+ const nextValue = typeof transform === "function" ? transform(this.data) : transform;
526
+ return new HTTPResponseBuilder().status(this.status).statusText(this.statusText).headers(this.headers).request(this.request).data(nextValue).build();
527
+ }
528
+ };
529
+ var HTTPResponseBuilder = class _HTTPResponseBuilder {
530
+ constructor() {
531
+ this.response = new HTTPResponse();
532
+ }
533
+ /**
534
+ * Creates a new empty builder.
535
+ */
536
+ static create() {
537
+ return new _HTTPResponseBuilder();
538
+ }
539
+ /**
540
+ * Produces a new builder seeded with the current response state.
541
+ */
542
+ derive() {
543
+ return _HTTPResponseBuilder.create().status(this.response.status).statusText(this.response.statusText).headers({ ...this.response.headers }).request(this.response.request).data(this.response.data);
544
+ }
545
+ /**
546
+ * Sets the response status code.
547
+ */
548
+ status(code) {
549
+ this.response.status = code;
550
+ return this;
551
+ }
552
+ /**
553
+ * Sets the textual status message.
554
+ */
555
+ statusText(text) {
556
+ this.response.statusText = text;
557
+ return this;
558
+ }
559
+ /**
560
+ * Attaches the response payload.
561
+ */
562
+ data(data) {
563
+ this.response.data = data;
564
+ return this;
565
+ }
566
+ /**
567
+ * Replaces the entire headers collection.
568
+ */
569
+ headers(dict) {
570
+ this.response.headers = { ...dict };
571
+ return this;
572
+ }
573
+ /**
574
+ * Sets or overrides a single response header.
575
+ */
576
+ header(name, value) {
577
+ this.response.headers[name] = value;
578
+ return this;
579
+ }
580
+ /**
581
+ * References the originating request.
582
+ */
583
+ request(request) {
584
+ this.response.request = request;
585
+ return this;
586
+ }
587
+ /**
588
+ * Builds the immutable {@link HTTPResponse} instance.
589
+ */
590
+ build() {
591
+ return this.response;
592
+ }
593
+ };
594
+
595
+ // src/schema.map.ts
596
+ var SchemaMap = class _SchemaMap {
597
+ constructor(map) {
598
+ if (map instanceof _SchemaMap) {
599
+ this.map = new Map(map.map);
600
+ return;
601
+ }
602
+ this.map = map ? new Map(map) : /* @__PURE__ */ new Map();
603
+ }
604
+ derive() {
605
+ return new _SchemaMap(this.map);
606
+ }
607
+ registerStatus(parser, ...codes) {
608
+ codes.forEach((code) => {
609
+ this.map.set(code, parser);
610
+ });
611
+ }
612
+ registerRange(parser, from, to) {
613
+ for (let code = from; code <= to; code++) {
614
+ this.map.set(code, parser);
615
+ }
616
+ }
617
+ validate(status, data, requireSchema) {
618
+ const parser = this.getParser(status, requireSchema);
619
+ if (!parser) {
620
+ return data;
621
+ }
622
+ if (typeof parser === "function") {
623
+ return parser(data);
624
+ }
625
+ if ("parse" in parser) {
626
+ return parser.parse(data);
627
+ }
628
+ if ("validate" in parser) {
629
+ return parser.validate(data);
630
+ }
631
+ return data;
632
+ }
633
+ getParser(status, requireSchema) {
634
+ const parser = this.map.get(status);
635
+ if (!parser && requireSchema) {
636
+ throw new Error(
637
+ `No schema parser registered for status code ${status} while requireSchema is true.`
638
+ );
639
+ }
640
+ return parser ?? null;
641
+ }
642
+ toObject() {
643
+ return Object.fromEntries(this.map);
644
+ }
645
+ };
646
+
647
+ // src/request-meta.config.ts
648
+ var MetaConfig = class {
649
+ constructor(init) {
650
+ this.schemas = new SchemaMap();
651
+ this.requireSchema = false;
652
+ this.allowPlainText = false;
653
+ this.onSend = [];
654
+ this.onReceive = [];
655
+ this.throwOnServerError = false;
656
+ this.options = {};
657
+ this.streamResponse = false;
658
+ this.timeoutMs = void 0;
659
+ Object.assign(this, init);
660
+ }
661
+ };
662
+ var MetaConfigBuilder = class _MetaConfigBuilder {
663
+ constructor() {
664
+ this.schemaMapValue = new SchemaMap();
665
+ this.requireSchemaValue = false;
666
+ this.allowPlainTextValue = false;
667
+ this.onBeforeSendHooks = [];
668
+ this.onAfterReceiveHooks = [];
669
+ this.throwOnServerErrorValue = false;
670
+ this.optionsValue = {};
671
+ this.streamResponseValue = false;
672
+ }
673
+ merge(builder) {
674
+ this.schemaMapValue = builder.schemaMapValue.derive();
675
+ this.requireSchemaValue = builder.requireSchemaValue;
676
+ this.allowPlainTextValue = builder.allowPlainTextValue;
677
+ this.onBeforeSendHooks = [...builder.onBeforeSendHooks];
678
+ this.onAfterReceiveHooks = [...builder.onAfterReceiveHooks];
679
+ this.throwOnServerErrorValue = builder.throwOnServerErrorValue;
680
+ this.optionsValue = { ...builder.optionsValue };
681
+ this.retryOptionsValue = builder.retryOptionsValue ? { ...builder.retryOptionsValue } : void 0;
682
+ this.streamResponseValue = builder.streamResponseValue;
683
+ this.timeoutMsValue = builder.timeoutMsValue;
684
+ return this;
685
+ }
686
+ schemaMap(map) {
687
+ this.schemaMapValue = map;
688
+ return this;
689
+ }
690
+ schema(parser, ...args) {
691
+ args.forEach((arg) => {
692
+ if (typeof arg === "number") {
693
+ this.schemaMapValue.registerStatus(parser, arg);
694
+ return;
695
+ }
696
+ if (Array.isArray(arg)) {
697
+ this.schemaMapValue.registerStatus(parser, ...arg);
698
+ return;
699
+ }
700
+ this.schemaMapValue.registerRange(parser, arg.from, arg.to);
701
+ });
702
+ return this;
703
+ }
704
+ requireSchema(value) {
705
+ this.requireSchemaValue = value;
706
+ return this;
707
+ }
708
+ allowPlainText(value) {
709
+ this.allowPlainTextValue = value;
710
+ return this;
711
+ }
712
+ onBeforeSend(description, hook) {
713
+ this.onBeforeSendHooks.push([description, hook]);
714
+ return this;
715
+ }
716
+ onReceiveResponse(description, hook) {
717
+ this.onAfterReceiveHooks.push([description, hook]);
718
+ return this;
719
+ }
720
+ throwOnServerError(value) {
721
+ this.throwOnServerErrorValue = value;
722
+ return this;
723
+ }
724
+ options(options) {
725
+ this.optionsValue = mergeOptions(this.optionsValue, options);
726
+ return this;
727
+ }
728
+ retry(options) {
729
+ this.retryOptionsValue = options ? { ...options } : void 0;
730
+ return this;
731
+ }
732
+ streamResponse(value) {
733
+ this.streamResponseValue = value;
734
+ return this;
735
+ }
736
+ timeout(duration) {
737
+ if (typeof duration === "number" && duration > 0) {
738
+ this.timeoutMsValue = duration;
739
+ } else {
740
+ this.timeoutMsValue = void 0;
741
+ }
742
+ return this;
743
+ }
744
+ build() {
745
+ const retry = this.retryOptionsValue ? { ...this.retryOptionsValue } : void 0;
746
+ return new MetaConfig({
747
+ schemas: this.schemaMapValue.derive(),
748
+ requireSchema: this.requireSchemaValue,
749
+ allowPlainText: this.allowPlainTextValue,
750
+ onSend: [...this.onBeforeSendHooks],
751
+ onReceive: [...this.onAfterReceiveHooks],
752
+ options: { ...this.optionsValue },
753
+ throwOnServerError: this.throwOnServerErrorValue,
754
+ ...retry ? { retry } : {},
755
+ streamResponse: this.streamResponseValue,
756
+ timeoutMs: this.timeoutMsValue
757
+ });
758
+ }
759
+ derive() {
760
+ return new _MetaConfigBuilder().schemaMap(this.schemaMapValue.derive()).requireSchema(this.requireSchemaValue).allowPlainText(this.allowPlainTextValue).throwOnServerError(this.throwOnServerErrorValue).options(this.optionsValue).retry(this.retryOptionsValue ?? null).streamResponse(this.streamResponseValue).timeout(this.timeoutMsValue).setOnBeforeSend(this.onBeforeSendHooks).setOnAfterReceive(this.onAfterReceiveHooks);
761
+ }
762
+ setOnBeforeSend(hooks) {
763
+ this.onBeforeSendHooks = [...hooks];
764
+ return this;
765
+ }
766
+ setOnAfterReceive(hooks) {
767
+ this.onAfterReceiveHooks = [...hooks];
768
+ return this;
769
+ }
770
+ };
771
+ function mergeOptions(target, updates) {
772
+ const next = { ...target };
773
+ for (const [key, value] of Object.entries(updates)) {
774
+ if (value === void 0) {
775
+ delete next[key];
776
+ } else {
777
+ next[key] = value;
778
+ }
779
+ }
780
+ return next;
781
+ }
782
+ function transformResponse(allowPlainText, data) {
783
+ if (data === null || data === void 0) {
784
+ return data;
785
+ }
786
+ if (typeof data === "string") {
787
+ const trimmed = data.trim();
788
+ if (trimmed.length === 0) {
789
+ return void 0;
790
+ }
791
+ if (trimmed.toLowerCase() === "undefined") {
792
+ return void 0;
793
+ }
794
+ }
795
+ const primitive = normalizePrimitive(data);
796
+ if (primitive !== void 0) {
797
+ return primitive;
798
+ }
799
+ if (typeof data === "object") {
800
+ return data;
801
+ }
802
+ if (allowPlainText) {
803
+ return String(data);
804
+ }
805
+ const rendered = typeof data === "string" ? data : String(data);
806
+ const message = [
807
+ "Could not parse response as JSON and plain text responses are disabled.",
808
+ "Call 'allowPlainText(true)' or 'sharedAllowPlainText(true)' to permit plain text responses.",
809
+ "",
810
+ cliHighlight.highlight(rendered, { language: "html" })
811
+ ].join("\n");
812
+ throw new errors.AutomationError(message);
813
+ }
814
+ function normalizePrimitive(data) {
815
+ if (typeof data === "string") {
816
+ const parsed = tryParseJson(data);
817
+ if (parsed !== void 0) {
818
+ return parsed;
819
+ }
820
+ const lowered = data.toLowerCase();
821
+ if (lowered === "true" || lowered === "false") {
822
+ return lowered === "true";
823
+ }
824
+ if (/^(?:\d+|\d*\.\d+)$/.test(data)) {
825
+ return Number(data);
826
+ }
827
+ return void 0;
828
+ }
829
+ if (isArrayBufferLike(data)) {
830
+ const text = bufferToString(data);
831
+ return normalizePrimitive(text) ?? text;
832
+ }
833
+ if (typeof data === "boolean" || typeof data === "number") {
834
+ return data;
835
+ }
836
+ return void 0;
837
+ }
838
+ function tryParseJson(value) {
839
+ try {
840
+ return JSON.parse(value);
841
+ } catch {
842
+ return void 0;
843
+ }
844
+ }
845
+ function isArrayBufferLike(value) {
846
+ return typeof ArrayBuffer !== "undefined" && value instanceof ArrayBuffer || typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(value);
847
+ }
848
+ function bufferToString(value) {
849
+ const view = value instanceof ArrayBuffer ? new Uint8Array(value) : new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
850
+ if (typeof TextDecoder !== "undefined") {
851
+ return new TextDecoder().decode(view);
852
+ }
853
+ let output = "";
854
+ for (let i = 0; i < view.length; i++) {
855
+ const code = view[i];
856
+ if (code === void 0) {
857
+ continue;
858
+ }
859
+ output += String.fromCharCode(code);
860
+ }
861
+ return output;
862
+ }
863
+
864
+ // src/http.ts
865
+ var HTTPError = class extends errors.AutomationError {
866
+ constructor(message, request, response, cause) {
867
+ super(message, {
868
+ cause: cause instanceof Error ? cause : void 0
869
+ });
870
+ this.request = request;
871
+ this.response = response;
872
+ this.originalError = cause;
873
+ this.name = this.constructor.name;
874
+ Object.setPrototypeOf(this, new.target.prototype);
875
+ }
876
+ };
877
+ var HTTPTransportError = class extends HTTPError {
878
+ constructor(request, cause) {
879
+ super("Failed to execute HTTP request", request, void 0, cause);
880
+ this.name = "HTTPTransportError";
881
+ }
882
+ };
883
+ var HTTPSchemaValidationError = class extends HTTPError {
884
+ constructor(request, response, cause) {
885
+ super("Response schema validation failed", request, response, cause);
886
+ this.name = "HTTPSchemaValidationError";
887
+ }
888
+ };
889
+ var HTTPServerError = class extends HTTPError {
890
+ constructor(request, response) {
891
+ super(`Server responded with status ${response.status}`, request, response);
892
+ this.name = "HTTPServerError";
893
+ }
894
+ };
895
+ var _HTTP = class _HTTP {
896
+ constructor(transport, builder, meta, sharedPlugins, scopedPlugins) {
897
+ this.transport = transport;
898
+ this.builder = builder;
899
+ this.meta = meta;
900
+ this.sharedPlugins = sharedPlugins;
901
+ this.scopedPlugins = scopedPlugins;
902
+ }
903
+ /**
904
+ * Factory helper that prepares an {@link HTTP} instance with shared state.
905
+ */
906
+ static create(options = {}) {
907
+ const transport = options.transport ?? createFetchTransport();
908
+ const plugins = [..._HTTP.sharedPlugins, ...options.plugins ?? []];
909
+ return new _HTTP(
910
+ transport,
911
+ HTTPRequestBuilder.create(),
912
+ new MetaConfigBuilder(),
913
+ plugins,
914
+ []
915
+ );
916
+ }
917
+ /**
918
+ * Registers a plugin applied to every client created via {@link HTTP.create}.
919
+ */
920
+ static registerSharedPlugin(plugin) {
921
+ this.sharedPlugins = [...this.sharedPlugins, plugin];
922
+ }
923
+ /**
924
+ * Replaces the shared plugin registry used by {@link HTTP.create}.
925
+ */
926
+ static setSharedPlugins(plugins) {
927
+ this.sharedPlugins = [...plugins];
928
+ }
929
+ /**
930
+ * Returns a copy of the currently registered shared plugins.
931
+ */
932
+ static getSharedPlugins() {
933
+ return [...this.sharedPlugins];
934
+ }
935
+ /**
936
+ * Registers a plugin that runs for every request executed by this instance and its clones.
937
+ */
938
+ use(plugin) {
939
+ this.sharedPlugins.push(plugin);
940
+ return this;
941
+ }
942
+ /**
943
+ * Returns a scoped clone with an additional plugin applied only to that clone.
944
+ */
945
+ plugin(plugin) {
946
+ return this.derive(({ plugins }) => {
947
+ plugins.push(plugin);
948
+ });
949
+ }
950
+ /**
951
+ * Mutates the current instance to use a different transport implementation.
952
+ */
953
+ useTransport(transport) {
954
+ this.transport = transport;
955
+ return this;
956
+ }
957
+ /**
958
+ * Produces a new client with an alternate transport without changing the original instance.
959
+ */
960
+ withTransport(transport) {
961
+ return this.derive(void 0, { transport });
962
+ }
963
+ /**
964
+ * Sets the base URL shared by subsequent requests.
965
+ */
966
+ url(url) {
967
+ this.builder.url(url);
968
+ return this;
969
+ }
970
+ /**
971
+ * Applies additional transport specific options to every request executed by this instance.
972
+ */
973
+ sharedOptions(options) {
974
+ this.meta.options(options);
975
+ return this;
976
+ }
977
+ /**
978
+ * Returns a derived client with extra transport options applied only to that clone.
979
+ */
980
+ withOptions(options) {
981
+ return this.derive(({ meta }) => {
982
+ meta.options(options);
983
+ });
984
+ }
985
+ /**
986
+ * Registers an {@link AbortSignal} that will be forwarded to every request issued by this instance.
987
+ */
988
+ sharedAbortSignal(signal) {
989
+ this.meta.options({ signal: signal ?? void 0 });
990
+ return this;
991
+ }
992
+ /**
993
+ * Returns a derived client configured with the provided {@link AbortSignal}.
994
+ */
995
+ abortSignal(signal) {
996
+ return this.derive(({ meta }) => {
997
+ meta.options({ signal: signal ?? void 0 });
998
+ });
999
+ }
1000
+ /**
1001
+ * Configures automatic retries for this instance and all derived clients.
1002
+ */
1003
+ sharedRetry(options) {
1004
+ this.meta.retry(options);
1005
+ return this;
1006
+ }
1007
+ /**
1008
+ * Returns a derived client with custom retry behaviour.
1009
+ */
1010
+ retry(options) {
1011
+ return this.derive(({ meta }) => {
1012
+ meta.retry(options);
1013
+ });
1014
+ }
1015
+ /**
1016
+ * Forces subsequent requests to return raw response streams without parsing.
1017
+ */
1018
+ sharedStreamResponse(enabled) {
1019
+ this.meta.streamResponse(enabled);
1020
+ return this;
1021
+ }
1022
+ /**
1023
+ * Returns a derived client configured for streaming responses.
1024
+ */
1025
+ streamResponse(enabled) {
1026
+ return this.derive(({ meta }) => {
1027
+ meta.streamResponse(enabled);
1028
+ });
1029
+ }
1030
+ /**
1031
+ * Convenience helper that returns a clone configured for streaming responses.
1032
+ */
1033
+ asStream() {
1034
+ return this.streamResponse(true);
1035
+ }
1036
+ /**
1037
+ * Executes a GET request while preserving the raw response stream.
1038
+ */
1039
+ stream(options) {
1040
+ return this.streamResponse(true).get(options);
1041
+ }
1042
+ /**
1043
+ * Sets a shared timeout (in milliseconds) applied to every request from this instance.
1044
+ */
1045
+ sharedTimeout(duration) {
1046
+ this.meta.timeout(duration);
1047
+ return this;
1048
+ }
1049
+ /**
1050
+ * Returns a derived client with a per-request timeout in milliseconds.
1051
+ */
1052
+ timeout(duration) {
1053
+ return this.derive(({ meta }) => {
1054
+ meta.timeout(duration);
1055
+ });
1056
+ }
1057
+ /**
1058
+ * Configures whether schema validation is required before resolving a response.
1059
+ */
1060
+ requireSchema(required) {
1061
+ this.meta.requireSchema(required);
1062
+ return this;
1063
+ }
1064
+ /**
1065
+ * Returns a clone with overridden plain text handling mode.
1066
+ */
1067
+ allowPlainText(allow) {
1068
+ return this.derive(({ meta }) => {
1069
+ meta.allowPlainText(allow);
1070
+ });
1071
+ }
1072
+ /**
1073
+ * Sets plain text handling for the current instance and all future requests.
1074
+ */
1075
+ sharedAllowPlainText(allow) {
1076
+ this.meta.allowPlainText(allow);
1077
+ return this;
1078
+ }
1079
+ /**
1080
+ * Adds path segments that will be included in every request.
1081
+ */
1082
+ sharedRoute(...segments) {
1083
+ this.builder.route(...segments);
1084
+ return this;
1085
+ }
1086
+ /**
1087
+ * Executes a request using the provided method.
1088
+ *
1089
+ * Use this when the verb is dynamic (e.g. provided by a parameter). It
1090
+ * behaves like calling {@link get}/{@link post}/{@link patch}, respecting any
1091
+ * route/headers/body configured earlier in the chain.
1092
+ */
1093
+ fetchWith(method, options) {
1094
+ const normalized = String(method).trim().toUpperCase();
1095
+ return this.execute(normalized, options);
1096
+ }
1097
+ /**
1098
+ * Returns a clone with additional path segments.
1099
+ */
1100
+ route(...segments) {
1101
+ return this.derive(({ builder }) => {
1102
+ builder.route(...segments);
1103
+ });
1104
+ }
1105
+ /**
1106
+ * Applies query serialization preferences to all future requests originating from this instance.
1107
+ */
1108
+ sharedQueryFormat(options) {
1109
+ this.builder.queryFormat(options);
1110
+ return this;
1111
+ }
1112
+ /**
1113
+ * Returns a derived client with custom query serialization that does not affect the source instance.
1114
+ */
1115
+ queryFormat(options) {
1116
+ return this.derive(({ builder }) => {
1117
+ builder.queryFormat(options);
1118
+ });
1119
+ }
1120
+ sharedSchema(parser, ...args) {
1121
+ this.meta.schema(parser, ...args);
1122
+ return this;
1123
+ }
1124
+ schema(parser, ...args) {
1125
+ return this.derive(({ meta }) => {
1126
+ meta.schema(parser, ...args);
1127
+ });
1128
+ }
1129
+ sharedParam(name, value, ...rest) {
1130
+ this.builder.param(name, toParamValue(value, rest));
1131
+ return this;
1132
+ }
1133
+ param(name, value, ...rest) {
1134
+ return this.derive(({ builder }) => {
1135
+ builder.param(name, toParamValue(value, rest));
1136
+ });
1137
+ }
1138
+ /**
1139
+ * Merges multiple shared query parameters into the instance.
1140
+ */
1141
+ sharedParams(dict) {
1142
+ this.builder.params(dict);
1143
+ return this;
1144
+ }
1145
+ /**
1146
+ * Derives a client with additional query parameters applied together.
1147
+ */
1148
+ params(dict) {
1149
+ return this.derive(({ builder }) => {
1150
+ builder.params(dict);
1151
+ });
1152
+ }
1153
+ /**
1154
+ * Sets a shared request body used by every request from this instance.
1155
+ */
1156
+ sharedData(data) {
1157
+ this.builder.data(data);
1158
+ return this;
1159
+ }
1160
+ /**
1161
+ * Derives a client with a one-off request body.
1162
+ */
1163
+ data(data) {
1164
+ return this.derive(({ builder }) => {
1165
+ builder.data(data);
1166
+ });
1167
+ }
1168
+ /**
1169
+ * Registers a header that will be resolved for every request on this instance.
1170
+ */
1171
+ sharedHeader(name, value) {
1172
+ this.builder.header(name, value);
1173
+ return this;
1174
+ }
1175
+ /**
1176
+ * Returns a clone with a header applied only to the resulting client.
1177
+ */
1178
+ header(name, value) {
1179
+ return this.derive(({ builder }) => {
1180
+ builder.header(name, value);
1181
+ });
1182
+ }
1183
+ /**
1184
+ * Registers multiple shared headers for every downstream request.
1185
+ */
1186
+ sharedHeaders(dict) {
1187
+ this.builder.headers(dict);
1188
+ return this;
1189
+ }
1190
+ /**
1191
+ * Returns a derived client with additional headers.
1192
+ */
1193
+ headers(dict) {
1194
+ return this.derive(({ builder }) => {
1195
+ builder.headers(dict);
1196
+ });
1197
+ }
1198
+ /**
1199
+ * Registers a request hook that runs before every execution on this instance.
1200
+ */
1201
+ sharedOnSend(description, hook) {
1202
+ this.meta.onBeforeSend(description, hook);
1203
+ return this;
1204
+ }
1205
+ /**
1206
+ * Returns a clone with a request hook used only for that clone.
1207
+ */
1208
+ onSend(description, hook) {
1209
+ return this.derive(({ meta }) => {
1210
+ meta.onBeforeSend(description, hook);
1211
+ });
1212
+ }
1213
+ /**
1214
+ * Registers a response hook executed after every transport response.
1215
+ */
1216
+ sharedOnReceive(description, hook) {
1217
+ this.meta.onReceiveResponse(description, hook);
1218
+ return this;
1219
+ }
1220
+ /**
1221
+ * Returns a derived client with a response hook limited to that client.
1222
+ */
1223
+ onReceive(description, hook) {
1224
+ return this.derive(({ meta }) => {
1225
+ meta.onReceiveResponse(description, hook);
1226
+ });
1227
+ }
1228
+ /**
1229
+ * Configures whether server errors (>=500) throw by default for every request.
1230
+ */
1231
+ sharedThrowOnServerError(value) {
1232
+ this.meta.throwOnServerError(value);
1233
+ return this;
1234
+ }
1235
+ /**
1236
+ * Returns a derived client with custom server error behaviour.
1237
+ */
1238
+ throwOnServerError(value) {
1239
+ return this.derive(({ meta }) => {
1240
+ meta.throwOnServerError(value);
1241
+ });
1242
+ }
1243
+ /**
1244
+ * Executes a GET request using the current configuration.
1245
+ */
1246
+ get(options) {
1247
+ return this.execute("GET", options);
1248
+ }
1249
+ /**
1250
+ * Executes a POST request using the current configuration.
1251
+ */
1252
+ post(options) {
1253
+ return this.execute("POST", options);
1254
+ }
1255
+ /**
1256
+ * Executes a PUT request using the current configuration.
1257
+ */
1258
+ put(options) {
1259
+ return this.execute("PUT", options);
1260
+ }
1261
+ /**
1262
+ * Executes a PATCH request using the current configuration.
1263
+ */
1264
+ patch(options) {
1265
+ return this.execute("PATCH", options);
1266
+ }
1267
+ /**
1268
+ * Executes a DELETE request using the current configuration.
1269
+ */
1270
+ delete(options) {
1271
+ return this.execute("DELETE", options);
1272
+ }
1273
+ /**
1274
+ * Executes a HEAD request using the current configuration.
1275
+ */
1276
+ head(options) {
1277
+ return this.execute("HEAD", options);
1278
+ }
1279
+ /**
1280
+ * Executes an OPTIONS request using the current configuration.
1281
+ */
1282
+ options(options) {
1283
+ return this.execute("OPTIONS", options);
1284
+ }
1285
+ /**
1286
+ * Executes a TRACE request using the current configuration.
1287
+ */
1288
+ trace(options) {
1289
+ return this.execute("TRACE", options);
1290
+ }
1291
+ /**
1292
+ * Executes a CONNECT request using the current configuration.
1293
+ */
1294
+ connect(options) {
1295
+ return this.execute("CONNECT", options);
1296
+ }
1297
+ async execute(method, options) {
1298
+ const baseBuilder = this.builder.clone().method(method);
1299
+ const meta = this.meta.derive().build();
1300
+ const baseOptions = mergeOptions2(meta.options, options);
1301
+ if (meta.streamResponse) {
1302
+ baseOptions.streamResponse = true;
1303
+ }
1304
+ const retryPolicy = meta.retry;
1305
+ const maxRetries = retryPolicy?.attempts ?? 0;
1306
+ for (let retriesUsed = 0; ; ) {
1307
+ const attemptBuilder = baseBuilder.clone();
1308
+ await attemptBuilder.resolveDynamicHeaders();
1309
+ const request = attemptBuilder.build();
1310
+ request.method = method;
1311
+ const attemptOptions = {
1312
+ ...baseOptions
1313
+ };
1314
+ let timeoutController;
1315
+ let timeoutHandle;
1316
+ let combinedSignal;
1317
+ if (typeof meta.timeoutMs === "number" && meta.timeoutMs > 0) {
1318
+ const setup = createTimeoutController(meta.timeoutMs);
1319
+ timeoutController = setup.controller;
1320
+ timeoutHandle = setup.timer;
1321
+ }
1322
+ const existingSignal = attemptOptions.signal;
1323
+ const signals = [];
1324
+ if (existingSignal) {
1325
+ signals.push(existingSignal);
1326
+ }
1327
+ if (timeoutController) {
1328
+ signals.push(timeoutController.signal);
1329
+ }
1330
+ if (signals.length === 1) {
1331
+ const singleSignal = signals[0];
1332
+ if (singleSignal) {
1333
+ attemptOptions.signal = singleSignal;
1334
+ } else if ("signal" in attemptOptions) {
1335
+ delete attemptOptions.signal;
1336
+ }
1337
+ } else if (signals.length > 1) {
1338
+ combinedSignal = combineAbortSignals(signals);
1339
+ attemptOptions.signal = combinedSignal.signal;
1340
+ } else if ("signal" in attemptOptions) {
1341
+ delete attemptOptions.signal;
1342
+ }
1343
+ const activeSignal = attemptOptions.signal;
1344
+ if (activeSignal?.aborted) {
1345
+ const reason = activeSignal.reason ?? createAbortError();
1346
+ throw new HTTPTransportError(request, reason);
1347
+ }
1348
+ const requestContext = {
1349
+ request,
1350
+ options: attemptOptions
1351
+ };
1352
+ let response;
1353
+ try {
1354
+ await this.runRequestPlugins(requestContext);
1355
+ await this.runOnSendHooks(meta, request);
1356
+ const raw = await this.transport.send(request, attemptOptions).catch((cause) => {
1357
+ throw new HTTPTransportError(request, cause);
1358
+ });
1359
+ response = this.buildResponse(raw, request);
1360
+ const isStreaming = meta.streamResponse;
1361
+ if (!isStreaming) {
1362
+ response.data = transformResponse(meta.allowPlainText, response.data);
1363
+ }
1364
+ if (meta.throwOnServerError && response.status >= 500) {
1365
+ throw new HTTPServerError(request, response);
1366
+ }
1367
+ await this.runOnReceiveHooks(meta, response);
1368
+ let validated;
1369
+ if (meta.streamResponse) {
1370
+ validated = response;
1371
+ } else {
1372
+ try {
1373
+ validated = this.validateResponse(response, meta);
1374
+ } catch (cause) {
1375
+ throw new HTTPSchemaValidationError(request, response, cause);
1376
+ }
1377
+ }
1378
+ await this.runResponsePlugins({
1379
+ request,
1380
+ response: validated,
1381
+ options: attemptOptions
1382
+ });
1383
+ return validated;
1384
+ } catch (thrown) {
1385
+ const normalized = thrown instanceof HTTPError ? thrown : thrown;
1386
+ const retryAttempt = retriesUsed + 1;
1387
+ const policy = retryPolicy;
1388
+ const canRetry = policy !== void 0 && retryAttempt <= maxRetries && await this.shouldRetryRequest(
1389
+ normalized,
1390
+ policy,
1391
+ retryAttempt,
1392
+ request
1393
+ );
1394
+ if (!canRetry) {
1395
+ await this.runErrorPlugins({
1396
+ request,
1397
+ options: attemptOptions,
1398
+ error: normalized
1399
+ });
1400
+ throw normalized;
1401
+ }
1402
+ retriesUsed += 1;
1403
+ await this.delayRetry(retryAttempt, policy);
1404
+ } finally {
1405
+ if (timeoutHandle !== void 0) {
1406
+ clearTimeout(timeoutHandle);
1407
+ }
1408
+ combinedSignal?.dispose();
1409
+ }
1410
+ }
1411
+ }
1412
+ async runRequestPlugins(context) {
1413
+ for (const plugin of this.plugins()) {
1414
+ if (plugin.onRequest) {
1415
+ await plugin.onRequest(context);
1416
+ }
1417
+ }
1418
+ }
1419
+ async runResponsePlugins(context) {
1420
+ for (const plugin of this.plugins()) {
1421
+ if (plugin.onResponse) {
1422
+ await plugin.onResponse(context);
1423
+ }
1424
+ }
1425
+ }
1426
+ async runErrorPlugins(context) {
1427
+ for (const plugin of this.plugins()) {
1428
+ if (plugin.onError) {
1429
+ await plugin.onError(context);
1430
+ }
1431
+ }
1432
+ }
1433
+ async runOnSendHooks(meta, request) {
1434
+ for (const [description, hook] of meta.onSend) {
1435
+ try {
1436
+ await hook(request);
1437
+ } catch (error) {
1438
+ throw new errors.AutomationError(
1439
+ `An error occurred in onSend hook "${description}"`,
1440
+ { cause: error }
1441
+ );
1442
+ }
1443
+ }
1444
+ }
1445
+ async runOnReceiveHooks(meta, response) {
1446
+ for (const [description, hook] of meta.onReceive) {
1447
+ try {
1448
+ await hook(response);
1449
+ } catch (error) {
1450
+ throw new errors.AutomationError(
1451
+ `An error occurred in onReceive hook "${description}"`,
1452
+ { cause: error }
1453
+ );
1454
+ }
1455
+ }
1456
+ }
1457
+ validateResponse(response, meta) {
1458
+ const validated = meta.schemas.validate(
1459
+ response.status,
1460
+ response.data,
1461
+ meta.requireSchema
1462
+ );
1463
+ response.data = validated;
1464
+ return response;
1465
+ }
1466
+ buildResponse(raw, request) {
1467
+ return HTTPResponseBuilder.create().status(raw.status).statusText(raw.statusText).headers(normalizeHeaders(raw.headers)).data(raw.data).request(request).build();
1468
+ }
1469
+ plugins() {
1470
+ return [...this.sharedPlugins, ...this.scopedPlugins];
1471
+ }
1472
+ async shouldRetryRequest(error, policy, attempt, request) {
1473
+ if (attempt > policy.attempts) {
1474
+ return false;
1475
+ }
1476
+ const response = error instanceof HTTPError ? error.response : void 0;
1477
+ if (policy.retryOn) {
1478
+ const retryContext = response ? { error, attempt, request, response } : { error, attempt, request };
1479
+ return await policy.retryOn(retryContext);
1480
+ }
1481
+ if (error instanceof HTTPTransportError) {
1482
+ return true;
1483
+ }
1484
+ if (response && response.status >= 500) {
1485
+ return true;
1486
+ }
1487
+ return false;
1488
+ }
1489
+ async delayRetry(attempt, policy) {
1490
+ const { delay } = policy;
1491
+ let duration;
1492
+ if (typeof delay === "function") {
1493
+ duration = await delay(attempt);
1494
+ } else if (typeof delay === "number") {
1495
+ duration = delay * attempt;
1496
+ } else {
1497
+ duration = attempt * 100;
1498
+ }
1499
+ if (!duration || duration <= 0) {
1500
+ return;
1501
+ }
1502
+ await new Promise((resolve) => setTimeout(resolve, duration));
1503
+ }
1504
+ derive(mutate, overrides) {
1505
+ const builder = this.builder.clone();
1506
+ const meta = this.meta.derive();
1507
+ const plugins = [...this.scopedPlugins];
1508
+ if (mutate) {
1509
+ mutate({ builder, meta, plugins });
1510
+ }
1511
+ return new _HTTP(
1512
+ overrides?.transport ?? this.transport,
1513
+ builder,
1514
+ meta,
1515
+ this.sharedPlugins,
1516
+ plugins
1517
+ );
1518
+ }
1519
+ };
1520
+ _HTTP.sharedPlugins = [];
1521
+ var HTTP = _HTTP;
1522
+ function mergeOptions2(base, overrides) {
1523
+ if (!overrides) {
1524
+ return { ...base };
1525
+ }
1526
+ const merged = { ...base };
1527
+ for (const [key, value] of Object.entries(overrides)) {
1528
+ if (value === void 0) {
1529
+ delete merged[key];
1530
+ } else {
1531
+ merged[key] = value;
1532
+ }
1533
+ }
1534
+ return merged;
1535
+ }
1536
+ function normalizeHeaders(headers) {
1537
+ const next = {};
1538
+ for (const [key, value] of Object.entries(headers)) {
1539
+ next[key] = Array.isArray(value) ? value.join(",") : String(value);
1540
+ }
1541
+ return next;
1542
+ }
1543
+ function toParamValue(value, rest) {
1544
+ if (rest.length > 0) {
1545
+ return [value, ...rest];
1546
+ }
1547
+ return value;
1548
+ }
1549
+ function createTimeoutController(timeoutMs) {
1550
+ const controller = new AbortController();
1551
+ const timer = setTimeout(() => {
1552
+ controller.abort(createAbortError(`Request timed out after ${timeoutMs} ms`));
1553
+ }, timeoutMs);
1554
+ maybeUnrefTimer(timer);
1555
+ return { controller, timer };
1556
+ }
1557
+ function combineAbortSignals(signals) {
1558
+ const controller = new AbortController();
1559
+ const aborted = signals.find((signal) => signal.aborted);
1560
+ if (aborted) {
1561
+ controller.abort(aborted.reason ?? createAbortError());
1562
+ return { signal: controller.signal, dispose: () => void 0 };
1563
+ }
1564
+ const listeners = [];
1565
+ for (const signal of signals) {
1566
+ const listener = () => {
1567
+ controller.abort(signal.reason ?? createAbortError());
1568
+ };
1569
+ signal.addEventListener("abort", listener, { once: true });
1570
+ listeners.push({ signal, listener });
1571
+ }
1572
+ const dispose = () => {
1573
+ for (const { signal, listener } of listeners) {
1574
+ signal.removeEventListener("abort", listener);
1575
+ }
1576
+ };
1577
+ controller.signal.addEventListener("abort", dispose, { once: true });
1578
+ return { signal: controller.signal, dispose };
1579
+ }
1580
+ function maybeUnrefTimer(timer) {
1581
+ if (typeof timer === "object" && timer !== null) {
1582
+ const maybeTimer = timer;
1583
+ if (typeof maybeTimer.unref === "function") {
1584
+ maybeTimer.unref();
1585
+ }
1586
+ }
1587
+ }
1588
+ function createAbortError(message = "The operation was aborted.") {
1589
+ const error = new Error(message);
1590
+ error.name = "AbortError";
1591
+ return error;
1592
+ }
1593
+
1594
+ // src/default-schema.ts
1595
+ function AnySchema(data) {
1596
+ return data;
1597
+ }
1598
+ function EmptySchema(data) {
1599
+ if (data !== null && data !== void 0 && data !== "null") {
1600
+ throw new Error(`Expected null but received ${describeValue(data)}`);
1601
+ }
1602
+ return data === "null" ? null : data;
1603
+ }
1604
+ function NullSchema(data) {
1605
+ if (data !== null && data !== "null") {
1606
+ throw new Error(`Expected null but received ${describeValue(data)}`);
1607
+ }
1608
+ return null;
1609
+ }
1610
+ function UndefinedSchema(data) {
1611
+ if (data !== void 0) {
1612
+ throw new Error(`Expected undefined but received ${describeValue(data)}`);
1613
+ }
1614
+ return void 0;
1615
+ }
1616
+ function BooleanSchema(data) {
1617
+ if (typeof data === "boolean" || typeof data === "string" && ["true", "false"].includes(data)) {
1618
+ return typeof data === "boolean" ? data : data === "true";
1619
+ }
1620
+ throw new Error(`Expected boolean but received ${describeValue(data)}`);
1621
+ }
1622
+ function NumberSchema(data) {
1623
+ if (typeof data === "number") {
1624
+ return data;
1625
+ }
1626
+ if (typeof data === "string" && /^(?:\d+|\d*\.\d+)$/.test(data)) {
1627
+ return Number(data);
1628
+ }
1629
+ throw new Error(`Expected number but received ${describeValue(data)}`);
1630
+ }
1631
+ function StringSchema(data) {
1632
+ if (typeof data === "string") {
1633
+ return data;
1634
+ }
1635
+ throw new Error(`Expected string but received ${describeValue(data)}`);
1636
+ }
1637
+ function JSONSchema(data) {
1638
+ if (typeof data === "object" && data !== null) {
1639
+ return data;
1640
+ }
1641
+ if (typeof data === "string") {
1642
+ const parsed = tryParseJson2(data);
1643
+ if (parsed !== void 0) {
1644
+ return parsed;
1645
+ }
1646
+ }
1647
+ throw new Error(`Expected JSON but received ${describeValue(data)}`);
1648
+ }
1649
+ function describeValue(value) {
1650
+ return `<${typeof value}> ${String(value)}`;
1651
+ }
1652
+ function tryParseJson2(value) {
1653
+ try {
1654
+ return JSON.parse(value);
1655
+ } catch {
1656
+ return void 0;
1657
+ }
1658
+ }
1659
+
1660
+ // src/plugins.ts
1661
+ function createLoggingPlugin(sink) {
1662
+ return {
1663
+ name: "http-logging",
1664
+ async onRequest(context) {
1665
+ await sink({
1666
+ type: "request",
1667
+ timestamp: Date.now(),
1668
+ request: context.request,
1669
+ options: context.options
1670
+ });
1671
+ },
1672
+ async onResponse(context) {
1673
+ await sink({
1674
+ type: "response",
1675
+ timestamp: Date.now(),
1676
+ request: context.request,
1677
+ response: context.response,
1678
+ options: context.options
1679
+ });
1680
+ },
1681
+ async onError(context) {
1682
+ await sink({
1683
+ type: "error",
1684
+ timestamp: Date.now(),
1685
+ request: context.request,
1686
+ error: context.error,
1687
+ options: context.options
1688
+ });
1689
+ }
1690
+ };
1691
+ }
1692
+
1693
+ // src/axios-transport.ts
1694
+ function createAxiosTransport(axios) {
1695
+ if (!axios || typeof axios.request !== "function") {
1696
+ throw new Error("Axios transport requires an axios-like client instance.");
1697
+ }
1698
+ return {
1699
+ async send(request, options = {}) {
1700
+ const {
1701
+ headers: optionHeaders,
1702
+ streamResponse,
1703
+ ...restOptions
1704
+ } = options;
1705
+ const config = {
1706
+ url: request.fullUrl ?? "",
1707
+ method: request.method ?? "GET",
1708
+ headers: { ...request.headers },
1709
+ data: request.data,
1710
+ validateStatus: () => true,
1711
+ ...restOptions
1712
+ };
1713
+ if (optionHeaders) {
1714
+ config.headers = mergeHeaders2(config.headers ?? {}, optionHeaders);
1715
+ }
1716
+ if (streamResponse) {
1717
+ config.responseType = config.responseType ?? "stream";
1718
+ }
1719
+ const response = await axios.request(config);
1720
+ return {
1721
+ status: response.status,
1722
+ statusText: response.statusText,
1723
+ headers: response.headers ?? {},
1724
+ data: response.data
1725
+ };
1726
+ }
1727
+ };
1728
+ }
1729
+ function mergeHeaders2(base, overrides) {
1730
+ const next = {};
1731
+ for (const [key, value] of Object.entries(base)) {
1732
+ if (value === void 0 || value === null) {
1733
+ continue;
1734
+ }
1735
+ next[key] = String(value);
1736
+ }
1737
+ for (const [key, value] of Object.entries(overrides)) {
1738
+ if (value === void 0 || value === null) {
1739
+ delete next[key];
1740
+ continue;
1741
+ }
1742
+ next[key] = String(value);
1743
+ }
1744
+ return next;
1745
+ }
1746
+ function ensureHttp(response, options = {}) {
1747
+ return new HttpEnsureChainImpl(response, {
1748
+ ...options.label ? { label: options.label } : {},
1749
+ negated: Boolean(options.negated)
1750
+ });
1751
+ }
1752
+ var HttpEnsureChainImpl = class _HttpEnsureChainImpl {
1753
+ constructor(value, state) {
1754
+ this.value = value;
1755
+ this.label = state.label;
1756
+ this.negated = state.negated;
1757
+ this.normalized = normalizeResponse(value);
1758
+ }
1759
+ get not() {
1760
+ return new _HttpEnsureChainImpl(this.value, {
1761
+ ...this.label ? { label: this.label } : {},
1762
+ negated: !this.negated
1763
+ });
1764
+ }
1765
+ toHaveStatus(expectation) {
1766
+ const { pass, description } = matchesStatus(
1767
+ this.normalized.status,
1768
+ expectation
1769
+ );
1770
+ if (shouldFail(pass, this.negated)) {
1771
+ const baseMessage = this.negated ? `Expected response status not to be ${description}` : `Expected response status to be ${description}`;
1772
+ this.fail({
1773
+ matcher: "toHaveStatus",
1774
+ message: baseMessage,
1775
+ actual: this.normalized.status,
1776
+ expected: description
1777
+ });
1778
+ }
1779
+ return this;
1780
+ }
1781
+ toHaveHeader(name, expectation) {
1782
+ const key = name.toLowerCase();
1783
+ const actual = this.normalized.headers[key];
1784
+ if (expectation === void 0) {
1785
+ const pass2 = actual !== void 0;
1786
+ if (shouldFail(pass2, this.negated)) {
1787
+ const baseMessage = this.negated ? `Expected response not to include header ${name}` : `Expected response to include header ${name}`;
1788
+ this.fail({
1789
+ matcher: "toHaveHeader",
1790
+ message: baseMessage,
1791
+ actual: actual ?? "<missing>",
1792
+ expected: name
1793
+ });
1794
+ }
1795
+ return this;
1796
+ }
1797
+ const pass = matchHeaderValue(actual, expectation);
1798
+ if (shouldFail(pass, this.negated)) {
1799
+ const baseMessage = this.negated ? `Expected header ${name} not to match` : `Expected header ${name} to match`;
1800
+ this.fail({
1801
+ matcher: "toHaveHeader",
1802
+ message: baseMessage,
1803
+ actual: actual ?? "<missing>",
1804
+ expected: expectation
1805
+ });
1806
+ }
1807
+ return this;
1808
+ }
1809
+ toBeCacheable(expectation = {}) {
1810
+ const cacheControl = this.normalized.headers["cache-control"];
1811
+ if (!cacheControl) {
1812
+ if (!this.negated) {
1813
+ this.fail({
1814
+ matcher: "toBeCacheable",
1815
+ message: "Expected Cache-Control header to be present",
1816
+ actual: "<missing>"
1817
+ });
1818
+ }
1819
+ return this;
1820
+ }
1821
+ const directives = parseCacheControl(cacheControl);
1822
+ const impliedCacheable = !("no-store" in directives || "no-cache" in directives);
1823
+ const expectationPass = evaluateCacheExpectations(directives, expectation);
1824
+ const pass = impliedCacheable && expectationPass;
1825
+ if (shouldFail(pass, this.negated)) {
1826
+ const baseMessage = this.negated ? "Expected response not to advertise cacheable directives" : "Expected response to advertise cacheable directives";
1827
+ this.fail({
1828
+ matcher: "toBeCacheable",
1829
+ message: baseMessage,
1830
+ actual: directives,
1831
+ expected: expectation
1832
+ });
1833
+ }
1834
+ return this;
1835
+ }
1836
+ toHaveCorrelationId(headerName = "x-correlation-id") {
1837
+ const key = headerName.toLowerCase();
1838
+ const value = this.normalized.headers[key];
1839
+ const pass = typeof value === "string" && value.trim().length > 0;
1840
+ if (shouldFail(pass, this.negated)) {
1841
+ const baseMessage = this.negated ? `Expected header ${headerName} to be missing or empty` : `Expected header ${headerName} to be present`;
1842
+ this.fail({
1843
+ matcher: "toHaveCorrelationId",
1844
+ message: baseMessage,
1845
+ actual: value ?? "<missing>",
1846
+ expected: headerName
1847
+ });
1848
+ }
1849
+ return this;
1850
+ }
1851
+ fail(details) {
1852
+ const merged = {
1853
+ ...details,
1854
+ ...this.label ? { receivedLabel: this.label } : {}
1855
+ };
1856
+ throw new assertions.EnsureError(merged);
1857
+ }
1858
+ };
1859
+ function shouldFail(pass, negated) {
1860
+ return negated ? pass : !pass;
1861
+ }
1862
+ function normalizeResponse(response) {
1863
+ return {
1864
+ status: response.status,
1865
+ statusText: response.statusText ?? "",
1866
+ headers: normalizeHeaders2(response.headers),
1867
+ original: response.raw ?? response
1868
+ };
1869
+ }
1870
+ function normalizeHeaders2(source) {
1871
+ const result = {};
1872
+ if (typeof source.get === "function") {
1873
+ const entries = source.entries;
1874
+ const iterator = entries ? entries.call(source) : source[Symbol.iterator]?.call(source);
1875
+ if (iterator) {
1876
+ for (const [name, value] of iterator) {
1877
+ result[String(name).toLowerCase()] = String(value);
1878
+ }
1879
+ return result;
1880
+ }
1881
+ }
1882
+ for (const [key, value] of Object.entries(
1883
+ source
1884
+ )) {
1885
+ result[String(key).toLowerCase()] = String(value);
1886
+ }
1887
+ return result;
1888
+ }
1889
+ function matchesStatus(status, expectation) {
1890
+ if (typeof expectation === "number") {
1891
+ return {
1892
+ pass: status === expectation,
1893
+ description: expectation.toString()
1894
+ };
1895
+ }
1896
+ if (typeof expectation === "string") {
1897
+ const digit = Number.parseInt(expectation.charAt(0), 10);
1898
+ if (!Number.isNaN(digit) && expectation.endsWith("xx")) {
1899
+ const min = digit * 100;
1900
+ return {
1901
+ pass: status >= min && status < min + 100,
1902
+ description: `${digit}xx`
1903
+ };
1904
+ }
1905
+ return {
1906
+ pass: status.toString() === expectation,
1907
+ description: expectation
1908
+ };
1909
+ }
1910
+ if (Array.isArray(expectation)) {
1911
+ const [min, max] = expectation;
1912
+ return {
1913
+ pass: status >= min && status <= max,
1914
+ description: `[${min}, ${max}]`
1915
+ };
1916
+ }
1917
+ if (typeof expectation === "function") {
1918
+ return {
1919
+ pass: expectation(status),
1920
+ description: "predicate(status)"
1921
+ };
1922
+ }
1923
+ const range = expectation;
1924
+ return {
1925
+ pass: status >= range.min && status <= range.max,
1926
+ description: `[${range.min}, ${range.max}]`
1927
+ };
1928
+ }
1929
+ function matchHeaderValue(actual, expected) {
1930
+ if (actual === void 0) {
1931
+ return false;
1932
+ }
1933
+ if (typeof expected === "string") {
1934
+ return actual === expected;
1935
+ }
1936
+ if (expected instanceof RegExp) {
1937
+ return expected.test(actual);
1938
+ }
1939
+ if (Array.isArray(expected)) {
1940
+ const list = expected;
1941
+ const actualParts = actual.split(",").map((part) => part.trim()).filter(Boolean);
1942
+ return list.every((value) => actualParts.includes(value));
1943
+ }
1944
+ return expected(actual);
1945
+ }
1946
+ function parseCacheControl(value) {
1947
+ const directives = {};
1948
+ for (const segment of value.split(",")) {
1949
+ const trimmed = segment.trim();
1950
+ if (!trimmed) {
1951
+ continue;
1952
+ }
1953
+ const [rawName, rawParameter] = trimmed.split("=", 2);
1954
+ const name = rawName?.trim();
1955
+ if (!name) {
1956
+ continue;
1957
+ }
1958
+ if (rawParameter === void 0) {
1959
+ directives[name.toLowerCase()] = true;
1960
+ continue;
1961
+ }
1962
+ const parameter = rawParameter.trim().replace(/^"|"$/g, "");
1963
+ directives[name.toLowerCase()] = parameter;
1964
+ }
1965
+ return directives;
1966
+ }
1967
+ function evaluateCacheExpectations(directives, expectation) {
1968
+ if (expectation.cacheability) {
1969
+ if (!(expectation.cacheability in directives)) {
1970
+ return false;
1971
+ }
1972
+ }
1973
+ if (expectation.maxAge !== void 0) {
1974
+ const raw = directives["max-age"];
1975
+ if (typeof raw !== "string") {
1976
+ return false;
1977
+ }
1978
+ const parsed = Number.parseInt(raw, 10);
1979
+ if (Number.isNaN(parsed)) {
1980
+ return false;
1981
+ }
1982
+ if (typeof expectation.maxAge === "number") {
1983
+ if (parsed !== expectation.maxAge) {
1984
+ return false;
1985
+ }
1986
+ } else {
1987
+ const { min, max } = expectation.maxAge;
1988
+ if (min !== void 0 && parsed < min) {
1989
+ return false;
1990
+ }
1991
+ if (max !== void 0 && parsed > max) {
1992
+ return false;
1993
+ }
1994
+ }
1995
+ }
1996
+ if (expectation.sMaxAge !== void 0) {
1997
+ const raw = directives["s-maxage"];
1998
+ if (typeof raw !== "string") {
1999
+ return false;
2000
+ }
2001
+ const parsed = Number.parseInt(raw, 10);
2002
+ if (Number.isNaN(parsed) || parsed !== expectation.sMaxAge) {
2003
+ return false;
2004
+ }
2005
+ }
2006
+ if (expectation.revalidate) {
2007
+ if (!("must-revalidate" in directives || "proxy-revalidate" in directives)) {
2008
+ return false;
2009
+ }
2010
+ }
2011
+ if (expectation.immutable && !("immutable" in directives)) {
2012
+ return false;
2013
+ }
2014
+ return true;
2015
+ }
2016
+
2017
+ // src/assertions/http-assertions-plugin.ts
2018
+ var httpAssertionsPlugin = () => ({ isNot }) => (_world) => {
2019
+ const facet = (response, options) => {
2020
+ return ensureHttp(response, {
2021
+ ...options?.label ? { label: options.label } : {},
2022
+ negated: isNot
2023
+ });
2024
+ };
2025
+ return facet;
2026
+ };
2027
+
2028
+ // src/assertions/http-adapters.ts
2029
+ function fromHttpResponse(response) {
2030
+ return {
2031
+ status: response.status,
2032
+ statusText: response.statusText ?? "",
2033
+ headers: response.headers,
2034
+ data: response.data,
2035
+ raw: response
2036
+ };
2037
+ }
2038
+ function fromFetchResponse(response, data) {
2039
+ return {
2040
+ status: response.status,
2041
+ statusText: response.statusText ?? "",
2042
+ headers: response.headers,
2043
+ data,
2044
+ raw: response
2045
+ };
2046
+ }
2047
+
2048
+ exports.AnySchema = AnySchema;
2049
+ exports.BooleanSchema = BooleanSchema;
2050
+ exports.EmptySchema = EmptySchema;
2051
+ exports.HTTP = HTTP;
2052
+ exports.HTTPError = HTTPError;
2053
+ exports.HTTPRequest = HTTPRequest;
2054
+ exports.HTTPRequestBuilder = HTTPRequestBuilder;
2055
+ exports.HTTPResponse = HTTPResponse;
2056
+ exports.HTTPResponseBuilder = HTTPResponseBuilder;
2057
+ exports.HTTPSchemaValidationError = HTTPSchemaValidationError;
2058
+ exports.HTTPTransportError = HTTPTransportError;
2059
+ exports.JSONSchema = JSONSchema;
2060
+ exports.MetaConfig = MetaConfig;
2061
+ exports.MetaConfigBuilder = MetaConfigBuilder;
2062
+ exports.NullSchema = NullSchema;
2063
+ exports.NumberSchema = NumberSchema;
2064
+ exports.SchemaMap = SchemaMap;
2065
+ exports.StringSchema = StringSchema;
2066
+ exports.UndefinedSchema = UndefinedSchema;
2067
+ exports.createAxiosTransport = createAxiosTransport;
2068
+ exports.createFetchTransport = createFetchTransport;
2069
+ exports.createLoggingPlugin = createLoggingPlugin;
2070
+ exports.ensureHttp = ensureHttp;
2071
+ exports.fromFetchResponse = fromFetchResponse;
2072
+ exports.fromHttpResponse = fromHttpResponse;
2073
+ exports.httpAssertionsPlugin = httpAssertionsPlugin;
2074
+ exports.transformResponse = transformResponse;
2075
+ //# sourceMappingURL=out.js.map
2076
+ //# sourceMappingURL=index.cjs.map