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