@autometa/http 1.2.0 → 1.3.0

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/index.js CHANGED
@@ -53,133 +53,425 @@ var __privateSet = (obj, member, value, setter) => {
53
53
  setter ? setter.call(obj, value) : member.set(obj, value);
54
54
  return value;
55
55
  };
56
+ var __privateMethod = (obj, member, method) => {
57
+ __accessCheck(obj, member, "access private method");
58
+ return method;
59
+ };
56
60
 
57
61
  // src/index.ts
58
62
  var src_exports = {};
59
63
  __export(src_exports, {
60
- DerivedHTTPResponse: () => DerivedHTTPResponse,
64
+ AnySchema: () => AnySchema,
65
+ AxiosClient: () => AxiosClient,
66
+ BooleanSchema: () => BooleanSchema,
67
+ EmptySchema: () => EmptySchema,
61
68
  HTTP: () => HTTP,
62
- HTTPResponse: () => HTTPResponse
69
+ HTTPClient: () => HTTPClient,
70
+ HTTPRequest: () => HTTPRequest,
71
+ HTTPRequestBuilder: () => HTTPRequestBuilder,
72
+ HTTPResponse: () => HTTPResponse,
73
+ HTTPResponseBuilder: () => HTTPResponseBuilder,
74
+ JSONSchema: () => JSONSchema,
75
+ NullSchema: () => NullSchema,
76
+ NumberSchema: () => NumberSchema,
77
+ StringSchema: () => StringSchema,
78
+ UndefinedSchema: () => UndefinedSchema,
79
+ defaultClient: () => defaultClient
63
80
  });
64
81
  module.exports = __toCommonJS(src_exports);
65
82
 
