@autometa/http 1.4.9 → 1.4.10

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @autometa/http
2
2
 
3
+ ## 1.4.10
4
+
5
+ ### Patch Changes
6
+
7
+ - dbc0eda: feat(http): allow client options to be created with `sharedOptions`
8
+
3
9
  ## 1.4.9
4
10
 
5
11
  ### Patch Changes
package/dist/esm/index.js CHANGED
@@ -357,9 +357,10 @@ var MetaConfig = class {
357
357
  constructor() {
358
358
  this.onSend = [];
359
359
  this.onReceive = [];
360
+ this.options = {};
360
361
  }
361
362
  };
362
- var _schemaMap, _requireSchema, _allowPlainText, _onBeforeSend, _onAfterSend, _throwOnServerError, _setOnSend, setOnSend_fn, _setOnReceive, setOnReceive_fn;
363
+ var _schemaMap, _requireSchema, _allowPlainText, _onBeforeSend, _onAfterSend, _throwOnServerError, _options, _setOnSend, setOnSend_fn, _setOnReceive, setOnReceive_fn;
363
364
  var _MetaConfigBuilder = class _MetaConfigBuilder {
364
365
  constructor() {
365
366
  __privateAdd(this, _setOnSend);
@@ -370,6 +371,11 @@ var _MetaConfigBuilder = class _MetaConfigBuilder {
370
371
  __privateAdd(this, _onBeforeSend, []);
371
372
  __privateAdd(this, _onAfterSend, []);
372
373
  __privateAdd(this, _throwOnServerError, false);
374
+ __privateAdd(this, _options, {});
375
+ }
376
+ options(options) {
377
+ __privateSet(this, _options, { options });
378
+ return this;
373
379
  }
374
380
  schemaMap(map) {
375
381
  __privateSet(this, _schemaMap, map);
@@ -414,6 +420,8 @@ var _MetaConfigBuilder = class _MetaConfigBuilder {
414
420
  config.allowPlainText = __privateGet(this, _allowPlainText);
415
421
  config.onSend = __privateGet(this, _onBeforeSend);
416
422
  config.onReceive = __privateGet(this, _onAfterSend);
423
+ config.options = __privateGet(this, _options);
424
+ config.throwOnServerError = __privateGet(this, _throwOnServerError);
417
425
  return config;
418
426
  }
419
427
  derive() {
@@ -427,6 +435,7 @@ _allowPlainText = new WeakMap();
427
435
  _onBeforeSend = new WeakMap();
428
436
  _onAfterSend = new WeakMap();
429
437
  _throwOnServerError = new WeakMap();
438
+ _options = new WeakMap();
430
439
  _setOnSend = new WeakSet();
431
440
  setOnSend_fn = function(hooks) {
432
441
  __privateSet(this, _onBeforeSend, [...hooks]);
@@ -516,6 +525,10 @@ var HTTP = class {
516
525
  __privateGet(this, _request2).url(url);
517
526
  return this;
518
527
  }
528
+ sharedOptions(options) {
529
+ __privateGet(this, _metaConfig).options(options);
530
+ return this;
531
+ }
519
532
  /**
520
533
  * If set to true, all requests derived from this client will require a schema be defined
521
534
  * matching any response status code. If set to false, a schema will still be used for validation
@@ -1004,7 +1017,8 @@ makeRequest_fn = async function(builder, options) {
1004
1017
  const request = (await builder.resolveDynamicHeaders()).build();
1005
1018
  const meta = __privateGet(this, _metaConfig).derive().build();
1006
1019
  await this.runOnSendHooks(meta, request);
1007
- const result = await this.client.request(request, options);
1020
+ const opts = { ...meta.options, ...options };
1021
+ const result = await this.client.request(request, opts);
1008
1022
  result.data = transformResponse(meta.allowPlainText, result.data);
1009
1023
  await this.runOnReceiveHooks(meta, result);
1010
1024
  const validated = __privateMethod(this, _validateResponse, validateResponse_fn).call(this, result, meta);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/http-response.ts","../../src/axios-client.ts","../../src/http-client.ts","../../src/http.ts","../../src/default-client-factory.ts","../../src/http-request.ts","../../src/schema.map.ts","../../src/request-meta.config.ts","../../src/transform-response.ts","../../src/default-schema.ts"],"sourcesContent":["import { HTTPRequest } from \"./http-request\";\nimport { StatusCode } from \"./types\";\n\nexport class HTTPResponse<T = unknown> {\n status: StatusCode;\n statusText: string;\n data: T;\n headers: Record<string, string>;\n request: HTTPRequest<unknown>;\n\n constructor() {\n this.headers = {};\n }\n\n static fromRaw<T>(response: HTTPResponse<T>) {\n const newResponse = new HTTPResponse<T>();\n Object.assign(newResponse, response);\n return response;\n }\n\n /**\n * Decomposes a response, creating an exact copy of the current response,\n * but with a new data value. The data can be provided directly as is, or it\n * can be generated through a callback function which receives the current\n * response data as an argument.\n *\n * ```ts\n * const response = await http.get(\"/products\");\n *\n * // direct value\n * const products = response.data;\n * const firstProduct = response.decompose(products[0]);\n * // callback transformer\n * const secondProduct = response.decompose((products) => products[1]);\n * // callback transformer with destructuring\n * const secondProduct = response.decompose(([product]) => product);\n * ```\n * @param value\n */\n decompose<K>(value: K): HTTPResponse<K>;\n decompose<K>(transformFn: (response: T) => K): HTTPResponse<K>;\n decompose<K>(transformFnOrVal: K | ((response: T) => K)): HTTPResponse<K> {\n const value = getDecompositionValue<T>(this.data, transformFnOrVal);\n return new HTTPResponseBuilder()\n .status(this.status)\n .statusText(this.statusText)\n .headers(this.headers)\n .request(this.request)\n .data(value)\n .build() as HTTPResponse<K>;\n }\n}\n\nfunction getDecompositionValue<T>(data: unknown, transformFn: unknown): T {\n return typeof transformFn === \"function\" ? transformFn(data) : transformFn;\n}\n\nexport class HTTPResponseBuilder {\n #response = new HTTPResponse();\n\n static create() {\n return new HTTPResponseBuilder();\n }\n\n derive() {\n return HTTPResponseBuilder.create()\n .data(this.#response.data)\n .headers(this.#response.headers)\n .request(this.#response.request)\n .status(this.#response.status)\n .statusText(this.#response.statusText);\n }\n\n status(code: StatusCode) {\n this.#response.status = code;\n return this;\n }\n\n statusText(text: string) {\n this.#response.statusText = text;\n return this;\n }\n\n data<T>(data: T) {\n this.#response.data = data;\n return this;\n }\n\n headers(dict: Record<string, string>) {\n this.#response.headers = dict;\n return this;\n }\n\n header(name: string, value: string) {\n this.#response.headers[name] = value;\n return this;\n }\n\n request(request: HTTPRequest<unknown>) {\n this.#response.request = request;\n return this;\n }\n\n build() {\n return this.#response;\n }\n}\n","import { HTTPRequest } from \"./http-request\";\nimport { HTTPResponse, HTTPResponseBuilder } from \"./http-response\";\nimport { HTTPAdditionalOptions, StatusCode } from \"./types\";\nimport axios, { AxiosRequestConfig } from \"axios\";\nimport { HTTPClient } from \"./http-client\";\n\n@HTTPClient.Use()\nexport class AxiosClient extends HTTPClient {\n async request<TRequestType, TResponseType>(\n request: HTTPRequest<TRequestType>,\n options: HTTPAdditionalOptions<AxiosRequestConfig>\n ): Promise<HTTPResponse<TResponseType>> {\n const { baseUrl, route, params, headers, method, data } = request;\n const url = [baseUrl, ...route].join(\"/\");\n const axiosRequest: AxiosRequestConfig = {\n url,\n params,\n headers,\n method: method,\n data,\n validateStatus: function (status) {\n return status >= 0 && status < 600;\n },\n ...options\n };\n const response = await axios(axiosRequest);\n return HTTPResponseBuilder.create()\n .status(response.status as StatusCode)\n .statusText(response.statusText)\n .data(response.data)\n .headers(response.headers as Record<string, string>)\n .request(request)\n .build() as HTTPResponse<TResponseType>;\n }\n}\n","import { HTTPRequest } from \"./http-request\";\nimport { HTTPResponse } from \"./http-response\";\nimport { HTTPAdditionalOptions } from \"./types\";\nimport { Class } from \"@autometa/types\";\nexport let defaultClient: Class<HTTPClient>;\nexport abstract class HTTPClient {\n static Use(): (target: Class<HTTPClient>) => void\n static Use(client?: Class<HTTPClient>) {\n if (client) {\n defaultClient = client\n }\n return function (target: Class<HTTPClient>) {\n defaultClient = target\n };\n }\n abstract request<TRequestType, TResponseType>(\n request: HTTPRequest<TRequestType>,\n options?: HTTPAdditionalOptions<unknown>\n ): Promise<HTTPResponse<TResponseType>>;\n}\n","import { Fixture, INJECTION_SCOPE } from \"@autometa/injection\";\nimport { AxiosClient } from \"./axios-client\";\nimport { HTTPClient } from \"./http-client\";\nimport { defaultClientFactory } from \"./default-client-factory\";\nimport { HTTPRequest, HTTPRequestBuilder } from \"./http-request\";\nimport { HTTPResponse } from \"./http-response\";\nimport { MetaConfig, MetaConfigBuilder } from \"./request-meta.config\";\nimport {\n HTTPAdditionalOptions,\n RequestHook,\n ResponseHook,\n SchemaParser,\n StatusCode\n} from \"./types\";\nimport { transformResponse } from \"./transform-response\";\nimport { AutomationError } from \"@autometa/errors\";\n\n/**\n * The HTTP fixture allows requests to be built and sent to a server. In general,\n * there are 2 modes of operation:\n *\n * * Shared Chain: The shared chain is used to configure the client for all requests, such as\n * routes this instance will always be used. When a shared chain method is called, it returns\n * the same instance of HTTP which can be further chained to configure the client.\n * * Request Chain: The request chain is used to configure a single request, inheriting values\n * set by the shared chain. When called, a new HTTP client instance is created and inherits the values\n * set by it's parent.\n *\n * The 2 modes are intended to simplify configuring an object through an inheritance chain. For example,\n * assume we have an API with 2 controller routes, `/product` and `/seller`. We can set up a Base Client\n * which consumes the HTTP fixture and configures it with the base url of our API.\n *\n * Inheritors can further configure their HTTP instance's routes.\n *\n * ```ts\n * \\@Constructor(HTTP)\n * export class BaseClient {\n * constructor(protected readonly http: HTTP) {\n * this.http.url(\"https://api.example.com\");\n * }\n * }\n *\n * export class ProductClient extends BaseClient {\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"product\");\n * }\n * getProduct(id: number) {\n * return this.http.route(id).get();\n * }\n *\n * export class SellerClient extends BaseClient {\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"seller\");\n * }\n *\n * getSeller(id: number) {\n * return this.http.route(id).get();\n * }\n * }\n * ```\n *\n * 'Schemas' can also be configured. A Schema is a function or an object with a `parse` method, which\n * takes a response data payload and returns a validated object. Schemas are mapped to\n * HTTP Status Codes, and if configured to be required the request will fail if no schema is found\n * matching that code.\n *\n * Defining a schema function:\n *\n * ```\n * // user.schema.ts\n * export function UserSchema(data: unknown) {\n * if(typeof data !== \"object\") {\n * throw new Error(\"Expected an object\");\n * }\n *\n * if(typeof data.name !== \"string\") {\n * throw new Error(\"Expected a string\");\n * }\n *\n * return data as { name: string };\n * }\n *\n * // user.controller.ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 });\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * // or\n * return this.http\n * .route(id)\n * .schema(UserSchema, { from: 200, to: 299 })\n * .get();\n * // or\n * return this.http\n * .route(id)\n * .schema(UserSchema, 200, 201, 202)\n * .get();\n * }\n * }\n * ```\n *\n * Validation libraries which use a `.parse` or `.validation`, method, such as Zod or MyZod, can also be used as schemas:\n *\n * ```ts\n * // user.schema.ts\n * import { z } from \"myzod\";\n *\n * export const UserSchema = z.object({\n * name: z.string()\n * });\n *\n * // user.controller.ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 })\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * }\n * }\n * ```\n */\n@Fixture(INJECTION_SCOPE.TRANSIENT)\nexport class HTTP {\n #request: HTTPRequestBuilder<HTTPRequest<unknown>>;\n #metaConfig: MetaConfigBuilder;\n constructor(\n private readonly client: HTTPClient = defaultClientFactory(),\n builder: HTTPRequestBuilder<\n HTTPRequest<unknown>\n > = new HTTPRequestBuilder(),\n metaConfig: MetaConfigBuilder = new MetaConfigBuilder()\n ) {\n this.#request = builder;\n this.#metaConfig = metaConfig.derive();\n }\n\n static create(\n client: HTTPClient = new AxiosClient(),\n builder: HTTPRequestBuilder<\n HTTPRequest<unknown>\n > = new HTTPRequestBuilder(),\n metaConfig: MetaConfigBuilder = new MetaConfigBuilder()\n ) {\n const derived = new HTTP(client, builder, metaConfig);\n return derived;\n }\n\n /**\n * Sets the base url of the request for this client, such as\n * `https://api.example.com`, and could include always-used routes like\n * the api version, such as `/v1` or `/api/v1` at the end.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export abstract class BaseClient {\n * constructor(protected readonly http: HTTP) {\n * this.http.url(\"https://api.example.com\");\n * }\n * }\n * ```\n * @param url\n * @returns\n */\n url(url: string) {\n this.#request.url(url);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will require a schema be defined\n * matching any response status code. If set to false, a schema will still be used for validation\n * if defined, or the unadulterated original body will be returned if no schema matches.\n *\n * @param required Whether or not a schema is required for all responses.\n * @returns This instance of HTTP.\n */\n requireSchema(required: boolean) {\n this.#metaConfig.requireSchema(required);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will allow plain text\n * responses. If set to false, plain text responses will throw an serialization error.\n *\n * Useful when an endpoint returns a HTML or plain text response. If the plain text\n * is the value of `true` or `false`, or a number, it will be parsed into the\n * appropriate type.\n *\n * This method is a shared chain method, and will return the same instance of HTTP.\n *\n * @param allow Whether or not plain text responses are allowed.\n * @returns This instance of HTTP.\n */\n sharedAllowPlainText(allow: boolean) {\n this.#metaConfig.allowPlainText(allow);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will allow plain text\n * responses. If set to false, plain text responses will throw an serialization error.\n *\n * Useful when an endpoint returns a HTML or plain text response. If the plain text\n * is the value of `true` or `false`, or a number, it will be parsed into the\n * appropriate type.\n *\n * This method is a request chain method, and will return a new instance of HTTP.\n *\n * @param allow Whether or not plain text responses are allowed.\n * @returns A new child instance of HTTP derived from this one.\n */\n allowPlainText(allow: boolean) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().allowPlainText(allow)\n );\n }\n\n /**\n * Attaches a route to the request, such as `/product` or `/user`. Subsequent calls\n * to this method will append the route to the existing route, such as `/product/1`.\n *\n * Numbers will be converted to strings automatically. Routes can be defined one\n * at a time or as a spread argument.\n *\n * ```ts\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"user\", id).get();\n * }\n *\n * // or\n *\n * constructor(http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedRoute(id)\n * .get();\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the routes defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param route A route or spread list of routes to append to the request.\n * @returns This instance of HTTP.\n */\n sharedRoute(...route: (string | number | boolean)[]) {\n this.#request.route(...route.map((r) => r.toString()));\n return this;\n }\n\n /**\n * Attaches a route to the request, such as `/product` or `/user`. Subsequent calls\n * to this method will append the route to the existing route, such as `/product/1`.\n *\n * Numbers will be converted to strings automatically. Routes can be defined one\n * at a time or as a spread argument.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http.route(\"user\", id).get();\n * }\n *\n * // or\n *\n * getUser(id: number) {\n * return this.http\n * .route(\"user\")\n * .route(id)\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any routes previously defined and appending the new route. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param route A route or spread list of routes to append to the request.\n * @returns A new child instance of HTTP derived from this one.\n */\n route(...route: (string | number | boolean)[]) {\n const mapped = route.map((r) => String(r));\n return HTTP.create(\n this.client,\n this.#request.derive().route(...mapped),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a shared schema mapping for all requests by this client. Schemas are\n * mapped to HTTP Status Codes, and if configured to be required the request will fail\n * if no schema is found matching that code.\n *\n * The status code mapping can be defined as a single code, a range of codes, or a spread list.\n *\n * ```ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(UserSchema, 200)\n * .sharedSchema(EmptySchema, 201, 204)\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 });\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the schemas defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param parser The schema parser to use for this mapping.\n * @param codes A single status code, a range of status codes, or a spread list of status codes.\n * @returns This instance of HTTP.\n */\n sharedSchema(parser: SchemaParser, ...codes: StatusCode[]): HTTP;\n sharedSchema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTP;\n sharedSchema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): HTTP {\n this.#metaConfig.schema(parser, ...args);\n return this;\n }\n\n /**\n * Attaches a schema mapping for this request. Schemas are\n * mapped to HTTP Status Codes, and if configured to be required the request will fail\n * if no schema is found matching that code.\n *\n * The status code mapping can be defined as a single code, a range of codes, or a spread list.\n *\n * ```ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .schema(ErrorSchema, { from: 400, to: 499 });\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * }\n *\n * getUsers(...ids: number[]) {\n * return this.http\n * .route(\"users\")\n * .schema(UserSchema, { from: 200, to: 299 })\n * .schema(UserSchema, 200)\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any schemas previously defined and appending the new schema. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param parser The schema parser to use for this mapping.\n * @param codes A single status code, a range of status codes, or a spread list of status codes.\n * @returns A new child instance of HTTP derived from this one.\n */\n schema(parser: SchemaParser, ...codes: StatusCode[]): HTTP;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTP;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): HTTP {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().schema(parser, ...args)\n );\n }\n\n /**\n * Attaches a shared query string parameter to all requests by this client. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n sharedParam(name: string, value: Record<string, unknown>): HTTP;\n sharedParam(name: string, ...value: (string | number | boolean)[]): HTTP;\n sharedParam(name: string, value: (string | number | boolean)[]): HTTP;\n sharedParam(\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value: any\n ): HTTP {\n this.#request.param(name, value);\n return this;\n }\n\n /**\n * `onSend` is a pre-request hook which will be executed in order of definition\n * immediately before the request is sent. This hook can be used to analyze or\n * log the request state.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedOnSend(\"log request\",\n * (request) => console.log(JSON.stringify(request, null, 2))\n * );\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the onSend hooks defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns This instance of HTTP.\n */\n sharedOnSend(description: string, hook: RequestHook) {\n this.#metaConfig.onBeforeSend(description, hook);\n return this;\n }\n\n /**\n * `onReceive` is a post-request hook which will be executed in order of definition\n * immediately after the response is received. This hook can be used to analyze or\n * log the response state.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedOnReceive(\"log response\",\n * (response) => console.log(JSON.stringify(response, null, 2))\n * );\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the onReceive hooks defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns This instance of HTTP.\n */\n sharedOnReceive(description: string, hook: ResponseHook<unknown>) {\n this.#metaConfig.onReceiveResponse(description, hook);\n return this;\n }\n\n /**\n * Attaches a query string parameter object to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * ```ts\n * constructor(http: HTTP) {\n * super(http);\n * this.http\n * .sharedParams({ 'is-test': \"true\" })\n * ```\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n sharedParams(dict: Record<string, unknown>) {\n this.#request.params(dict);\n return this;\n }\n\n /**\n * Attaches a query string parameter to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any query string parameters previously defined and appending the new parameter. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .param(\"name\", \"John\")\n * .param(\"age\", 30)\n * ```\n *\n * Note: Numbers and Booleans will be converted to strings automatically.\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns A new child instance of HTTP derived from this one.\n */\n param(name: string, value: Record<string, unknown>): HTTP;\n param(name: string, ...value: (string | number | boolean)[]): HTTP;\n param(name: string, value: (string | number | boolean)[]): HTTP;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n param(name: string, ...value: any) {\n return HTTP.create(\n this.client,\n this.#request.derive().param(name, value),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a query string parameter object to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .param({ name: \"John\", age: \"30\" })\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n params(dict: Record<string, string>) {\n this.#request.params(dict);\n return HTTP.create(\n this.client,\n this.#request.derive().params(dict),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a shared data payload to this client. The data payload is the body of the request,\n * and can be any type. If the data payload is an object, it will be serialized to JSON.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the data payload defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param data The data payload to attach to the request.\n * @returns This instance of HTTP.\n */\n sharedData<T>(data: T) {\n this.#request.data(data);\n return this;\n }\n\n /**\n * Attaches a shared header to this client. Headers are string:string key-value pairs which are\n * sent with the request, such as `Content-Type: application/json`.\n *\n * Numbers, Booleans and Null will be converted to string values automatically.\n *\n * A Factory function can also be provided to generate the header value at the time of request.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the header defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param name The name of the header.\n * @param value The value of the header.\n */\n sharedHeader(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n ) {\n this.#request.header(name, value);\n return this;\n }\n\n header(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n ) {\n return HTTP.create(\n this.client,\n this.#request.derive().header(name, value),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a data payload to this request. The data payload is the body of the request,\n * and can be any type. If the data payload is an object, it will be serialized to JSON.\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any data payload previously defined and appending the new payload. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param data The data payload to attach to the request.\n * @returns A new child instance of HTTP derived from this one.\n */\n data<T>(data: T) {\n this.#request.data(data);\n return HTTP.create(\n this.client,\n this.#request.derive().data(data),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * `onSend` is a pre-request hook which will be executed in order of definition\n * immediately before the request is sent. This hook can be used to modify the request,\n * or to log the state of a request before final send-off.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * }\n *\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .onSend(\"log request\",\n * (request) => console.log(JSON.stringify(request, null, 2)\n * )\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any onSend hooks previously defined and appending the new hook. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns A new child instance of HTTP derived from this one.\n */\n onSend(description: string, hook: RequestHook) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().onBeforeSend(description, hook)\n );\n }\n\n /**\n * `onReceive` is a post-request hook which will be executed in order of definition\n * immediately after the response is received. This hook can be used to modify the response,\n * or to log the state of a response after it is received.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * }\n *\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .onReceive(\"log response\",\n * (response) => console.log(JSON.stringify(response, null, 2)\n * )\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any onReceive hooks previously defined and appending the new hook. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns A new child instance of HTTP derived from this one.\n */\n onReceive(description: string, hook: ResponseHook<unknown>) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().onReceiveResponse(description, hook)\n );\n }\n\n /**\n * Executes the current request state as a GET request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n get<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"GET\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a POST request.\n *\n * @param data The data payload to attach to the request.\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n post<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"POST\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a DELETE request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n * as e.g Axios configuration values.\n */\n delete<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"DELETE\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a PUT request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n put<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"PUT\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n /**\n * Executes the current request state as a PATCH request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n patch<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"PATCH\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n head<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"HEAD\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n options<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"OPTIONS\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n trace<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"TRACE\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n connect<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"CONNECT\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n async #makeRequest(\n builder: HTTPRequestBuilder<HTTPRequest<unknown>>,\n options?: HTTPAdditionalOptions<unknown>\n ) {\n const request = (await builder.resolveDynamicHeaders()).build();\n const meta = this.#metaConfig.derive().build();\n await this.runOnSendHooks(meta, request);\n const result = await this.client.request<unknown, string>(request, options);\n result.data = transformResponse(meta.allowPlainText, result.data);\n await this.runOnReceiveHooks(meta, result);\n const validated = this.#validateResponse(result, meta);\n return validated;\n }\n\n private async runOnSendHooks(\n meta: MetaConfig,\n request: HTTPRequest<unknown>\n ) {\n for (const [description, hook] of meta.onSend) {\n try {\n await hook(request);\n } catch (e) {\n const cause = e as Error;\n const msg = `An error occurred while sending a request in hook: '${description}'`;\n throw new AutomationError(msg, { cause });\n }\n }\n }\n private async runOnReceiveHooks(\n meta: MetaConfig,\n response: HTTPResponse<unknown>\n ) {\n for (const [description, hook] of meta.onReceive) {\n try {\n await hook(response);\n } catch (e) {\n const cause = e as Error;\n const msg = `An error occurred while receiving a response in hook: '${description}'`;\n throw new AutomationError(msg, { cause });\n }\n }\n }\n\n #validateResponse<T>(\n response: HTTPResponse<unknown>,\n meta: MetaConfig\n ): HTTPResponse<T> {\n const { status, data } = response;\n const validated = meta.schemas.validate(\n status,\n data,\n meta.requireSchema\n ) as T;\n response.data = validated;\n return response as HTTPResponse<T>;\n }\n}\n","import { Class } from \"@autometa/types\";\nimport { defaultClient, type HTTPClient } from \"./http-client\";\n\nexport function defaultClientFactory() {\n const type = defaultClient as Class<HTTPClient>;\n return new type();\n}\n","import { RequestConfig, RequestConfigBasic } from \"./request.config\";\nimport { HTTPMethod } from \"./types\";\nimport { urlJoinP } from \"url-join-ts\";\nexport class HTTPRequest<T = unknown> implements RequestConfig<T> {\n headers: Record<string, string> = {};\n params: Record<string, string | string[] | Record<string, unknown>> = {};\n baseUrl?: string;\n route: string[] = [];\n method: HTTPMethod;\n data: T;\n\n constructor(config?: RequestConfigBasic) {\n Object.assign(this, config);\n }\n\n /**\n * Returns the full URL of the request, including the base url,\n * routes, and query parameters.\n *\n * ```ts\n * console.log(request.fullUrl())// https://example.com/foo?bar=baz?array=1,2,3\n * ```\n *\n * Note characters may be converted to escape codes. I.e (space => %20) and (comma => %2C)\n *\n * N.B this getter estimates what the url will be. The actual value\n * might be different depending on your underlying HTTPClient and\n * configuration. For example, query parameters might\n * use different array formats.\n */\n get fullUrl() {\n return urlJoinP(this.baseUrl, this.route, this.params);\n }\n\n /**\n * Returns a new independent copy of the request.\n */\n static derive(original: HTTPRequest<unknown>) {\n const request = new HTTPRequest();\n request.headers = { ...original.headers };\n request.params = { ...original.params };\n request.baseUrl = original.baseUrl;\n request.route = [...original.route];\n request.method = original.method;\n request.data = original.data;\n return request;\n }\n}\n\nexport class HTTPRequestBuilder<T extends HTTPRequest<unknown>> {\n #request: T;\n #dynamicHeaders = new Map<\n string,\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n >();\n\n constructor(request: T | (() => T) = () => new HTTPRequest() as T) {\n if (typeof request === \"function\") {\n this.#request = request();\n return;\n }\n this.#request = request;\n }\n\n static create<T extends HTTPRequest<unknown>>() {\n return new HTTPRequestBuilder<T>();\n }\n\n get request() {\n return this.#request;\n }\n\n async resolveDynamicHeaders(\n request: HTTPRequest<T> = this.#request as HTTPRequest<T>\n ) {\n for (const [name, value] of this.#dynamicHeaders) {\n try {\n if (!request.headers) request.headers = {};\n request.headers[name] = String(await value());\n } catch (e) {\n const cause = e as Error;\n const msg = `Failed to resolve dynamic header \"${name}\": \n${cause}`;\n throw new Error(msg);\n }\n }\n return this;\n }\n\n url(url: string) {\n this.#request.baseUrl = url;\n return this;\n }\n\n route(...route: string[]) {\n this.#request.route.push(...route);\n return this;\n }\n\n param(\n name: string,\n value:\n | string\n | number\n | boolean\n | (string | number | boolean)[]\n | Record<string, string | number | boolean>\n ) {\n if (Array.isArray(value)) {\n const asStr = value.flatMap(String);\n this.#request.params[name] = asStr;\n return this;\n }\n if (!Array.isArray(value) && typeof value === \"object\") {\n this.#request.params[name] = value;\n return this;\n }\n this.#request.params[name] = String(value);\n return this;\n }\n\n params(dict: Record<string, unknown>) {\n Object.assign(this.#request.params, dict);\n return this;\n }\n\n data<T>(data: T) {\n this.#request.data = data;\n return this;\n }\n\n header(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>),\n onArray: (value: (string | number | boolean)[]) => string = (value) =>\n value.join(\",\")\n ) {\n if (typeof value === \"function\") {\n this.#dynamicHeaders.set(name, value);\n return this;\n }\n const val = Array.isArray(value) ? onArray(value) : String(value);\n this.#request.headers[name] = val;\n return this;\n }\n\n headers(dict: Record<string, string>) {\n Object.assign(this.#request.headers, dict);\n return this;\n }\n\n get() {\n return this.#request;\n }\n\n method(method: HTTPMethod) {\n this.#request.method = method;\n return this;\n }\n\n #setDynamicHeaders(\n headers: Map<\n string,\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n >\n ) {\n this.#dynamicHeaders = new Map(headers);\n return this;\n }\n\n derive(): HTTPRequestBuilder<T> {\n const request = HTTPRequest.derive(this.#request);\n return new HTTPRequestBuilder(request).#setDynamicHeaders(\n this.#dynamicHeaders\n ) as HTTPRequestBuilder<T>;\n }\n\n build(): HTTPRequest<T> {\n return this.#request as HTTPRequest<T>;\n }\n\n async buildAsync(): Promise<HTTPRequest<T>> {\n await this.resolveDynamicHeaders();\n return this.#request as HTTPRequest<T>;\n }\n}\n","import { SchemaParser, StatusCode } from \"./types\";\nexport class SchemaMap {\n #map: Map<StatusCode, SchemaParser>;\n constructor(map?: Map<StatusCode, SchemaParser> | SchemaMap) {\n if (map instanceof SchemaMap) {\n this.#map = new Map(map.#map);\n return;\n }\n this.#map = new Map(map);\n }\n\n derive() {\n return new SchemaMap(this.#map);\n }\n\n registerStatus(parser: SchemaParser, ...codes: StatusCode[]) {\n codes.forEach((code) => {\n if (this.#map.has(code)) {\n const msg = `Status code ${code} is already registered with a parser`;\n throw new Error(msg);\n }\n this.#map.set(code, parser);\n });\n }\n\n registerRange(parser: SchemaParser, from: StatusCode, to: StatusCode) {\n for (let i = from; i <= to; i++) {\n if (this.#map.has(i)) {\n throw new Error(`Status code ${i} is already registered with a parser`);\n }\n this.#map.set(i, parser);\n }\n }\n\n validate(status: StatusCode, data: unknown, requireSchema: boolean) {\n const parser = this.getParser(status, requireSchema);\n if (\"parse\" in parser) {\n return parser.parse(data);\n }\n if('validate' in parser) {\n return parser.validate(data);\n }\n try {\n return parser(data);\n } catch (e) {\n const msg = `Failed to schema parse response data for status code ${status} with data:\n \n${JSON.stringify(data, null, 2)}}`;\n throw new Error(msg);\n }\n }\n\n getParser(status: StatusCode, requireSchema: boolean) {\n const parser = this.#map.get(status);\n if (!parser && requireSchema) {\n const msg = `No parser registered for status code ${status} but 'requireSchema' is true`;\n throw new Error(msg);\n }\n if (parser) {\n return parser;\n }\n return (data: unknown) => data;\n }\n\n toObject() {\n return Object.fromEntries(this.#map) as Record<StatusCode, SchemaParser>;\n }\n}\n","import { SchemaMap } from \"./schema.map\";\nimport { RequestHook, ResponseHook, SchemaParser, StatusCode } from \"./types\";\n\nexport interface SchemaConfig {\n schemas: SchemaMap;\n requireSchema: boolean;\n allowPlainText: boolean;\n}\n\nexport interface HTTPHooks {\n onSend: [string, RequestHook][];\n onReceive: [string, ResponseHook<unknown>][];\n}\n\n// export type MetaConfig = SchemaConfig & HTTPHooks;\n\nexport class MetaConfig implements SchemaConfig, HTTPHooks {\n schemas: SchemaMap;\n requireSchema: boolean;\n allowPlainText: boolean;\n onSend: [string, RequestHook][] = [];\n onReceive: [string, ResponseHook<unknown>][] = [];\n throwOnServerError: boolean;\n}\n\nexport class MetaConfigBuilder {\n #schemaMap = new SchemaMap();\n #requireSchema = false;\n #allowPlainText = false;\n #onBeforeSend: [string, RequestHook][] = [];\n #onAfterSend: [string, ResponseHook<unknown>][] = [];\n #throwOnServerError = false;\n\n schemaMap(map: SchemaMap) {\n this.#schemaMap = map;\n return this;\n }\n\n schema(parser: SchemaParser, ...codes: StatusCode[]): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n args.forEach((arg) => {\n if (typeof arg === \"number\") {\n this.#schemaMap.registerStatus(parser, arg);\n } else if (Array.isArray(arg)) {\n this.#schemaMap.registerStatus(parser, ...arg);\n } else {\n this.#schemaMap.registerRange(parser, arg.from, arg.to);\n }\n });\n\n return this;\n }\n\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n\n onBeforeSend(description: string, hook: RequestHook) {\n this.#onBeforeSend.push([description, hook]);\n return this;\n }\n\n #setOnSend(hooks: [string, RequestHook][]) {\n this.#onBeforeSend = [...hooks];\n return this;\n }\n\n throwOnServerError(value: boolean) {\n this.#throwOnServerError = value;\n return this;\n }\n\n onReceiveResponse(description: string, hook: ResponseHook<unknown>) {\n this.#onAfterSend.push([description, hook]);\n return this;\n }\n\n #setOnReceive(hooks: [string, ResponseHook<unknown>][]) {\n this.#onAfterSend = [...hooks];\n return this;\n }\n\n build() {\n const config = new MetaConfig();\n config.schemas = this.#schemaMap.derive();\n config.requireSchema = this.#requireSchema;\n config.allowPlainText = this.#allowPlainText;\n config.onSend = this.#onBeforeSend;\n config.onReceive = this.#onAfterSend;\n return config;\n }\n\n derive() {\n return new MetaConfigBuilder()\n .schemaMap(this.#schemaMap.derive())\n .requireSchema(this.#requireSchema)\n .allowPlainText(this.#allowPlainText)\n .throwOnServerError(this.#throwOnServerError)\n .#setOnSend(this.#onBeforeSend)\n .#setOnReceive(this.#onAfterSend);\n }\n}\n","import { AutomationError } from \"@autometa/errors\";\nimport isJson from \"@stdlib/assert-is-json\";\nimport { highlight } from \"cli-highlight\";\n\nexport function transformResponse(\n allowPlainText: boolean,\n data: null | undefined | string\n) {\n if (data === null) {\n return null;\n }\n if (data === undefined) {\n return undefined;\n }\n if (data === \"\") {\n return data;\n }\n if (isJson(data)) {\n return JSON.parse(data);\n }\n if (typeof data === \"string\" && [\"true\", \"false\"].includes(data)) {\n return JSON.parse(data);\n }\n if (typeof data === \"string\" && /^\\d*\\.?\\d+$/.test(data)) {\n return JSON.parse(data);\n }\n\n if (typeof data === \"object\") {\n return data;\n }\n if (allowPlainText) {\n return data;\n }\n\n const response = highlight(data, { language: \"html\" });\n const message = [\n `Could not parse a response as json, and this request was not configured to allow plain text responses.`,\n `To allow plain text responses, use the 'allowPlainText' method on the HTTP client.`,\n \"\",\n response\n ];\n throw new AutomationError(message.join(\"\\n\"));\n}\n","import isJson from \"@stdlib/assert-is-json\";\n\n/**\n * Schema which does not care about data validation.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response does not matter.\n * @param data\n * @returns\n */\nexport function AnySchema(data: unknown) {\n return data;\n}\n\n/**\n * Schema which validates that a response is empty. This can mean\n * the data payload was `null`, `undefined` or the string `'null'`.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be null or not defined.\n * @param data\n * @returns\n */\nexport function EmptySchema(data: unknown) {\n if (data !== null && data !== undefined && data !== \"null\") {\n throw new Error(`Expected null but got <${typeof data}> for ${data}`);\n }\n return data === \"null\" ? null : data;\n}\n\n/**\n * Schema which validates a response was null.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be null.\n * @param data\n * @returns\n */\nexport function NullSchema(data: unknown) {\n if (data !== null && data !== \"null\") {\n throw new Error(`Expected null but got <${typeof data}> for ${data}`);\n }\n return null;\n}\n\n/**\n * Schema which validates a response was undefined.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be undefined.\n *\n * @param data\n * @returns\n */\nexport function UndefinedSchema(data: unknown) {\n if (data !== undefined) {\n throw new Error(`Expected undefined but got <${typeof data}> for ${data}`);\n }\n return undefined;\n}\n\n/**\n * Schema which validates a response was a boolean, or a string of value\n * `'true'` or `'false'`.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a boolean.\n *\n * @param data\n * @returns\n */\nexport function BooleanSchema(data: unknown) {\n if (\n !(typeof data === \"boolean\") &&\n [\"true\", \"false\"].includes(String(data)) === false\n ) {\n throw new Error(`Expected boolean but got <${typeof data}> for ${data}`);\n }\n return JSON.parse(data as string);\n}\n\n/**\n * Schema which validates a response was a number, or a string of value\n * of a number.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a number.\n *\n * @param data\n * @returns\n */\nexport function NumberSchema(data: unknown) {\n if (\n !(typeof data === \"number\") &&\n /^\\d*\\.?\\d+$/.test(String(data)) === false\n ) {\n throw new Error(`Expected number but got <${typeof data}> for ${data}`);\n }\n return JSON.parse(data as string);\n}\n\n/**\n * Schema which validates a response was a string.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a string.\n *\n * @param data\n * @returns\n */\nexport function StringSchema(data: unknown) {\n if (typeof data !== \"string\") {\n throw new Error(`Expected string but got <${typeof data}> for ${data}`);\n }\n return data;\n}\n\n\nexport function JSONSchema<T = unknown>(data: unknown) {\n if(typeof data === 'object') {\n return data as T;\n }\n if (!isJson(data)) {\n throw new Error(`Expected JSON but got <${typeof data}> for ${data}`);\n }\n const result = JSON.parse(data);\n return result;\n}"],"mappings":"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","names":["value","AutomationError","_request","AutomationError","isJson"]}
1
+ {"version":3,"sources":["../../src/http-response.ts","../../src/axios-client.ts","../../src/http-client.ts","../../src/http.ts","../../src/default-client-factory.ts","../../src/http-request.ts","../../src/schema.map.ts","../../src/request-meta.config.ts","../../src/transform-response.ts","../../src/default-schema.ts"],"sourcesContent":["import { HTTPRequest } from \"./http-request\";\nimport { StatusCode } from \"./types\";\n\nexport class HTTPResponse<T = unknown> {\n status: StatusCode;\n statusText: string;\n data: T;\n headers: Record<string, string>;\n request: HTTPRequest<unknown>;\n\n constructor() {\n this.headers = {};\n }\n\n static fromRaw<T>(response: HTTPResponse<T>) {\n const newResponse = new HTTPResponse<T>();\n Object.assign(newResponse, response);\n return response;\n }\n\n /**\n * Decomposes a response, creating an exact copy of the current response,\n * but with a new data value. The data can be provided directly as is, or it\n * can be generated through a callback function which receives the current\n * response data as an argument.\n *\n * ```ts\n * const response = await http.get(\"/products\");\n *\n * // direct value\n * const products = response.data;\n * const firstProduct = response.decompose(products[0]);\n * // callback transformer\n * const secondProduct = response.decompose((products) => products[1]);\n * // callback transformer with destructuring\n * const secondProduct = response.decompose(([product]) => product);\n * ```\n * @param value\n */\n decompose<K>(value: K): HTTPResponse<K>;\n decompose<K>(transformFn: (response: T) => K): HTTPResponse<K>;\n decompose<K>(transformFnOrVal: K | ((response: T) => K)): HTTPResponse<K> {\n const value = getDecompositionValue<T>(this.data, transformFnOrVal);\n return new HTTPResponseBuilder()\n .status(this.status)\n .statusText(this.statusText)\n .headers(this.headers)\n .request(this.request)\n .data(value)\n .build() as HTTPResponse<K>;\n }\n}\n\nfunction getDecompositionValue<T>(data: unknown, transformFn: unknown): T {\n return typeof transformFn === \"function\" ? transformFn(data) : transformFn;\n}\n\nexport class HTTPResponseBuilder {\n #response = new HTTPResponse();\n\n static create() {\n return new HTTPResponseBuilder();\n }\n\n derive() {\n return HTTPResponseBuilder.create()\n .data(this.#response.data)\n .headers(this.#response.headers)\n .request(this.#response.request)\n .status(this.#response.status)\n .statusText(this.#response.statusText);\n }\n\n status(code: StatusCode) {\n this.#response.status = code;\n return this;\n }\n\n statusText(text: string) {\n this.#response.statusText = text;\n return this;\n }\n\n data<T>(data: T) {\n this.#response.data = data;\n return this;\n }\n\n headers(dict: Record<string, string>) {\n this.#response.headers = dict;\n return this;\n }\n\n header(name: string, value: string) {\n this.#response.headers[name] = value;\n return this;\n }\n\n request(request: HTTPRequest<unknown>) {\n this.#response.request = request;\n return this;\n }\n\n build() {\n return this.#response;\n }\n}\n","import { HTTPRequest } from \"./http-request\";\nimport { HTTPResponse, HTTPResponseBuilder } from \"./http-response\";\nimport { HTTPAdditionalOptions, StatusCode } from \"./types\";\nimport axios, { AxiosRequestConfig } from \"axios\";\nimport { HTTPClient } from \"./http-client\";\n\n@HTTPClient.Use()\nexport class AxiosClient extends HTTPClient {\n async request<TRequestType, TResponseType>(\n request: HTTPRequest<TRequestType>,\n options: HTTPAdditionalOptions<AxiosRequestConfig>\n ): Promise<HTTPResponse<TResponseType>> {\n const { baseUrl, route, params, headers, method, data } = request;\n const url = [baseUrl, ...route].join(\"/\");\n const axiosRequest: AxiosRequestConfig = {\n url,\n params,\n headers,\n method: method,\n data,\n validateStatus: function (status) {\n return status >= 0 && status < 600;\n },\n ...options\n };\n const response = await axios(axiosRequest);\n return HTTPResponseBuilder.create()\n .status(response.status as StatusCode)\n .statusText(response.statusText)\n .data(response.data)\n .headers(response.headers as Record<string, string>)\n .request(request)\n .build() as HTTPResponse<TResponseType>;\n }\n}\n","import { HTTPRequest } from \"./http-request\";\nimport { HTTPResponse } from \"./http-response\";\nimport { HTTPAdditionalOptions } from \"./types\";\nimport { Class } from \"@autometa/types\";\nexport let defaultClient: Class<HTTPClient>;\nexport abstract class HTTPClient {\n static Use(): (target: Class<HTTPClient>) => void\n static Use(client?: Class<HTTPClient>) {\n if (client) {\n defaultClient = client\n }\n return function (target: Class<HTTPClient>) {\n defaultClient = target\n };\n }\n abstract request<TRequestType, TResponseType>(\n request: HTTPRequest<TRequestType>,\n options?: HTTPAdditionalOptions<unknown>\n ): Promise<HTTPResponse<TResponseType>>;\n}\n","import { Fixture, INJECTION_SCOPE } from \"@autometa/injection\";\nimport { AxiosClient } from \"./axios-client\";\nimport { HTTPClient } from \"./http-client\";\nimport { defaultClientFactory } from \"./default-client-factory\";\nimport { HTTPRequest, HTTPRequestBuilder } from \"./http-request\";\nimport { HTTPResponse } from \"./http-response\";\nimport { MetaConfig, MetaConfigBuilder } from \"./request-meta.config\";\nimport {\n HTTPAdditionalOptions,\n RequestHook,\n ResponseHook,\n SchemaParser,\n StatusCode\n} from \"./types\";\nimport { transformResponse } from \"./transform-response\";\nimport { AutomationError } from \"@autometa/errors\";\n\n/**\n * The HTTP fixture allows requests to be built and sent to a server. In general,\n * there are 2 modes of operation:\n *\n * * Shared Chain: The shared chain is used to configure the client for all requests, such as\n * routes this instance will always be used. When a shared chain method is called, it returns\n * the same instance of HTTP which can be further chained to configure the client.\n * * Request Chain: The request chain is used to configure a single request, inheriting values\n * set by the shared chain. When called, a new HTTP client instance is created and inherits the values\n * set by it's parent.\n *\n * The 2 modes are intended to simplify configuring an object through an inheritance chain. For example,\n * assume we have an API with 2 controller routes, `/product` and `/seller`. We can set up a Base Client\n * which consumes the HTTP fixture and configures it with the base url of our API.\n *\n * Inheritors can further configure their HTTP instance's routes.\n *\n * ```ts\n * \\@Constructor(HTTP)\n * export class BaseClient {\n * constructor(protected readonly http: HTTP) {\n * this.http.url(\"https://api.example.com\");\n * }\n * }\n *\n * export class ProductClient extends BaseClient {\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"product\");\n * }\n * getProduct(id: number) {\n * return this.http.route(id).get();\n * }\n *\n * export class SellerClient extends BaseClient {\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"seller\");\n * }\n *\n * getSeller(id: number) {\n * return this.http.route(id).get();\n * }\n * }\n * ```\n *\n * 'Schemas' can also be configured. A Schema is a function or an object with a `parse` method, which\n * takes a response data payload and returns a validated object. Schemas are mapped to\n * HTTP Status Codes, and if configured to be required the request will fail if no schema is found\n * matching that code.\n *\n * Defining a schema function:\n *\n * ```\n * // user.schema.ts\n * export function UserSchema(data: unknown) {\n * if(typeof data !== \"object\") {\n * throw new Error(\"Expected an object\");\n * }\n *\n * if(typeof data.name !== \"string\") {\n * throw new Error(\"Expected a string\");\n * }\n *\n * return data as { name: string };\n * }\n *\n * // user.controller.ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 });\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * // or\n * return this.http\n * .route(id)\n * .schema(UserSchema, { from: 200, to: 299 })\n * .get();\n * // or\n * return this.http\n * .route(id)\n * .schema(UserSchema, 200, 201, 202)\n * .get();\n * }\n * }\n * ```\n *\n * Validation libraries which use a `.parse` or `.validation`, method, such as Zod or MyZod, can also be used as schemas:\n *\n * ```ts\n * // user.schema.ts\n * import { z } from \"myzod\";\n *\n * export const UserSchema = z.object({\n * name: z.string()\n * });\n *\n * // user.controller.ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 })\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * }\n * }\n * ```\n */\n@Fixture(INJECTION_SCOPE.TRANSIENT)\nexport class HTTP {\n #request: HTTPRequestBuilder<HTTPRequest<unknown>>;\n #metaConfig: MetaConfigBuilder;\n constructor(\n private readonly client: HTTPClient = defaultClientFactory(),\n builder: HTTPRequestBuilder<\n HTTPRequest<unknown>\n > = new HTTPRequestBuilder(),\n metaConfig: MetaConfigBuilder = new MetaConfigBuilder()\n ) {\n this.#request = builder;\n this.#metaConfig = metaConfig.derive();\n }\n\n static create(\n client: HTTPClient = new AxiosClient(),\n builder: HTTPRequestBuilder<\n HTTPRequest<unknown>\n > = new HTTPRequestBuilder(),\n metaConfig: MetaConfigBuilder = new MetaConfigBuilder()\n ) {\n const derived = new HTTP(client, builder, metaConfig);\n return derived;\n }\n\n /**\n * Sets the base url of the request for this client, such as\n * `https://api.example.com`, and could include always-used routes like\n * the api version, such as `/v1` or `/api/v1` at the end.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export abstract class BaseClient {\n * constructor(protected readonly http: HTTP) {\n * this.http.url(\"https://api.example.com\");\n * }\n * }\n * ```\n * @param url\n * @returns\n */\n url(url: string) {\n this.#request.url(url);\n return this;\n }\n\n sharedOptions(options: HTTPAdditionalOptions<unknown>) {\n this.#metaConfig.options(options);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will require a schema be defined\n * matching any response status code. If set to false, a schema will still be used for validation\n * if defined, or the unadulterated original body will be returned if no schema matches.\n *\n * @param required Whether or not a schema is required for all responses.\n * @returns This instance of HTTP.\n */\n requireSchema(required: boolean) {\n this.#metaConfig.requireSchema(required);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will allow plain text\n * responses. If set to false, plain text responses will throw an serialization error.\n *\n * Useful when an endpoint returns a HTML or plain text response. If the plain text\n * is the value of `true` or `false`, or a number, it will be parsed into the\n * appropriate type.\n *\n * This method is a shared chain method, and will return the same instance of HTTP.\n *\n * @param allow Whether or not plain text responses are allowed.\n * @returns This instance of HTTP.\n */\n sharedAllowPlainText(allow: boolean) {\n this.#metaConfig.allowPlainText(allow);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will allow plain text\n * responses. If set to false, plain text responses will throw an serialization error.\n *\n * Useful when an endpoint returns a HTML or plain text response. If the plain text\n * is the value of `true` or `false`, or a number, it will be parsed into the\n * appropriate type.\n *\n * This method is a request chain method, and will return a new instance of HTTP.\n *\n * @param allow Whether or not plain text responses are allowed.\n * @returns A new child instance of HTTP derived from this one.\n */\n allowPlainText(allow: boolean) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().allowPlainText(allow)\n );\n }\n\n /**\n * Attaches a route to the request, such as `/product` or `/user`. Subsequent calls\n * to this method will append the route to the existing route, such as `/product/1`.\n *\n * Numbers will be converted to strings automatically. Routes can be defined one\n * at a time or as a spread argument.\n *\n * ```ts\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"user\", id).get();\n * }\n *\n * // or\n *\n * constructor(http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedRoute(id)\n * .get();\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the routes defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param route A route or spread list of routes to append to the request.\n * @returns This instance of HTTP.\n */\n sharedRoute(...route: (string | number | boolean)[]) {\n this.#request.route(...route.map((r) => r.toString()));\n return this;\n }\n\n /**\n * Attaches a route to the request, such as `/product` or `/user`. Subsequent calls\n * to this method will append the route to the existing route, such as `/product/1`.\n *\n * Numbers will be converted to strings automatically. Routes can be defined one\n * at a time or as a spread argument.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http.route(\"user\", id).get();\n * }\n *\n * // or\n *\n * getUser(id: number) {\n * return this.http\n * .route(\"user\")\n * .route(id)\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any routes previously defined and appending the new route. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param route A route or spread list of routes to append to the request.\n * @returns A new child instance of HTTP derived from this one.\n */\n route(...route: (string | number | boolean)[]) {\n const mapped = route.map((r) => String(r));\n return HTTP.create(\n this.client,\n this.#request.derive().route(...mapped),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a shared schema mapping for all requests by this client. Schemas are\n * mapped to HTTP Status Codes, and if configured to be required the request will fail\n * if no schema is found matching that code.\n *\n * The status code mapping can be defined as a single code, a range of codes, or a spread list.\n *\n * ```ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(UserSchema, 200)\n * .sharedSchema(EmptySchema, 201, 204)\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 });\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the schemas defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param parser The schema parser to use for this mapping.\n * @param codes A single status code, a range of status codes, or a spread list of status codes.\n * @returns This instance of HTTP.\n */\n sharedSchema(parser: SchemaParser, ...codes: StatusCode[]): HTTP;\n sharedSchema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTP;\n sharedSchema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): HTTP {\n this.#metaConfig.schema(parser, ...args);\n return this;\n }\n\n /**\n * Attaches a schema mapping for this request. Schemas are\n * mapped to HTTP Status Codes, and if configured to be required the request will fail\n * if no schema is found matching that code.\n *\n * The status code mapping can be defined as a single code, a range of codes, or a spread list.\n *\n * ```ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .schema(ErrorSchema, { from: 400, to: 499 });\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * }\n *\n * getUsers(...ids: number[]) {\n * return this.http\n * .route(\"users\")\n * .schema(UserSchema, { from: 200, to: 299 })\n * .schema(UserSchema, 200)\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any schemas previously defined and appending the new schema. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param parser The schema parser to use for this mapping.\n * @param codes A single status code, a range of status codes, or a spread list of status codes.\n * @returns A new child instance of HTTP derived from this one.\n */\n schema(parser: SchemaParser, ...codes: StatusCode[]): HTTP;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTP;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): HTTP {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().schema(parser, ...args)\n );\n }\n\n /**\n * Attaches a shared query string parameter to all requests by this client. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n sharedParam(name: string, value: Record<string, unknown>): HTTP;\n sharedParam(name: string, ...value: (string | number | boolean)[]): HTTP;\n sharedParam(name: string, value: (string | number | boolean)[]): HTTP;\n sharedParam(\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value: any\n ): HTTP {\n this.#request.param(name, value);\n return this;\n }\n\n /**\n * `onSend` is a pre-request hook which will be executed in order of definition\n * immediately before the request is sent. This hook can be used to analyze or\n * log the request state.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedOnSend(\"log request\",\n * (request) => console.log(JSON.stringify(request, null, 2))\n * );\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the onSend hooks defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns This instance of HTTP.\n */\n sharedOnSend(description: string, hook: RequestHook) {\n this.#metaConfig.onBeforeSend(description, hook);\n return this;\n }\n\n /**\n * `onReceive` is a post-request hook which will be executed in order of definition\n * immediately after the response is received. This hook can be used to analyze or\n * log the response state.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedOnReceive(\"log response\",\n * (response) => console.log(JSON.stringify(response, null, 2))\n * );\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the onReceive hooks defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns This instance of HTTP.\n */\n sharedOnReceive(description: string, hook: ResponseHook<unknown>) {\n this.#metaConfig.onReceiveResponse(description, hook);\n return this;\n }\n\n /**\n * Attaches a query string parameter object to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * ```ts\n * constructor(http: HTTP) {\n * super(http);\n * this.http\n * .sharedParams({ 'is-test': \"true\" })\n * ```\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n sharedParams(dict: Record<string, unknown>) {\n this.#request.params(dict);\n return this;\n }\n\n /**\n * Attaches a query string parameter to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any query string parameters previously defined and appending the new parameter. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .param(\"name\", \"John\")\n * .param(\"age\", 30)\n * ```\n *\n * Note: Numbers and Booleans will be converted to strings automatically.\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns A new child instance of HTTP derived from this one.\n */\n param(name: string, value: Record<string, unknown>): HTTP;\n param(name: string, ...value: (string | number | boolean)[]): HTTP;\n param(name: string, value: (string | number | boolean)[]): HTTP;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n param(name: string, ...value: any) {\n return HTTP.create(\n this.client,\n this.#request.derive().param(name, value),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a query string parameter object to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .param({ name: \"John\", age: \"30\" })\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n params(dict: Record<string, string>) {\n this.#request.params(dict);\n return HTTP.create(\n this.client,\n this.#request.derive().params(dict),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a shared data payload to this client. The data payload is the body of the request,\n * and can be any type. If the data payload is an object, it will be serialized to JSON.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the data payload defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param data The data payload to attach to the request.\n * @returns This instance of HTTP.\n */\n sharedData<T>(data: T) {\n this.#request.data(data);\n return this;\n }\n\n /**\n * Attaches a shared header to this client. Headers are string:string key-value pairs which are\n * sent with the request, such as `Content-Type: application/json`.\n *\n * Numbers, Booleans and Null will be converted to string values automatically.\n *\n * A Factory function can also be provided to generate the header value at the time of request.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the header defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param name The name of the header.\n * @param value The value of the header.\n */\n sharedHeader(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n ) {\n this.#request.header(name, value);\n return this;\n }\n\n header(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n ) {\n return HTTP.create(\n this.client,\n this.#request.derive().header(name, value),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a data payload to this request. The data payload is the body of the request,\n * and can be any type. If the data payload is an object, it will be serialized to JSON.\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any data payload previously defined and appending the new payload. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param data The data payload to attach to the request.\n * @returns A new child instance of HTTP derived from this one.\n */\n data<T>(data: T) {\n this.#request.data(data);\n return HTTP.create(\n this.client,\n this.#request.derive().data(data),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * `onSend` is a pre-request hook which will be executed in order of definition\n * immediately before the request is sent. This hook can be used to modify the request,\n * or to log the state of a request before final send-off.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * }\n *\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .onSend(\"log request\",\n * (request) => console.log(JSON.stringify(request, null, 2)\n * )\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any onSend hooks previously defined and appending the new hook. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns A new child instance of HTTP derived from this one.\n */\n onSend(description: string, hook: RequestHook) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().onBeforeSend(description, hook)\n );\n }\n\n /**\n * `onReceive` is a post-request hook which will be executed in order of definition\n * immediately after the response is received. This hook can be used to modify the response,\n * or to log the state of a response after it is received.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * }\n *\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .onReceive(\"log response\",\n * (response) => console.log(JSON.stringify(response, null, 2)\n * )\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any onReceive hooks previously defined and appending the new hook. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns A new child instance of HTTP derived from this one.\n */\n onReceive(description: string, hook: ResponseHook<unknown>) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().onReceiveResponse(description, hook)\n );\n }\n\n /**\n * Executes the current request state as a GET request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n get<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"GET\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a POST request.\n *\n * @param data The data payload to attach to the request.\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n post<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"POST\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a DELETE request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n * as e.g Axios configuration values.\n */\n delete<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"DELETE\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a PUT request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n put<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"PUT\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n /**\n * Executes the current request state as a PATCH request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n patch<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"PATCH\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n head<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"HEAD\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n options<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"OPTIONS\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n trace<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"TRACE\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n connect<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"CONNECT\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n async #makeRequest(\n builder: HTTPRequestBuilder<HTTPRequest<unknown>>,\n options?: HTTPAdditionalOptions<unknown>\n ) {\n const request = (await builder.resolveDynamicHeaders()).build();\n const meta = this.#metaConfig.derive().build();\n await this.runOnSendHooks(meta, request);\n const opts = { ...meta.options, ...options };\n const result = await this.client.request<unknown, string>(request, opts);\n result.data = transformResponse(meta.allowPlainText, result.data);\n await this.runOnReceiveHooks(meta, result);\n const validated = this.#validateResponse(result, meta);\n return validated;\n }\n\n private async runOnSendHooks(\n meta: MetaConfig,\n request: HTTPRequest<unknown>\n ) {\n for (const [description, hook] of meta.onSend) {\n try {\n await hook(request);\n } catch (e) {\n const cause = e as Error;\n const msg = `An error occurred while sending a request in hook: '${description}'`;\n throw new AutomationError(msg, { cause });\n }\n }\n }\n private async runOnReceiveHooks(\n meta: MetaConfig,\n response: HTTPResponse<unknown>\n ) {\n for (const [description, hook] of meta.onReceive) {\n try {\n await hook(response);\n } catch (e) {\n const cause = e as Error;\n const msg = `An error occurred while receiving a response in hook: '${description}'`;\n throw new AutomationError(msg, { cause });\n }\n }\n }\n\n #validateResponse<T>(\n response: HTTPResponse<unknown>,\n meta: MetaConfig\n ): HTTPResponse<T> {\n const { status, data } = response;\n const validated = meta.schemas.validate(\n status,\n data,\n meta.requireSchema\n ) as T;\n response.data = validated;\n return response as HTTPResponse<T>;\n }\n}\n","import { Class } from \"@autometa/types\";\nimport { defaultClient, type HTTPClient } from \"./http-client\";\n\nexport function defaultClientFactory() {\n const type = defaultClient as Class<HTTPClient>;\n return new type();\n}\n","import { RequestConfig, RequestConfigBasic } from \"./request.config\";\nimport { HTTPMethod } from \"./types\";\nimport { urlJoinP } from \"url-join-ts\";\nexport class HTTPRequest<T = unknown> implements RequestConfig<T> {\n headers: Record<string, string> = {};\n params: Record<string, string | string[] | Record<string, unknown>> = {};\n baseUrl?: string;\n route: string[] = [];\n method: HTTPMethod;\n data: T;\n\n constructor(config?: RequestConfigBasic) {\n Object.assign(this, config);\n }\n\n /**\n * Returns the full URL of the request, including the base url,\n * routes, and query parameters.\n *\n * ```ts\n * console.log(request.fullUrl())// https://example.com/foo?bar=baz?array=1,2,3\n * ```\n *\n * Note characters may be converted to escape codes. I.e (space => %20) and (comma => %2C)\n *\n * N.B this getter estimates what the url will be. The actual value\n * might be different depending on your underlying HTTPClient and\n * configuration. For example, query parameters might\n * use different array formats.\n */\n get fullUrl() {\n return urlJoinP(this.baseUrl, this.route, this.params);\n }\n\n /**\n * Returns a new independent copy of the request.\n */\n static derive(original: HTTPRequest<unknown>) {\n const request = new HTTPRequest();\n request.headers = { ...original.headers };\n request.params = { ...original.params };\n request.baseUrl = original.baseUrl;\n request.route = [...original.route];\n request.method = original.method;\n request.data = original.data;\n return request;\n }\n}\n\nexport class HTTPRequestBuilder<T extends HTTPRequest<unknown>> {\n #request: T;\n #dynamicHeaders = new Map<\n string,\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n >();\n\n constructor(request: T | (() => T) = () => new HTTPRequest() as T) {\n if (typeof request === \"function\") {\n this.#request = request();\n return;\n }\n this.#request = request;\n }\n\n static create<T extends HTTPRequest<unknown>>() {\n return new HTTPRequestBuilder<T>();\n }\n\n get request() {\n return this.#request;\n }\n\n async resolveDynamicHeaders(\n request: HTTPRequest<T> = this.#request as HTTPRequest<T>\n ) {\n for (const [name, value] of this.#dynamicHeaders) {\n try {\n if (!request.headers) request.headers = {};\n request.headers[name] = String(await value());\n } catch (e) {\n const cause = e as Error;\n const msg = `Failed to resolve dynamic header \"${name}\": \n${cause}`;\n throw new Error(msg);\n }\n }\n return this;\n }\n\n url(url: string) {\n this.#request.baseUrl = url;\n return this;\n }\n\n route(...route: string[]) {\n this.#request.route.push(...route);\n return this;\n }\n\n param(\n name: string,\n value:\n | string\n | number\n | boolean\n | (string | number | boolean)[]\n | Record<string, string | number | boolean>\n ) {\n if (Array.isArray(value)) {\n const asStr = value.flatMap(String);\n this.#request.params[name] = asStr;\n return this;\n }\n if (!Array.isArray(value) && typeof value === \"object\") {\n this.#request.params[name] = value;\n return this;\n }\n this.#request.params[name] = String(value);\n return this;\n }\n\n params(dict: Record<string, unknown>) {\n Object.assign(this.#request.params, dict);\n return this;\n }\n\n data<T>(data: T) {\n this.#request.data = data;\n return this;\n }\n\n header(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>),\n onArray: (value: (string | number | boolean)[]) => string = (value) =>\n value.join(\",\")\n ) {\n if (typeof value === \"function\") {\n this.#dynamicHeaders.set(name, value);\n return this;\n }\n const val = Array.isArray(value) ? onArray(value) : String(value);\n this.#request.headers[name] = val;\n return this;\n }\n\n headers(dict: Record<string, string>) {\n Object.assign(this.#request.headers, dict);\n return this;\n }\n\n get() {\n return this.#request;\n }\n\n method(method: HTTPMethod) {\n this.#request.method = method;\n return this;\n }\n\n #setDynamicHeaders(\n headers: Map<\n string,\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n >\n ) {\n this.#dynamicHeaders = new Map(headers);\n return this;\n }\n\n derive(): HTTPRequestBuilder<T> {\n const request = HTTPRequest.derive(this.#request);\n return new HTTPRequestBuilder(request).#setDynamicHeaders(\n this.#dynamicHeaders\n ) as HTTPRequestBuilder<T>;\n }\n\n build(): HTTPRequest<T> {\n return this.#request as HTTPRequest<T>;\n }\n\n async buildAsync(): Promise<HTTPRequest<T>> {\n await this.resolveDynamicHeaders();\n return this.#request as HTTPRequest<T>;\n }\n}\n","import { SchemaParser, StatusCode } from \"./types\";\nexport class SchemaMap {\n #map: Map<StatusCode, SchemaParser>;\n constructor(map?: Map<StatusCode, SchemaParser> | SchemaMap) {\n if (map instanceof SchemaMap) {\n this.#map = new Map(map.#map);\n return;\n }\n this.#map = new Map(map);\n }\n\n derive() {\n return new SchemaMap(this.#map);\n }\n\n registerStatus(parser: SchemaParser, ...codes: StatusCode[]) {\n codes.forEach((code) => {\n if (this.#map.has(code)) {\n const msg = `Status code ${code} is already registered with a parser`;\n throw new Error(msg);\n }\n this.#map.set(code, parser);\n });\n }\n\n registerRange(parser: SchemaParser, from: StatusCode, to: StatusCode) {\n for (let i = from; i <= to; i++) {\n if (this.#map.has(i)) {\n throw new Error(`Status code ${i} is already registered with a parser`);\n }\n this.#map.set(i, parser);\n }\n }\n\n validate(status: StatusCode, data: unknown, requireSchema: boolean) {\n const parser = this.getParser(status, requireSchema);\n if (\"parse\" in parser) {\n return parser.parse(data);\n }\n if('validate' in parser) {\n return parser.validate(data);\n }\n try {\n return parser(data);\n } catch (e) {\n const msg = `Failed to schema parse response data for status code ${status} with data:\n \n${JSON.stringify(data, null, 2)}}`;\n throw new Error(msg);\n }\n }\n\n getParser(status: StatusCode, requireSchema: boolean) {\n const parser = this.#map.get(status);\n if (!parser && requireSchema) {\n const msg = `No parser registered for status code ${status} but 'requireSchema' is true`;\n throw new Error(msg);\n }\n if (parser) {\n return parser;\n }\n return (data: unknown) => data;\n }\n\n toObject() {\n return Object.fromEntries(this.#map) as Record<StatusCode, SchemaParser>;\n }\n}\n","import { SchemaMap } from \"./schema.map\";\nimport {\n HTTPAdditionalOptions,\n RequestHook,\n ResponseHook,\n SchemaParser,\n StatusCode\n} from \"./types\";\n\nexport interface SchemaConfig {\n schemas: SchemaMap;\n requireSchema: boolean;\n allowPlainText: boolean;\n}\n\nexport interface HTTPHooks {\n onSend: [string, RequestHook][];\n onReceive: [string, ResponseHook<unknown>][];\n}\n\n// export type MetaConfig = SchemaConfig & HTTPHooks;\n\nexport class MetaConfig implements SchemaConfig, HTTPHooks {\n schemas: SchemaMap;\n requireSchema: boolean;\n allowPlainText: boolean;\n onSend: [string, RequestHook][] = [];\n onReceive: [string, ResponseHook<unknown>][] = [];\n throwOnServerError: boolean;\n options: HTTPAdditionalOptions<unknown> = {};\n}\n\nexport class MetaConfigBuilder {\n #schemaMap = new SchemaMap();\n #requireSchema = false;\n #allowPlainText = false;\n #onBeforeSend: [string, RequestHook][] = [];\n #onAfterSend: [string, ResponseHook<unknown>][] = [];\n #throwOnServerError = false;\n #options: HTTPAdditionalOptions<unknown> = {};\n\n options(options: HTTPAdditionalOptions<unknown>) {\n this.#options = { options };\n return this;\n }\n schemaMap(map: SchemaMap) {\n this.#schemaMap = map;\n return this;\n }\n\n schema(parser: SchemaParser, ...codes: StatusCode[]): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n args.forEach((arg) => {\n if (typeof arg === \"number\") {\n this.#schemaMap.registerStatus(parser, arg);\n } else if (Array.isArray(arg)) {\n this.#schemaMap.registerStatus(parser, ...arg);\n } else {\n this.#schemaMap.registerRange(parser, arg.from, arg.to);\n }\n });\n\n return this;\n }\n\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n\n onBeforeSend(description: string, hook: RequestHook) {\n this.#onBeforeSend.push([description, hook]);\n return this;\n }\n\n #setOnSend(hooks: [string, RequestHook][]) {\n this.#onBeforeSend = [...hooks];\n return this;\n }\n\n throwOnServerError(value: boolean) {\n this.#throwOnServerError = value;\n return this;\n }\n\n onReceiveResponse(description: string, hook: ResponseHook<unknown>) {\n this.#onAfterSend.push([description, hook]);\n return this;\n }\n\n #setOnReceive(hooks: [string, ResponseHook<unknown>][]) {\n this.#onAfterSend = [...hooks];\n return this;\n }\n\n build() {\n const config = new MetaConfig();\n config.schemas = this.#schemaMap.derive();\n config.requireSchema = this.#requireSchema;\n config.allowPlainText = this.#allowPlainText;\n config.onSend = this.#onBeforeSend;\n config.onReceive = this.#onAfterSend;\n config.options = this.#options;\n config.throwOnServerError = this.#throwOnServerError;\n return config;\n }\n\n derive() {\n return new MetaConfigBuilder()\n .schemaMap(this.#schemaMap.derive())\n .requireSchema(this.#requireSchema)\n .allowPlainText(this.#allowPlainText)\n .throwOnServerError(this.#throwOnServerError)\n .#setOnSend(this.#onBeforeSend)\n .#setOnReceive(this.#onAfterSend);\n }\n}\n","import { AutomationError } from \"@autometa/errors\";\nimport isJson from \"@stdlib/assert-is-json\";\nimport { highlight } from \"cli-highlight\";\n\nexport function transformResponse(\n allowPlainText: boolean,\n data: null | undefined | string\n) {\n if (data === null) {\n return null;\n }\n if (data === undefined) {\n return undefined;\n }\n if (data === \"\") {\n return data;\n }\n if (isJson(data)) {\n return JSON.parse(data);\n }\n if (typeof data === \"string\" && [\"true\", \"false\"].includes(data)) {\n return JSON.parse(data);\n }\n if (typeof data === \"string\" && /^\\d*\\.?\\d+$/.test(data)) {\n return JSON.parse(data);\n }\n\n if (typeof data === \"object\") {\n return data;\n }\n if (allowPlainText) {\n return data;\n }\n\n const response = highlight(data, { language: \"html\" });\n const message = [\n `Could not parse a response as json, and this request was not configured to allow plain text responses.`,\n `To allow plain text responses, use the 'allowPlainText' method on the HTTP client.`,\n \"\",\n response\n ];\n throw new AutomationError(message.join(\"\\n\"));\n}\n","import isJson from \"@stdlib/assert-is-json\";\n\n/**\n * Schema which does not care about data validation.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response does not matter.\n * @param data\n * @returns\n */\nexport function AnySchema(data: unknown) {\n return data;\n}\n\n/**\n * Schema which validates that a response is empty. This can mean\n * the data payload was `null`, `undefined` or the string `'null'`.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be null or not defined.\n * @param data\n * @returns\n */\nexport function EmptySchema(data: unknown) {\n if (data !== null && data !== undefined && data !== \"null\") {\n throw new Error(`Expected null but got <${typeof data}> for ${data}`);\n }\n return data === \"null\" ? null : data;\n}\n\n/**\n * Schema which validates a response was null.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be null.\n * @param data\n * @returns\n */\nexport function NullSchema(data: unknown) {\n if (data !== null && data !== \"null\") {\n throw new Error(`Expected null but got <${typeof data}> for ${data}`);\n }\n return null;\n}\n\n/**\n * Schema which validates a response was undefined.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be undefined.\n *\n * @param data\n * @returns\n */\nexport function UndefinedSchema(data: unknown) {\n if (data !== undefined) {\n throw new Error(`Expected undefined but got <${typeof data}> for ${data}`);\n }\n return undefined;\n}\n\n/**\n * Schema which validates a response was a boolean, or a string of value\n * `'true'` or `'false'`.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a boolean.\n *\n * @param data\n * @returns\n */\nexport function BooleanSchema(data: unknown) {\n if (\n !(typeof data === \"boolean\") &&\n [\"true\", \"false\"].includes(String(data)) === false\n ) {\n throw new Error(`Expected boolean but got <${typeof data}> for ${data}`);\n }\n return JSON.parse(data as string);\n}\n\n/**\n * Schema which validates a response was a number, or a string of value\n * of a number.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a number.\n *\n * @param data\n * @returns\n */\nexport function NumberSchema(data: unknown) {\n if (\n !(typeof data === \"number\") &&\n /^\\d*\\.?\\d+$/.test(String(data)) === false\n ) {\n throw new Error(`Expected number but got <${typeof data}> for ${data}`);\n }\n return JSON.parse(data as string);\n}\n\n/**\n * Schema which validates a response was a string.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a string.\n *\n * @param data\n * @returns\n */\nexport function StringSchema(data: unknown) {\n if (typeof data !== \"string\") {\n throw new Error(`Expected string but got <${typeof data}> for ${data}`);\n }\n return data;\n}\n\n\nexport function JSONSchema<T = unknown>(data: unknown) {\n if(typeof data === 'object') {\n return data as T;\n }\n if (!isJson(data)) {\n throw new Error(`Expected JSON but got <${typeof data}> for ${data}`);\n }\n const result = JSON.parse(data);\n return result;\n}"],"mappings":"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","names":["value","AutomationError","_request","AutomationError","isJson"]}
package/dist/index.d.cts CHANGED
@@ -403,9 +403,11 @@ declare class MetaConfig implements SchemaConfig, HTTPHooks {
403
403
  onSend: [string, RequestHook][];
404
404
  onReceive: [string, ResponseHook<unknown>][];
405
405
  throwOnServerError: boolean;
406
+ options: HTTPAdditionalOptions<unknown>;
406
407
  }
407
408
  declare class MetaConfigBuilder {
408
409
  #private;
410
+ options(options: HTTPAdditionalOptions<unknown>): this;
409
411
  schemaMap(map: SchemaMap): this;
410
412
  schema(parser: SchemaParser, ...codes: StatusCode[]): MetaConfigBuilder;
411
413
  schema(parser: SchemaParser, ...range: {
@@ -567,6 +569,7 @@ declare class HTTP {
567
569
  * @returns
568
570
  */
569
571
  url(url: string): this;
572
+ sharedOptions(options: HTTPAdditionalOptions<unknown>): this;
570
573
  /**
571
574
  * If set to true, all requests derived from this client will require a schema be defined
572
575
  * matching any response status code. If set to false, a schema will still be used for validation
package/dist/index.d.ts CHANGED
@@ -403,9 +403,11 @@ declare class MetaConfig implements SchemaConfig, HTTPHooks {
403
403
  onSend: [string, RequestHook][];
404
404
  onReceive: [string, ResponseHook<unknown>][];
405
405
  throwOnServerError: boolean;
406
+ options: HTTPAdditionalOptions<unknown>;
406
407
  }
407
408
  declare class MetaConfigBuilder {
408
409
  #private;
410
+ options(options: HTTPAdditionalOptions<unknown>): this;
409
411
  schemaMap(map: SchemaMap): this;
410
412
  schema(parser: SchemaParser, ...codes: StatusCode[]): MetaConfigBuilder;
411
413
  schema(parser: SchemaParser, ...range: {
@@ -567,6 +569,7 @@ declare class HTTP {
567
569
  * @returns
568
570
  */
569
571
  url(url: string): this;
572
+ sharedOptions(options: HTTPAdditionalOptions<unknown>): this;
570
573
  /**
571
574
  * If set to true, all requests derived from this client will require a schema be defined
572
575
  * matching any response status code. If set to false, a schema will still be used for validation
package/dist/index.js CHANGED
@@ -405,9 +405,10 @@ var MetaConfig = class {
405
405
  constructor() {
406
406
  this.onSend = [];
407
407
  this.onReceive = [];
408
+ this.options = {};
408
409
  }
409
410
  };
410
- var _schemaMap, _requireSchema, _allowPlainText, _onBeforeSend, _onAfterSend, _throwOnServerError, _setOnSend, setOnSend_fn, _setOnReceive, setOnReceive_fn;
411
+ var _schemaMap, _requireSchema, _allowPlainText, _onBeforeSend, _onAfterSend, _throwOnServerError, _options, _setOnSend, setOnSend_fn, _setOnReceive, setOnReceive_fn;
411
412
  var _MetaConfigBuilder = class _MetaConfigBuilder {
412
413
  constructor() {
413
414
  __privateAdd(this, _setOnSend);
@@ -418,6 +419,11 @@ var _MetaConfigBuilder = class _MetaConfigBuilder {
418
419
  __privateAdd(this, _onBeforeSend, []);
419
420
  __privateAdd(this, _onAfterSend, []);
420
421
  __privateAdd(this, _throwOnServerError, false);
422
+ __privateAdd(this, _options, {});
423
+ }
424
+ options(options) {
425
+ __privateSet(this, _options, { options });
426
+ return this;
421
427
  }
422
428
  schemaMap(map) {
423
429
  __privateSet(this, _schemaMap, map);
@@ -462,6 +468,8 @@ var _MetaConfigBuilder = class _MetaConfigBuilder {
462
468
  config.allowPlainText = __privateGet(this, _allowPlainText);
463
469
  config.onSend = __privateGet(this, _onBeforeSend);
464
470
  config.onReceive = __privateGet(this, _onAfterSend);
471
+ config.options = __privateGet(this, _options);
472
+ config.throwOnServerError = __privateGet(this, _throwOnServerError);
465
473
  return config;
466
474
  }
467
475
  derive() {
@@ -475,6 +483,7 @@ _allowPlainText = new WeakMap();
475
483
  _onBeforeSend = new WeakMap();
476
484
  _onAfterSend = new WeakMap();
477
485
  _throwOnServerError = new WeakMap();
486
+ _options = new WeakMap();
478
487
  _setOnSend = new WeakSet();
479
488
  setOnSend_fn = function(hooks) {
480
489
  __privateSet(this, _onBeforeSend, [...hooks]);
@@ -564,6 +573,10 @@ var HTTP = class {
564
573
  __privateGet(this, _request2).url(url);
565
574
  return this;
566
575
  }
576
+ sharedOptions(options) {
577
+ __privateGet(this, _metaConfig).options(options);
578
+ return this;
579
+ }
567
580
  /**
568
581
  * If set to true, all requests derived from this client will require a schema be defined
569
582
  * matching any response status code. If set to false, a schema will still be used for validation
@@ -1052,7 +1065,8 @@ makeRequest_fn = async function(builder, options) {
1052
1065
  const request = (await builder.resolveDynamicHeaders()).build();
1053
1066
  const meta = __privateGet(this, _metaConfig).derive().build();
1054
1067
  await this.runOnSendHooks(meta, request);
1055
- const result = await this.client.request(request, options);
1068
+ const opts = { ...meta.options, ...options };
1069
+ const result = await this.client.request(request, opts);
1056
1070
  result.data = transformResponse(meta.allowPlainText, result.data);
1057
1071
  await this.runOnReceiveHooks(meta, result);
1058
1072
  const validated = __privateMethod(this, _validateResponse, validateResponse_fn).call(this, result, meta);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/http-response.ts","../src/axios-client.ts","../src/http-client.ts","../src/http.ts","../src/default-client-factory.ts","../src/http-request.ts","../src/schema.map.ts","../src/request-meta.config.ts","../src/transform-response.ts","../src/default-schema.ts"],"sourcesContent":["export * from \"./axios-client\";\nexport * from \"./http-client\";\nexport * from \"./http\";\nexport * from \"./http-request\";\nexport * from \"./http-response\";\nexport * from \"./default-schema\";\nexport type {\n HTTPAdditionalOptions,\n HTTPMethod,\n SchemaParser,\n RequestHook,\n ResponseHook\n} from \"./types\";\n","import { HTTPRequest } from \"./http-request\";\nimport { StatusCode } from \"./types\";\n\nexport class HTTPResponse<T = unknown> {\n status: StatusCode;\n statusText: string;\n data: T;\n headers: Record<string, string>;\n request: HTTPRequest<unknown>;\n\n constructor() {\n this.headers = {};\n }\n\n static fromRaw<T>(response: HTTPResponse<T>) {\n const newResponse = new HTTPResponse<T>();\n Object.assign(newResponse, response);\n return response;\n }\n\n /**\n * Decomposes a response, creating an exact copy of the current response,\n * but with a new data value. The data can be provided directly as is, or it\n * can be generated through a callback function which receives the current\n * response data as an argument.\n *\n * ```ts\n * const response = await http.get(\"/products\");\n *\n * // direct value\n * const products = response.data;\n * const firstProduct = response.decompose(products[0]);\n * // callback transformer\n * const secondProduct = response.decompose((products) => products[1]);\n * // callback transformer with destructuring\n * const secondProduct = response.decompose(([product]) => product);\n * ```\n * @param value\n */\n decompose<K>(value: K): HTTPResponse<K>;\n decompose<K>(transformFn: (response: T) => K): HTTPResponse<K>;\n decompose<K>(transformFnOrVal: K | ((response: T) => K)): HTTPResponse<K> {\n const value = getDecompositionValue<T>(this.data, transformFnOrVal);\n return new HTTPResponseBuilder()\n .status(this.status)\n .statusText(this.statusText)\n .headers(this.headers)\n .request(this.request)\n .data(value)\n .build() as HTTPResponse<K>;\n }\n}\n\nfunction getDecompositionValue<T>(data: unknown, transformFn: unknown): T {\n return typeof transformFn === \"function\" ? transformFn(data) : transformFn;\n}\n\nexport class HTTPResponseBuilder {\n #response = new HTTPResponse();\n\n static create() {\n return new HTTPResponseBuilder();\n }\n\n derive() {\n return HTTPResponseBuilder.create()\n .data(this.#response.data)\n .headers(this.#response.headers)\n .request(this.#response.request)\n .status(this.#response.status)\n .statusText(this.#response.statusText);\n }\n\n status(code: StatusCode) {\n this.#response.status = code;\n return this;\n }\n\n statusText(text: string) {\n this.#response.statusText = text;\n return this;\n }\n\n data<T>(data: T) {\n this.#response.data = data;\n return this;\n }\n\n headers(dict: Record<string, string>) {\n this.#response.headers = dict;\n return this;\n }\n\n header(name: string, value: string) {\n this.#response.headers[name] = value;\n return this;\n }\n\n request(request: HTTPRequest<unknown>) {\n this.#response.request = request;\n return this;\n }\n\n build() {\n return this.#response;\n }\n}\n","import { HTTPRequest } from \"./http-request\";\nimport { HTTPResponse, HTTPResponseBuilder } from \"./http-response\";\nimport { HTTPAdditionalOptions, StatusCode } from \"./types\";\nimport axios, { AxiosRequestConfig } from \"axios\";\nimport { HTTPClient } from \"./http-client\";\n\n@HTTPClient.Use()\nexport class AxiosClient extends HTTPClient {\n async request<TRequestType, TResponseType>(\n request: HTTPRequest<TRequestType>,\n options: HTTPAdditionalOptions<AxiosRequestConfig>\n ): Promise<HTTPResponse<TResponseType>> {\n const { baseUrl, route, params, headers, method, data } = request;\n const url = [baseUrl, ...route].join(\"/\");\n const axiosRequest: AxiosRequestConfig = {\n url,\n params,\n headers,\n method: method,\n data,\n validateStatus: function (status) {\n return status >= 0 && status < 600;\n },\n ...options\n };\n const response = await axios(axiosRequest);\n return HTTPResponseBuilder.create()\n .status(response.status as StatusCode)\n .statusText(response.statusText)\n .data(response.data)\n .headers(response.headers as Record<string, string>)\n .request(request)\n .build() as HTTPResponse<TResponseType>;\n }\n}\n","import { HTTPRequest } from \"./http-request\";\nimport { HTTPResponse } from \"./http-response\";\nimport { HTTPAdditionalOptions } from \"./types\";\nimport { Class } from \"@autometa/types\";\nexport let defaultClient: Class<HTTPClient>;\nexport abstract class HTTPClient {\n static Use(): (target: Class<HTTPClient>) => void\n static Use(client?: Class<HTTPClient>) {\n if (client) {\n defaultClient = client\n }\n return function (target: Class<HTTPClient>) {\n defaultClient = target\n };\n }\n abstract request<TRequestType, TResponseType>(\n request: HTTPRequest<TRequestType>,\n options?: HTTPAdditionalOptions<unknown>\n ): Promise<HTTPResponse<TResponseType>>;\n}\n","import { Fixture, INJECTION_SCOPE } from \"@autometa/injection\";\nimport { AxiosClient } from \"./axios-client\";\nimport { HTTPClient } from \"./http-client\";\nimport { defaultClientFactory } from \"./default-client-factory\";\nimport { HTTPRequest, HTTPRequestBuilder } from \"./http-request\";\nimport { HTTPResponse } from \"./http-response\";\nimport { MetaConfig, MetaConfigBuilder } from \"./request-meta.config\";\nimport {\n HTTPAdditionalOptions,\n RequestHook,\n ResponseHook,\n SchemaParser,\n StatusCode\n} from \"./types\";\nimport { transformResponse } from \"./transform-response\";\nimport { AutomationError } from \"@autometa/errors\";\n\n/**\n * The HTTP fixture allows requests to be built and sent to a server. In general,\n * there are 2 modes of operation:\n *\n * * Shared Chain: The shared chain is used to configure the client for all requests, such as\n * routes this instance will always be used. When a shared chain method is called, it returns\n * the same instance of HTTP which can be further chained to configure the client.\n * * Request Chain: The request chain is used to configure a single request, inheriting values\n * set by the shared chain. When called, a new HTTP client instance is created and inherits the values\n * set by it's parent.\n *\n * The 2 modes are intended to simplify configuring an object through an inheritance chain. For example,\n * assume we have an API with 2 controller routes, `/product` and `/seller`. We can set up a Base Client\n * which consumes the HTTP fixture and configures it with the base url of our API.\n *\n * Inheritors can further configure their HTTP instance's routes.\n *\n * ```ts\n * \\@Constructor(HTTP)\n * export class BaseClient {\n * constructor(protected readonly http: HTTP) {\n * this.http.url(\"https://api.example.com\");\n * }\n * }\n *\n * export class ProductClient extends BaseClient {\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"product\");\n * }\n * getProduct(id: number) {\n * return this.http.route(id).get();\n * }\n *\n * export class SellerClient extends BaseClient {\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"seller\");\n * }\n *\n * getSeller(id: number) {\n * return this.http.route(id).get();\n * }\n * }\n * ```\n *\n * 'Schemas' can also be configured. A Schema is a function or an object with a `parse` method, which\n * takes a response data payload and returns a validated object. Schemas are mapped to\n * HTTP Status Codes, and if configured to be required the request will fail if no schema is found\n * matching that code.\n *\n * Defining a schema function:\n *\n * ```\n * // user.schema.ts\n * export function UserSchema(data: unknown) {\n * if(typeof data !== \"object\") {\n * throw new Error(\"Expected an object\");\n * }\n *\n * if(typeof data.name !== \"string\") {\n * throw new Error(\"Expected a string\");\n * }\n *\n * return data as { name: string };\n * }\n *\n * // user.controller.ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 });\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * // or\n * return this.http\n * .route(id)\n * .schema(UserSchema, { from: 200, to: 299 })\n * .get();\n * // or\n * return this.http\n * .route(id)\n * .schema(UserSchema, 200, 201, 202)\n * .get();\n * }\n * }\n * ```\n *\n * Validation libraries which use a `.parse` or `.validation`, method, such as Zod or MyZod, can also be used as schemas:\n *\n * ```ts\n * // user.schema.ts\n * import { z } from \"myzod\";\n *\n * export const UserSchema = z.object({\n * name: z.string()\n * });\n *\n * // user.controller.ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 })\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * }\n * }\n * ```\n */\n@Fixture(INJECTION_SCOPE.TRANSIENT)\nexport class HTTP {\n #request: HTTPRequestBuilder<HTTPRequest<unknown>>;\n #metaConfig: MetaConfigBuilder;\n constructor(\n private readonly client: HTTPClient = defaultClientFactory(),\n builder: HTTPRequestBuilder<\n HTTPRequest<unknown>\n > = new HTTPRequestBuilder(),\n metaConfig: MetaConfigBuilder = new MetaConfigBuilder()\n ) {\n this.#request = builder;\n this.#metaConfig = metaConfig.derive();\n }\n\n static create(\n client: HTTPClient = new AxiosClient(),\n builder: HTTPRequestBuilder<\n HTTPRequest<unknown>\n > = new HTTPRequestBuilder(),\n metaConfig: MetaConfigBuilder = new MetaConfigBuilder()\n ) {\n const derived = new HTTP(client, builder, metaConfig);\n return derived;\n }\n\n /**\n * Sets the base url of the request for this client, such as\n * `https://api.example.com`, and could include always-used routes like\n * the api version, such as `/v1` or `/api/v1` at the end.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export abstract class BaseClient {\n * constructor(protected readonly http: HTTP) {\n * this.http.url(\"https://api.example.com\");\n * }\n * }\n * ```\n * @param url\n * @returns\n */\n url(url: string) {\n this.#request.url(url);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will require a schema be defined\n * matching any response status code. If set to false, a schema will still be used for validation\n * if defined, or the unadulterated original body will be returned if no schema matches.\n *\n * @param required Whether or not a schema is required for all responses.\n * @returns This instance of HTTP.\n */\n requireSchema(required: boolean) {\n this.#metaConfig.requireSchema(required);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will allow plain text\n * responses. If set to false, plain text responses will throw an serialization error.\n *\n * Useful when an endpoint returns a HTML or plain text response. If the plain text\n * is the value of `true` or `false`, or a number, it will be parsed into the\n * appropriate type.\n *\n * This method is a shared chain method, and will return the same instance of HTTP.\n *\n * @param allow Whether or not plain text responses are allowed.\n * @returns This instance of HTTP.\n */\n sharedAllowPlainText(allow: boolean) {\n this.#metaConfig.allowPlainText(allow);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will allow plain text\n * responses. If set to false, plain text responses will throw an serialization error.\n *\n * Useful when an endpoint returns a HTML or plain text response. If the plain text\n * is the value of `true` or `false`, or a number, it will be parsed into the\n * appropriate type.\n *\n * This method is a request chain method, and will return a new instance of HTTP.\n *\n * @param allow Whether or not plain text responses are allowed.\n * @returns A new child instance of HTTP derived from this one.\n */\n allowPlainText(allow: boolean) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().allowPlainText(allow)\n );\n }\n\n /**\n * Attaches a route to the request, such as `/product` or `/user`. Subsequent calls\n * to this method will append the route to the existing route, such as `/product/1`.\n *\n * Numbers will be converted to strings automatically. Routes can be defined one\n * at a time or as a spread argument.\n *\n * ```ts\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"user\", id).get();\n * }\n *\n * // or\n *\n * constructor(http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedRoute(id)\n * .get();\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the routes defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param route A route or spread list of routes to append to the request.\n * @returns This instance of HTTP.\n */\n sharedRoute(...route: (string | number | boolean)[]) {\n this.#request.route(...route.map((r) => r.toString()));\n return this;\n }\n\n /**\n * Attaches a route to the request, such as `/product` or `/user`. Subsequent calls\n * to this method will append the route to the existing route, such as `/product/1`.\n *\n * Numbers will be converted to strings automatically. Routes can be defined one\n * at a time or as a spread argument.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http.route(\"user\", id).get();\n * }\n *\n * // or\n *\n * getUser(id: number) {\n * return this.http\n * .route(\"user\")\n * .route(id)\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any routes previously defined and appending the new route. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param route A route or spread list of routes to append to the request.\n * @returns A new child instance of HTTP derived from this one.\n */\n route(...route: (string | number | boolean)[]) {\n const mapped = route.map((r) => String(r));\n return HTTP.create(\n this.client,\n this.#request.derive().route(...mapped),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a shared schema mapping for all requests by this client. Schemas are\n * mapped to HTTP Status Codes, and if configured to be required the request will fail\n * if no schema is found matching that code.\n *\n * The status code mapping can be defined as a single code, a range of codes, or a spread list.\n *\n * ```ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(UserSchema, 200)\n * .sharedSchema(EmptySchema, 201, 204)\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 });\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the schemas defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param parser The schema parser to use for this mapping.\n * @param codes A single status code, a range of status codes, or a spread list of status codes.\n * @returns This instance of HTTP.\n */\n sharedSchema(parser: SchemaParser, ...codes: StatusCode[]): HTTP;\n sharedSchema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTP;\n sharedSchema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): HTTP {\n this.#metaConfig.schema(parser, ...args);\n return this;\n }\n\n /**\n * Attaches a schema mapping for this request. Schemas are\n * mapped to HTTP Status Codes, and if configured to be required the request will fail\n * if no schema is found matching that code.\n *\n * The status code mapping can be defined as a single code, a range of codes, or a spread list.\n *\n * ```ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .schema(ErrorSchema, { from: 400, to: 499 });\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * }\n *\n * getUsers(...ids: number[]) {\n * return this.http\n * .route(\"users\")\n * .schema(UserSchema, { from: 200, to: 299 })\n * .schema(UserSchema, 200)\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any schemas previously defined and appending the new schema. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param parser The schema parser to use for this mapping.\n * @param codes A single status code, a range of status codes, or a spread list of status codes.\n * @returns A new child instance of HTTP derived from this one.\n */\n schema(parser: SchemaParser, ...codes: StatusCode[]): HTTP;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTP;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): HTTP {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().schema(parser, ...args)\n );\n }\n\n /**\n * Attaches a shared query string parameter to all requests by this client. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n sharedParam(name: string, value: Record<string, unknown>): HTTP;\n sharedParam(name: string, ...value: (string | number | boolean)[]): HTTP;\n sharedParam(name: string, value: (string | number | boolean)[]): HTTP;\n sharedParam(\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value: any\n ): HTTP {\n this.#request.param(name, value);\n return this;\n }\n\n /**\n * `onSend` is a pre-request hook which will be executed in order of definition\n * immediately before the request is sent. This hook can be used to analyze or\n * log the request state.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedOnSend(\"log request\",\n * (request) => console.log(JSON.stringify(request, null, 2))\n * );\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the onSend hooks defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns This instance of HTTP.\n */\n sharedOnSend(description: string, hook: RequestHook) {\n this.#metaConfig.onBeforeSend(description, hook);\n return this;\n }\n\n /**\n * `onReceive` is a post-request hook which will be executed in order of definition\n * immediately after the response is received. This hook can be used to analyze or\n * log the response state.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedOnReceive(\"log response\",\n * (response) => console.log(JSON.stringify(response, null, 2))\n * );\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the onReceive hooks defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns This instance of HTTP.\n */\n sharedOnReceive(description: string, hook: ResponseHook<unknown>) {\n this.#metaConfig.onReceiveResponse(description, hook);\n return this;\n }\n\n /**\n * Attaches a query string parameter object to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * ```ts\n * constructor(http: HTTP) {\n * super(http);\n * this.http\n * .sharedParams({ 'is-test': \"true\" })\n * ```\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n sharedParams(dict: Record<string, unknown>) {\n this.#request.params(dict);\n return this;\n }\n\n /**\n * Attaches a query string parameter to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any query string parameters previously defined and appending the new parameter. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .param(\"name\", \"John\")\n * .param(\"age\", 30)\n * ```\n *\n * Note: Numbers and Booleans will be converted to strings automatically.\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns A new child instance of HTTP derived from this one.\n */\n param(name: string, value: Record<string, unknown>): HTTP;\n param(name: string, ...value: (string | number | boolean)[]): HTTP;\n param(name: string, value: (string | number | boolean)[]): HTTP;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n param(name: string, ...value: any) {\n return HTTP.create(\n this.client,\n this.#request.derive().param(name, value),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a query string parameter object to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .param({ name: \"John\", age: \"30\" })\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n params(dict: Record<string, string>) {\n this.#request.params(dict);\n return HTTP.create(\n this.client,\n this.#request.derive().params(dict),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a shared data payload to this client. The data payload is the body of the request,\n * and can be any type. If the data payload is an object, it will be serialized to JSON.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the data payload defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param data The data payload to attach to the request.\n * @returns This instance of HTTP.\n */\n sharedData<T>(data: T) {\n this.#request.data(data);\n return this;\n }\n\n /**\n * Attaches a shared header to this client. Headers are string:string key-value pairs which are\n * sent with the request, such as `Content-Type: application/json`.\n *\n * Numbers, Booleans and Null will be converted to string values automatically.\n *\n * A Factory function can also be provided to generate the header value at the time of request.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the header defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param name The name of the header.\n * @param value The value of the header.\n */\n sharedHeader(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n ) {\n this.#request.header(name, value);\n return this;\n }\n\n header(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n ) {\n return HTTP.create(\n this.client,\n this.#request.derive().header(name, value),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a data payload to this request. The data payload is the body of the request,\n * and can be any type. If the data payload is an object, it will be serialized to JSON.\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any data payload previously defined and appending the new payload. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param data The data payload to attach to the request.\n * @returns A new child instance of HTTP derived from this one.\n */\n data<T>(data: T) {\n this.#request.data(data);\n return HTTP.create(\n this.client,\n this.#request.derive().data(data),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * `onSend` is a pre-request hook which will be executed in order of definition\n * immediately before the request is sent. This hook can be used to modify the request,\n * or to log the state of a request before final send-off.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * }\n *\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .onSend(\"log request\",\n * (request) => console.log(JSON.stringify(request, null, 2)\n * )\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any onSend hooks previously defined and appending the new hook. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns A new child instance of HTTP derived from this one.\n */\n onSend(description: string, hook: RequestHook) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().onBeforeSend(description, hook)\n );\n }\n\n /**\n * `onReceive` is a post-request hook which will be executed in order of definition\n * immediately after the response is received. This hook can be used to modify the response,\n * or to log the state of a response after it is received.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * }\n *\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .onReceive(\"log response\",\n * (response) => console.log(JSON.stringify(response, null, 2)\n * )\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any onReceive hooks previously defined and appending the new hook. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns A new child instance of HTTP derived from this one.\n */\n onReceive(description: string, hook: ResponseHook<unknown>) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().onReceiveResponse(description, hook)\n );\n }\n\n /**\n * Executes the current request state as a GET request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n get<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"GET\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a POST request.\n *\n * @param data The data payload to attach to the request.\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n post<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"POST\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a DELETE request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n * as e.g Axios configuration values.\n */\n delete<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"DELETE\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a PUT request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n put<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"PUT\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n /**\n * Executes the current request state as a PATCH request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n patch<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"PATCH\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n head<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"HEAD\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n options<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"OPTIONS\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n trace<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"TRACE\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n connect<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"CONNECT\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n async #makeRequest(\n builder: HTTPRequestBuilder<HTTPRequest<unknown>>,\n options?: HTTPAdditionalOptions<unknown>\n ) {\n const request = (await builder.resolveDynamicHeaders()).build();\n const meta = this.#metaConfig.derive().build();\n await this.runOnSendHooks(meta, request);\n const result = await this.client.request<unknown, string>(request, options);\n result.data = transformResponse(meta.allowPlainText, result.data);\n await this.runOnReceiveHooks(meta, result);\n const validated = this.#validateResponse(result, meta);\n return validated;\n }\n\n private async runOnSendHooks(\n meta: MetaConfig,\n request: HTTPRequest<unknown>\n ) {\n for (const [description, hook] of meta.onSend) {\n try {\n await hook(request);\n } catch (e) {\n const cause = e as Error;\n const msg = `An error occurred while sending a request in hook: '${description}'`;\n throw new AutomationError(msg, { cause });\n }\n }\n }\n private async runOnReceiveHooks(\n meta: MetaConfig,\n response: HTTPResponse<unknown>\n ) {\n for (const [description, hook] of meta.onReceive) {\n try {\n await hook(response);\n } catch (e) {\n const cause = e as Error;\n const msg = `An error occurred while receiving a response in hook: '${description}'`;\n throw new AutomationError(msg, { cause });\n }\n }\n }\n\n #validateResponse<T>(\n response: HTTPResponse<unknown>,\n meta: MetaConfig\n ): HTTPResponse<T> {\n const { status, data } = response;\n const validated = meta.schemas.validate(\n status,\n data,\n meta.requireSchema\n ) as T;\n response.data = validated;\n return response as HTTPResponse<T>;\n }\n}\n","import { Class } from \"@autometa/types\";\nimport { defaultClient, type HTTPClient } from \"./http-client\";\n\nexport function defaultClientFactory() {\n const type = defaultClient as Class<HTTPClient>;\n return new type();\n}\n","import { RequestConfig, RequestConfigBasic } from \"./request.config\";\nimport { HTTPMethod } from \"./types\";\nimport { urlJoinP } from \"url-join-ts\";\nexport class HTTPRequest<T = unknown> implements RequestConfig<T> {\n headers: Record<string, string> = {};\n params: Record<string, string | string[] | Record<string, unknown>> = {};\n baseUrl?: string;\n route: string[] = [];\n method: HTTPMethod;\n data: T;\n\n constructor(config?: RequestConfigBasic) {\n Object.assign(this, config);\n }\n\n /**\n * Returns the full URL of the request, including the base url,\n * routes, and query parameters.\n *\n * ```ts\n * console.log(request.fullUrl())// https://example.com/foo?bar=baz?array=1,2,3\n * ```\n *\n * Note characters may be converted to escape codes. I.e (space => %20) and (comma => %2C)\n *\n * N.B this getter estimates what the url will be. The actual value\n * might be different depending on your underlying HTTPClient and\n * configuration. For example, query parameters might\n * use different array formats.\n */\n get fullUrl() {\n return urlJoinP(this.baseUrl, this.route, this.params);\n }\n\n /**\n * Returns a new independent copy of the request.\n */\n static derive(original: HTTPRequest<unknown>) {\n const request = new HTTPRequest();\n request.headers = { ...original.headers };\n request.params = { ...original.params };\n request.baseUrl = original.baseUrl;\n request.route = [...original.route];\n request.method = original.method;\n request.data = original.data;\n return request;\n }\n}\n\nexport class HTTPRequestBuilder<T extends HTTPRequest<unknown>> {\n #request: T;\n #dynamicHeaders = new Map<\n string,\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n >();\n\n constructor(request: T | (() => T) = () => new HTTPRequest() as T) {\n if (typeof request === \"function\") {\n this.#request = request();\n return;\n }\n this.#request = request;\n }\n\n static create<T extends HTTPRequest<unknown>>() {\n return new HTTPRequestBuilder<T>();\n }\n\n get request() {\n return this.#request;\n }\n\n async resolveDynamicHeaders(\n request: HTTPRequest<T> = this.#request as HTTPRequest<T>\n ) {\n for (const [name, value] of this.#dynamicHeaders) {\n try {\n if (!request.headers) request.headers = {};\n request.headers[name] = String(await value());\n } catch (e) {\n const cause = e as Error;\n const msg = `Failed to resolve dynamic header \"${name}\": \n${cause}`;\n throw new Error(msg);\n }\n }\n return this;\n }\n\n url(url: string) {\n this.#request.baseUrl = url;\n return this;\n }\n\n route(...route: string[]) {\n this.#request.route.push(...route);\n return this;\n }\n\n param(\n name: string,\n value:\n | string\n | number\n | boolean\n | (string | number | boolean)[]\n | Record<string, string | number | boolean>\n ) {\n if (Array.isArray(value)) {\n const asStr = value.flatMap(String);\n this.#request.params[name] = asStr;\n return this;\n }\n if (!Array.isArray(value) && typeof value === \"object\") {\n this.#request.params[name] = value;\n return this;\n }\n this.#request.params[name] = String(value);\n return this;\n }\n\n params(dict: Record<string, unknown>) {\n Object.assign(this.#request.params, dict);\n return this;\n }\n\n data<T>(data: T) {\n this.#request.data = data;\n return this;\n }\n\n header(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>),\n onArray: (value: (string | number | boolean)[]) => string = (value) =>\n value.join(\",\")\n ) {\n if (typeof value === \"function\") {\n this.#dynamicHeaders.set(name, value);\n return this;\n }\n const val = Array.isArray(value) ? onArray(value) : String(value);\n this.#request.headers[name] = val;\n return this;\n }\n\n headers(dict: Record<string, string>) {\n Object.assign(this.#request.headers, dict);\n return this;\n }\n\n get() {\n return this.#request;\n }\n\n method(method: HTTPMethod) {\n this.#request.method = method;\n return this;\n }\n\n #setDynamicHeaders(\n headers: Map<\n string,\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n >\n ) {\n this.#dynamicHeaders = new Map(headers);\n return this;\n }\n\n derive(): HTTPRequestBuilder<T> {\n const request = HTTPRequest.derive(this.#request);\n return new HTTPRequestBuilder(request).#setDynamicHeaders(\n this.#dynamicHeaders\n ) as HTTPRequestBuilder<T>;\n }\n\n build(): HTTPRequest<T> {\n return this.#request as HTTPRequest<T>;\n }\n\n async buildAsync(): Promise<HTTPRequest<T>> {\n await this.resolveDynamicHeaders();\n return this.#request as HTTPRequest<T>;\n }\n}\n","import { SchemaParser, StatusCode } from \"./types\";\nexport class SchemaMap {\n #map: Map<StatusCode, SchemaParser>;\n constructor(map?: Map<StatusCode, SchemaParser> | SchemaMap) {\n if (map instanceof SchemaMap) {\n this.#map = new Map(map.#map);\n return;\n }\n this.#map = new Map(map);\n }\n\n derive() {\n return new SchemaMap(this.#map);\n }\n\n registerStatus(parser: SchemaParser, ...codes: StatusCode[]) {\n codes.forEach((code) => {\n if (this.#map.has(code)) {\n const msg = `Status code ${code} is already registered with a parser`;\n throw new Error(msg);\n }\n this.#map.set(code, parser);\n });\n }\n\n registerRange(parser: SchemaParser, from: StatusCode, to: StatusCode) {\n for (let i = from; i <= to; i++) {\n if (this.#map.has(i)) {\n throw new Error(`Status code ${i} is already registered with a parser`);\n }\n this.#map.set(i, parser);\n }\n }\n\n validate(status: StatusCode, data: unknown, requireSchema: boolean) {\n const parser = this.getParser(status, requireSchema);\n if (\"parse\" in parser) {\n return parser.parse(data);\n }\n if('validate' in parser) {\n return parser.validate(data);\n }\n try {\n return parser(data);\n } catch (e) {\n const msg = `Failed to schema parse response data for status code ${status} with data:\n \n${JSON.stringify(data, null, 2)}}`;\n throw new Error(msg);\n }\n }\n\n getParser(status: StatusCode, requireSchema: boolean) {\n const parser = this.#map.get(status);\n if (!parser && requireSchema) {\n const msg = `No parser registered for status code ${status} but 'requireSchema' is true`;\n throw new Error(msg);\n }\n if (parser) {\n return parser;\n }\n return (data: unknown) => data;\n }\n\n toObject() {\n return Object.fromEntries(this.#map) as Record<StatusCode, SchemaParser>;\n }\n}\n","import { SchemaMap } from \"./schema.map\";\nimport { RequestHook, ResponseHook, SchemaParser, StatusCode } from \"./types\";\n\nexport interface SchemaConfig {\n schemas: SchemaMap;\n requireSchema: boolean;\n allowPlainText: boolean;\n}\n\nexport interface HTTPHooks {\n onSend: [string, RequestHook][];\n onReceive: [string, ResponseHook<unknown>][];\n}\n\n// export type MetaConfig = SchemaConfig & HTTPHooks;\n\nexport class MetaConfig implements SchemaConfig, HTTPHooks {\n schemas: SchemaMap;\n requireSchema: boolean;\n allowPlainText: boolean;\n onSend: [string, RequestHook][] = [];\n onReceive: [string, ResponseHook<unknown>][] = [];\n throwOnServerError: boolean;\n}\n\nexport class MetaConfigBuilder {\n #schemaMap = new SchemaMap();\n #requireSchema = false;\n #allowPlainText = false;\n #onBeforeSend: [string, RequestHook][] = [];\n #onAfterSend: [string, ResponseHook<unknown>][] = [];\n #throwOnServerError = false;\n\n schemaMap(map: SchemaMap) {\n this.#schemaMap = map;\n return this;\n }\n\n schema(parser: SchemaParser, ...codes: StatusCode[]): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n args.forEach((arg) => {\n if (typeof arg === \"number\") {\n this.#schemaMap.registerStatus(parser, arg);\n } else if (Array.isArray(arg)) {\n this.#schemaMap.registerStatus(parser, ...arg);\n } else {\n this.#schemaMap.registerRange(parser, arg.from, arg.to);\n }\n });\n\n return this;\n }\n\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n\n onBeforeSend(description: string, hook: RequestHook) {\n this.#onBeforeSend.push([description, hook]);\n return this;\n }\n\n #setOnSend(hooks: [string, RequestHook][]) {\n this.#onBeforeSend = [...hooks];\n return this;\n }\n\n throwOnServerError(value: boolean) {\n this.#throwOnServerError = value;\n return this;\n }\n\n onReceiveResponse(description: string, hook: ResponseHook<unknown>) {\n this.#onAfterSend.push([description, hook]);\n return this;\n }\n\n #setOnReceive(hooks: [string, ResponseHook<unknown>][]) {\n this.#onAfterSend = [...hooks];\n return this;\n }\n\n build() {\n const config = new MetaConfig();\n config.schemas = this.#schemaMap.derive();\n config.requireSchema = this.#requireSchema;\n config.allowPlainText = this.#allowPlainText;\n config.onSend = this.#onBeforeSend;\n config.onReceive = this.#onAfterSend;\n return config;\n }\n\n derive() {\n return new MetaConfigBuilder()\n .schemaMap(this.#schemaMap.derive())\n .requireSchema(this.#requireSchema)\n .allowPlainText(this.#allowPlainText)\n .throwOnServerError(this.#throwOnServerError)\n .#setOnSend(this.#onBeforeSend)\n .#setOnReceive(this.#onAfterSend);\n }\n}\n","import { AutomationError } from \"@autometa/errors\";\nimport isJson from \"@stdlib/assert-is-json\";\nimport { highlight } from \"cli-highlight\";\n\nexport function transformResponse(\n allowPlainText: boolean,\n data: null | undefined | string\n) {\n if (data === null) {\n return null;\n }\n if (data === undefined) {\n return undefined;\n }\n if (data === \"\") {\n return data;\n }\n if (isJson(data)) {\n return JSON.parse(data);\n }\n if (typeof data === \"string\" && [\"true\", \"false\"].includes(data)) {\n return JSON.parse(data);\n }\n if (typeof data === \"string\" && /^\\d*\\.?\\d+$/.test(data)) {\n return JSON.parse(data);\n }\n\n if (typeof data === \"object\") {\n return data;\n }\n if (allowPlainText) {\n return data;\n }\n\n const response = highlight(data, { language: \"html\" });\n const message = [\n `Could not parse a response as json, and this request was not configured to allow plain text responses.`,\n `To allow plain text responses, use the 'allowPlainText' method on the HTTP client.`,\n \"\",\n response\n ];\n throw new AutomationError(message.join(\"\\n\"));\n}\n","import isJson from \"@stdlib/assert-is-json\";\n\n/**\n * Schema which does not care about data validation.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response does not matter.\n * @param data\n * @returns\n */\nexport function AnySchema(data: unknown) {\n return data;\n}\n\n/**\n * Schema which validates that a response is empty. This can mean\n * the data payload was `null`, `undefined` or the string `'null'`.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be null or not defined.\n * @param data\n * @returns\n */\nexport function EmptySchema(data: unknown) {\n if (data !== null && data !== undefined && data !== \"null\") {\n throw new Error(`Expected null but got <${typeof data}> for ${data}`);\n }\n return data === \"null\" ? null : data;\n}\n\n/**\n * Schema which validates a response was null.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be null.\n * @param data\n * @returns\n */\nexport function NullSchema(data: unknown) {\n if (data !== null && data !== \"null\") {\n throw new Error(`Expected null but got <${typeof data}> for ${data}`);\n }\n return null;\n}\n\n/**\n * Schema which validates a response was undefined.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be undefined.\n *\n * @param data\n * @returns\n */\nexport function UndefinedSchema(data: unknown) {\n if (data !== undefined) {\n throw new Error(`Expected undefined but got <${typeof data}> for ${data}`);\n }\n return undefined;\n}\n\n/**\n * Schema which validates a response was a boolean, or a string of value\n * `'true'` or `'false'`.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a boolean.\n *\n * @param data\n * @returns\n */\nexport function BooleanSchema(data: unknown) {\n if (\n !(typeof data === \"boolean\") &&\n [\"true\", \"false\"].includes(String(data)) === false\n ) {\n throw new Error(`Expected boolean but got <${typeof data}> for ${data}`);\n }\n return JSON.parse(data as string);\n}\n\n/**\n * Schema which validates a response was a number, or a string of value\n * of a number.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a number.\n *\n * @param data\n * @returns\n */\nexport function NumberSchema(data: unknown) {\n if (\n !(typeof data === \"number\") &&\n /^\\d*\\.?\\d+$/.test(String(data)) === false\n ) {\n throw new Error(`Expected number but got <${typeof data}> for ${data}`);\n }\n return JSON.parse(data as string);\n}\n\n/**\n * Schema which validates a response was a string.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a string.\n *\n * @param data\n * @returns\n */\nexport function StringSchema(data: unknown) {\n if (typeof data !== \"string\") {\n throw new Error(`Expected string but got <${typeof data}> for ${data}`);\n }\n return data;\n}\n\n\nexport function JSONSchema<T = unknown>(data: unknown) {\n if(typeof data === 'object') {\n return data as T;\n }\n if (!isJson(data)) {\n throw new Error(`Expected JSON but got <${typeof data}> for ${data}`);\n }\n const result = JSON.parse(data);\n return result;\n}"],"mappings":"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","names":["axios","value","isJson","import_errors","_request","import_assert_is_json","isJson"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/http-response.ts","../src/axios-client.ts","../src/http-client.ts","../src/http.ts","../src/default-client-factory.ts","../src/http-request.ts","../src/schema.map.ts","../src/request-meta.config.ts","../src/transform-response.ts","../src/default-schema.ts"],"sourcesContent":["export * from \"./axios-client\";\nexport * from \"./http-client\";\nexport * from \"./http\";\nexport * from \"./http-request\";\nexport * from \"./http-response\";\nexport * from \"./default-schema\";\nexport type {\n HTTPAdditionalOptions,\n HTTPMethod,\n SchemaParser,\n RequestHook,\n ResponseHook\n} from \"./types\";\n","import { HTTPRequest } from \"./http-request\";\nimport { StatusCode } from \"./types\";\n\nexport class HTTPResponse<T = unknown> {\n status: StatusCode;\n statusText: string;\n data: T;\n headers: Record<string, string>;\n request: HTTPRequest<unknown>;\n\n constructor() {\n this.headers = {};\n }\n\n static fromRaw<T>(response: HTTPResponse<T>) {\n const newResponse = new HTTPResponse<T>();\n Object.assign(newResponse, response);\n return response;\n }\n\n /**\n * Decomposes a response, creating an exact copy of the current response,\n * but with a new data value. The data can be provided directly as is, or it\n * can be generated through a callback function which receives the current\n * response data as an argument.\n *\n * ```ts\n * const response = await http.get(\"/products\");\n *\n * // direct value\n * const products = response.data;\n * const firstProduct = response.decompose(products[0]);\n * // callback transformer\n * const secondProduct = response.decompose((products) => products[1]);\n * // callback transformer with destructuring\n * const secondProduct = response.decompose(([product]) => product);\n * ```\n * @param value\n */\n decompose<K>(value: K): HTTPResponse<K>;\n decompose<K>(transformFn: (response: T) => K): HTTPResponse<K>;\n decompose<K>(transformFnOrVal: K | ((response: T) => K)): HTTPResponse<K> {\n const value = getDecompositionValue<T>(this.data, transformFnOrVal);\n return new HTTPResponseBuilder()\n .status(this.status)\n .statusText(this.statusText)\n .headers(this.headers)\n .request(this.request)\n .data(value)\n .build() as HTTPResponse<K>;\n }\n}\n\nfunction getDecompositionValue<T>(data: unknown, transformFn: unknown): T {\n return typeof transformFn === \"function\" ? transformFn(data) : transformFn;\n}\n\nexport class HTTPResponseBuilder {\n #response = new HTTPResponse();\n\n static create() {\n return new HTTPResponseBuilder();\n }\n\n derive() {\n return HTTPResponseBuilder.create()\n .data(this.#response.data)\n .headers(this.#response.headers)\n .request(this.#response.request)\n .status(this.#response.status)\n .statusText(this.#response.statusText);\n }\n\n status(code: StatusCode) {\n this.#response.status = code;\n return this;\n }\n\n statusText(text: string) {\n this.#response.statusText = text;\n return this;\n }\n\n data<T>(data: T) {\n this.#response.data = data;\n return this;\n }\n\n headers(dict: Record<string, string>) {\n this.#response.headers = dict;\n return this;\n }\n\n header(name: string, value: string) {\n this.#response.headers[name] = value;\n return this;\n }\n\n request(request: HTTPRequest<unknown>) {\n this.#response.request = request;\n return this;\n }\n\n build() {\n return this.#response;\n }\n}\n","import { HTTPRequest } from \"./http-request\";\nimport { HTTPResponse, HTTPResponseBuilder } from \"./http-response\";\nimport { HTTPAdditionalOptions, StatusCode } from \"./types\";\nimport axios, { AxiosRequestConfig } from \"axios\";\nimport { HTTPClient } from \"./http-client\";\n\n@HTTPClient.Use()\nexport class AxiosClient extends HTTPClient {\n async request<TRequestType, TResponseType>(\n request: HTTPRequest<TRequestType>,\n options: HTTPAdditionalOptions<AxiosRequestConfig>\n ): Promise<HTTPResponse<TResponseType>> {\n const { baseUrl, route, params, headers, method, data } = request;\n const url = [baseUrl, ...route].join(\"/\");\n const axiosRequest: AxiosRequestConfig = {\n url,\n params,\n headers,\n method: method,\n data,\n validateStatus: function (status) {\n return status >= 0 && status < 600;\n },\n ...options\n };\n const response = await axios(axiosRequest);\n return HTTPResponseBuilder.create()\n .status(response.status as StatusCode)\n .statusText(response.statusText)\n .data(response.data)\n .headers(response.headers as Record<string, string>)\n .request(request)\n .build() as HTTPResponse<TResponseType>;\n }\n}\n","import { HTTPRequest } from \"./http-request\";\nimport { HTTPResponse } from \"./http-response\";\nimport { HTTPAdditionalOptions } from \"./types\";\nimport { Class } from \"@autometa/types\";\nexport let defaultClient: Class<HTTPClient>;\nexport abstract class HTTPClient {\n static Use(): (target: Class<HTTPClient>) => void\n static Use(client?: Class<HTTPClient>) {\n if (client) {\n defaultClient = client\n }\n return function (target: Class<HTTPClient>) {\n defaultClient = target\n };\n }\n abstract request<TRequestType, TResponseType>(\n request: HTTPRequest<TRequestType>,\n options?: HTTPAdditionalOptions<unknown>\n ): Promise<HTTPResponse<TResponseType>>;\n}\n","import { Fixture, INJECTION_SCOPE } from \"@autometa/injection\";\nimport { AxiosClient } from \"./axios-client\";\nimport { HTTPClient } from \"./http-client\";\nimport { defaultClientFactory } from \"./default-client-factory\";\nimport { HTTPRequest, HTTPRequestBuilder } from \"./http-request\";\nimport { HTTPResponse } from \"./http-response\";\nimport { MetaConfig, MetaConfigBuilder } from \"./request-meta.config\";\nimport {\n HTTPAdditionalOptions,\n RequestHook,\n ResponseHook,\n SchemaParser,\n StatusCode\n} from \"./types\";\nimport { transformResponse } from \"./transform-response\";\nimport { AutomationError } from \"@autometa/errors\";\n\n/**\n * The HTTP fixture allows requests to be built and sent to a server. In general,\n * there are 2 modes of operation:\n *\n * * Shared Chain: The shared chain is used to configure the client for all requests, such as\n * routes this instance will always be used. When a shared chain method is called, it returns\n * the same instance of HTTP which can be further chained to configure the client.\n * * Request Chain: The request chain is used to configure a single request, inheriting values\n * set by the shared chain. When called, a new HTTP client instance is created and inherits the values\n * set by it's parent.\n *\n * The 2 modes are intended to simplify configuring an object through an inheritance chain. For example,\n * assume we have an API with 2 controller routes, `/product` and `/seller`. We can set up a Base Client\n * which consumes the HTTP fixture and configures it with the base url of our API.\n *\n * Inheritors can further configure their HTTP instance's routes.\n *\n * ```ts\n * \\@Constructor(HTTP)\n * export class BaseClient {\n * constructor(protected readonly http: HTTP) {\n * this.http.url(\"https://api.example.com\");\n * }\n * }\n *\n * export class ProductClient extends BaseClient {\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"product\");\n * }\n * getProduct(id: number) {\n * return this.http.route(id).get();\n * }\n *\n * export class SellerClient extends BaseClient {\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"seller\");\n * }\n *\n * getSeller(id: number) {\n * return this.http.route(id).get();\n * }\n * }\n * ```\n *\n * 'Schemas' can also be configured. A Schema is a function or an object with a `parse` method, which\n * takes a response data payload and returns a validated object. Schemas are mapped to\n * HTTP Status Codes, and if configured to be required the request will fail if no schema is found\n * matching that code.\n *\n * Defining a schema function:\n *\n * ```\n * // user.schema.ts\n * export function UserSchema(data: unknown) {\n * if(typeof data !== \"object\") {\n * throw new Error(\"Expected an object\");\n * }\n *\n * if(typeof data.name !== \"string\") {\n * throw new Error(\"Expected a string\");\n * }\n *\n * return data as { name: string };\n * }\n *\n * // user.controller.ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 });\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * // or\n * return this.http\n * .route(id)\n * .schema(UserSchema, { from: 200, to: 299 })\n * .get();\n * // or\n * return this.http\n * .route(id)\n * .schema(UserSchema, 200, 201, 202)\n * .get();\n * }\n * }\n * ```\n *\n * Validation libraries which use a `.parse` or `.validation`, method, such as Zod or MyZod, can also be used as schemas:\n *\n * ```ts\n * // user.schema.ts\n * import { z } from \"myzod\";\n *\n * export const UserSchema = z.object({\n * name: z.string()\n * });\n *\n * // user.controller.ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 })\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * }\n * }\n * ```\n */\n@Fixture(INJECTION_SCOPE.TRANSIENT)\nexport class HTTP {\n #request: HTTPRequestBuilder<HTTPRequest<unknown>>;\n #metaConfig: MetaConfigBuilder;\n constructor(\n private readonly client: HTTPClient = defaultClientFactory(),\n builder: HTTPRequestBuilder<\n HTTPRequest<unknown>\n > = new HTTPRequestBuilder(),\n metaConfig: MetaConfigBuilder = new MetaConfigBuilder()\n ) {\n this.#request = builder;\n this.#metaConfig = metaConfig.derive();\n }\n\n static create(\n client: HTTPClient = new AxiosClient(),\n builder: HTTPRequestBuilder<\n HTTPRequest<unknown>\n > = new HTTPRequestBuilder(),\n metaConfig: MetaConfigBuilder = new MetaConfigBuilder()\n ) {\n const derived = new HTTP(client, builder, metaConfig);\n return derived;\n }\n\n /**\n * Sets the base url of the request for this client, such as\n * `https://api.example.com`, and could include always-used routes like\n * the api version, such as `/v1` or `/api/v1` at the end.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export abstract class BaseClient {\n * constructor(protected readonly http: HTTP) {\n * this.http.url(\"https://api.example.com\");\n * }\n * }\n * ```\n * @param url\n * @returns\n */\n url(url: string) {\n this.#request.url(url);\n return this;\n }\n\n sharedOptions(options: HTTPAdditionalOptions<unknown>) {\n this.#metaConfig.options(options);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will require a schema be defined\n * matching any response status code. If set to false, a schema will still be used for validation\n * if defined, or the unadulterated original body will be returned if no schema matches.\n *\n * @param required Whether or not a schema is required for all responses.\n * @returns This instance of HTTP.\n */\n requireSchema(required: boolean) {\n this.#metaConfig.requireSchema(required);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will allow plain text\n * responses. If set to false, plain text responses will throw an serialization error.\n *\n * Useful when an endpoint returns a HTML or plain text response. If the plain text\n * is the value of `true` or `false`, or a number, it will be parsed into the\n * appropriate type.\n *\n * This method is a shared chain method, and will return the same instance of HTTP.\n *\n * @param allow Whether or not plain text responses are allowed.\n * @returns This instance of HTTP.\n */\n sharedAllowPlainText(allow: boolean) {\n this.#metaConfig.allowPlainText(allow);\n return this;\n }\n\n /**\n * If set to true, all requests derived from this client will allow plain text\n * responses. If set to false, plain text responses will throw an serialization error.\n *\n * Useful when an endpoint returns a HTML or plain text response. If the plain text\n * is the value of `true` or `false`, or a number, it will be parsed into the\n * appropriate type.\n *\n * This method is a request chain method, and will return a new instance of HTTP.\n *\n * @param allow Whether or not plain text responses are allowed.\n * @returns A new child instance of HTTP derived from this one.\n */\n allowPlainText(allow: boolean) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().allowPlainText(allow)\n );\n }\n\n /**\n * Attaches a route to the request, such as `/product` or `/user`. Subsequent calls\n * to this method will append the route to the existing route, such as `/product/1`.\n *\n * Numbers will be converted to strings automatically. Routes can be defined one\n * at a time or as a spread argument.\n *\n * ```ts\n * constructor(http: HTTP) {\n * super(http);\n * this.http.sharedRoute(\"user\", id).get();\n * }\n *\n * // or\n *\n * constructor(http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedRoute(id)\n * .get();\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the routes defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param route A route or spread list of routes to append to the request.\n * @returns This instance of HTTP.\n */\n sharedRoute(...route: (string | number | boolean)[]) {\n this.#request.route(...route.map((r) => r.toString()));\n return this;\n }\n\n /**\n * Attaches a route to the request, such as `/product` or `/user`. Subsequent calls\n * to this method will append the route to the existing route, such as `/product/1`.\n *\n * Numbers will be converted to strings automatically. Routes can be defined one\n * at a time or as a spread argument.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http.route(\"user\", id).get();\n * }\n *\n * // or\n *\n * getUser(id: number) {\n * return this.http\n * .route(\"user\")\n * .route(id)\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any routes previously defined and appending the new route. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param route A route or spread list of routes to append to the request.\n * @returns A new child instance of HTTP derived from this one.\n */\n route(...route: (string | number | boolean)[]) {\n const mapped = route.map((r) => String(r));\n return HTTP.create(\n this.client,\n this.#request.derive().route(...mapped),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a shared schema mapping for all requests by this client. Schemas are\n * mapped to HTTP Status Codes, and if configured to be required the request will fail\n * if no schema is found matching that code.\n *\n * The status code mapping can be defined as a single code, a range of codes, or a spread list.\n *\n * ```ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedSchema(UserSchema, 200)\n * .sharedSchema(EmptySchema, 201, 204)\n * .sharedSchema(ErrorSchema, { from: 400, to: 499 });\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the schemas defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param parser The schema parser to use for this mapping.\n * @param codes A single status code, a range of status codes, or a spread list of status codes.\n * @returns This instance of HTTP.\n */\n sharedSchema(parser: SchemaParser, ...codes: StatusCode[]): HTTP;\n sharedSchema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTP;\n sharedSchema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): HTTP {\n this.#metaConfig.schema(parser, ...args);\n return this;\n }\n\n /**\n * Attaches a schema mapping for this request. Schemas are\n * mapped to HTTP Status Codes, and if configured to be required the request will fail\n * if no schema is found matching that code.\n *\n * The status code mapping can be defined as a single code, a range of codes, or a spread list.\n *\n * ```ts\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .schema(ErrorSchema, { from: 400, to: 499 });\n * }\n *\n * getUser(id: number) {\n * return this.http.route(id).schema(UserSchema, 200).get();\n * }\n *\n * getUsers(...ids: number[]) {\n * return this.http\n * .route(\"users\")\n * .schema(UserSchema, { from: 200, to: 299 })\n * .schema(UserSchema, 200)\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any schemas previously defined and appending the new schema. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param parser The schema parser to use for this mapping.\n * @param codes A single status code, a range of status codes, or a spread list of status codes.\n * @returns A new child instance of HTTP derived from this one.\n */\n schema(parser: SchemaParser, ...codes: StatusCode[]): HTTP;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTP;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): HTTP {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().schema(parser, ...args)\n );\n }\n\n /**\n * Attaches a shared query string parameter to all requests by this client. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n sharedParam(name: string, value: Record<string, unknown>): HTTP;\n sharedParam(name: string, ...value: (string | number | boolean)[]): HTTP;\n sharedParam(name: string, value: (string | number | boolean)[]): HTTP;\n sharedParam(\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value: any\n ): HTTP {\n this.#request.param(name, value);\n return this;\n }\n\n /**\n * `onSend` is a pre-request hook which will be executed in order of definition\n * immediately before the request is sent. This hook can be used to analyze or\n * log the request state.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedOnSend(\"log request\",\n * (request) => console.log(JSON.stringify(request, null, 2))\n * );\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the onSend hooks defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns This instance of HTTP.\n */\n sharedOnSend(description: string, hook: RequestHook) {\n this.#metaConfig.onBeforeSend(description, hook);\n return this;\n }\n\n /**\n * `onReceive` is a post-request hook which will be executed in order of definition\n * immediately after the response is received. This hook can be used to analyze or\n * log the response state.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * this.http\n * .sharedRoute(\"user\")\n * .sharedOnReceive(\"log response\",\n * (response) => console.log(JSON.stringify(response, null, 2))\n * );\n * }\n * }\n * ```\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the onReceive hooks defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns This instance of HTTP.\n */\n sharedOnReceive(description: string, hook: ResponseHook<unknown>) {\n this.#metaConfig.onReceiveResponse(description, hook);\n return this;\n }\n\n /**\n * Attaches a query string parameter object to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * ```ts\n * constructor(http: HTTP) {\n * super(http);\n * this.http\n * .sharedParams({ 'is-test': \"true\" })\n * ```\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n sharedParams(dict: Record<string, unknown>) {\n this.#request.params(dict);\n return this;\n }\n\n /**\n * Attaches a query string parameter to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any query string parameters previously defined and appending the new parameter. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .param(\"name\", \"John\")\n * .param(\"age\", 30)\n * ```\n *\n * Note: Numbers and Booleans will be converted to strings automatically.\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns A new child instance of HTTP derived from this one.\n */\n param(name: string, value: Record<string, unknown>): HTTP;\n param(name: string, ...value: (string | number | boolean)[]): HTTP;\n param(name: string, value: (string | number | boolean)[]): HTTP;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n param(name: string, ...value: any) {\n return HTTP.create(\n this.client,\n this.#request.derive().param(name, value),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a query string parameter object to the request. Query string\n * parameters are key-value pairs which are appended to the request url, such as\n * `https://api.example.com?name=John&age=30`.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the query string parameters defined by this method. Useful to configure\n * in the constructor body.\n *\n * ```ts\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .param({ name: \"John\", age: \"30\" })\n *\n * @param name The name of the query string parameter.\n * @param value The value of the query string parameter.\n * @returns This instance of HTTP.\n */\n params(dict: Record<string, string>) {\n this.#request.params(dict);\n return HTTP.create(\n this.client,\n this.#request.derive().params(dict),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a shared data payload to this client. The data payload is the body of the request,\n * and can be any type. If the data payload is an object, it will be serialized to JSON.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the data payload defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param data The data payload to attach to the request.\n * @returns This instance of HTTP.\n */\n sharedData<T>(data: T) {\n this.#request.data(data);\n return this;\n }\n\n /**\n * Attaches a shared header to this client. Headers are string:string key-value pairs which are\n * sent with the request, such as `Content-Type: application/json`.\n *\n * Numbers, Booleans and Null will be converted to string values automatically.\n *\n * A Factory function can also be provided to generate the header value at the time of request.\n *\n * This method is a shared chain method, and will return the same instance of HTTP. All\n * child clients will inherit the header defined by this method. Useful to configure\n * in the constructor body.\n *\n * @param name The name of the header.\n * @param value The value of the header.\n */\n sharedHeader(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n ) {\n this.#request.header(name, value);\n return this;\n }\n\n header(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n ) {\n return HTTP.create(\n this.client,\n this.#request.derive().header(name, value),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * Attaches a data payload to this request. The data payload is the body of the request,\n * and can be any type. If the data payload is an object, it will be serialized to JSON.\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any data payload previously defined and appending the new payload. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param data The data payload to attach to the request.\n * @returns A new child instance of HTTP derived from this one.\n */\n data<T>(data: T) {\n this.#request.data(data);\n return HTTP.create(\n this.client,\n this.#request.derive().data(data),\n this.#metaConfig.derive()\n );\n }\n\n /**\n * `onSend` is a pre-request hook which will be executed in order of definition\n * immediately before the request is sent. This hook can be used to modify the request,\n * or to log the state of a request before final send-off.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * }\n *\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .onSend(\"log request\",\n * (request) => console.log(JSON.stringify(request, null, 2)\n * )\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any onSend hooks previously defined and appending the new hook. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns A new child instance of HTTP derived from this one.\n */\n onSend(description: string, hook: RequestHook) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().onBeforeSend(description, hook)\n );\n }\n\n /**\n * `onReceive` is a post-request hook which will be executed in order of definition\n * immediately after the response is received. This hook can be used to modify the response,\n * or to log the state of a response after it is received.\n *\n * ```ts\n *\n * \\@Fixture(INJECTION_SCOPE.TRANSIENT)\n * export class UserController extends BaseController {\n * constructor(private readonly http: HTTP) {\n * super(http);\n * }\n *\n * getUser(id: number) {\n * return this.http\n * .route(id)\n * .onReceive(\"log response\",\n * (response) => console.log(JSON.stringify(response, null, 2)\n * )\n * .get();\n * }\n * ```\n *\n * This method is a request chain method, and will return a new instance of HTTP, inheriting\n * any onReceive hooks previously defined and appending the new hook. Useful to configure\n * in class methods as part of finalizing a request.\n *\n * @param description A description of the hook, used for debugging.\n * @param hook The hook to execute.\n * @returns A new child instance of HTTP derived from this one.\n */\n onReceive(description: string, hook: ResponseHook<unknown>) {\n return HTTP.create(\n this.client,\n this.#request.derive(),\n this.#metaConfig.derive().onReceiveResponse(description, hook)\n );\n }\n\n /**\n * Executes the current request state as a GET request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n get<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"GET\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a POST request.\n *\n * @param data The data payload to attach to the request.\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n post<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"POST\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a DELETE request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n * as e.g Axios configuration values.\n */\n delete<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"DELETE\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n /**\n * Executes the current request state as a PUT request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n put<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"PUT\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n /**\n * Executes the current request state as a PATCH request.\n *\n * @param options Additional options to pass to the underlying http client, such\n * as e.g Axios configuration values.\n * @returns A promise which resolves to the response.\n */\n patch<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"PATCH\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n head<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"HEAD\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n options<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"OPTIONS\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n trace<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"TRACE\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n connect<TResponseType>(options?: HTTPAdditionalOptions<unknown>) {\n return this.#makeRequest(\n this.#request.derive().method(\"CONNECT\"),\n options\n ) as Promise<HTTPResponse<TResponseType>>;\n }\n\n async #makeRequest(\n builder: HTTPRequestBuilder<HTTPRequest<unknown>>,\n options?: HTTPAdditionalOptions<unknown>\n ) {\n const request = (await builder.resolveDynamicHeaders()).build();\n const meta = this.#metaConfig.derive().build();\n await this.runOnSendHooks(meta, request);\n const opts = { ...meta.options, ...options };\n const result = await this.client.request<unknown, string>(request, opts);\n result.data = transformResponse(meta.allowPlainText, result.data);\n await this.runOnReceiveHooks(meta, result);\n const validated = this.#validateResponse(result, meta);\n return validated;\n }\n\n private async runOnSendHooks(\n meta: MetaConfig,\n request: HTTPRequest<unknown>\n ) {\n for (const [description, hook] of meta.onSend) {\n try {\n await hook(request);\n } catch (e) {\n const cause = e as Error;\n const msg = `An error occurred while sending a request in hook: '${description}'`;\n throw new AutomationError(msg, { cause });\n }\n }\n }\n private async runOnReceiveHooks(\n meta: MetaConfig,\n response: HTTPResponse<unknown>\n ) {\n for (const [description, hook] of meta.onReceive) {\n try {\n await hook(response);\n } catch (e) {\n const cause = e as Error;\n const msg = `An error occurred while receiving a response in hook: '${description}'`;\n throw new AutomationError(msg, { cause });\n }\n }\n }\n\n #validateResponse<T>(\n response: HTTPResponse<unknown>,\n meta: MetaConfig\n ): HTTPResponse<T> {\n const { status, data } = response;\n const validated = meta.schemas.validate(\n status,\n data,\n meta.requireSchema\n ) as T;\n response.data = validated;\n return response as HTTPResponse<T>;\n }\n}\n","import { Class } from \"@autometa/types\";\nimport { defaultClient, type HTTPClient } from \"./http-client\";\n\nexport function defaultClientFactory() {\n const type = defaultClient as Class<HTTPClient>;\n return new type();\n}\n","import { RequestConfig, RequestConfigBasic } from \"./request.config\";\nimport { HTTPMethod } from \"./types\";\nimport { urlJoinP } from \"url-join-ts\";\nexport class HTTPRequest<T = unknown> implements RequestConfig<T> {\n headers: Record<string, string> = {};\n params: Record<string, string | string[] | Record<string, unknown>> = {};\n baseUrl?: string;\n route: string[] = [];\n method: HTTPMethod;\n data: T;\n\n constructor(config?: RequestConfigBasic) {\n Object.assign(this, config);\n }\n\n /**\n * Returns the full URL of the request, including the base url,\n * routes, and query parameters.\n *\n * ```ts\n * console.log(request.fullUrl())// https://example.com/foo?bar=baz?array=1,2,3\n * ```\n *\n * Note characters may be converted to escape codes. I.e (space => %20) and (comma => %2C)\n *\n * N.B this getter estimates what the url will be. The actual value\n * might be different depending on your underlying HTTPClient and\n * configuration. For example, query parameters might\n * use different array formats.\n */\n get fullUrl() {\n return urlJoinP(this.baseUrl, this.route, this.params);\n }\n\n /**\n * Returns a new independent copy of the request.\n */\n static derive(original: HTTPRequest<unknown>) {\n const request = new HTTPRequest();\n request.headers = { ...original.headers };\n request.params = { ...original.params };\n request.baseUrl = original.baseUrl;\n request.route = [...original.route];\n request.method = original.method;\n request.data = original.data;\n return request;\n }\n}\n\nexport class HTTPRequestBuilder<T extends HTTPRequest<unknown>> {\n #request: T;\n #dynamicHeaders = new Map<\n string,\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n >();\n\n constructor(request: T | (() => T) = () => new HTTPRequest() as T) {\n if (typeof request === \"function\") {\n this.#request = request();\n return;\n }\n this.#request = request;\n }\n\n static create<T extends HTTPRequest<unknown>>() {\n return new HTTPRequestBuilder<T>();\n }\n\n get request() {\n return this.#request;\n }\n\n async resolveDynamicHeaders(\n request: HTTPRequest<T> = this.#request as HTTPRequest<T>\n ) {\n for (const [name, value] of this.#dynamicHeaders) {\n try {\n if (!request.headers) request.headers = {};\n request.headers[name] = String(await value());\n } catch (e) {\n const cause = e as Error;\n const msg = `Failed to resolve dynamic header \"${name}\": \n${cause}`;\n throw new Error(msg);\n }\n }\n return this;\n }\n\n url(url: string) {\n this.#request.baseUrl = url;\n return this;\n }\n\n route(...route: string[]) {\n this.#request.route.push(...route);\n return this;\n }\n\n param(\n name: string,\n value:\n | string\n | number\n | boolean\n | (string | number | boolean)[]\n | Record<string, string | number | boolean>\n ) {\n if (Array.isArray(value)) {\n const asStr = value.flatMap(String);\n this.#request.params[name] = asStr;\n return this;\n }\n if (!Array.isArray(value) && typeof value === \"object\") {\n this.#request.params[name] = value;\n return this;\n }\n this.#request.params[name] = String(value);\n return this;\n }\n\n params(dict: Record<string, unknown>) {\n Object.assign(this.#request.params, dict);\n return this;\n }\n\n data<T>(data: T) {\n this.#request.data = data;\n return this;\n }\n\n header(\n name: string,\n value:\n | string\n | number\n | boolean\n | null\n | (string | number | boolean)[]\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>),\n onArray: (value: (string | number | boolean)[]) => string = (value) =>\n value.join(\",\")\n ) {\n if (typeof value === \"function\") {\n this.#dynamicHeaders.set(name, value);\n return this;\n }\n const val = Array.isArray(value) ? onArray(value) : String(value);\n this.#request.headers[name] = val;\n return this;\n }\n\n headers(dict: Record<string, string>) {\n Object.assign(this.#request.headers, dict);\n return this;\n }\n\n get() {\n return this.#request;\n }\n\n method(method: HTTPMethod) {\n this.#request.method = method;\n return this;\n }\n\n #setDynamicHeaders(\n headers: Map<\n string,\n | (() => string | number | boolean | null)\n | (() => Promise<string | number | boolean | null>)\n >\n ) {\n this.#dynamicHeaders = new Map(headers);\n return this;\n }\n\n derive(): HTTPRequestBuilder<T> {\n const request = HTTPRequest.derive(this.#request);\n return new HTTPRequestBuilder(request).#setDynamicHeaders(\n this.#dynamicHeaders\n ) as HTTPRequestBuilder<T>;\n }\n\n build(): HTTPRequest<T> {\n return this.#request as HTTPRequest<T>;\n }\n\n async buildAsync(): Promise<HTTPRequest<T>> {\n await this.resolveDynamicHeaders();\n return this.#request as HTTPRequest<T>;\n }\n}\n","import { SchemaParser, StatusCode } from \"./types\";\nexport class SchemaMap {\n #map: Map<StatusCode, SchemaParser>;\n constructor(map?: Map<StatusCode, SchemaParser> | SchemaMap) {\n if (map instanceof SchemaMap) {\n this.#map = new Map(map.#map);\n return;\n }\n this.#map = new Map(map);\n }\n\n derive() {\n return new SchemaMap(this.#map);\n }\n\n registerStatus(parser: SchemaParser, ...codes: StatusCode[]) {\n codes.forEach((code) => {\n if (this.#map.has(code)) {\n const msg = `Status code ${code} is already registered with a parser`;\n throw new Error(msg);\n }\n this.#map.set(code, parser);\n });\n }\n\n registerRange(parser: SchemaParser, from: StatusCode, to: StatusCode) {\n for (let i = from; i <= to; i++) {\n if (this.#map.has(i)) {\n throw new Error(`Status code ${i} is already registered with a parser`);\n }\n this.#map.set(i, parser);\n }\n }\n\n validate(status: StatusCode, data: unknown, requireSchema: boolean) {\n const parser = this.getParser(status, requireSchema);\n if (\"parse\" in parser) {\n return parser.parse(data);\n }\n if('validate' in parser) {\n return parser.validate(data);\n }\n try {\n return parser(data);\n } catch (e) {\n const msg = `Failed to schema parse response data for status code ${status} with data:\n \n${JSON.stringify(data, null, 2)}}`;\n throw new Error(msg);\n }\n }\n\n getParser(status: StatusCode, requireSchema: boolean) {\n const parser = this.#map.get(status);\n if (!parser && requireSchema) {\n const msg = `No parser registered for status code ${status} but 'requireSchema' is true`;\n throw new Error(msg);\n }\n if (parser) {\n return parser;\n }\n return (data: unknown) => data;\n }\n\n toObject() {\n return Object.fromEntries(this.#map) as Record<StatusCode, SchemaParser>;\n }\n}\n","import { SchemaMap } from \"./schema.map\";\nimport {\n HTTPAdditionalOptions,\n RequestHook,\n ResponseHook,\n SchemaParser,\n StatusCode\n} from \"./types\";\n\nexport interface SchemaConfig {\n schemas: SchemaMap;\n requireSchema: boolean;\n allowPlainText: boolean;\n}\n\nexport interface HTTPHooks {\n onSend: [string, RequestHook][];\n onReceive: [string, ResponseHook<unknown>][];\n}\n\n// export type MetaConfig = SchemaConfig & HTTPHooks;\n\nexport class MetaConfig implements SchemaConfig, HTTPHooks {\n schemas: SchemaMap;\n requireSchema: boolean;\n allowPlainText: boolean;\n onSend: [string, RequestHook][] = [];\n onReceive: [string, ResponseHook<unknown>][] = [];\n throwOnServerError: boolean;\n options: HTTPAdditionalOptions<unknown> = {};\n}\n\nexport class MetaConfigBuilder {\n #schemaMap = new SchemaMap();\n #requireSchema = false;\n #allowPlainText = false;\n #onBeforeSend: [string, RequestHook][] = [];\n #onAfterSend: [string, ResponseHook<unknown>][] = [];\n #throwOnServerError = false;\n #options: HTTPAdditionalOptions<unknown> = {};\n\n options(options: HTTPAdditionalOptions<unknown>) {\n this.#options = { options };\n return this;\n }\n schemaMap(map: SchemaMap) {\n this.#schemaMap = map;\n return this;\n }\n\n schema(parser: SchemaParser, ...codes: StatusCode[]): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ): MetaConfigBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n args.forEach((arg) => {\n if (typeof arg === \"number\") {\n this.#schemaMap.registerStatus(parser, arg);\n } else if (Array.isArray(arg)) {\n this.#schemaMap.registerStatus(parser, ...arg);\n } else {\n this.#schemaMap.registerRange(parser, arg.from, arg.to);\n }\n });\n\n return this;\n }\n\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n\n onBeforeSend(description: string, hook: RequestHook) {\n this.#onBeforeSend.push([description, hook]);\n return this;\n }\n\n #setOnSend(hooks: [string, RequestHook][]) {\n this.#onBeforeSend = [...hooks];\n return this;\n }\n\n throwOnServerError(value: boolean) {\n this.#throwOnServerError = value;\n return this;\n }\n\n onReceiveResponse(description: string, hook: ResponseHook<unknown>) {\n this.#onAfterSend.push([description, hook]);\n return this;\n }\n\n #setOnReceive(hooks: [string, ResponseHook<unknown>][]) {\n this.#onAfterSend = [...hooks];\n return this;\n }\n\n build() {\n const config = new MetaConfig();\n config.schemas = this.#schemaMap.derive();\n config.requireSchema = this.#requireSchema;\n config.allowPlainText = this.#allowPlainText;\n config.onSend = this.#onBeforeSend;\n config.onReceive = this.#onAfterSend;\n config.options = this.#options;\n config.throwOnServerError = this.#throwOnServerError;\n return config;\n }\n\n derive() {\n return new MetaConfigBuilder()\n .schemaMap(this.#schemaMap.derive())\n .requireSchema(this.#requireSchema)\n .allowPlainText(this.#allowPlainText)\n .throwOnServerError(this.#throwOnServerError)\n .#setOnSend(this.#onBeforeSend)\n .#setOnReceive(this.#onAfterSend);\n }\n}\n","import { AutomationError } from \"@autometa/errors\";\nimport isJson from \"@stdlib/assert-is-json\";\nimport { highlight } from \"cli-highlight\";\n\nexport function transformResponse(\n allowPlainText: boolean,\n data: null | undefined | string\n) {\n if (data === null) {\n return null;\n }\n if (data === undefined) {\n return undefined;\n }\n if (data === \"\") {\n return data;\n }\n if (isJson(data)) {\n return JSON.parse(data);\n }\n if (typeof data === \"string\" && [\"true\", \"false\"].includes(data)) {\n return JSON.parse(data);\n }\n if (typeof data === \"string\" && /^\\d*\\.?\\d+$/.test(data)) {\n return JSON.parse(data);\n }\n\n if (typeof data === \"object\") {\n return data;\n }\n if (allowPlainText) {\n return data;\n }\n\n const response = highlight(data, { language: \"html\" });\n const message = [\n `Could not parse a response as json, and this request was not configured to allow plain text responses.`,\n `To allow plain text responses, use the 'allowPlainText' method on the HTTP client.`,\n \"\",\n response\n ];\n throw new AutomationError(message.join(\"\\n\"));\n}\n","import isJson from \"@stdlib/assert-is-json\";\n\n/**\n * Schema which does not care about data validation.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response does not matter.\n * @param data\n * @returns\n */\nexport function AnySchema(data: unknown) {\n return data;\n}\n\n/**\n * Schema which validates that a response is empty. This can mean\n * the data payload was `null`, `undefined` or the string `'null'`.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be null or not defined.\n * @param data\n * @returns\n */\nexport function EmptySchema(data: unknown) {\n if (data !== null && data !== undefined && data !== \"null\") {\n throw new Error(`Expected null but got <${typeof data}> for ${data}`);\n }\n return data === \"null\" ? null : data;\n}\n\n/**\n * Schema which validates a response was null.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be null.\n * @param data\n * @returns\n */\nexport function NullSchema(data: unknown) {\n if (data !== null && data !== \"null\") {\n throw new Error(`Expected null but got <${typeof data}> for ${data}`);\n }\n return null;\n}\n\n/**\n * Schema which validates a response was undefined.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be undefined.\n *\n * @param data\n * @returns\n */\nexport function UndefinedSchema(data: unknown) {\n if (data !== undefined) {\n throw new Error(`Expected undefined but got <${typeof data}> for ${data}`);\n }\n return undefined;\n}\n\n/**\n * Schema which validates a response was a boolean, or a string of value\n * `'true'` or `'false'`.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a boolean.\n *\n * @param data\n * @returns\n */\nexport function BooleanSchema(data: unknown) {\n if (\n !(typeof data === \"boolean\") &&\n [\"true\", \"false\"].includes(String(data)) === false\n ) {\n throw new Error(`Expected boolean but got <${typeof data}> for ${data}`);\n }\n return JSON.parse(data as string);\n}\n\n/**\n * Schema which validates a response was a number, or a string of value\n * of a number.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a number.\n *\n * @param data\n * @returns\n */\nexport function NumberSchema(data: unknown) {\n if (\n !(typeof data === \"number\") &&\n /^\\d*\\.?\\d+$/.test(String(data)) === false\n ) {\n throw new Error(`Expected number but got <${typeof data}> for ${data}`);\n }\n return JSON.parse(data as string);\n}\n\n/**\n * Schema which validates a response was a string.\n *\n * Useful if `requireSchema` is set to true, but a specific\n * endpoints response should be a string.\n *\n * @param data\n * @returns\n */\nexport function StringSchema(data: unknown) {\n if (typeof data !== \"string\") {\n throw new Error(`Expected string but got <${typeof data}> for ${data}`);\n }\n return data;\n}\n\n\nexport function JSONSchema<T = unknown>(data: unknown) {\n if(typeof data === 'object') {\n return data as T;\n }\n if (!isJson(data)) {\n throw new Error(`Expected JSON but got <${typeof data}> for ${data}`);\n }\n const result = JSON.parse(data);\n return result;\n}"],"mappings":"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","names":["axios","value","isJson","import_errors","_request","import_assert_is_json","isJson"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autometa/http",
3
- "version": "1.4.9",
3
+ "version": "1.4.10",
4
4
  "description": "An Axios Based HTTP Client for Autometa",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/http.ts CHANGED
@@ -182,6 +182,11 @@ export class HTTP {
182
182
  return this;
183
183
  }
184
184
 
185
+ sharedOptions(options: HTTPAdditionalOptions<unknown>) {
186
+ this.#metaConfig.options(options);
187
+ return this;
188
+ }
189
+
185
190
  /**
186
191
  * If set to true, all requests derived from this client will require a schema be defined
187
192
  * matching any response status code. If set to false, a schema will still be used for validation
@@ -850,7 +855,8 @@ export class HTTP {
850
855
  const request = (await builder.resolveDynamicHeaders()).build();
851
856
  const meta = this.#metaConfig.derive().build();
852
857
  await this.runOnSendHooks(meta, request);
853
- const result = await this.client.request<unknown, string>(request, options);
858
+ const opts = { ...meta.options, ...options };
859
+ const result = await this.client.request<unknown, string>(request, opts);
854
860
  result.data = transformResponse(meta.allowPlainText, result.data);
855
861
  await this.runOnReceiveHooks(meta, result);
856
862
  const validated = this.#validateResponse(result, meta);
@@ -1,5 +1,11 @@
1
1
  import { SchemaMap } from "./schema.map";
2
- import { RequestHook, ResponseHook, SchemaParser, StatusCode } from "./types";
2
+ import {
3
+ HTTPAdditionalOptions,
4
+ RequestHook,
5
+ ResponseHook,
6
+ SchemaParser,
7
+ StatusCode
8
+ } from "./types";
3
9
 
4
10
  export interface SchemaConfig {
5
11
  schemas: SchemaMap;
@@ -21,6 +27,7 @@ export class MetaConfig implements SchemaConfig, HTTPHooks {
21
27
  onSend: [string, RequestHook][] = [];
22
28
  onReceive: [string, ResponseHook<unknown>][] = [];
23
29
  throwOnServerError: boolean;
30
+ options: HTTPAdditionalOptions<unknown> = {};
24
31
  }
25
32
 
26
33
  export class MetaConfigBuilder {
@@ -30,7 +37,12 @@ export class MetaConfigBuilder {
30
37
  #onBeforeSend: [string, RequestHook][] = [];
31
38
  #onAfterSend: [string, ResponseHook<unknown>][] = [];
32
39
  #throwOnServerError = false;
40
+ #options: HTTPAdditionalOptions<unknown> = {};
33
41
 
42
+ options(options: HTTPAdditionalOptions<unknown>) {
43
+ this.#options = { options };
44
+ return this;
45
+ }
34
46
  schemaMap(map: SchemaMap) {
35
47
  this.#schemaMap = map;
36
48
  return this;
@@ -104,6 +116,8 @@ export class MetaConfigBuilder {
104
116
  config.allowPlainText = this.#allowPlainText;
105
117
  config.onSend = this.#onBeforeSend;
106
118
  config.onReceive = this.#onAfterSend;
119
+ config.options = this.#options;
120
+ config.throwOnServerError = this.#throwOnServerError;
107
121
  return config;
108
122
  }
109
123