@autometa/http 0.1.2 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/esm/index.js +29 -21
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +29 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @autometa/http
|
|
2
2
|
|
|
3
|
+
## 1.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e9a8dc8: fix: parsing numbers from raw response string
|
|
8
|
+
|
|
9
|
+
## 1.0.0
|
|
10
|
+
|
|
11
|
+
### Major Changes
|
|
12
|
+
|
|
13
|
+
- c7b973f: fix: onRecieve hooks not executing if schema validation fails
|
|
14
|
+
|
|
3
15
|
## 0.1.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/esm/index.js
CHANGED
|
@@ -37,14 +37,16 @@ import { urlJoinP } from "url-join-ts";
|
|
|
37
37
|
|
|
38
38
|
// src/http.response.ts
|
|
39
39
|
var HTTPResponse = class _HTTPResponse {
|
|
40
|
-
static fromRaw(data, status, statusText, headers, url) {
|
|
40
|
+
static fromRaw(data, status, statusText, headers, url, validated, passedValidation) {
|
|
41
41
|
const response = new _HTTPResponse();
|
|
42
42
|
response.data = data;
|
|
43
43
|
response.status = status;
|
|
44
44
|
response.statusText = statusText;
|
|
45
45
|
response.headers = headers;
|
|
46
46
|
response.request = {
|
|
47
|
-
url
|
|
47
|
+
url,
|
|
48
|
+
validated,
|
|
49
|
+
passedValidation
|
|
48
50
|
};
|
|
49
51
|
return response;
|
|
50
52
|
}
|
|
@@ -260,9 +262,11 @@ var HTTPRequestBuilder = class {
|
|
|
260
262
|
const headers = __privateGet(this, _headers) && Object.fromEntries(__privateGet(this, _headers));
|
|
261
263
|
const responseType = __privateGet(this, _responseType);
|
|
262
264
|
const data = __privateGet(this, _data);
|
|
265
|
+
let response = void 0;
|
|
266
|
+
let skipFailedAfterHooks = false;
|
|
263
267
|
try {
|
|
264
268
|
this.tryRunBeforeHooks();
|
|
265
|
-
|
|
269
|
+
response = await axios({
|
|
266
270
|
method,
|
|
267
271
|
url,
|
|
268
272
|
headers,
|
|
@@ -274,22 +278,20 @@ var HTTPRequestBuilder = class {
|
|
|
274
278
|
transformResponse: transformResponse.bind(null, __privateGet(this, _allowPlainText))
|
|
275
279
|
});
|
|
276
280
|
const instance = this.makeResponse(response);
|
|
281
|
+
skipFailedAfterHooks = true;
|
|
277
282
|
this.tryRunAfterHooks(instance);
|
|
278
283
|
return instance;
|
|
279
284
|
} catch (e) {
|
|
285
|
+
if (response && !skipFailedAfterHooks) {
|
|
286
|
+
const instance = this.createWrapper(response);
|
|
287
|
+
this.tryRunAfterHooks(instance);
|
|
288
|
+
}
|
|
280
289
|
const error = e;
|
|
281
290
|
const message = `HTTP Client failed while while making request to ${url} with:
|
|
282
291
|
* headers: ${JSON.stringify(headers, null, 2)}
|
|
283
292
|
|
|
284
293
|
* data: ${data && JSON.stringify(data, null, 2)}`;
|
|
285
294
|
throw new AutomationError2(message, { cause: error });
|
|
286
|
-
} finally {
|
|
287
|
-
__privateGet(this, _headers).clear();
|
|
288
|
-
__privateGet(this, _params).clear();
|
|
289
|
-
__privateSet(this, _route, []);
|
|
290
|
-
__privateSet(this, _url, "");
|
|
291
|
-
__privateSet(this, _responseType, void 0);
|
|
292
|
-
__privateSet(this, _data, void 0);
|
|
293
295
|
}
|
|
294
296
|
}
|
|
295
297
|
tryRunBeforeHooks() {
|
|
@@ -319,24 +321,31 @@ var HTTPRequestBuilder = class {
|
|
|
319
321
|
}
|
|
320
322
|
}
|
|
321
323
|
makeResponse(res) {
|
|
322
|
-
const { status, data
|
|
323
|
-
const parsed =
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
);
|
|
324
|
+
const { status, data } = res;
|
|
325
|
+
const parsed = this.validateSchemas(status, data);
|
|
326
|
+
return this.createWrapper(res, parsed);
|
|
327
|
+
}
|
|
328
|
+
createWrapper({ status, statusText, headers, data }, parsed) {
|
|
328
329
|
const params = Object.fromEntries(__privateGet(this, _params));
|
|
329
330
|
const url = urlJoinP(__privateGet(this, _url), __privateGet(this, _route), params);
|
|
330
331
|
return plainToClass(HTTPResponse, {
|
|
331
332
|
status,
|
|
332
333
|
statusText,
|
|
333
334
|
headers,
|
|
334
|
-
data: parsed,
|
|
335
|
+
data: parsed ?? data,
|
|
335
336
|
request: {
|
|
336
|
-
url
|
|
337
|
+
url,
|
|
338
|
+
validated: !!parsed
|
|
337
339
|
}
|
|
338
340
|
});
|
|
339
341
|
}
|
|
342
|
+
validateSchemas(status, data) {
|
|
343
|
+
return __privateGet(this, _schemaMap).validate(
|
|
344
|
+
status,
|
|
345
|
+
data,
|
|
346
|
+
__privateGet(this, _requireSchema)
|
|
347
|
+
);
|
|
348
|
+
}
|
|
340
349
|
};
|
|
341
350
|
_headers = new WeakMap();
|
|
342
351
|
_params = new WeakMap();
|
|
@@ -360,9 +369,8 @@ function transformResponse(allowPlainText, data) {
|
|
|
360
369
|
if (["true", "false"].includes(data)) {
|
|
361
370
|
return JSON.parse(data);
|
|
362
371
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
return asNumber;
|
|
372
|
+
if (/^\d*\.?\d+$/.test(data)) {
|
|
373
|
+
return Number(data);
|
|
366
374
|
}
|
|
367
375
|
if (allowPlainText) {
|
|
368
376
|
return data;
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/http.builder.ts","../../src/http.response.ts","../../src/schema.map.ts","../../src/http.ts"],"sourcesContent":["import { Fixture, LIFE_CYCLE } from \"@autometa/app\";\nimport { AutomationError } from \"@autometa/errors\";\nimport axios, { AxiosResponse, Method, ResponseType } from \"axios\";\nimport { plainToClass } from \"class-transformer\";\nimport { urlJoinP } from \"url-join-ts\";\nimport { HTTPResponse } from \"./http.response\";\nimport { SchemaMap } from \"./schema.map\";\nimport { SchemaParser, StatusCode } from \"./types\";\nimport isJson from \"@stdlib/assert-is-json\";\nimport { highlight } from \"cli-highlight\";\nexport type RequestState = {\n headers: Map<string, string>;\n params: Map<string, unknown>;\n url: string;\n route: string[];\n responseType: ResponseType | undefined;\n data: unknown;\n method: Method;\n get fullUrl(): string;\n};\n\nexport type RequestHook = (state: RequestState) => unknown;\nexport type ResponseHook<T> = (state: HTTPResponse<T>) => unknown;\n\n@Fixture(LIFE_CYCLE.Transient)\nexport class HTTPRequestBuilder {\n #headers = new Map<string, string>();\n #params = new Map<string, unknown>();\n #url: string;\n #route: string[] = [];\n #method: Method;\n #schemaMap = new SchemaMap();\n #responseType: ResponseType | undefined = \"json\";\n #data: unknown;\n #requireSchema = false;\n #allowPlainText = false;\n #onBeforeSend: RequestHook[] = [];\n #onAfterSend: ResponseHook<unknown>[] = [];\n constructor(map: SchemaMap) {\n this.#schemaMap = new SchemaMap().including(map);\n }\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n get currentState(): RequestState {\n const fullUrl = this.currentUrl;\n return {\n headers: this.#headers,\n params: this.#params,\n url: this.#url,\n route: this.#route,\n responseType: this.#responseType,\n data: this.#data,\n method: this.#method,\n fullUrl\n };\n }\n\n get currentUrl() {\n const params = Object.fromEntries(this.#params);\n return urlJoinP(this.#url, this.#route, params);\n }\n\n url(url: string) {\n this.#url = url;\n return this;\n }\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n schema(parser: SchemaParser, ...codes: number[]): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: number; to: number }[]\n ): HTTPRequestBuilder;\n\n schema(\n parser: SchemaParser,\n ...args: (number | { from: number; to: number })[]\n ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#schemaMap.register(parser, ...(args as any));\n return this;\n }\n\n onBeforeSend(...hook: RequestHook[]) {\n this.#onBeforeSend.push(...hook);\n return this;\n }\n\n onReceivedResponse(...hook: ResponseHook<unknown>[]) {\n this.#onAfterSend.push(...hook);\n return this;\n }\n\n route(...route: (string | number | boolean)[]) {\n this.#route.push(...route.map((it) => `${it}`));\n return this;\n }\n\n header<T>(name: string, value: T) {\n const val = Array.isArray(value) ? value.join(\",\") : `${value}`;\n this.#headers.set(name, val);\n return this;\n }\n\n headers(dict: Record<string, string>) {\n Object.entries(dict).forEach(([name, value]) =>\n this.#headers.set(name, value)\n );\n return this;\n }\n\n param<T>(name: string, value: T) {\n this.#params.set(name, value);\n return this;\n }\n\n params(dict: Record<string, unknown>) {\n Object.entries(dict).forEach(([name, value]) => this.param(name, value));\n return this;\n }\n\n data<T>(data: T) {\n this.#data = data;\n return this;\n }\n\n async post<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"POST\");\n }\n\n async get<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"GET\");\n }\n\n async delete<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"DELETE\");\n }\n\n async put<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"PUT\");\n }\n\n private async _request<T>(method: Method) {\n this.#method = method;\n const url = this.currentUrl;\n const headers = this.#headers && Object.fromEntries(this.#headers);\n const responseType = this.#responseType;\n const data = this.#data;\n try {\n this.tryRunBeforeHooks();\n const response = await axios({\n method,\n url,\n headers,\n data,\n responseType,\n validateStatus: function (status) {\n return status >= 100 && status < 500;\n },\n transformResponse: transformResponse.bind(null, this.#allowPlainText)\n });\n const instance = this.makeResponse<T>(response);\n\n this.tryRunAfterHooks<T>(instance);\n return instance;\n } catch (e) {\n const error = e as Error;\n const message = `HTTP Client failed while while making request to ${url} with:\n* headers: ${JSON.stringify(headers, null, 2)}\n\n* data: ${data && JSON.stringify(data, null, 2)}`;\n throw new AutomationError(message, { cause: error });\n } finally {\n this.#headers.clear();\n this.#params.clear();\n this.#route = [];\n this.#url = \"\";\n this.#responseType = undefined;\n this.#data = undefined;\n }\n }\n\n private tryRunBeforeHooks() {\n let index = 0;\n try {\n for (const hook of this.#onBeforeSend) {\n hook(this.currentState);\n index++;\n }\n } catch (e) {\n const error = e as Error;\n const message = `HTTP Client encountered an error while running 'onBeforeRequest' hooks at index ${index}`;\n throw new AutomationError(message, { cause: error });\n }\n }\n private tryRunAfterHooks<T>(response: HTTPResponse<T>) {\n let index = 0;\n try {\n for (const hook of this.#onAfterSend) {\n hook(response);\n index++;\n }\n } catch (e) {\n const error = e as Error;\n const message = `HTTP Client encountered an error while running 'onAfterRequest' hooks at index ${index}`;\n throw new AutomationError(message, { cause: error });\n }\n }\n makeResponse<T>(res: AxiosResponse) {\n const { status, data, statusText, headers } = res;\n const parsed = this.#schemaMap.validate<T>(\n status as StatusCode,\n data,\n this.#requireSchema\n );\n const params = Object.fromEntries(this.#params);\n const url = urlJoinP(this.#url, this.#route, params);\n return plainToClass(HTTPResponse<T>, {\n status,\n statusText,\n headers,\n data: parsed,\n request: {\n url\n }\n });\n }\n}\n\nfunction transformResponse(allowPlainText: boolean, data: string) {\n if (isJson(data)) {\n return JSON.parse(data);\n }\n if ([\"true\", \"false\"].includes(data)) {\n return JSON.parse(data);\n }\n const asNumber = Number(data);\n if (!isNaN(asNumber)) {\n return asNumber;\n }\n if (allowPlainText) {\n return data;\n }\n const response = highlight(data, { language: \"html\" });\n const message = [\n `HTTP Client received a response which could not be parsed as JSON, and plain text responses were not configured for this request, Instead the body was:`,\n \" \",\n response\n ];\n throw new AutomationError(message.join(\"\\n\"));\n}\n","export class HTTPResponse<T> {\n status: number;\n statusText: string;\n data: T;\n headers: Record<string, string>;\n request: {\n url: string;\n };\n\n static fromRaw<T>(\n data: T,\n status: number,\n statusText: string,\n headers: Record<string, string>,\n url: string\n ) {\n const response = new HTTPResponse<T>();\n response.data = data;\n response.status = status;\n response.statusText = statusText;\n response.headers = headers;\n response.request = {\n url\n };\n return response;\n }\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: TDerived\n ): HTTPResponse<TDerived>;\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: (original: TOriginal) => TDerived\n ): HTTPResponse<TDerived>;\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: TDerived | ((original: TOriginal) => TDerived)\n ) {\n const response = new DerivedHTTPResponse<TDerived, TOriginal>();\n if (typeof data === \"function\") {\n const fn = data as (original: TOriginal) => TDerived;\n response.data = fn(original.data);\n } else {\n response.data = data;\n }\n response.status = original.status;\n response.statusText = original.statusText;\n response.headers = original.headers;\n response.request = original.request;\n response.actual = original as HTTPResponse<TOriginal>;\n return response;\n }\n}\n\nexport class DerivedHTTPResponse<T, K> extends HTTPResponse<T> {\n actual: HTTPResponse<K>;\n}\n","import { StatusCode, SchemaParser } from \"./types\";\nimport { AutomationError } from \"@autometa/errors\";\nimport { StatusCodes } from \"@autometa/status-codes\";\n\nexport class SchemaMap {\n #children: SchemaMap[] = [];\n #map: Map<StatusCode, SchemaParser> = new Map();\n register(\n parser: SchemaParser,\n ...codes: StatusCode[]\n ): (typeof parser)[\"parse\"];\n register(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): (typeof parser)[\"parse\"];\n register(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n args.forEach((arg) => {\n if (typeof arg === \"number\") {\n this.registerSingle(parser, arg);\n } else {\n this.registerRange(parser, arg);\n }\n });\n return parser.parse;\n }\n\n registerSingle(parser: SchemaParser, ...codes: StatusCode[]) {\n codes.forEach((code) => {\n if (this.#map.has(code)) {\n throw new AutomationError(\n `Status code ${code} is already registered with a parser`\n );\n }\n assertIsStatusCode(code);\n this.#map.set(code, parser);\n });\n }\n\n including(map: SchemaMap) {\n this.#children.includes(map);\n return this;\n }\n registerRange(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ) {\n range.forEach(({ from, to }) => {\n assertIsStatusCode(from);\n assertIsStatusCode(to);\n for (let i = from; i <= to; i++) {\n if (!IsStatusCode(i)) {\n continue;\n }\n if (this.#map.has(i)) {\n throw new AutomationError(\n `Status code ${i} is already registered with a parser`\n );\n }\n this.#map.set(i, parser);\n }\n });\n }\n\n get(status: StatusCode): SchemaParser | undefined {\n assertIsStatusCode(status);\n const local = this.#map.get(status);\n if (local) {\n return local;\n }\n const nested = this.#children.find((it) => it.#map.has(status));\n return nested?.get(status);\n }\n\n validate<T>(status: StatusCode, response: T, strict: boolean) {\n const parser = this.get(status);\n if (!parser) {\n if (!strict) {\n return response;\n }\n throw new AutomationError(\n `No schema parser registered for status code ${status} and 'requireSchema' is set to true`\n );\n }\n return parser.parse(response);\n }\n}\n\nexport function assertIsStatusCode(value: number): asserts value is StatusCode {\n const result = Object.values(StatusCodes)\n .map((it) => it.status as number)\n .includes(value);\n if (!result) {\n throw new AutomationError(\n `Expected status code ${value} to be a valid status code, but it is not a known HTTP codeF`\n );\n }\n}\n\nexport function IsStatusCode(value: number): value is StatusCode {\n return Object.values(StatusCodes)\n .map((it) => it.status as number)\n .includes(value);\n}\n","import { Fixture, LIFE_CYCLE } from \"@autometa/app\";\nimport { HTTPRequestBuilder, RequestHook, ResponseHook } from \"./http.builder\";\nimport { SchemaMap } from \"./schema.map\";\nimport { SchemaParser, StatusCode } from \"./types\";\n@Fixture(LIFE_CYCLE.Transient)\nexport class HTTP {\n #url: string;\n #route: string[] = [];\n #headers = new Map<string, string>();\n #requireSchema = false;\n #schemaMap: SchemaMap = new SchemaMap();\n #onBeforeSend: RequestHook[] = [];\n #onAfterSend: ResponseHook<unknown>[] = [];\n #allowPlainText = false;\n\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n\n url(url: string) {\n this.#url = url;\n return this;\n }\n\n sharedOnBeforeSend(hook: RequestHook) {\n this.#onBeforeSend.push(hook);\n return this;\n }\n\n sharedOnReceiveResponse(hook: ResponseHook<unknown>) {\n this.#onAfterSend.push(hook);\n return this;\n }\n\n onBeforeSend(hook: RequestHook) {\n return this.builder().onBeforeSend(hook);\n }\n\n onReceiveResponse(hook: ResponseHook<unknown>) {\n return this.builder().onReceivedResponse(hook);\n }\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 ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#schemaMap.register(parser, ...(args as any));\n return this;\n }\n\n schema(parser: SchemaParser, ...codes: StatusCode[]): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return this.builder().schema(parser, ...(args as any));\n }\n\n sharedRoute(...route: string[]) {\n this.#route.push(...route);\n return this;\n }\n\n param(name: string, value: string) {\n return this.builder().param(name, value);\n }\n\n params(dict: Record<string, string>) {\n return this.builder().params(dict);\n }\n\n data<T>(data: T) {\n return this.builder().data(data);\n }\n\n sharedHeader(name: string, value: string) {\n this.#headers.set(name, value);\n return this;\n }\n\n route(...route: (string | number | boolean)[]) {\n return this.builder().route(...route);\n }\n\n header<T>(name: string, value: T) {\n return this.builder().header(name, value);\n }\n\n headers(dict: Record<string, string>) {\n return this.builder().headers(dict);\n }\n\n get() {\n return this.builder().get();\n }\n\n private builder() {\n return new HTTPRequestBuilder(this.#schemaMap)\n .url(this.#url)\n .route(...this.#route)\n .allowPlainText(this.#allowPlainText)\n .headers(Object.fromEntries(this.#headers))\n .requireSchema(this.#requireSchema)\n .onBeforeSend(...this.#onBeforeSend)\n .onReceivedResponse(...this.#onAfterSend);\n }\n}\n"],"mappings":"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","names":["AutomationError","AutomationError","Fixture","LIFE_CYCLE","_url","_route","_headers","_requireSchema","_schemaMap","_onBeforeSend","_onAfterSend","_allowPlainText","Fixture","LIFE_CYCLE"]}
|
|
1
|
+
{"version":3,"sources":["../../src/http.builder.ts","../../src/http.response.ts","../../src/schema.map.ts","../../src/http.ts"],"sourcesContent":["import { Fixture, LIFE_CYCLE } from \"@autometa/app\";\nimport { AutomationError } from \"@autometa/errors\";\nimport axios, { AxiosResponse, Method, ResponseType } from \"axios\";\nimport { plainToClass } from \"class-transformer\";\nimport { urlJoinP } from \"url-join-ts\";\nimport { HTTPResponse } from \"./http.response\";\nimport { SchemaMap } from \"./schema.map\";\nimport { SchemaParser, StatusCode } from \"./types\";\nimport isJson from \"@stdlib/assert-is-json\";\nimport { highlight } from \"cli-highlight\";\nexport type RequestState = {\n headers: Map<string, string>;\n params: Map<string, unknown>;\n url: string;\n route: string[];\n responseType: ResponseType | undefined;\n data: unknown;\n method: Method;\n get fullUrl(): string;\n};\n\nexport type RequestHook = (state: RequestState) => unknown;\nexport type ResponseHook<T> = (state: HTTPResponse<T>) => unknown;\n\n@Fixture(LIFE_CYCLE.Transient)\nexport class HTTPRequestBuilder {\n #headers = new Map<string, string>();\n #params = new Map<string, unknown>();\n #url: string;\n #route: string[] = [];\n #method: Method;\n #schemaMap = new SchemaMap();\n #responseType: ResponseType | undefined = \"json\";\n #data: unknown;\n #requireSchema = false;\n #allowPlainText = false;\n #onBeforeSend: RequestHook[] = [];\n #onAfterSend: ResponseHook<unknown>[] = [];\n constructor(map: SchemaMap) {\n this.#schemaMap = new SchemaMap().including(map);\n }\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n get currentState(): RequestState {\n const fullUrl = this.currentUrl;\n return {\n headers: this.#headers,\n params: this.#params,\n url: this.#url,\n route: this.#route,\n responseType: this.#responseType,\n data: this.#data,\n method: this.#method,\n fullUrl\n };\n }\n\n get currentUrl() {\n const params = Object.fromEntries(this.#params);\n return urlJoinP(this.#url, this.#route, params);\n }\n\n url(url: string) {\n this.#url = url;\n return this;\n }\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n schema(parser: SchemaParser, ...codes: number[]): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: number; to: number }[]\n ): HTTPRequestBuilder;\n\n schema(\n parser: SchemaParser,\n ...args: (number | { from: number; to: number })[]\n ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#schemaMap.register(parser, ...(args as any));\n return this;\n }\n\n onBeforeSend(...hook: RequestHook[]) {\n this.#onBeforeSend.push(...hook);\n return this;\n }\n\n onReceivedResponse(...hook: ResponseHook<unknown>[]) {\n this.#onAfterSend.push(...hook);\n return this;\n }\n\n route(...route: (string | number | boolean)[]) {\n this.#route.push(...route.map((it) => `${it}`));\n return this;\n }\n\n header<T>(name: string, value: T) {\n const val = Array.isArray(value) ? value.join(\",\") : `${value}`;\n this.#headers.set(name, val);\n return this;\n }\n\n headers(dict: Record<string, string>) {\n Object.entries(dict).forEach(([name, value]) =>\n this.#headers.set(name, value)\n );\n return this;\n }\n\n param<T>(name: string, value: T) {\n this.#params.set(name, value);\n return this;\n }\n\n params(dict: Record<string, unknown>) {\n Object.entries(dict).forEach(([name, value]) => this.param(name, value));\n return this;\n }\n\n data<T>(data: T) {\n this.#data = data;\n return this;\n }\n\n async post<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"POST\");\n }\n\n async get<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"GET\");\n }\n\n async delete<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"DELETE\");\n }\n\n async put<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"PUT\");\n }\n\n private async _request<T>(method: Method) {\n this.#method = method;\n const url = this.currentUrl;\n const headers = this.#headers && Object.fromEntries(this.#headers);\n const responseType = this.#responseType;\n const data = this.#data;\n let response: AxiosResponse = undefined as unknown as AxiosResponse;\n let skipFailedAfterHooks = false;\n try {\n this.tryRunBeforeHooks();\n response = await axios({\n method,\n url,\n headers,\n data,\n responseType,\n validateStatus: function (status) {\n return status >= 100 && status < 500;\n },\n transformResponse: transformResponse.bind(null, this.#allowPlainText)\n });\n const instance = this.makeResponse<T>(response);\n\n skipFailedAfterHooks = true;\n this.tryRunAfterHooks<T>(instance);\n return instance;\n } catch (e) {\n if (response && !skipFailedAfterHooks) {\n const instance = this.createWrapper<T>(response);\n this.tryRunAfterHooks<T>(instance);\n }\n const error = e as Error;\n const message = `HTTP Client failed while while making request to ${url} with:\n* headers: ${JSON.stringify(headers, null, 2)}\n\n* data: ${data && JSON.stringify(data, null, 2)}`;\n throw new AutomationError(message, { cause: error });\n }\n }\n\n private tryRunBeforeHooks() {\n let index = 0;\n try {\n for (const hook of this.#onBeforeSend) {\n hook(this.currentState);\n index++;\n }\n } catch (e) {\n const error = e as Error;\n const message = `HTTP Client encountered an error while running 'onBeforeRequest' hooks at index ${index}`;\n throw new AutomationError(message, { cause: error });\n }\n }\n private tryRunAfterHooks<T>(response: HTTPResponse<T>) {\n let index = 0;\n try {\n for (const hook of this.#onAfterSend) {\n hook(response);\n index++;\n }\n } catch (e) {\n const error = e as Error;\n const message = `HTTP Client encountered an error while running 'onAfterRequest' hooks at index ${index}`;\n throw new AutomationError(message, { cause: error });\n }\n }\n makeResponse<T>(res: AxiosResponse) {\n const { status, data } = res;\n const parsed = this.validateSchemas<T>(status, data);\n return this.createWrapper<T>(res, parsed);\n }\n\n private createWrapper<T>(\n { status, statusText, headers, data }: AxiosResponse<T>,\n parsed?: T\n ) {\n const params = Object.fromEntries(this.#params);\n const url = urlJoinP(this.#url, this.#route, params);\n return plainToClass(HTTPResponse<T>, {\n status,\n statusText,\n headers,\n data: parsed ?? data,\n request: {\n url,\n validated: !!parsed,\n }\n });\n }\n\n private validateSchemas<T>(status: number, data: T): T {\n return this.#schemaMap.validate<T>(\n status as StatusCode,\n data,\n this.#requireSchema\n );\n }\n}\n\nfunction transformResponse(allowPlainText: boolean, data: string) {\n if (isJson(data)) {\n return JSON.parse(data);\n }\n if ([\"true\", \"false\"].includes(data)) {\n return JSON.parse(data);\n }\n if(/^\\d*\\.?\\d+$/.test(data)) {\n return Number(data);\n }\n if (allowPlainText) {\n return data;\n }\n const response = highlight(data, { language: \"html\" });\n const message = [\n `HTTP Client received a response which could not be parsed as JSON, and plain text responses were not configured for this request, Instead the body was:`,\n \" \",\n response\n ];\n throw new AutomationError(message.join(\"\\n\"));\n}\n","export class HTTPResponse<T> {\n status: number;\n statusText: string;\n data: T;\n headers: Record<string, string>;\n request: {\n url: string;\n validated: boolean;\n passedValidation: boolean\n };\n\n static fromRaw<T>(\n data: T,\n status: number,\n statusText: string,\n headers: Record<string, string>,\n url: string,\n validated: boolean,\n passedValidation: boolean\n ) {\n const response = new HTTPResponse<T>();\n response.data = data;\n response.status = status;\n response.statusText = statusText;\n response.headers = headers;\n response.request = {\n url,\n validated,\n passedValidation\n };\n return response;\n }\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: TDerived\n ): HTTPResponse<TDerived>;\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: (original: TOriginal) => TDerived\n ): HTTPResponse<TDerived>;\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: TDerived | ((original: TOriginal) => TDerived)\n ) {\n const response = new DerivedHTTPResponse<TDerived, TOriginal>();\n if (typeof data === \"function\") {\n const fn = data as (original: TOriginal) => TDerived;\n response.data = fn(original.data);\n } else {\n response.data = data;\n }\n response.status = original.status;\n response.statusText = original.statusText;\n response.headers = original.headers;\n response.request = original.request;\n response.actual = original as HTTPResponse<TOriginal>;\n return response;\n }\n}\n\nexport class DerivedHTTPResponse<T, K> extends HTTPResponse<T> {\n actual: HTTPResponse<K>;\n}\n","import { StatusCode, SchemaParser } from \"./types\";\nimport { AutomationError } from \"@autometa/errors\";\nimport { StatusCodes } from \"@autometa/status-codes\";\n\nexport class SchemaMap {\n #children: SchemaMap[] = [];\n #map: Map<StatusCode, SchemaParser> = new Map();\n register(\n parser: SchemaParser,\n ...codes: StatusCode[]\n ): (typeof parser)[\"parse\"];\n register(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): (typeof parser)[\"parse\"];\n register(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n args.forEach((arg) => {\n if (typeof arg === \"number\") {\n this.registerSingle(parser, arg);\n } else {\n this.registerRange(parser, arg);\n }\n });\n return parser.parse;\n }\n\n registerSingle(parser: SchemaParser, ...codes: StatusCode[]) {\n codes.forEach((code) => {\n if (this.#map.has(code)) {\n throw new AutomationError(\n `Status code ${code} is already registered with a parser`\n );\n }\n assertIsStatusCode(code);\n this.#map.set(code, parser);\n });\n }\n\n including(map: SchemaMap) {\n this.#children.includes(map);\n return this;\n }\n registerRange(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ) {\n range.forEach(({ from, to }) => {\n assertIsStatusCode(from);\n assertIsStatusCode(to);\n for (let i = from; i <= to; i++) {\n if (!IsStatusCode(i)) {\n continue;\n }\n if (this.#map.has(i)) {\n throw new AutomationError(\n `Status code ${i} is already registered with a parser`\n );\n }\n this.#map.set(i, parser);\n }\n });\n }\n\n get(status: StatusCode): SchemaParser | undefined {\n assertIsStatusCode(status);\n const local = this.#map.get(status);\n if (local) {\n return local;\n }\n const nested = this.#children.find((it) => it.#map.has(status));\n return nested?.get(status);\n }\n\n validate<T>(status: StatusCode, response: T, strict: boolean): T {\n const parser = this.get(status);\n if (!parser) {\n if (!strict) {\n return response;\n }\n throw new AutomationError(\n `No schema parser registered for status code ${status} and 'requireSchema' is set to true`\n );\n }\n return parser.parse(response) as T;\n }\n}\n\nexport function assertIsStatusCode(value: number): asserts value is StatusCode {\n const result = Object.values(StatusCodes)\n .map((it) => it.status as number)\n .includes(value);\n if (!result) {\n throw new AutomationError(\n `Expected status code ${value} to be a valid status code, but it is not a known HTTP codeF`\n );\n }\n}\n\nexport function IsStatusCode(value: number): value is StatusCode {\n return Object.values(StatusCodes)\n .map((it) => it.status as number)\n .includes(value);\n}\n","import { Fixture, LIFE_CYCLE } from \"@autometa/app\";\nimport { HTTPRequestBuilder, RequestHook, ResponseHook } from \"./http.builder\";\nimport { SchemaMap } from \"./schema.map\";\nimport { SchemaParser, StatusCode } from \"./types\";\n@Fixture(LIFE_CYCLE.Transient)\nexport class HTTP {\n #url: string;\n #route: string[] = [];\n #headers = new Map<string, string>();\n #requireSchema = false;\n #schemaMap: SchemaMap = new SchemaMap();\n #onBeforeSend: RequestHook[] = [];\n #onAfterSend: ResponseHook<unknown>[] = [];\n #allowPlainText = false;\n\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n\n url(url: string) {\n this.#url = url;\n return this;\n }\n\n sharedOnBeforeSend(hook: RequestHook) {\n this.#onBeforeSend.push(hook);\n return this;\n }\n\n sharedOnReceiveResponse(hook: ResponseHook<unknown>) {\n this.#onAfterSend.push(hook);\n return this;\n }\n\n onBeforeSend(hook: RequestHook) {\n return this.builder().onBeforeSend(hook);\n }\n\n onReceiveResponse(hook: ResponseHook<unknown>) {\n return this.builder().onReceivedResponse(hook);\n }\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 ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#schemaMap.register(parser, ...(args as any));\n return this;\n }\n\n schema(parser: SchemaParser, ...codes: StatusCode[]): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return this.builder().schema(parser, ...(args as any));\n }\n\n sharedRoute(...route: string[]) {\n this.#route.push(...route);\n return this;\n }\n\n param(name: string, value: string) {\n return this.builder().param(name, value);\n }\n\n params(dict: Record<string, string>) {\n return this.builder().params(dict);\n }\n\n data<T>(data: T) {\n return this.builder().data(data);\n }\n\n sharedHeader(name: string, value: string) {\n this.#headers.set(name, value);\n return this;\n }\n\n route(...route: (string | number | boolean)[]) {\n return this.builder().route(...route);\n }\n\n header<T>(name: string, value: T) {\n return this.builder().header(name, value);\n }\n\n headers(dict: Record<string, string>) {\n return this.builder().headers(dict);\n }\n\n get() {\n return this.builder().get();\n }\n\n private builder() {\n return new HTTPRequestBuilder(this.#schemaMap)\n .url(this.#url)\n .route(...this.#route)\n .allowPlainText(this.#allowPlainText)\n .headers(Object.fromEntries(this.#headers))\n .requireSchema(this.#requireSchema)\n .onBeforeSend(...this.#onBeforeSend)\n .onReceivedResponse(...this.#onAfterSend);\n }\n}\n"],"mappings":"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","names":["AutomationError","AutomationError","Fixture","LIFE_CYCLE","_url","_route","_headers","_requireSchema","_schemaMap","_onBeforeSend","_onAfterSend","_allowPlainText","Fixture","LIFE_CYCLE"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -8,8 +8,10 @@ declare class HTTPResponse<T> {
|
|
|
8
8
|
headers: Record<string, string>;
|
|
9
9
|
request: {
|
|
10
10
|
url: string;
|
|
11
|
+
validated: boolean;
|
|
12
|
+
passedValidation: boolean;
|
|
11
13
|
};
|
|
12
|
-
static fromRaw<T>(data: T, status: number, statusText: string, headers: Record<string, string>, url: string): HTTPResponse<T>;
|
|
14
|
+
static fromRaw<T>(data: T, status: number, statusText: string, headers: Record<string, string>, url: string, validated: boolean, passedValidation: boolean): HTTPResponse<T>;
|
|
13
15
|
static derive<TOriginal, TDerived>(original: HTTPResponse<TOriginal>, data: TDerived): HTTPResponse<TDerived>;
|
|
14
16
|
static derive<TOriginal, TDerived>(original: HTTPResponse<TOriginal>, data: (original: TOriginal) => TDerived): HTTPResponse<TDerived>;
|
|
15
17
|
}
|
|
@@ -40,7 +42,7 @@ declare class SchemaMap {
|
|
|
40
42
|
to: StatusCode;
|
|
41
43
|
}[]): void;
|
|
42
44
|
get(status: StatusCode): SchemaParser | undefined;
|
|
43
|
-
validate<T>(status: StatusCode, response: T, strict: boolean):
|
|
45
|
+
validate<T>(status: StatusCode, response: T, strict: boolean): T;
|
|
44
46
|
}
|
|
45
47
|
declare function assertIsStatusCode(value: number): asserts value is StatusCode;
|
|
46
48
|
declare function IsStatusCode(value: number): value is StatusCode;
|
|
@@ -86,6 +88,8 @@ declare class HTTPRequestBuilder {
|
|
|
86
88
|
private tryRunBeforeHooks;
|
|
87
89
|
private tryRunAfterHooks;
|
|
88
90
|
makeResponse<T>(res: AxiosResponse): HTTPResponse<T>;
|
|
91
|
+
private createWrapper;
|
|
92
|
+
private validateSchemas;
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
declare class HTTP {
|
package/dist/index.d.ts
CHANGED
|
@@ -8,8 +8,10 @@ declare class HTTPResponse<T> {
|
|
|
8
8
|
headers: Record<string, string>;
|
|
9
9
|
request: {
|
|
10
10
|
url: string;
|
|
11
|
+
validated: boolean;
|
|
12
|
+
passedValidation: boolean;
|
|
11
13
|
};
|
|
12
|
-
static fromRaw<T>(data: T, status: number, statusText: string, headers: Record<string, string>, url: string): HTTPResponse<T>;
|
|
14
|
+
static fromRaw<T>(data: T, status: number, statusText: string, headers: Record<string, string>, url: string, validated: boolean, passedValidation: boolean): HTTPResponse<T>;
|
|
13
15
|
static derive<TOriginal, TDerived>(original: HTTPResponse<TOriginal>, data: TDerived): HTTPResponse<TDerived>;
|
|
14
16
|
static derive<TOriginal, TDerived>(original: HTTPResponse<TOriginal>, data: (original: TOriginal) => TDerived): HTTPResponse<TDerived>;
|
|
15
17
|
}
|
|
@@ -40,7 +42,7 @@ declare class SchemaMap {
|
|
|
40
42
|
to: StatusCode;
|
|
41
43
|
}[]): void;
|
|
42
44
|
get(status: StatusCode): SchemaParser | undefined;
|
|
43
|
-
validate<T>(status: StatusCode, response: T, strict: boolean):
|
|
45
|
+
validate<T>(status: StatusCode, response: T, strict: boolean): T;
|
|
44
46
|
}
|
|
45
47
|
declare function assertIsStatusCode(value: number): asserts value is StatusCode;
|
|
46
48
|
declare function IsStatusCode(value: number): value is StatusCode;
|
|
@@ -86,6 +88,8 @@ declare class HTTPRequestBuilder {
|
|
|
86
88
|
private tryRunBeforeHooks;
|
|
87
89
|
private tryRunAfterHooks;
|
|
88
90
|
makeResponse<T>(res: AxiosResponse): HTTPResponse<T>;
|
|
91
|
+
private createWrapper;
|
|
92
|
+
private validateSchemas;
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
declare class HTTP {
|
package/dist/index.js
CHANGED
|
@@ -76,14 +76,16 @@ var import_url_join_ts = require("url-join-ts");
|
|
|
76
76
|
|
|
77
77
|
// src/http.response.ts
|
|
78
78
|
var HTTPResponse = class _HTTPResponse {
|
|
79
|
-
static fromRaw(data, status, statusText, headers, url) {
|
|
79
|
+
static fromRaw(data, status, statusText, headers, url, validated, passedValidation) {
|
|
80
80
|
const response = new _HTTPResponse();
|
|
81
81
|
response.data = data;
|
|
82
82
|
response.status = status;
|
|
83
83
|
response.statusText = statusText;
|
|
84
84
|
response.headers = headers;
|
|
85
85
|
response.request = {
|
|
86
|
-
url
|
|
86
|
+
url,
|
|
87
|
+
validated,
|
|
88
|
+
passedValidation
|
|
87
89
|
};
|
|
88
90
|
return response;
|
|
89
91
|
}
|
|
@@ -299,9 +301,11 @@ var HTTPRequestBuilder = class {
|
|
|
299
301
|
const headers = __privateGet(this, _headers) && Object.fromEntries(__privateGet(this, _headers));
|
|
300
302
|
const responseType = __privateGet(this, _responseType);
|
|
301
303
|
const data = __privateGet(this, _data);
|
|
304
|
+
let response = void 0;
|
|
305
|
+
let skipFailedAfterHooks = false;
|
|
302
306
|
try {
|
|
303
307
|
this.tryRunBeforeHooks();
|
|
304
|
-
|
|
308
|
+
response = await (0, import_axios.default)({
|
|
305
309
|
method,
|
|
306
310
|
url,
|
|
307
311
|
headers,
|
|
@@ -313,22 +317,20 @@ var HTTPRequestBuilder = class {
|
|
|
313
317
|
transformResponse: transformResponse.bind(null, __privateGet(this, _allowPlainText))
|
|
314
318
|
});
|
|
315
319
|
const instance = this.makeResponse(response);
|
|
320
|
+
skipFailedAfterHooks = true;
|
|
316
321
|
this.tryRunAfterHooks(instance);
|
|
317
322
|
return instance;
|
|
318
323
|
} catch (e) {
|
|
324
|
+
if (response && !skipFailedAfterHooks) {
|
|
325
|
+
const instance = this.createWrapper(response);
|
|
326
|
+
this.tryRunAfterHooks(instance);
|
|
327
|
+
}
|
|
319
328
|
const error = e;
|
|
320
329
|
const message = `HTTP Client failed while while making request to ${url} with:
|
|
321
330
|
* headers: ${JSON.stringify(headers, null, 2)}
|
|
322
331
|
|
|
323
332
|
* data: ${data && JSON.stringify(data, null, 2)}`;
|
|
324
333
|
throw new import_errors2.AutomationError(message, { cause: error });
|
|
325
|
-
} finally {
|
|
326
|
-
__privateGet(this, _headers).clear();
|
|
327
|
-
__privateGet(this, _params).clear();
|
|
328
|
-
__privateSet(this, _route, []);
|
|
329
|
-
__privateSet(this, _url, "");
|
|
330
|
-
__privateSet(this, _responseType, void 0);
|
|
331
|
-
__privateSet(this, _data, void 0);
|
|
332
334
|
}
|
|
333
335
|
}
|
|
334
336
|
tryRunBeforeHooks() {
|
|
@@ -358,24 +360,31 @@ var HTTPRequestBuilder = class {
|
|
|
358
360
|
}
|
|
359
361
|
}
|
|
360
362
|
makeResponse(res) {
|
|
361
|
-
const { status, data
|
|
362
|
-
const parsed =
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
);
|
|
363
|
+
const { status, data } = res;
|
|
364
|
+
const parsed = this.validateSchemas(status, data);
|
|
365
|
+
return this.createWrapper(res, parsed);
|
|
366
|
+
}
|
|
367
|
+
createWrapper({ status, statusText, headers, data }, parsed) {
|
|
367
368
|
const params = Object.fromEntries(__privateGet(this, _params));
|
|
368
369
|
const url = (0, import_url_join_ts.urlJoinP)(__privateGet(this, _url), __privateGet(this, _route), params);
|
|
369
370
|
return (0, import_class_transformer.plainToClass)(HTTPResponse, {
|
|
370
371
|
status,
|
|
371
372
|
statusText,
|
|
372
373
|
headers,
|
|
373
|
-
data: parsed,
|
|
374
|
+
data: parsed ?? data,
|
|
374
375
|
request: {
|
|
375
|
-
url
|
|
376
|
+
url,
|
|
377
|
+
validated: !!parsed
|
|
376
378
|
}
|
|
377
379
|
});
|
|
378
380
|
}
|
|
381
|
+
validateSchemas(status, data) {
|
|
382
|
+
return __privateGet(this, _schemaMap).validate(
|
|
383
|
+
status,
|
|
384
|
+
data,
|
|
385
|
+
__privateGet(this, _requireSchema)
|
|
386
|
+
);
|
|
387
|
+
}
|
|
379
388
|
};
|
|
380
389
|
_headers = new WeakMap();
|
|
381
390
|
_params = new WeakMap();
|
|
@@ -399,9 +408,8 @@ function transformResponse(allowPlainText, data) {
|
|
|
399
408
|
if (["true", "false"].includes(data)) {
|
|
400
409
|
return JSON.parse(data);
|
|
401
410
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
return asNumber;
|
|
411
|
+
if (/^\d*\.?\d+$/.test(data)) {
|
|
412
|
+
return Number(data);
|
|
405
413
|
}
|
|
406
414
|
if (allowPlainText) {
|
|
407
415
|
return data;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/http.builder.ts","../src/http.response.ts","../src/schema.map.ts","../src/http.ts"],"sourcesContent":["export * from \"./http.builder\";\nexport * from \"./http.response\";\nexport * from \"./types\";\nexport * from \"./schema.map\";\nexport * from \"./http\";\n","import { Fixture, LIFE_CYCLE } from \"@autometa/app\";\nimport { AutomationError } from \"@autometa/errors\";\nimport axios, { AxiosResponse, Method, ResponseType } from \"axios\";\nimport { plainToClass } from \"class-transformer\";\nimport { urlJoinP } from \"url-join-ts\";\nimport { HTTPResponse } from \"./http.response\";\nimport { SchemaMap } from \"./schema.map\";\nimport { SchemaParser, StatusCode } from \"./types\";\nimport isJson from \"@stdlib/assert-is-json\";\nimport { highlight } from \"cli-highlight\";\nexport type RequestState = {\n headers: Map<string, string>;\n params: Map<string, unknown>;\n url: string;\n route: string[];\n responseType: ResponseType | undefined;\n data: unknown;\n method: Method;\n get fullUrl(): string;\n};\n\nexport type RequestHook = (state: RequestState) => unknown;\nexport type ResponseHook<T> = (state: HTTPResponse<T>) => unknown;\n\n@Fixture(LIFE_CYCLE.Transient)\nexport class HTTPRequestBuilder {\n #headers = new Map<string, string>();\n #params = new Map<string, unknown>();\n #url: string;\n #route: string[] = [];\n #method: Method;\n #schemaMap = new SchemaMap();\n #responseType: ResponseType | undefined = \"json\";\n #data: unknown;\n #requireSchema = false;\n #allowPlainText = false;\n #onBeforeSend: RequestHook[] = [];\n #onAfterSend: ResponseHook<unknown>[] = [];\n constructor(map: SchemaMap) {\n this.#schemaMap = new SchemaMap().including(map);\n }\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n get currentState(): RequestState {\n const fullUrl = this.currentUrl;\n return {\n headers: this.#headers,\n params: this.#params,\n url: this.#url,\n route: this.#route,\n responseType: this.#responseType,\n data: this.#data,\n method: this.#method,\n fullUrl\n };\n }\n\n get currentUrl() {\n const params = Object.fromEntries(this.#params);\n return urlJoinP(this.#url, this.#route, params);\n }\n\n url(url: string) {\n this.#url = url;\n return this;\n }\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n schema(parser: SchemaParser, ...codes: number[]): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: number; to: number }[]\n ): HTTPRequestBuilder;\n\n schema(\n parser: SchemaParser,\n ...args: (number | { from: number; to: number })[]\n ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#schemaMap.register(parser, ...(args as any));\n return this;\n }\n\n onBeforeSend(...hook: RequestHook[]) {\n this.#onBeforeSend.push(...hook);\n return this;\n }\n\n onReceivedResponse(...hook: ResponseHook<unknown>[]) {\n this.#onAfterSend.push(...hook);\n return this;\n }\n\n route(...route: (string | number | boolean)[]) {\n this.#route.push(...route.map((it) => `${it}`));\n return this;\n }\n\n header<T>(name: string, value: T) {\n const val = Array.isArray(value) ? value.join(\",\") : `${value}`;\n this.#headers.set(name, val);\n return this;\n }\n\n headers(dict: Record<string, string>) {\n Object.entries(dict).forEach(([name, value]) =>\n this.#headers.set(name, value)\n );\n return this;\n }\n\n param<T>(name: string, value: T) {\n this.#params.set(name, value);\n return this;\n }\n\n params(dict: Record<string, unknown>) {\n Object.entries(dict).forEach(([name, value]) => this.param(name, value));\n return this;\n }\n\n data<T>(data: T) {\n this.#data = data;\n return this;\n }\n\n async post<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"POST\");\n }\n\n async get<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"GET\");\n }\n\n async delete<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"DELETE\");\n }\n\n async put<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"PUT\");\n }\n\n private async _request<T>(method: Method) {\n this.#method = method;\n const url = this.currentUrl;\n const headers = this.#headers && Object.fromEntries(this.#headers);\n const responseType = this.#responseType;\n const data = this.#data;\n try {\n this.tryRunBeforeHooks();\n const response = await axios({\n method,\n url,\n headers,\n data,\n responseType,\n validateStatus: function (status) {\n return status >= 100 && status < 500;\n },\n transformResponse: transformResponse.bind(null, this.#allowPlainText)\n });\n const instance = this.makeResponse<T>(response);\n\n this.tryRunAfterHooks<T>(instance);\n return instance;\n } catch (e) {\n const error = e as Error;\n const message = `HTTP Client failed while while making request to ${url} with:\n* headers: ${JSON.stringify(headers, null, 2)}\n\n* data: ${data && JSON.stringify(data, null, 2)}`;\n throw new AutomationError(message, { cause: error });\n } finally {\n this.#headers.clear();\n this.#params.clear();\n this.#route = [];\n this.#url = \"\";\n this.#responseType = undefined;\n this.#data = undefined;\n }\n }\n\n private tryRunBeforeHooks() {\n let index = 0;\n try {\n for (const hook of this.#onBeforeSend) {\n hook(this.currentState);\n index++;\n }\n } catch (e) {\n const error = e as Error;\n const message = `HTTP Client encountered an error while running 'onBeforeRequest' hooks at index ${index}`;\n throw new AutomationError(message, { cause: error });\n }\n }\n private tryRunAfterHooks<T>(response: HTTPResponse<T>) {\n let index = 0;\n try {\n for (const hook of this.#onAfterSend) {\n hook(response);\n index++;\n }\n } catch (e) {\n const error = e as Error;\n const message = `HTTP Client encountered an error while running 'onAfterRequest' hooks at index ${index}`;\n throw new AutomationError(message, { cause: error });\n }\n }\n makeResponse<T>(res: AxiosResponse) {\n const { status, data, statusText, headers } = res;\n const parsed = this.#schemaMap.validate<T>(\n status as StatusCode,\n data,\n this.#requireSchema\n );\n const params = Object.fromEntries(this.#params);\n const url = urlJoinP(this.#url, this.#route, params);\n return plainToClass(HTTPResponse<T>, {\n status,\n statusText,\n headers,\n data: parsed,\n request: {\n url\n }\n });\n }\n}\n\nfunction transformResponse(allowPlainText: boolean, data: string) {\n if (isJson(data)) {\n return JSON.parse(data);\n }\n if ([\"true\", \"false\"].includes(data)) {\n return JSON.parse(data);\n }\n const asNumber = Number(data);\n if (!isNaN(asNumber)) {\n return asNumber;\n }\n if (allowPlainText) {\n return data;\n }\n const response = highlight(data, { language: \"html\" });\n const message = [\n `HTTP Client received a response which could not be parsed as JSON, and plain text responses were not configured for this request, Instead the body was:`,\n \" \",\n response\n ];\n throw new AutomationError(message.join(\"\\n\"));\n}\n","export class HTTPResponse<T> {\n status: number;\n statusText: string;\n data: T;\n headers: Record<string, string>;\n request: {\n url: string;\n };\n\n static fromRaw<T>(\n data: T,\n status: number,\n statusText: string,\n headers: Record<string, string>,\n url: string\n ) {\n const response = new HTTPResponse<T>();\n response.data = data;\n response.status = status;\n response.statusText = statusText;\n response.headers = headers;\n response.request = {\n url\n };\n return response;\n }\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: TDerived\n ): HTTPResponse<TDerived>;\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: (original: TOriginal) => TDerived\n ): HTTPResponse<TDerived>;\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: TDerived | ((original: TOriginal) => TDerived)\n ) {\n const response = new DerivedHTTPResponse<TDerived, TOriginal>();\n if (typeof data === \"function\") {\n const fn = data as (original: TOriginal) => TDerived;\n response.data = fn(original.data);\n } else {\n response.data = data;\n }\n response.status = original.status;\n response.statusText = original.statusText;\n response.headers = original.headers;\n response.request = original.request;\n response.actual = original as HTTPResponse<TOriginal>;\n return response;\n }\n}\n\nexport class DerivedHTTPResponse<T, K> extends HTTPResponse<T> {\n actual: HTTPResponse<K>;\n}\n","import { StatusCode, SchemaParser } from \"./types\";\nimport { AutomationError } from \"@autometa/errors\";\nimport { StatusCodes } from \"@autometa/status-codes\";\n\nexport class SchemaMap {\n #children: SchemaMap[] = [];\n #map: Map<StatusCode, SchemaParser> = new Map();\n register(\n parser: SchemaParser,\n ...codes: StatusCode[]\n ): (typeof parser)[\"parse\"];\n register(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): (typeof parser)[\"parse\"];\n register(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n args.forEach((arg) => {\n if (typeof arg === \"number\") {\n this.registerSingle(parser, arg);\n } else {\n this.registerRange(parser, arg);\n }\n });\n return parser.parse;\n }\n\n registerSingle(parser: SchemaParser, ...codes: StatusCode[]) {\n codes.forEach((code) => {\n if (this.#map.has(code)) {\n throw new AutomationError(\n `Status code ${code} is already registered with a parser`\n );\n }\n assertIsStatusCode(code);\n this.#map.set(code, parser);\n });\n }\n\n including(map: SchemaMap) {\n this.#children.includes(map);\n return this;\n }\n registerRange(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ) {\n range.forEach(({ from, to }) => {\n assertIsStatusCode(from);\n assertIsStatusCode(to);\n for (let i = from; i <= to; i++) {\n if (!IsStatusCode(i)) {\n continue;\n }\n if (this.#map.has(i)) {\n throw new AutomationError(\n `Status code ${i} is already registered with a parser`\n );\n }\n this.#map.set(i, parser);\n }\n });\n }\n\n get(status: StatusCode): SchemaParser | undefined {\n assertIsStatusCode(status);\n const local = this.#map.get(status);\n if (local) {\n return local;\n }\n const nested = this.#children.find((it) => it.#map.has(status));\n return nested?.get(status);\n }\n\n validate<T>(status: StatusCode, response: T, strict: boolean) {\n const parser = this.get(status);\n if (!parser) {\n if (!strict) {\n return response;\n }\n throw new AutomationError(\n `No schema parser registered for status code ${status} and 'requireSchema' is set to true`\n );\n }\n return parser.parse(response);\n }\n}\n\nexport function assertIsStatusCode(value: number): asserts value is StatusCode {\n const result = Object.values(StatusCodes)\n .map((it) => it.status as number)\n .includes(value);\n if (!result) {\n throw new AutomationError(\n `Expected status code ${value} to be a valid status code, but it is not a known HTTP codeF`\n );\n }\n}\n\nexport function IsStatusCode(value: number): value is StatusCode {\n return Object.values(StatusCodes)\n .map((it) => it.status as number)\n .includes(value);\n}\n","import { Fixture, LIFE_CYCLE } from \"@autometa/app\";\nimport { HTTPRequestBuilder, RequestHook, ResponseHook } from \"./http.builder\";\nimport { SchemaMap } from \"./schema.map\";\nimport { SchemaParser, StatusCode } from \"./types\";\n@Fixture(LIFE_CYCLE.Transient)\nexport class HTTP {\n #url: string;\n #route: string[] = [];\n #headers = new Map<string, string>();\n #requireSchema = false;\n #schemaMap: SchemaMap = new SchemaMap();\n #onBeforeSend: RequestHook[] = [];\n #onAfterSend: ResponseHook<unknown>[] = [];\n #allowPlainText = false;\n\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n\n url(url: string) {\n this.#url = url;\n return this;\n }\n\n sharedOnBeforeSend(hook: RequestHook) {\n this.#onBeforeSend.push(hook);\n return this;\n }\n\n sharedOnReceiveResponse(hook: ResponseHook<unknown>) {\n this.#onAfterSend.push(hook);\n return this;\n }\n\n onBeforeSend(hook: RequestHook) {\n return this.builder().onBeforeSend(hook);\n }\n\n onReceiveResponse(hook: ResponseHook<unknown>) {\n return this.builder().onReceivedResponse(hook);\n }\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 ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#schemaMap.register(parser, ...(args as any));\n return this;\n }\n\n schema(parser: SchemaParser, ...codes: StatusCode[]): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return this.builder().schema(parser, ...(args as any));\n }\n\n sharedRoute(...route: string[]) {\n this.#route.push(...route);\n return this;\n }\n\n param(name: string, value: string) {\n return this.builder().param(name, value);\n }\n\n params(dict: Record<string, string>) {\n return this.builder().params(dict);\n }\n\n data<T>(data: T) {\n return this.builder().data(data);\n }\n\n sharedHeader(name: string, value: string) {\n this.#headers.set(name, value);\n return this;\n }\n\n route(...route: (string | number | boolean)[]) {\n return this.builder().route(...route);\n }\n\n header<T>(name: string, value: T) {\n return this.builder().header(name, value);\n }\n\n headers(dict: Record<string, string>) {\n return this.builder().headers(dict);\n }\n\n get() {\n return this.builder().get();\n }\n\n private builder() {\n return new HTTPRequestBuilder(this.#schemaMap)\n .url(this.#url)\n .route(...this.#route)\n .allowPlainText(this.#allowPlainText)\n .headers(Object.fromEntries(this.#headers))\n .requireSchema(this.#requireSchema)\n .onBeforeSend(...this.#onBeforeSend)\n .onReceivedResponse(...this.#onAfterSend);\n }\n}\n"],"mappings":"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","names":["import_errors","axios","isJson","import_app","_url","_route","_headers","_requireSchema","_schemaMap","_onBeforeSend","_onAfterSend","_allowPlainText"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/http.builder.ts","../src/http.response.ts","../src/schema.map.ts","../src/http.ts"],"sourcesContent":["export * from \"./http.builder\";\nexport * from \"./http.response\";\nexport * from \"./types\";\nexport * from \"./schema.map\";\nexport * from \"./http\";\n","import { Fixture, LIFE_CYCLE } from \"@autometa/app\";\nimport { AutomationError } from \"@autometa/errors\";\nimport axios, { AxiosResponse, Method, ResponseType } from \"axios\";\nimport { plainToClass } from \"class-transformer\";\nimport { urlJoinP } from \"url-join-ts\";\nimport { HTTPResponse } from \"./http.response\";\nimport { SchemaMap } from \"./schema.map\";\nimport { SchemaParser, StatusCode } from \"./types\";\nimport isJson from \"@stdlib/assert-is-json\";\nimport { highlight } from \"cli-highlight\";\nexport type RequestState = {\n headers: Map<string, string>;\n params: Map<string, unknown>;\n url: string;\n route: string[];\n responseType: ResponseType | undefined;\n data: unknown;\n method: Method;\n get fullUrl(): string;\n};\n\nexport type RequestHook = (state: RequestState) => unknown;\nexport type ResponseHook<T> = (state: HTTPResponse<T>) => unknown;\n\n@Fixture(LIFE_CYCLE.Transient)\nexport class HTTPRequestBuilder {\n #headers = new Map<string, string>();\n #params = new Map<string, unknown>();\n #url: string;\n #route: string[] = [];\n #method: Method;\n #schemaMap = new SchemaMap();\n #responseType: ResponseType | undefined = \"json\";\n #data: unknown;\n #requireSchema = false;\n #allowPlainText = false;\n #onBeforeSend: RequestHook[] = [];\n #onAfterSend: ResponseHook<unknown>[] = [];\n constructor(map: SchemaMap) {\n this.#schemaMap = new SchemaMap().including(map);\n }\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n get currentState(): RequestState {\n const fullUrl = this.currentUrl;\n return {\n headers: this.#headers,\n params: this.#params,\n url: this.#url,\n route: this.#route,\n responseType: this.#responseType,\n data: this.#data,\n method: this.#method,\n fullUrl\n };\n }\n\n get currentUrl() {\n const params = Object.fromEntries(this.#params);\n return urlJoinP(this.#url, this.#route, params);\n }\n\n url(url: string) {\n this.#url = url;\n return this;\n }\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n schema(parser: SchemaParser, ...codes: number[]): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: number; to: number }[]\n ): HTTPRequestBuilder;\n\n schema(\n parser: SchemaParser,\n ...args: (number | { from: number; to: number })[]\n ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#schemaMap.register(parser, ...(args as any));\n return this;\n }\n\n onBeforeSend(...hook: RequestHook[]) {\n this.#onBeforeSend.push(...hook);\n return this;\n }\n\n onReceivedResponse(...hook: ResponseHook<unknown>[]) {\n this.#onAfterSend.push(...hook);\n return this;\n }\n\n route(...route: (string | number | boolean)[]) {\n this.#route.push(...route.map((it) => `${it}`));\n return this;\n }\n\n header<T>(name: string, value: T) {\n const val = Array.isArray(value) ? value.join(\",\") : `${value}`;\n this.#headers.set(name, val);\n return this;\n }\n\n headers(dict: Record<string, string>) {\n Object.entries(dict).forEach(([name, value]) =>\n this.#headers.set(name, value)\n );\n return this;\n }\n\n param<T>(name: string, value: T) {\n this.#params.set(name, value);\n return this;\n }\n\n params(dict: Record<string, unknown>) {\n Object.entries(dict).forEach(([name, value]) => this.param(name, value));\n return this;\n }\n\n data<T>(data: T) {\n this.#data = data;\n return this;\n }\n\n async post<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"POST\");\n }\n\n async get<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"GET\");\n }\n\n async delete<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"DELETE\");\n }\n\n async put<TReturn>(): Promise<HTTPResponse<TReturn>> {\n return this._request(\"PUT\");\n }\n\n private async _request<T>(method: Method) {\n this.#method = method;\n const url = this.currentUrl;\n const headers = this.#headers && Object.fromEntries(this.#headers);\n const responseType = this.#responseType;\n const data = this.#data;\n let response: AxiosResponse = undefined as unknown as AxiosResponse;\n let skipFailedAfterHooks = false;\n try {\n this.tryRunBeforeHooks();\n response = await axios({\n method,\n url,\n headers,\n data,\n responseType,\n validateStatus: function (status) {\n return status >= 100 && status < 500;\n },\n transformResponse: transformResponse.bind(null, this.#allowPlainText)\n });\n const instance = this.makeResponse<T>(response);\n\n skipFailedAfterHooks = true;\n this.tryRunAfterHooks<T>(instance);\n return instance;\n } catch (e) {\n if (response && !skipFailedAfterHooks) {\n const instance = this.createWrapper<T>(response);\n this.tryRunAfterHooks<T>(instance);\n }\n const error = e as Error;\n const message = `HTTP Client failed while while making request to ${url} with:\n* headers: ${JSON.stringify(headers, null, 2)}\n\n* data: ${data && JSON.stringify(data, null, 2)}`;\n throw new AutomationError(message, { cause: error });\n }\n }\n\n private tryRunBeforeHooks() {\n let index = 0;\n try {\n for (const hook of this.#onBeforeSend) {\n hook(this.currentState);\n index++;\n }\n } catch (e) {\n const error = e as Error;\n const message = `HTTP Client encountered an error while running 'onBeforeRequest' hooks at index ${index}`;\n throw new AutomationError(message, { cause: error });\n }\n }\n private tryRunAfterHooks<T>(response: HTTPResponse<T>) {\n let index = 0;\n try {\n for (const hook of this.#onAfterSend) {\n hook(response);\n index++;\n }\n } catch (e) {\n const error = e as Error;\n const message = `HTTP Client encountered an error while running 'onAfterRequest' hooks at index ${index}`;\n throw new AutomationError(message, { cause: error });\n }\n }\n makeResponse<T>(res: AxiosResponse) {\n const { status, data } = res;\n const parsed = this.validateSchemas<T>(status, data);\n return this.createWrapper<T>(res, parsed);\n }\n\n private createWrapper<T>(\n { status, statusText, headers, data }: AxiosResponse<T>,\n parsed?: T\n ) {\n const params = Object.fromEntries(this.#params);\n const url = urlJoinP(this.#url, this.#route, params);\n return plainToClass(HTTPResponse<T>, {\n status,\n statusText,\n headers,\n data: parsed ?? data,\n request: {\n url,\n validated: !!parsed,\n }\n });\n }\n\n private validateSchemas<T>(status: number, data: T): T {\n return this.#schemaMap.validate<T>(\n status as StatusCode,\n data,\n this.#requireSchema\n );\n }\n}\n\nfunction transformResponse(allowPlainText: boolean, data: string) {\n if (isJson(data)) {\n return JSON.parse(data);\n }\n if ([\"true\", \"false\"].includes(data)) {\n return JSON.parse(data);\n }\n if(/^\\d*\\.?\\d+$/.test(data)) {\n return Number(data);\n }\n if (allowPlainText) {\n return data;\n }\n const response = highlight(data, { language: \"html\" });\n const message = [\n `HTTP Client received a response which could not be parsed as JSON, and plain text responses were not configured for this request, Instead the body was:`,\n \" \",\n response\n ];\n throw new AutomationError(message.join(\"\\n\"));\n}\n","export class HTTPResponse<T> {\n status: number;\n statusText: string;\n data: T;\n headers: Record<string, string>;\n request: {\n url: string;\n validated: boolean;\n passedValidation: boolean\n };\n\n static fromRaw<T>(\n data: T,\n status: number,\n statusText: string,\n headers: Record<string, string>,\n url: string,\n validated: boolean,\n passedValidation: boolean\n ) {\n const response = new HTTPResponse<T>();\n response.data = data;\n response.status = status;\n response.statusText = statusText;\n response.headers = headers;\n response.request = {\n url,\n validated,\n passedValidation\n };\n return response;\n }\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: TDerived\n ): HTTPResponse<TDerived>;\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: (original: TOriginal) => TDerived\n ): HTTPResponse<TDerived>;\n static derive<TOriginal, TDerived>(\n original: HTTPResponse<TOriginal>,\n data: TDerived | ((original: TOriginal) => TDerived)\n ) {\n const response = new DerivedHTTPResponse<TDerived, TOriginal>();\n if (typeof data === \"function\") {\n const fn = data as (original: TOriginal) => TDerived;\n response.data = fn(original.data);\n } else {\n response.data = data;\n }\n response.status = original.status;\n response.statusText = original.statusText;\n response.headers = original.headers;\n response.request = original.request;\n response.actual = original as HTTPResponse<TOriginal>;\n return response;\n }\n}\n\nexport class DerivedHTTPResponse<T, K> extends HTTPResponse<T> {\n actual: HTTPResponse<K>;\n}\n","import { StatusCode, SchemaParser } from \"./types\";\nimport { AutomationError } from \"@autometa/errors\";\nimport { StatusCodes } from \"@autometa/status-codes\";\n\nexport class SchemaMap {\n #children: SchemaMap[] = [];\n #map: Map<StatusCode, SchemaParser> = new Map();\n register(\n parser: SchemaParser,\n ...codes: StatusCode[]\n ): (typeof parser)[\"parse\"];\n register(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): (typeof parser)[\"parse\"];\n register(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n args.forEach((arg) => {\n if (typeof arg === \"number\") {\n this.registerSingle(parser, arg);\n } else {\n this.registerRange(parser, arg);\n }\n });\n return parser.parse;\n }\n\n registerSingle(parser: SchemaParser, ...codes: StatusCode[]) {\n codes.forEach((code) => {\n if (this.#map.has(code)) {\n throw new AutomationError(\n `Status code ${code} is already registered with a parser`\n );\n }\n assertIsStatusCode(code);\n this.#map.set(code, parser);\n });\n }\n\n including(map: SchemaMap) {\n this.#children.includes(map);\n return this;\n }\n registerRange(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ) {\n range.forEach(({ from, to }) => {\n assertIsStatusCode(from);\n assertIsStatusCode(to);\n for (let i = from; i <= to; i++) {\n if (!IsStatusCode(i)) {\n continue;\n }\n if (this.#map.has(i)) {\n throw new AutomationError(\n `Status code ${i} is already registered with a parser`\n );\n }\n this.#map.set(i, parser);\n }\n });\n }\n\n get(status: StatusCode): SchemaParser | undefined {\n assertIsStatusCode(status);\n const local = this.#map.get(status);\n if (local) {\n return local;\n }\n const nested = this.#children.find((it) => it.#map.has(status));\n return nested?.get(status);\n }\n\n validate<T>(status: StatusCode, response: T, strict: boolean): T {\n const parser = this.get(status);\n if (!parser) {\n if (!strict) {\n return response;\n }\n throw new AutomationError(\n `No schema parser registered for status code ${status} and 'requireSchema' is set to true`\n );\n }\n return parser.parse(response) as T;\n }\n}\n\nexport function assertIsStatusCode(value: number): asserts value is StatusCode {\n const result = Object.values(StatusCodes)\n .map((it) => it.status as number)\n .includes(value);\n if (!result) {\n throw new AutomationError(\n `Expected status code ${value} to be a valid status code, but it is not a known HTTP codeF`\n );\n }\n}\n\nexport function IsStatusCode(value: number): value is StatusCode {\n return Object.values(StatusCodes)\n .map((it) => it.status as number)\n .includes(value);\n}\n","import { Fixture, LIFE_CYCLE } from \"@autometa/app\";\nimport { HTTPRequestBuilder, RequestHook, ResponseHook } from \"./http.builder\";\nimport { SchemaMap } from \"./schema.map\";\nimport { SchemaParser, StatusCode } from \"./types\";\n@Fixture(LIFE_CYCLE.Transient)\nexport class HTTP {\n #url: string;\n #route: string[] = [];\n #headers = new Map<string, string>();\n #requireSchema = false;\n #schemaMap: SchemaMap = new SchemaMap();\n #onBeforeSend: RequestHook[] = [];\n #onAfterSend: ResponseHook<unknown>[] = [];\n #allowPlainText = false;\n\n allowPlainText(value: boolean) {\n this.#allowPlainText = value;\n return this;\n }\n requireSchema(value: boolean) {\n this.#requireSchema = value;\n return this;\n }\n\n url(url: string) {\n this.#url = url;\n return this;\n }\n\n sharedOnBeforeSend(hook: RequestHook) {\n this.#onBeforeSend.push(hook);\n return this;\n }\n\n sharedOnReceiveResponse(hook: ResponseHook<unknown>) {\n this.#onAfterSend.push(hook);\n return this;\n }\n\n onBeforeSend(hook: RequestHook) {\n return this.builder().onBeforeSend(hook);\n }\n\n onReceiveResponse(hook: ResponseHook<unknown>) {\n return this.builder().onReceivedResponse(hook);\n }\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 ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.#schemaMap.register(parser, ...(args as any));\n return this;\n }\n\n schema(parser: SchemaParser, ...codes: StatusCode[]): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...range: { from: StatusCode; to: StatusCode }[]\n ): HTTPRequestBuilder;\n schema(\n parser: SchemaParser,\n ...args: (StatusCode | { from: StatusCode; to: StatusCode })[]\n ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return this.builder().schema(parser, ...(args as any));\n }\n\n sharedRoute(...route: string[]) {\n this.#route.push(...route);\n return this;\n }\n\n param(name: string, value: string) {\n return this.builder().param(name, value);\n }\n\n params(dict: Record<string, string>) {\n return this.builder().params(dict);\n }\n\n data<T>(data: T) {\n return this.builder().data(data);\n }\n\n sharedHeader(name: string, value: string) {\n this.#headers.set(name, value);\n return this;\n }\n\n route(...route: (string | number | boolean)[]) {\n return this.builder().route(...route);\n }\n\n header<T>(name: string, value: T) {\n return this.builder().header(name, value);\n }\n\n headers(dict: Record<string, string>) {\n return this.builder().headers(dict);\n }\n\n get() {\n return this.builder().get();\n }\n\n private builder() {\n return new HTTPRequestBuilder(this.#schemaMap)\n .url(this.#url)\n .route(...this.#route)\n .allowPlainText(this.#allowPlainText)\n .headers(Object.fromEntries(this.#headers))\n .requireSchema(this.#requireSchema)\n .onBeforeSend(...this.#onBeforeSend)\n .onReceivedResponse(...this.#onAfterSend);\n }\n}\n"],"mappings":"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","names":["import_errors","axios","isJson","import_app","_url","_route","_headers","_requireSchema","_schemaMap","_onBeforeSend","_onAfterSend","_allowPlainText"]}
|