66
- // src/http.response.ts
67
- var HTTPResponse = class {
68
- static derive(original, data) {
69
- const response = new DerivedHTTPResponse();
70
- if (typeof data === "function") {
71
- const fn = data;
72
- response.data = fn(original.data);
73
- } else {
74
- response.data = data;
75
- }
76
- response.status = original.status;
77
- response.statusText = original.statusText;
78
- response.headers = original.headers;
79
- response.request = original.request;
80
- response.actual = original;
83
+ // src/http-response.ts
84
+ var HTTPResponse = class _HTTPResponse {
85
+ constructor() {
86
+ this.headers = {};
87
+ }
88
+ static fromRaw(response) {
89
+ const newResponse = new _HTTPResponse();
90
+ Object.assign(newResponse, response);
81
91
  return response;
82
92
  }
93
+ decompose(transformFn) {
94
+ const value = getDecompositionValue(this.data, transformFn);
95
+ return new HTTPResponseBuilder().status(this.status).statusText(this.statusText).headers(this.headers).request(this.request).data(value).build();
96
+ }
83
97
  };
84
- var DerivedHTTPResponse = class extends HTTPResponse {
98
+ function getDecompositionValue(data, transformFn) {
99
+ return typeof transformFn === "function" ? transformFn(data) : transformFn;
100
+ }
101
+ var _response;
102
+ var _HTTPResponseBuilder = class _HTTPResponseBuilder {
103
+ constructor() {
104
+ __privateAdd(this, _response, new HTTPResponse());
105
+ }
106
+ static create() {
107
+ return new _HTTPResponseBuilder();
108
+ }
109
+ derive() {
110
+ return _HTTPResponseBuilder.create().data(__privateGet(this, _response).data).headers(__privateGet(this, _response).headers).request(__privateGet(this, _response).request).status(__privateGet(this, _response).status).statusText(__privateGet(this, _response).statusText);
111
+ }
112
+ status(code) {
113
+ __privateGet(this, _response).status = code;
114
+ return this;
115
+ }
116
+ statusText(text) {
117
+ __privateGet(this, _response).statusText = text;
118
+ return this;
119
+ }
120
+ data(data) {
121
+ __privateGet(this, _response).data = data;
122
+ return this;
123
+ }
124
+ headers(dict) {
125
+ __privateGet(this, _response).headers = dict;
126
+ return this;
127
+ }
128
+ header(name, value) {
129
+ __privateGet(this, _response).headers[name] = value;
130
+ return this;
131
+ }
132
+ request(request) {
133
+ __privateGet(this, _response).request = request;
134
+ return this;
135
+ }
136
+ build() {
137
+ return __privateGet(this, _response);
138
+ }
139
+ };
140
+ _response = new WeakMap();
141
+ var HTTPResponseBuilder = _HTTPResponseBuilder;
142
+
143
+ // src/axios-client.ts
144
+ var import_axios = __toESM(require("axios"), 1);
145
+
146
+ // src/http-client.ts
147
+ var defaultClient;
148
+ var HTTPClient = class {
149
+ static Use(client) {
150
+ if (client) {
151
+ defaultClient = client;
152
+ }
153
+ return function(target) {
154
+ defaultClient = target;
155
+ };
156
+ }
85
157
  };
86
158
 
159
+ // src/axios-client.ts
160
+ var AxiosClient = class extends HTTPClient {
161
+ async request(request, options) {
162
+ const { baseUrl, route, params, headers, method, data } = request;
163
+ const url = [baseUrl, ...route].join("/");
164
+ const axiosRequest = {
165
+ url,
166
+ params,
167
+ headers,
168
+ method,
169
+ data,
170
+ validateStatus: function(status) {
171
+ return status >= 0 && status < 600;
172
+ },
173
+ ...options
174
+ };
175
+ const response = await (0, import_axios.default)(axiosRequest);
176
+ return HTTPResponseBuilder.create().status(response.status).statusText(response.statusText).data(response.data).headers(response.headers).request(request).build();
177
+ }
178
+ };
179
+ AxiosClient = __decorateClass([
180
+ HTTPClient.Use()
181
+ ], AxiosClient);
182
+
87
183
  // src/http.ts
88
- var import_injection2 = require("@autometa/injection");
184
+ var import_injection = require("@autometa/injection");
185
+
186
+ // src/default-client-factory.ts
187
+ function defaultClientFactory() {
188
+ const type = defaultClient;
189
+ return new type();
190
+ }
89
191
 
90
- // src/http.builder.ts
91
- var import_errors4 = require("@autometa/errors");
192
+ // src/http-request.ts
92
193
  var import_url_join_ts = require("url-join-ts");
194
+ var HTTPRequest = class _HTTPRequest {
195
+ constructor(config) {
196
+ this.headers = {};
197
+ this.params = {};
198
+ this.route = [];
199
+ Object.assign(this, config);
200
+ }
201
+ /**
202
+ * Returns the full URL of the request, including the base url,
203
+ * routes, and query parameters.
204
+ *
205
+ * ```ts
206
+ * console.log(request.fullUrl())// https://example.com/foo?bar=baz?array=1,2,3
207
+ * ```
208
+ *
209
+ * Note characters may be converted to escape codes. I.e (space => %20) and (comma => %2C)
210
+ *
211
+ * N.B this method estimates what the url will be. The actual value
212
+ * might be different depending on your underlying HTTPClient and
213
+ * configuration. For example, query parameters might
214
+ * use different array formats.
215
+ */
216
+ fullUrl() {
217
+ return (0, import_url_join_ts.urlJoinP)(this.baseUrl, this.route, this.params);
218
+ }
219
+ /**
220
+ * Returns a new independent copy of the request.
221
+ */
222
+ static derive(original) {
223
+ const request = new _HTTPRequest();
224
+ request.headers = { ...original.headers };
225
+ request.params = { ...original.params };
226
+ request.baseUrl = original.baseUrl;
227
+ request.route = [...original.route];
228
+ request.method = original.method;
229
+ request.data = original.data;
230
+ return request;
231
+ }
232
+ };
233
+ var _request, _dynamicHeaders;
234
+ var _HTTPRequestBuilder = class _HTTPRequestBuilder {
235
+ constructor(request = () => new HTTPRequest()) {
236
+ __privateAdd(this, _request, void 0);
237
+ __privateAdd(this, _dynamicHeaders, /* @__PURE__ */ new Map());
238
+ if (typeof request === "function") {
239
+ __privateSet(this, _request, request());
240
+ return;
241
+ }
242
+ __privateSet(this, _request, request);
243
+ }
244
+ static create() {
245
+ return new _HTTPRequestBuilder();
246
+ }
247
+ get request() {
248
+ return __privateGet(this, _request);
249
+ }
250
+ resolveDynamicHeaders() {
251
+ for (const [name, value] of __privateGet(this, _dynamicHeaders)) {
252
+ try {
253
+ __privateGet(this, _request).headers[name] = String(value());
254
+ } catch (e) {
255
+ const cause = e;
256
+ const msg = `Failed to resolve dynamic header "${name}":
257
+ ${cause}`;
258
+ throw new Error(msg);
259
+ }
260
+ }
261
+ return this;
262
+ }
263
+ url(url) {
264
+ __privateGet(this, _request).baseUrl = url;
265
+ return this;
266
+ }
267
+ route(...route) {
268
+ __privateGet(this, _request).route.push(...route);
269
+ return this;
270
+ }
271
+ param(name, value) {
272
+ if (Array.isArray(value)) {
273
+ const asStr = value.map(String);
274
+ __privateGet(this, _request).params[name] = asStr;
275
+ return this;
276
+ }
277
+ if (!Array.isArray(value) && typeof value === "object") {
278
+ __privateGet(this, _request).params[name] = value;
279
+ return this;
280
+ }
281
+ __privateGet(this, _request).params[name] = String(value);
282
+ return this;
283
+ }
284
+ params(dict) {
285
+ Object.assign(__privateGet(this, _request).params, dict);
286
+ return this;
287
+ }
288
+ data(data) {
289
+ __privateGet(this, _request).data = data;
290
+ return this;
291
+ }
292
+ header(name, value) {
293
+ if (typeof value === "function") {
294
+ value = value();
295
+ }
296
+ __privateGet(this, _request).headers[name] = String(value);
297
+ return this;
298
+ }
299
+ headers(dict) {
300
+ Object.assign(__privateGet(this, _request).headers, dict);
301
+ return this;
302
+ }
303
+ get() {
304
+ return __privateGet(this, _request);
305
+ }
306
+ method(method) {
307
+ __privateGet(this, _request).method = method;
308
+ return this;
309
+ }
310
+ derive() {
311
+ const request = HTTPRequest.derive(__privateGet(this, _request));
312
+ return new _HTTPRequestBuilder(request);
313
+ }
314
+ build() {
315
+ return __privateGet(this, _request);
316
+ }
317
+ };
318
+ _request = new WeakMap();
319
+ _dynamicHeaders = new WeakMap();
320
+ var HTTPRequestBuilder = _HTTPRequestBuilder;
93
321
 
94
322
  // src/schema.map.ts
95
- var import_errors = require("@autometa/errors");
96
- var import_status_codes = require("@autometa/status-codes");
97
- var _children, _map;
98
- var SchemaMap = class {
99
- constructor() {
100
- __privateAdd(this, _children, []);
101
- __privateAdd(this, _map, /* @__PURE__ */ new Map());
323
+ var _map;
324
+ var _SchemaMap = class _SchemaMap {
325
+ constructor(map) {
326
+ __privateAdd(this, _map, void 0);
327
+ if (map instanceof _SchemaMap) {
328
+ __privateSet(this, _map, new Map(__privateGet(map, _map)));
329
+ return;
330
+ }
331
+ __privateSet(this, _map, new Map(map));
102
332
  }
103
- register(parser, ...args) {
104
- args.forEach((arg) => {
105
- if (typeof arg === "number") {
106
- this.registerSingle(parser, arg);
107
- } else {
108
- this.registerRange(parser, arg);
109
- }
110
- });
111
- return parser.parse;
333
+ derive() {
334
+ return new _SchemaMap(__privateGet(this, _map));
112
335
  }
113
- registerSingle(parser, ...codes) {
336
+ registerStatus(parser, ...codes) {
114
337
  codes.forEach((code) => {
115
338
  if (__privateGet(this, _map).has(code)) {
116
- throw new import_errors.AutomationError(
117
- `Status code ${code} is already registered with a parser`
118
- );
339
+ const msg = `Status code ${code} is already registered with a parser`;
340
+ throw new Error(msg);
119
341
  }
120
- assertIsStatusCode(code);
121
342
  __privateGet(this, _map).set(code, parser);
122
343
  });
123
344
  }
124
- including(map) {
125
- __privateGet(this, _children).includes(map);
126
- return this;
127
- }
128
- registerRange(parser, ...range) {
129
- range.forEach(({ from, to }) => {
130
- assertIsStatusCode(from);
131
- assertIsStatusCode(to);
132
- for (let i = from; i <= to; i++) {
133
- if (!IsStatusCode(i)) {
134
- continue;
135
- }
136
- if (__privateGet(this, _map).has(i)) {
137
- throw new import_errors.AutomationError(
138
- `Status code ${i} is already registered with a parser`
139
- );
140
- }
141
- __privateGet(this, _map).set(i, parser);
345
+ registerRange(parser, from, to) {
346
+ for (let i = from; i <= to; i++) {
347
+ if (__privateGet(this, _map).has(i)) {
348
+ throw new Error(`Status code ${i} is already registered with a parser`);
142
349
  }
143
- });
350
+ __privateGet(this, _map).set(i, parser);
351
+ }
144
352
  }
145
- get(status) {
146
- assertIsStatusCode(status);
147
- const local = __privateGet(this, _map).get(status);
148
- if (local) {
149
- return local;
353
+ validate(status, data, requireSchema) {
354
+ const parser = this.getParser(status, requireSchema);
355
+ if ("parse" in parser) {
356
+ return parser.parse(data);
150
357
  }
151
- const nested = __privateGet(this, _children).find((it) => __privateGet(it, _map).has(status));
152
- return nested?.get(status);
153
- }
154
- validate(status, response, strict) {
155
- const parser = this.get(status);
156
- if (!parser) {
157
- if (!strict) {
158
- return response;
159
- }
160
- throw new import_errors.AutomationError(
161
- `No schema parser registered for status code ${status} and 'requireSchema' is set to true`
162
- );
358
+ if ("validate" in parser) {
359
+ return parser.validate(data);
360
+ }
361
+ try {
362
+ return parser(data);
363
+ } catch (e) {
364
+ const msg = `Failed to schema parse response data for status code ${status} with data:
365
+
366
+ ${JSON.stringify(data, null, 2)}}`;
367
+ throw new Error(msg);
368
+ }
369
+ }
370
+ getParser(status, requireSchema) {
371
+ const parser = __privateGet(this, _map).get(status);
372
+ if (!parser && requireSchema) {
373
+ const msg = `No parser registered for status code ${status} but 'requireSchema' is true`;
374
+ throw new Error(msg);
375
+ }
376
+ if (parser) {
377
+ return parser;
163
378
  }
164
- return parser.parse(response);
379
+ return (data) => data;
380
+ }
381
+ toObject() {
382
+ return Object.fromEntries(__privateGet(this, _map));
165
383
  }
166
384
  };
167
- _children = new WeakMap();
168
385
  _map = new WeakMap();
169
- function assertIsStatusCode(value) {
170
- const result = Object.values(import_status_codes.StatusCodes).map((it) => it.status).includes(value);
171
- if (!result) {
172
- throw new import_errors.AutomationError(
173
- `Expected status code ${value} to be a valid status code, but it is not a known HTTP codeF`
174
- );
386
+ var SchemaMap = _SchemaMap;
387
+
388
+ // src/request-meta.config.ts
389
+ var MetaConfig = class {
390
+ constructor() {
391
+ this.onSend = [];
392
+ this.onReceive = [];
175
393
  }
176
- }
177
- function IsStatusCode(value) {
178
- return Object.values(import_status_codes.StatusCodes).map((it) => it.status).includes(value);
179
- }
394
+ };
395
+ var _schemaMap, _requireSchema, _allowPlainText, _onBeforeSend, _onAfterSend, _throwOnServerError, _setOnSend, setOnSend_fn, _setOnReceive, setOnReceive_fn;
396
+ var _MetaConfigBuilder = class _MetaConfigBuilder {
397
+ constructor() {
398
+ __privateAdd(this, _setOnSend);
399
+ __privateAdd(this, _setOnReceive);
400
+ __privateAdd(this, _schemaMap, new SchemaMap());
401
+ __privateAdd(this, _requireSchema, false);
402
+ __privateAdd(this, _allowPlainText, false);
403
+ __privateAdd(this, _onBeforeSend, []);
404
+ __privateAdd(this, _onAfterSend, []);
405
+ __privateAdd(this, _throwOnServerError, false);
406
+ }
407
+ schemaMap(map) {
408
+ __privateSet(this, _schemaMap, map);
409
+ return this;
410
+ }
411
+ schema(parser, ...args) {
412
+ args.forEach((arg) => {
413
+ if (typeof arg === "number") {
414
+ __privateGet(this, _schemaMap).registerStatus(parser, arg);
415
+ } else {
416
+ __privateGet(this, _schemaMap).registerRange(parser, arg.from, arg.to);
417
+ }
418
+ });
419
+ return this;
420
+ }
421
+ requireSchema(value) {
422
+ __privateSet(this, _requireSchema, value);
423
+ return this;
424
+ }
425
+ allowPlainText(value) {
426
+ __privateSet(this, _allowPlainText, value);
427
+ return this;
428
+ }
429
+ onBeforeSend(description, hook) {
430
+ __privateGet(this, _onBeforeSend).push([description, hook]);
431
+ return this;
432
+ }
433
+ throwOnServerError(value) {
434
+ __privateSet(this, _throwOnServerError, value);
435
+ return this;
436
+ }
437
+ onReceiveResponse(description, hook) {
438
+ __privateGet(this, _onAfterSend).push([description, hook]);
439
+ return this;
440
+ }
441
+ build() {
442
+ const config = new MetaConfig();
443
+ config.schemas = __privateGet(this, _schemaMap).derive();
444
+ config.requireSchema = __privateGet(this, _requireSchema);
445
+ config.allowPlainText = __privateGet(this, _allowPlainText);
446
+ config.onSend = __privateGet(this, _onBeforeSend);
447
+ config.onReceive = __privateGet(this, _onAfterSend);
448
+ return config;
449
+ }
450
+ derive() {
451
+ var _a, _b;
452
+ return __privateMethod(_b = __privateMethod(_a = new _MetaConfigBuilder().schemaMap(__privateGet(this, _schemaMap).derive()).requireSchema(__privateGet(this, _requireSchema)).allowPlainText(__privateGet(this, _allowPlainText)).throwOnServerError(__privateGet(this, _throwOnServerError)), _setOnSend, setOnSend_fn).call(_a, __privateGet(this, _onBeforeSend)), _setOnReceive, setOnReceive_fn).call(_b, __privateGet(this, _onAfterSend));
453
+ }
454
+ };
455
+ _schemaMap = new WeakMap();
456
+ _requireSchema = new WeakMap();
457
+ _allowPlainText = new WeakMap();
458
+ _onBeforeSend = new WeakMap();
459
+ _onAfterSend = new WeakMap();
460
+ _throwOnServerError = new WeakMap();
461
+ _setOnSend = new WeakSet();
462
+ setOnSend_fn = function(hooks) {
463
+ __privateSet(this, _onBeforeSend, hooks);
464
+ return this;
465
+ };
466
+ _setOnReceive = new WeakSet();
467
+ setOnReceive_fn = function(hooks) {
468
+ __privateSet(this, _onAfterSend, hooks);
469
+ return this;
470
+ };
471
+ var MetaConfigBuilder = _MetaConfigBuilder;
180
472
 
181
473
  // src/transform-response.ts
182
- var import_errors2 = require("@autometa/errors");
474
+ var import_errors = require("@autometa/errors");
183
475
  var import_assert_is_json = __toESM(require("@stdlib/assert-is-json"), 1);
184
476
  var import_cli_highlight = require("cli-highlight");
185
477
  function transformResponse(allowPlainText, data) {
@@ -195,12 +487,15 @@ function transformResponse(allowPlainText, data) {
195
487
  if ((0, import_assert_is_json.default)(data)) {
196
488
  return JSON.parse(data);
197
489
  }
198
- if (["true", "false"].includes(data)) {
490
+ if (typeof data === "string" && ["true", "false"].includes(data)) {
199
491
  return JSON.parse(data);
200
492
  }
201
- if (/^\d*\.?\d+$/.test(data)) {
493
+ if (typeof data === "string" && /^\d*\.?\d+$/.test(data)) {
202
494
  return JSON.parse(data);
203
495
  }
496
+ if (typeof data === "object") {
497
+ return data;
498
+ }
204
499
  if (allowPlainText) {
205
500
  return data;
206
501
  }
@@ -208,394 +503,606 @@ function transformResponse(allowPlainText, data) {
208
503
  const message = [
209
504
  `Could not parse a response as json, and this request was not configured to allow plain text responses.`,
210
505
  `To allow plain text responses, use the 'allowPlainText' method on the HTTP client.`,
211
- " ",
506
+ "",
212
507
  response
213
508
  ];
214
- throw new import_errors2.AutomationError(message.join("\n"));
509
+ throw new import_errors.AutomationError(message.join("\n"));
215
510
  }
216
511
 
217
- // src/axios-executor.ts
218
- var import_axios = __toESM(require("axios"), 1);
219
- var import_class_transformer = require("class-transformer");
220
- var import_errors3 = require("@autometa/errors");
221
- var _result;
222
- var AxiosExecutor = class {
223
- constructor(options, schemaMap, requestState, requireSchema) {
224
- this.options = options;
225
- this.schemaMap = schemaMap;
226
- this.requestState = requestState;
227
- this.requireSchema = requireSchema;
228
- __privateAdd(this, _result, {});
229
- }
230
- get error() {
231
- return __privateGet(this, _result).error;
232
- }
233
- get requestSucceeded() {
234
- return __privateGet(this, _result).response !== void 0;
235
- }
236
- get validationFailed() {
237
- return __privateGet(this, _result).validated === void 0;
238
- }
239
- async tryRequest() {
240
- try {
241
- __privateGet(this, _result).response = await (0, import_axios.default)(this.options);
242
- this.tryValidate();
243
- } catch (e) {
244
- if (__privateGet(this, _result).error) {
245
- return;
246
- }
247
- const { method, fullUrl, data, headers } = this.requestState;
248
- const body = JSON.stringify(data, null, 2);
249
- const headersString = JSON.stringify(headers, null, 2);
250
- const message = `Failed to send request to ${method}:${fullUrl}.
251
- headers:
252
- ${headersString}
253
-
254
- body:
255
- ${body}`;
256
- __privateGet(this, _result).error = new import_errors3.AutomationError(message, { cause: e });
257
- }
512
+ // src/http.ts
513
+ var import_errors2 = require("@autometa/errors");
514
+ var _request2, _metaConfig, _makeRequest, makeRequest_fn, _validateResponse, validateResponse_fn;
515
+ var HTTP = class {
516
+ constructor(client = defaultClientFactory(), builder = new HTTPRequestBuilder(), metaConfig = new MetaConfigBuilder()) {
517
+ this.client = client;
518
+ __privateAdd(this, _makeRequest);
519
+ __privateAdd(this, _validateResponse);
520
+ __privateAdd(this, _request2, void 0);
521
+ __privateAdd(this, _metaConfig, void 0);
522
+ __privateSet(this, _request2, builder.derive());
523
+ __privateSet(this, _metaConfig, metaConfig.derive());
524
+ }
525
+ static create(client = new AxiosClient(), builder = new HTTPRequestBuilder(), metaConfig = new MetaConfigBuilder()) {
526
+ return new HTTP(client, builder, metaConfig);
527
+ }
528
+ /**
529
+ * Sets the base url of the request for this client, such as
530
+ * `https://api.example.com`, and could include always-used routes like
531
+ * the api version, such as `/v1` or `/api/v1` at the end.
532
+ *
533
+ * ```ts
534
+ *
535
+ * \@Fixture(INJECTION_SCOPE.TRANSIENT)
536
+ * export abstract class BaseClient {
537
+ * constructor(protected readonly http: HTTP) {
538
+ * this.http.url("https://api.example.com");
539
+ * }
540
+ * }
541
+ * ```
542
+ * @param url
543
+ * @returns
544
+ */
545
+ url(url) {
546
+ __privateGet(this, _request2).url(url);
547
+ return this;
258
548
  }
259
- async tryValidate() {
260
- const { status, data } = __privateGet(this, _result).response;
261
- const { method, fullUrl } = this.requestState;
262
- try {
263
- __privateGet(this, _result).validated = this.schemaMap.validate(
264
- status,
265
- data,
266
- this.requireSchema
267
- );
268
- } catch (e) {
269
- const error = e;
270
- const message = `Failed to validate response from ${method}:${fullUrl}.
271
-
272
- Provided body was:
273
- ${JSON.stringify(data, null, 2)}`;
274
- __privateGet(this, _result).error = new import_errors3.AutomationError(message, { cause: error });
275
- }
549
+ /**
550
+ * If set to true, all requests derived from this client will require a schema be defined
551
+ * matching any response status code. If set to false, a schema will still be used for validation
552
+ * if defined, or the unadulterated original body will be returned if no schema matches.
553
+ *
554
+ * @param required Whether or not a schema is required for all responses.
555
+ * @returns This instance of HTTP.
556
+ */
557
+ requireSchema(required) {
558
+ __privateGet(this, _metaConfig).requireSchema(required);
559
+ return this;
276
560
  }
277
- getValidatedResponse() {
278
- const { status, statusText, headers } = __privateGet(this, _result).response;
279
- const { validated: data } = __privateGet(this, _result);
280
- const { fullUrl: url, method } = this.requestState;
281
- return (0, import_class_transformer.plainToInstance)(HTTPResponse, {
282
- status,
283
- statusText,
284
- headers,
285
- data,
286
- request: {
287
- url,
288
- method
289
- }
290
- });
561
+ /**
562
+ * If set to true, all requests derived from this client will allow plain text
563
+ * responses. If set to false, plain text responses will throw an serialization error.
564
+ *
565
+ * Useful when an endpoint returns a HTML or plain text response. If the plain text
566
+ * is the value of `true` or `false`, or a number, it will be parsed into the
567
+ * appropriate type.
568
+ *
569
+ * This method is a shared chain method, and will return the same instance of HTTP.
570
+ *
571
+ * @param allow Whether or not plain text responses are allowed.
572
+ * @returns This instance of HTTP.
573
+ */
574
+ sharedAllowPlainText(allow) {
575
+ __privateGet(this, _metaConfig).allowPlainText(allow);
576
+ return this;
291
577
  }
292
- getResponse() {
293
- const { status, statusText, headers, data } = __privateGet(this, _result).response;
294
- const { fullUrl: url, method } = this.requestState;
295
- return (0, import_class_transformer.plainToInstance)(
296
- HTTPResponse,
297
- {
298
- status,
299
- statusText,
300
- headers,
301
- data,
302
- request: {
303
- url,
304
- method
305
- }
306
- },
307
- { excludeExtraneousValues: true }
578
+ /**
579
+ * If set to true, all requests derived from this client will allow plain text
580
+ * responses. If set to false, plain text responses will throw an serialization error.
581
+ *
582
+ * Useful when an endpoint returns a HTML or plain text response. If the plain text
583
+ * is the value of `true` or `false`, or a number, it will be parsed into the
584
+ * appropriate type.
585
+ *
586
+ * This method is a request chain method, and will return a new instance of HTTP.
587
+ *
588
+ * @param allow Whether or not plain text responses are allowed.
589
+ * @returns A new child instance of HTTP derived from this one.
590
+ */
591
+ allowPlainText(allow) {
592
+ return HTTP.create(
593
+ this.client,
594
+ __privateGet(this, _request2).derive(),
595
+ __privateGet(this, _metaConfig).derive().allowPlainText(allow)
308
596
  );
309
597
  }
310
- };
311
- _result = new WeakMap();
312
-
313
- // src/http.builder.ts
314
- var import_injection = require("@autometa/injection");
315
- var _headers, _params, _url, _route, _method, _schemaMap, _responseType, _data, _requireSchema, _allowPlainText, _onBeforeSend, _onAfterSend;
316
- var HTTPRequestBuilder = class {
317
- constructor(map) {
318
- __privateAdd(this, _headers, /* @__PURE__ */ new Map());
319
- __privateAdd(this, _params, /* @__PURE__ */ new Map());
320
- __privateAdd(this, _url, void 0);
321
- __privateAdd(this, _route, []);
322
- __privateAdd(this, _method, void 0);
323
- __privateAdd(this, _schemaMap, new SchemaMap());
324
- __privateAdd(this, _responseType, "json");
325
- __privateAdd(this, _data, void 0);
326
- __privateAdd(this, _requireSchema, false);
327
- __privateAdd(this, _allowPlainText, false);
328
- __privateAdd(this, _onBeforeSend, []);
329
- __privateAdd(this, _onAfterSend, []);
330
- __privateSet(this, _schemaMap, new SchemaMap().including(map));
331
- }
332
- requireSchema(value) {
333
- __privateSet(this, _requireSchema, value);
598
+ /**
599
+ * Attaches a route to the request, such as `/product` or `/user`. Subsequent calls
600
+ * to this method will append the route to the existing route, such as `/product/1`.
601
+ *
602
+ * Numbers will be converted to strings automatically. Routes can be defined one
603
+ * at a time or as a spread argument.
604
+ *
605
+ * ```ts
606
+ * constructor(http: HTTP) {
607
+ * super(http);
608
+ * this.http.sharedRoute("user", id).get();
609
+ * }
610
+ *
611
+ * // or
612
+ *
613
+ * constructor(http: HTTP) {
614
+ * super(http);
615
+ * this.http
616
+ * .sharedRoute("user")
617
+ * .sharedRoute(id)
618
+ * .get();
619
+ * }
620
+ * ```
621
+ *
622
+ * This method is a shared chain method, and will return the same instance of HTTP. All
623
+ * child clients will inherit the routes defined by this method. Useful to configure
624
+ * in the constructor body.
625
+ *
626
+ * @param route A route or spread list of routes to append to the request.
627
+ * @returns This instance of HTTP.
628
+ */
629
+ sharedRoute(...route) {
630
+ __privateGet(this, _request2).route(...route.map((r) => r.toString()));
334
631
  return this;
335
632
  }
336
- get currentState() {
337
- const fullUrl = this.currentUrl;
338
- return {
339
- headers: Object.fromEntries(__privateGet(this, _headers)),
340
- params: Object.fromEntries(__privateGet(this, _params)),
341
- url: __privateGet(this, _url),
342
- route: __privateGet(this, _route),
343
- responseType: __privateGet(this, _responseType),
344
- data: __privateGet(this, _data),
345
- method: __privateGet(this, _method),
346
- fullUrl
347
- };
348
- }
349
- get currentUrl() {
350
- const params = Object.fromEntries(__privateGet(this, _params));
351
- return (0, import_url_join_ts.urlJoinP)(__privateGet(this, _url), __privateGet(this, _route), params);
352
- }
353
- url(url) {
354
- __privateSet(this, _url, url);
355
- return this;
633
+ /**
634
+ * Attaches a route to the request, such as `/product` or `/user`. Subsequent calls
635
+ * to this method will append the route to the existing route, such as `/product/1`.
636
+ *
637
+ * Numbers will be converted to strings automatically. Routes can be defined one
638
+ * at a time or as a spread argument.
639
+ *
640
+ * ```ts
641
+ * getUser(id: number) {
642
+ * return this.http.route("user", id).get();
643
+ * }
644
+ *
645
+ * // or
646
+ *
647
+ * getUser(id: number) {
648
+ * return this.http
649
+ * .route("user")
650
+ * .route(id)
651
+ * .get();
652
+ * }
653
+ * ```
654
+ *
655
+ * This method is a request chain method, and will return a new instance of HTTP, inheriting
656
+ * any routes previously defined and appending the new route. Useful to configure
657
+ * in class methods as part of finalizing a request.
658
+ *
659
+ * @param route A route or spread list of routes to append to the request.
660
+ * @returns A new child instance of HTTP derived from this one.
661
+ */
662
+ route(...route) {
663
+ const mapped = route.map((r) => String(r));
664
+ return HTTP.create(this.client, __privateGet(this, _request2).derive().route(...mapped));
356
665
  }
357
- allowPlainText(value) {
358
- __privateSet(this, _allowPlainText, value);
666
+ sharedSchema(parser, ...args) {
667
+ __privateGet(this, _metaConfig).schema(parser, ...args);
359
668
  return this;
360
669
  }
361
670
  schema(parser, ...args) {
362
- __privateGet(this, _schemaMap).register(parser, ...args);
363
- return this;
364
- }
365
- onBeforeSend(...hook) {
366
- __privateGet(this, _onBeforeSend).push(...hook);
367
- return this;
671
+ return HTTP.create(
672
+ this.client,
673
+ __privateGet(this, _request2).derive(),
674
+ __privateGet(this, _metaConfig).derive().schema(parser, ...args)
675
+ );
368
676
  }
369
- onReceivedResponse(...hook) {
370
- __privateGet(this, _onAfterSend).push(...hook);
677
+ sharedParam(name, value) {
678
+ __privateGet(this, _request2).param(name, value);
371
679
  return this;
372
680
  }
373
- route(...route) {
374
- __privateGet(this, _route).push(...route.map((it) => `${it}`));
681
+ /**
682
+ * `onSend` is a pre-request hook which will be executed in order of definition
683
+ * immediately before the request is sent. This hook can be used to analyze or
684
+ * log the request state.
685
+ *
686
+ * ```ts
687
+ *
688
+ * \@Fixture(INJECTION_SCOPE.TRANSIENT)
689
+ * export class UserController extends BaseController {
690
+ * constructor(private readonly http: HTTP) {
691
+ * super(http);
692
+ * this.http
693
+ * .sharedRoute("user")
694
+ * .sharedOnSend("log request",
695
+ * (request) => console.log(JSON.stringify(request, null, 2))
696
+ * );
697
+ * }
698
+ * }
699
+ * ```
700
+ *
701
+ * This method is a shared chain method, and will return the same instance of HTTP. All
702
+ * child clients will inherit the onSend hooks defined by this method. Useful to configure
703
+ * in the constructor body.
704
+ *
705
+ * @param description A description of the hook, used for debugging.
706
+ * @param hook The hook to execute.
707
+ * @returns This instance of HTTP.
708
+ */
709
+ sharedOnSend(description, hook) {
710
+ __privateGet(this, _metaConfig).onBeforeSend(description, hook);
375
711
  return this;
376
712
  }
377
- header(name, value) {
378
- const val = Array.isArray(value) ? value.join(",") : `${value}`;
379
- __privateGet(this, _headers).set(name, val);
713
+ /**
714
+ * `onReceive` is a post-request hook which will be executed in order of definition
715
+ * immediately after the response is received. This hook can be used to analyze or
716
+ * log the response state.
717
+ *
718
+ * ```ts
719
+ *
720
+ * \@Fixture(INJECTION_SCOPE.TRANSIENT)
721
+ * export class UserController extends BaseController {
722
+ * constructor(private readonly http: HTTP) {
723
+ * super(http);
724
+ * this.http
725
+ * .sharedRoute("user")
726
+ * .sharedOnReceive("log response",
727
+ * (response) => console.log(JSON.stringify(response, null, 2))
728
+ * );
729
+ * }
730
+ * }
731
+ * ```
732
+ *
733
+ * This method is a shared chain method, and will return the same instance of HTTP. All
734
+ * child clients will inherit the onReceive hooks defined by this method. Useful to configure
735
+ * in the constructor body.
736
+ *
737
+ * @param description A description of the hook, used for debugging.
738
+ * @param hook The hook to execute.
739
+ * @returns This instance of HTTP.
740
+ */
741
+ sharedOnReceive(description, hook) {
742
+ __privateGet(this, _metaConfig).onReceiveResponse(description, hook);
380
743
  return this;
381
744
  }
382
- headers(dict) {
383
- Object.entries(dict).forEach(
384
- ([name, value]) => __privateGet(this, _headers).set(name, value)
385
- );
745
+ /**
746
+ * Attaches a query string parameter object to the request. Query string
747
+ * parameters are key-value pairs which are appended to the request url, such as
748
+ * `https://api.example.com?name=John&age=30`.
749
+ *
750
+ * This method is a shared chain method, and will return the same instance of HTTP. All
751
+ * child clients will inherit the query string parameters defined by this method. Useful to configure
752
+ * in the constructor body.
753
+ *
754
+ * ```ts
755
+ * constructor(http: HTTP) {
756
+ * super(http);
757
+ * this.http
758
+ * .sharedParams({ 'is-test': "true" })
759
+ * ```
760
+ * @param name The name of the query string parameter.
761
+ * @param value The value of the query string parameter.
762
+ * @returns This instance of HTTP.
763
+ */
764
+ sharedParams(dict) {
765
+ __privateGet(this, _request2).params(dict);
386
766
  return this;
387
767
  }
768
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
388
769
  param(name, value) {
389
- __privateGet(this, _params).set(name, value);
390
- return this;
391
- }
770
+ return HTTP.create(this.client, __privateGet(this, _request2).derive().param(name, value));
771
+ }
772
+ /**
773
+ * Attaches a query string parameter object to the request. Query string
774
+ * parameters are key-value pairs which are appended to the request url, such as
775
+ * `https://api.example.com?name=John&age=30`.
776
+ *
777
+ * This method is a shared chain method, and will return the same instance of HTTP. All
778
+ * child clients will inherit the query string parameters defined by this method. Useful to configure
779
+ * in the constructor body.
780
+ *
781
+ * ```ts
782
+ * getUser(id: number) {
783
+ * return this.http
784
+ * .route(id)
785
+ * .param({ name: "John", age: "30" })
786
+ *
787
+ * @param name The name of the query string parameter.
788
+ * @param value The value of the query string parameter.
789
+ * @returns This instance of HTTP.
790
+ */
392
791
  params(dict) {
393
- Object.entries(dict).forEach(([name, value]) => this.param(name, value));
792
+ __privateGet(this, _request2).params(dict);
793
+ return HTTP.create(this.client, __privateGet(this, _request2).derive().params(dict));
794
+ }
795
+ /**
796
+ * Attaches a shared data payload to this client. The data payload is the body of the request,
797
+ * and can be any type. If the data payload is an object, it will be serialized to JSON.
798
+ *
799
+ * This method is a shared chain method, and will return the same instance of HTTP. All
800
+ * child clients will inherit the data payload defined by this method. Useful to configure
801
+ * in the constructor body.
802
+ *
803
+ * @param data The data payload to attach to the request.
804
+ * @returns This instance of HTTP.
805
+ */
806
+ sharedData(data) {
807
+ __privateGet(this, _request2).data(data);
394
808
  return this;
395
809
  }
396
- data(data) {
397
- __privateSet(this, _data, data);
810
+ /**
811
+ * Attaches a shared header to this client. Headers are string:string key-value pairs which are
812
+ * sent with the request, such as `Content-Type: application/json`.
813
+ *
814
+ * Numbers, Booleans and Null will be converted to string values automatically.
815
+ *
816
+ * A Factory function can also be provided to generate the header value at the time of request.
817
+ *
818
+ * This method is a shared chain method, and will return the same instance of HTTP. All
819
+ * child clients will inherit the header defined by this method. Useful to configure
820
+ * in the constructor body.
821
+ *
822
+ * @param name The name of the header.
823
+ * @param value The value of the header.
824
+ */
825
+ sharedHeader(name, value) {
826
+ __privateGet(this, _request2).header(name, value);
398
827
  return this;
399
828
  }
400
- async post() {
401
- return this._request("POST");
402
- }
403
- async get() {
404
- return this._request("GET");
405
- }
406
- async delete() {
407
- return this._request("DELETE");
408
- }
409
- async put() {
410
- return this._request("PUT");
411
- }
412
- async patch() {
413
- return this._request("PATCH");
829
+ header(name, value) {
830
+ return HTTP.create(this.client, __privateGet(this, _request2).derive().header(name, value));
831
+ }
832
+ /**
833
+ * Attaches a data payload to this request. The data payload is the body of the request,
834
+ * and can be any type. If the data payload is an object, it will be serialized to JSON.
835
+ *
836
+ * This method is a request chain method, and will return a new instance of HTTP, inheriting
837
+ * any data payload previously defined and appending the new payload. Useful to configure
838
+ * in class methods as part of finalizing a request.
839
+ *
840
+ * @param data The data payload to attach to the request.
841
+ * @returns A new child instance of HTTP derived from this one.
842
+ */
843
+ data(data) {
844
+ __privateGet(this, _request2).data(data);
845
+ return HTTP.create(this.client, __privateGet(this, _request2).derive().data(data));
846
+ }
847
+ /**
848
+ * `onSend` is a pre-request hook which will be executed in order of definition
849
+ * immediately before the request is sent. This hook can be used to modify the request,
850
+ * or to log the state of a request before final send-off.
851
+ *
852
+ * ```ts
853
+ *
854
+ * \@Fixture(INJECTION_SCOPE.TRANSIENT)
855
+ * export class UserController extends BaseController {
856
+ * constructor(private readonly http: HTTP) {
857
+ * super(http);
858
+ * }
859
+ *
860
+ * getUser(id: number) {
861
+ * return this.http
862
+ * .route(id)
863
+ * .onSend("log request",
864
+ * (request) => console.log(JSON.stringify(request, null, 2)
865
+ * )
866
+ * .get();
867
+ * }
868
+ * ```
869
+ *
870
+ * This method is a request chain method, and will return a new instance of HTTP, inheriting
871
+ * any onSend hooks previously defined and appending the new hook. Useful to configure
872
+ * in class methods as part of finalizing a request.
873
+ *
874
+ * @param description A description of the hook, used for debugging.
875
+ * @param hook The hook to execute.
876
+ * @returns A new child instance of HTTP derived from this one.
877
+ */
878
+ onSend(description, hook) {
879
+ return HTTP.create(
880
+ this.client,
881
+ __privateGet(this, _request2).derive(),
882
+ __privateGet(this, _metaConfig).derive().onBeforeSend(description, hook)
883
+ );
414
884
  }
415
- async _request(method) {
416
- __privateSet(this, _method, method);
417
- const options = this.constructOptions(method);
418
- this.tryRunBeforeHooks();
419
- const executor = new AxiosExecutor(
420
- options,
421
- __privateGet(this, _schemaMap),
422
- this.currentState,
423
- __privateGet(this, _requireSchema)
885
+ /**
886
+ * `onReceive` is a post-request hook which will be executed in order of definition
887
+ * immediately after the response is received. This hook can be used to modify the response,
888
+ * or to log the state of a response after it is received.
889
+ *
890
+ * ```ts
891
+ *
892
+ * \@Fixture(INJECTION_SCOPE.TRANSIENT)
893
+ * export class UserController extends BaseController {
894
+ * constructor(private readonly http: HTTP) {
895
+ * super(http);
896
+ * }
897
+ *
898
+ * getUser(id: number) {
899
+ * return this.http
900
+ * .route(id)
901
+ * .onReceive("log response",
902
+ * (response) => console.log(JSON.stringify(response, null, 2)
903
+ * )
904
+ * .get();
905
+ * }
906
+ * ```
907
+ *
908
+ * This method is a request chain method, and will return a new instance of HTTP, inheriting
909
+ * any onReceive hooks previously defined and appending the new hook. Useful to configure
910
+ * in class methods as part of finalizing a request.
911
+ *
912
+ * @param description A description of the hook, used for debugging.
913
+ * @param hook The hook to execute.
914
+ * @returns A new child instance of HTTP derived from this one.
915
+ */
916
+ onReceive(description, hook) {
917
+ return HTTP.create(
918
+ this.client,
919
+ __privateGet(this, _request2).derive(),
920
+ __privateGet(this, _metaConfig).derive().onReceiveResponse(description, hook)
424
921
  );
425
- await executor.tryRequest();
426
- if (executor.requestSucceeded && !executor.validationFailed) {
427
- const response = executor.getValidatedResponse();
428
- this.tryRunAfterHooks(response);
429
- return response;
430
- }
431
- if (executor.requestSucceeded) {
432
- const response = executor.getResponse();
433
- this.tryRunAfterHooks(response);
434
- }
435
- throw executor.error;
436
- }
437
- constructOptions(method) {
438
- const url = this.currentUrl;
439
- const headers = __privateGet(this, _headers) && Object.fromEntries(__privateGet(this, _headers));
440
- const responseType = __privateGet(this, _responseType);
441
- const data = __privateGet(this, _data);
442
- return {
443
- method,
444
- url,
445
- headers,
446
- data,
447
- responseType,
448
- validateStatus: function(status) {
449
- return status >= 100 && status < 500;
450
- },
451
- transformResponse: transformResponse.bind(null, __privateGet(this, _allowPlainText))
452
- };
453
922
  }
454
- tryRunBeforeHooks() {
455
- let index = 0;
456
- try {
457
- for (const hook of __privateGet(this, _onBeforeSend)) {
458
- hook(this.currentState);
459
- index++;
923
+ /**
924
+ * Executes the current request state as a GET request.
925
+ *
926
+ * @param options Additional options to pass to the underlying http client, such
927
+ * as e.g Axios configuration values.
928
+ * @returns A promise which resolves to the response.
929
+ */
930
+ get(options) {
931
+ return __privateMethod(this, _makeRequest, makeRequest_fn).call(this, __privateGet(this, _request2).derive().method("GET"), options);
932
+ }
933
+ /**
934
+ * Executes the current request state as a POST request.
935
+ *
936
+ * @param data The data payload to attach to the request.
937
+ * @param options Additional options to pass to the underlying http client, such
938
+ * as e.g Axios configuration values.
939
+ * @returns A promise which resolves to the response.
940
+ */
941
+ post(options) {
942
+ return __privateMethod(this, _makeRequest, makeRequest_fn).call(this, __privateGet(this, _request2).derive().method("POST"), options);
943
+ }
944
+ /**
945
+ * Executes the current request state as a DELETE request.
946
+ *
947
+ * @param options Additional options to pass to the underlying http client, such
948
+ * as e.g Axios configuration values.
949
+ * @returns A promise which resolves to the response.
950
+ * as e.g Axios configuration values.
951
+ */
952
+ delete(options) {
953
+ return __privateMethod(this, _makeRequest, makeRequest_fn).call(this, __privateGet(this, _request2).derive().method("DELETE"), options);
954
+ }
955
+ /**
956
+ * Executes the current request state as a PUT request.
957
+ *
958
+ * @param options Additional options to pass to the underlying http client, such
959
+ * as e.g Axios configuration values.
960
+ * @returns A promise which resolves to the response.
961
+ */
962
+ put(options) {
963
+ return __privateMethod(this, _makeRequest, makeRequest_fn).call(this, __privateGet(this, _request2).derive().method("PUT"), options);
964
+ }
965
+ /**
966
+ * Executes the current request state as a PATCH request.
967
+ *
968
+ * @param options Additional options to pass to the underlying http client, such
969
+ * as e.g Axios configuration values.
970
+ * @returns A promise which resolves to the response.
971
+ */
972
+ patch(options) {
973
+ return __privateMethod(this, _makeRequest, makeRequest_fn).call(this, __privateGet(this, _request2).derive().method("PATCH"), options);
974
+ }
975
+ head(options) {
976
+ return __privateMethod(this, _makeRequest, makeRequest_fn).call(this, __privateGet(this, _request2).derive().method("HEAD"), options);
977
+ }
978
+ options(options) {
979
+ return __privateMethod(this, _makeRequest, makeRequest_fn).call(this, __privateGet(this, _request2).derive().method("OPTIONS"), options);
980
+ }
981
+ trace(options) {
982
+ return __privateMethod(this, _makeRequest, makeRequest_fn).call(this, __privateGet(this, _request2).derive().method("TRACE"), options);
983
+ }
984
+ connect(options) {
985
+ return __privateMethod(this, _makeRequest, makeRequest_fn).call(this, __privateGet(this, _request2).derive().method("CONNECT"), options);
986
+ }
987
+ async runOnSendHooks(meta, request) {
988
+ for (const [description, hook] of meta.onSend) {
989
+ try {
990
+ await hook(request);
991
+ } catch (e) {
992
+ const cause = e;
993
+ const msg = `An error occurred while sending a request in hook: '${description}'`;
994
+ throw new import_errors2.AutomationError(msg, { cause });
460
995
  }
461
- } catch (e) {
462
- const error = e;
463
- const message = `HTTP Client 'onBeforeRequest' experienced an error at listener count ${index}`;
464
- throw new import_errors4.AutomationError(message, { cause: error });
465
996
  }
466
997
  }
467
- tryRunAfterHooks(response) {
468
- let index = 0;
469
- try {
470
- for (const hook of __privateGet(this, _onAfterSend)) {
471
- hook(response);
472
- index++;
998
+ async runOnReceiveHooks(meta, response) {
999
+ for (const [description, hook] of meta.onReceive) {
1000
+ try {
1001
+ await hook(response);
1002
+ } catch (e) {
1003
+ const cause = e;
1004
+ const msg = `An error occurred while receiving a response in hook: '${description}'`;
1005
+ throw new import_errors2.AutomationError(msg, { cause });
473
1006
  }
474
- } catch (e) {
475
- const error = e;
476
- const message = `HTTP Client 'onRequestReceived' experienced an error at listener count ${index}`;
477
- throw new import_errors4.AutomationError(message, { cause: error });
478
1007
  }
479
1008
  }
480
1009
  };
481
- _headers = new WeakMap();
482
- _params = new WeakMap();
483
- _url = new WeakMap();
484
- _route = new WeakMap();
485
- _method = new WeakMap();
486
- _schemaMap = new WeakMap();
487
- _responseType = new WeakMap();
488
- _data = new WeakMap();
489
- _requireSchema = new WeakMap();
490
- _allowPlainText = new WeakMap();
491
- _onBeforeSend = new WeakMap();
492
- _onAfterSend = new WeakMap();
493
- HTTPRequestBuilder = __decorateClass([
1010
+ _request2 = new WeakMap();
1011
+ _metaConfig = new WeakMap();
1012
+ _makeRequest = new WeakSet();
1013
+ makeRequest_fn = async function(builder, options) {
1014
+ const request = builder.resolveDynamicHeaders().build();
1015
+ const meta = __privateGet(this, _metaConfig).derive().build();
1016
+ await this.runOnSendHooks(meta, request);
1017
+ const result = await this.client.request(request, options);
1018
+ result.data = transformResponse(meta.allowPlainText, result.data);
1019
+ await this.runOnReceiveHooks(meta, result);
1020
+ const validated = __privateMethod(this, _validateResponse, validateResponse_fn).call(this, result, meta);
1021
+ return validated;
1022
+ };
1023
+ _validateResponse = new WeakSet();
1024
+ validateResponse_fn = function(response, meta) {
1025
+ const { status, data } = response;
1026
+ const validated = meta.schemas.validate(
1027
+ status,
1028
+ data,
1029
+ meta.requireSchema
1030
+ );
1031
+ response.data = validated;
1032
+ return response;
1033
+ };
1034
+ HTTP = __decorateClass([
494
1035
  (0, import_injection.Fixture)(import_injection.INJECTION_SCOPE.TRANSIENT)
495
- ], HTTPRequestBuilder);
1036
+ ], HTTP);
496
1037
 
497
- // src/http.ts
498
- var _url2, _route2, _headers2, _requireSchema2, _schemaMap2, _onBeforeSend2, _onAfterSend2, _allowPlainText2;
499
- var HTTP = class {
500
- constructor() {
501
- __privateAdd(this, _url2, void 0);
502
- __privateAdd(this, _route2, []);
503
- __privateAdd(this, _headers2, /* @__PURE__ */ new Map());
504
- __privateAdd(this, _requireSchema2, false);
505
- __privateAdd(this, _schemaMap2, new SchemaMap());
506
- __privateAdd(this, _onBeforeSend2, []);
507
- __privateAdd(this, _onAfterSend2, []);
508
- __privateAdd(this, _allowPlainText2, false);
509
- }
510
- allowPlainText(value) {
511
- __privateSet(this, _allowPlainText2, value);
512
- return this;
513
- }
514
- requireSchema(value) {
515
- __privateSet(this, _requireSchema2, value);
516
- return this;
517
- }
518
- url(url) {
519
- __privateSet(this, _url2, url);
520
- return this;
521
- }
522
- sharedOnBeforeSend(hook) {
523
- __privateGet(this, _onBeforeSend2).push(hook);
524
- return this;
525
- }
526
- sharedOnReceiveResponse(hook) {
527
- __privateGet(this, _onAfterSend2).push(hook);
528
- return this;
529
- }
530
- onBeforeSend(hook) {
531
- return this.builder().onBeforeSend(hook);
532
- }
533
- onReceiveResponse(hook) {
534
- return this.builder().onReceivedResponse(hook);
535
- }
536
- sharedSchema(parser, ...args) {
537
- __privateGet(this, _schemaMap2).register(parser, ...args);
538
- return this;
539
- }
540
- schema(parser, ...args) {
541
- return this.builder().schema(parser, ...args);
542
- }
543
- sharedRoute(...route) {
544
- __privateGet(this, _route2).push(...route);
545
- return this;
546
- }
547
- param(name, value) {
548
- return this.builder().param(name, value);
549
- }
550
- params(dict) {
551
- return this.builder().params(dict);
552
- }
553
- data(data) {
554
- return this.builder().data(data);
1038
+ // src/default-schema.ts
1039
+ var import_assert_is_json2 = __toESM(require("@stdlib/assert-is-json"), 1);
1040
+ function AnySchema(data) {
1041
+ return data;
1042
+ }
1043
+ function EmptySchema(data) {
1044
+ if (data !== null && data !== void 0 && data !== "null") {
1045
+ throw new Error(`Expected null but got <${typeof data}> for ${data}`);
555
1046
  }
556
- sharedHeader(name, value) {
557
- __privateGet(this, _headers2).set(name, value);
558
- return this;
1047
+ return data === "null" ? null : data;
1048
+ }
1049
+ function NullSchema(data) {
1050
+ if (data !== null && data !== "null") {
1051
+ throw new Error(`Expected null but got <${typeof data}> for ${data}`);
559
1052
  }
560
- route(...route) {
561
- return this.builder().route(...route);
1053
+ return null;
1054
+ }
1055
+ function UndefinedSchema(data) {
1056
+ if (data !== void 0) {
1057
+ throw new Error(`Expected undefined but got <${typeof data}> for ${data}`);
562
1058
  }
563
- header(name, value) {
564
- return this.builder().header(name, value);
1059
+ return void 0;
1060
+ }
1061
+ function BooleanSchema(data) {
1062
+ if (!(typeof data === "boolean") && ["true", "false"].includes(String(data)) === false) {
1063
+ throw new Error(`Expected boolean but got <${typeof data}> for ${data}`);
565
1064
  }
566
- headers(dict) {
567
- return this.builder().headers(dict);
1065
+ return JSON.parse(data);
1066
+ }
1067
+ function NumberSchema(data) {
1068
+ if (!(typeof data === "number") && /^\d*\.?\d+$/.test(String(data)) === false) {
1069
+ throw new Error(`Expected number but got <${typeof data}> for ${data}`);
568
1070
  }
569
- get() {
570
- return this.builder().get();
1071
+ return JSON.parse(data);
1072
+ }
1073
+ function StringSchema(data) {
1074
+ if (typeof data !== "string") {
1075
+ throw new Error(`Expected string but got <${typeof data}> for ${data}`);
571
1076
  }
572
- builder() {
573
- const headers = this.convertFactoriesToString();
574
- return new HTTPRequestBuilder(__privateGet(this, _schemaMap2)).url(__privateGet(this, _url2)).route(...__privateGet(this, _route2)).allowPlainText(__privateGet(this, _allowPlainText2)).headers(headers).requireSchema(__privateGet(this, _requireSchema2)).onBeforeSend(...__privateGet(this, _onBeforeSend2)).onReceivedResponse(...__privateGet(this, _onAfterSend2));
1077
+ return data;
1078
+ }
1079
+ function JSONSchema(data) {
1080
+ if (typeof data === "object") {
1081
+ return data;
575
1082
  }
576
- convertFactoriesToString() {
577
- const dict = {};
578
- for (const [key, value] of __privateGet(this, _headers2).entries()) {
579
- dict[key] = typeof value === "string" ? value : value();
580
- }
581
- return dict;
1083
+ if (!(0, import_assert_is_json2.default)(data)) {
1084
+ throw new Error(`Expected JSON but got <${typeof data}> for ${data}`);
582
1085
  }
583
- };
584
- _url2 = new WeakMap();
585
- _route2 = new WeakMap();
586
- _headers2 = new WeakMap();
587
- _requireSchema2 = new WeakMap();
588
- _schemaMap2 = new WeakMap();
589
- _onBeforeSend2 = new WeakMap();
590
- _onAfterSend2 = new WeakMap();
591
- _allowPlainText2 = new WeakMap();
592
- HTTP = __decorateClass([
593
- (0, import_injection2.Fixture)(import_injection2.INJECTION_SCOPE.TRANSIENT)
594
- ], HTTP);
1086
+ const result = JSON.parse(data);
1087
+ return result;
1088
+ }
595
1089
  // Annotate the CommonJS export names for ESM import in node:
596
1090
  0 && (module.exports = {
597
- DerivedHTTPResponse,
1091
+ AnySchema,
1092
+ AxiosClient,
1093
+ BooleanSchema,
1094
+ EmptySchema,
598
1095
  HTTP,
599
- HTTPResponse
1096
+ HTTPClient,
1097
+ HTTPRequest,
1098
+ HTTPRequestBuilder,
1099
+ HTTPResponse,
1100
+ HTTPResponseBuilder,
1101
+ JSONSchema,
1102
+ NullSchema,
1103
+ NumberSchema,
1104
+ StringSchema,
1105
+ UndefinedSchema,
1106
+ defaultClient
600
1107
  });
601
1108
  //# sourceMappingURL=index.js.map