@hyperttp/core 1.1.12 → 1.2.5
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/Core/HyperCore.d.ts +21 -9
- package/Core/HyperCore.d.ts.map +1 -1
- package/Core/HyperCore.js +187 -116
- package/Core/HyperCore.js.map +1 -1
- package/Core/index.d.ts +0 -1
- package/Core/index.d.ts.map +1 -1
- package/Core/index.js +0 -1
- package/Core/index.js.map +1 -1
- package/LICENSE +21 -0
- package/README.md +178 -0
- package/defaultConfig.d.ts +1 -1
- package/defaultConfig.d.ts.map +1 -1
- package/defaultConfig.js +0 -1
- package/defaultConfig.js.map +1 -1
- package/index.d.ts +1 -4
- package/index.d.ts.map +1 -1
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/package.json +19 -6
- package/transports/node.d.ts +11 -7
- package/transports/node.d.ts.map +1 -1
- package/transports/node.js +367 -135
- package/transports/node.js.map +1 -1
- package/utils/errors.d.ts +49 -0
- package/utils/errors.d.ts.map +1 -0
- package/utils/errors.js +63 -0
- package/utils/errors.js.map +1 -0
- package/utils/merge.d.ts +8 -1
- package/utils/merge.d.ts.map +1 -1
- package/utils/merge.js +27 -13
- package/utils/merge.js.map +1 -1
- package/utils/pipeline.d.ts +42 -0
- package/utils/pipeline.d.ts.map +1 -0
- package/utils/pipeline.js +86 -0
- package/utils/pipeline.js.map +1 -0
- package/utils/response.d.ts +44 -0
- package/utils/response.d.ts.map +1 -0
- package/utils/response.js +86 -0
- package/utils/response.js.map +1 -0
- package/utils/retryUtils.d.ts +5 -0
- package/utils/retryUtils.d.ts.map +1 -0
- package/utils/retryUtils.js +35 -0
- package/utils/retryUtils.js.map +1 -0
- package/Core/RequestExecutor.d.ts +0 -64
- package/Core/RequestExecutor.d.ts.map +0 -1
- package/Core/RequestExecutor.js +0 -213
- package/Core/RequestExecutor.js.map +0 -1
- package/transports/bun.d.ts +0 -16
- package/transports/bun.d.ts.map +0 -1
- package/transports/bun.js +0 -181
- package/transports/bun.js.map +0 -1
- package/types/errors.d.ts +0 -20
- package/types/errors.d.ts.map +0 -1
- package/types/errors.js +0 -28
- package/types/errors.js.map +0 -1
- package/types/http.d.ts +0 -5
- package/types/http.d.ts.map +0 -1
- package/types/http.js +0 -2
- package/types/http.js.map +0 -1
- package/types/hyper.d.ts +0 -34
- package/types/hyper.d.ts.map +0 -1
- package/types/hyper.js +0 -2
- package/types/hyper.js.map +0 -1
- package/types/index.d.ts +0 -12
- package/types/index.d.ts.map +0 -1
- package/types/index.js +0 -12
- package/types/index.js.map +0 -1
- package/types/metrics.d.ts +0 -65
- package/types/metrics.d.ts.map +0 -1
- package/types/metrics.js +0 -2
- package/types/metrics.js.map +0 -1
- package/types/network.d.ts +0 -65
- package/types/network.d.ts.map +0 -1
- package/types/network.js +0 -2
- package/types/network.js.map +0 -1
- package/types/options.d.ts +0 -51
- package/types/options.d.ts.map +0 -1
- package/types/options.js +0 -2
- package/types/options.js.map +0 -1
- package/types/plugins.d.ts +0 -47
- package/types/plugins.d.ts.map +0 -1
- package/types/plugins.js +0 -2
- package/types/plugins.js.map +0 -1
- package/types/request.d.ts +0 -114
- package/types/request.d.ts.map +0 -1
- package/types/request.js +0 -2
- package/types/request.js.map +0 -1
- package/types/retry.d.ts +0 -28
- package/types/retry.d.ts.map +0 -1
- package/types/retry.js +0 -2
- package/types/retry.js.map +0 -1
- package/types/stream.d.ts +0 -39
- package/types/stream.d.ts.map +0 -1
- package/types/stream.js +0 -2
- package/types/stream.js.map +0 -1
- package/types/transport.d.ts +0 -25
- package/types/transport.d.ts.map +0 -1
- package/types/transport.js +0 -2
- package/types/transport.js.map +0 -1
package/utils/errors.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ru Базовый класс ошибок клиента Hyperttp, агрегирующий контекст неудачного сетевого запроса.
|
|
3
|
+
* @en Base error class for the Hyperttp client, providing explicit layout context for failed requests.
|
|
4
|
+
*/
|
|
5
|
+
export class HttpClientError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
statusCode;
|
|
8
|
+
originalError;
|
|
9
|
+
url;
|
|
10
|
+
method;
|
|
11
|
+
/**
|
|
12
|
+
* @ru Создает новый экземпляр HttpClientError.
|
|
13
|
+
* @en Creates a new HttpClientError instance.
|
|
14
|
+
* @param message - Human-readable error message text.
|
|
15
|
+
* @param code - Internal stringified error state identifier code.
|
|
16
|
+
* @param statusCode - Numerical HTTP response status code received from the server.
|
|
17
|
+
* @param originalError - Raw captured exception instance causing this failure.
|
|
18
|
+
* @param url - Targeted request URL destination string.
|
|
19
|
+
* @param method - HTTP method verb utilized for the request.
|
|
20
|
+
*/
|
|
21
|
+
constructor(message, code = "HTTP_ERROR", statusCode, originalError, url, method) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.code = code;
|
|
24
|
+
this.statusCode = statusCode;
|
|
25
|
+
this.originalError = originalError;
|
|
26
|
+
this.url = url;
|
|
27
|
+
this.method = method;
|
|
28
|
+
this.name = "HttpClientError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* @ru Ошибка, возникающая при превышении лимита времени ожидания ответа от сервера.
|
|
33
|
+
* @en Error thrown when a network request exceeds its allocated execution timeout threshold.
|
|
34
|
+
*/
|
|
35
|
+
export class TimeoutError extends HttpClientError {
|
|
36
|
+
/**
|
|
37
|
+
* @ru Создает новый экземпляр TimeoutError.
|
|
38
|
+
* @en Creates a new TimeoutError instance.
|
|
39
|
+
* @param url - Targeted request URL destination string.
|
|
40
|
+
* @param timeout - Threshold duration statement in milliseconds.
|
|
41
|
+
*/
|
|
42
|
+
constructor(url, timeout) {
|
|
43
|
+
super(`Timeout after ${timeout}ms`, "TIMEOUT", 408, undefined, url);
|
|
44
|
+
this.name = "TimeoutError";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* @ru Ошибка, генерируемая при получении HTTP-статуса 429 (превышение лимита частоты запросов).
|
|
49
|
+
* @en Error triggered when encountering an HTTP 429 status code indicating rate limit exhaustion.
|
|
50
|
+
*/
|
|
51
|
+
export class RateLimitError extends HttpClientError {
|
|
52
|
+
/**
|
|
53
|
+
* @ru Создает новый экземпляр RateLimitError.
|
|
54
|
+
* @en Creates a new RateLimitError instance.
|
|
55
|
+
* @param url - Targeted request URL destination string.
|
|
56
|
+
* @param retryAfter - Optional cool-down period duration in milliseconds before the next retry attempt.
|
|
57
|
+
*/
|
|
58
|
+
constructor(url, retryAfter) {
|
|
59
|
+
super(`Rate limited${retryAfter ? ` retry in ${retryAfter}ms` : ""}`, "RATE_LIMIT", 429, undefined, url);
|
|
60
|
+
this.name = "RateLimitError";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAa/B;IACA;IACA;IACA;IACA;IAhBT;;;;;;;;;OASG;IACH,YACE,OAAe,EACR,OAAe,YAAY,EAC3B,UAAmB,EACnB,aAAqB,EACrB,GAAY,EACZ,MAAe;QAEtB,KAAK,CAAC,OAAO,CAAC,CAAC;QANR,SAAI,GAAJ,IAAI,CAAuB;QAC3B,eAAU,GAAV,UAAU,CAAS;QACnB,kBAAa,GAAb,aAAa,CAAQ;QACrB,QAAG,GAAH,GAAG,CAAS;QACZ,WAAM,GAAN,MAAM,CAAS;QAGtB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,YAAa,SAAQ,eAAe;IAC/C;;;;;OAKG;IACH,YAAY,GAAW,EAAE,OAAe;QACtC,KAAK,CAAC,iBAAiB,OAAO,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,cAAe,SAAQ,eAAe;IACjD;;;;;OAKG;IACH,YAAY,GAAW,EAAE,UAAmB;QAC1C,KAAK,CACH,eAAe,UAAU,CAAC,CAAC,CAAC,aAAa,UAAU,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAC9D,YAAY,EACZ,GAAG,EACH,SAAS,EACT,GAAG,CACJ,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF"}
|
package/utils/merge.d.ts
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @ru Рекурсивно объединяет два объекта. Избегает лишних аллокаций памяти и защищает от разделения ссылок nested-структур.
|
|
3
|
+
* @en Recursively merges two objects. Avoids redundant memory allocations and prevents shared reference leakage for nested structures.
|
|
4
|
+
* @param target - Foundational target base object layout.
|
|
5
|
+
* @param source - High-priority source object containing overrides.
|
|
6
|
+
* @returns New deeply merged intersection object.
|
|
7
|
+
*/
|
|
8
|
+
export declare function deepMerge<T extends Record<string, unknown>, S extends Record<string, unknown>>(target: T, source: S): T & S;
|
|
2
9
|
//# sourceMappingURL=merge.d.ts.map
|
package/utils/merge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/utils/merge.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CACvB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/utils/merge.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAuB7B"}
|
package/utils/merge.js
CHANGED
|
@@ -1,25 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ru Рекурсивно объединяет два объекта. Избегает лишних аллокаций памяти и защищает от разделения ссылок nested-структур.
|
|
3
|
+
* @en Recursively merges two objects. Avoids redundant memory allocations and prevents shared reference leakage for nested structures.
|
|
4
|
+
* @param target - Foundational target base object layout.
|
|
5
|
+
* @param source - High-priority source object containing overrides.
|
|
6
|
+
* @returns New deeply merged intersection object.
|
|
7
|
+
*/
|
|
1
8
|
export function deepMerge(target, source) {
|
|
2
9
|
const output = { ...target };
|
|
3
10
|
if (isObject(target) && isObject(source)) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (
|
|
9
|
-
|
|
11
|
+
for (const key in source) {
|
|
12
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
13
|
+
const sourceValue = source[key];
|
|
14
|
+
const targetValue = output[key];
|
|
15
|
+
if (isObject(sourceValue)) {
|
|
16
|
+
if (key in output && isObject(targetValue)) {
|
|
17
|
+
output[key] = deepMerge(targetValue, sourceValue);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
output[key] = deepMerge({}, sourceValue);
|
|
21
|
+
}
|
|
10
22
|
}
|
|
11
|
-
else {
|
|
12
|
-
output[key] =
|
|
23
|
+
else if (sourceValue !== undefined) {
|
|
24
|
+
output[key] = sourceValue;
|
|
13
25
|
}
|
|
14
26
|
}
|
|
15
|
-
|
|
16
|
-
Object.assign(output, { [key]: sourceValue });
|
|
17
|
-
}
|
|
18
|
-
});
|
|
27
|
+
}
|
|
19
28
|
}
|
|
20
29
|
return output;
|
|
21
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* @ru Быстрая проверка, является ли переданный элемент чистым объектом (исключая массивы и null).
|
|
33
|
+
* @en Fast check verifying if the provided item is a plain object layout (excluding arrays and null).
|
|
34
|
+
* @param item - Evaluated runtime variable value context.
|
|
35
|
+
*/
|
|
22
36
|
function isObject(item) {
|
|
23
|
-
return
|
|
37
|
+
return typeof item === "object" && item !== null && !Array.isArray(item);
|
|
24
38
|
}
|
|
25
39
|
//# sourceMappingURL=merge.js.map
|
package/utils/merge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/utils/merge.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS,CAGvB,MAAS,EAAE,MAAS;IACpB,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/utils/merge.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAGvB,MAAS,EAAE,MAAS;IACpB,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,EAA6B,CAAC;IAExD,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;gBACtD,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;gBAChC,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;gBAEhC,IAAI,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC1B,IAAI,GAAG,IAAI,MAAM,IAAI,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;wBAC3C,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;oBACpD,CAAC;yBAAM,CAAC;wBACN,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;oBAC3C,CAAC;gBACH,CAAC;qBAAM,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;oBACrC,MAAM,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;gBAC5B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAe,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,SAAS,QAAQ,CAAC,IAAa;IAC7B,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { HyperPlugin, PluginContext, InternalRequest, HttpResponse, HyperttpError, HttpClientOptions } from "@hyperttp/types";
|
|
2
|
+
/**
|
|
3
|
+
* @ru Структура записи хука с метаданными для оптимизации и сортировки.
|
|
4
|
+
* @en Hook record structure with metadata for optimization and sorting.
|
|
5
|
+
*/
|
|
6
|
+
export interface HookRecord<T> {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly priority: number;
|
|
9
|
+
readonly run: T;
|
|
10
|
+
}
|
|
11
|
+
export interface PipelineContainer {
|
|
12
|
+
readonly request: HookRecord<Required<HyperPlugin>["onRequest"]>[];
|
|
13
|
+
readonly responseMutators: HookRecord<Required<HyperPlugin>["onResponse"]>[];
|
|
14
|
+
readonly responseSideEffects: HookRecord<Required<HyperPlugin>["onResponse"]>[];
|
|
15
|
+
readonly error: HookRecord<Required<HyperPlugin>["onError"]>[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* @ru Создает пустой контейнер для конвейеров плагинов.
|
|
19
|
+
* @en Creates an empty container for plugin pipelines.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createPipelines(): PipelineContainer;
|
|
22
|
+
/**
|
|
23
|
+
* @ru Вставляет хук в массив с сохранением сортировки по убыванию приоритета (деревья поиска тут избыточны).
|
|
24
|
+
* @en Inserts a hook into the array maintaining descending priority order.
|
|
25
|
+
*/
|
|
26
|
+
export declare function insertHookSorted<T>(list: HookRecord<T>[], hook: HookRecord<T>): void;
|
|
27
|
+
/**
|
|
28
|
+
* @ru Выполняет конвейер пред-запроса. Поддерживает short-circuit (ранний возврат ответа).
|
|
29
|
+
* @en Executes the pre-request pipeline. Supports short-circuiting.
|
|
30
|
+
*/
|
|
31
|
+
export declare function executeRequestPipeline(hooks: readonly HookRecord<Required<HyperPlugin>["onRequest"]>[], req: InternalRequest, ctx: PluginContext): Promise<HttpResponse<unknown> | null>;
|
|
32
|
+
/**
|
|
33
|
+
* @ru Выполняет конвейер пост-ответа. Разделен на мутаторы (последовательно) и сайд-эффекты (в фоне).
|
|
34
|
+
* @en Executes the post-response pipeline. Split into mutators (sequential) and side-effects (background).
|
|
35
|
+
*/
|
|
36
|
+
export declare function executeResponsePipeline(mutators: readonly HookRecord<Required<HyperPlugin>["onResponse"]>[], sideEffects: readonly HookRecord<Required<HyperPlugin>["onResponse"]>[], res: HttpResponse<unknown>, req: InternalRequest, ctx: PluginContext, logger?: HttpClientOptions["logger"]): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* @ru Выполняет конвейер перехвата ошибок. Первый вернувший HttpResponse плагин прерывает панику.
|
|
39
|
+
* @en Executes the error interception pipeline. First plugin to return HttpResponse stops the panic.
|
|
40
|
+
*/
|
|
41
|
+
export declare function executeErrorPipeline(hooks: readonly HookRecord<Required<HyperPlugin>["onError"]>[], error: HyperttpError, req: InternalRequest, ctx: PluginContext): Promise<HttpResponse<unknown> | null>;
|
|
42
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/utils/pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACb,eAAe,EACf,YAAY,EACZ,aAAa,EACb,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AAEzB;;;GAGG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;IACnE,QAAQ,CAAC,gBAAgB,EAAE,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;IAC7E,QAAQ,CAAC,mBAAmB,EAAE,UAAU,CACtC,QAAQ,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CACpC,EAAE,CAAC;IACJ,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;CAChE;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,iBAAiB,CAOnD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,EACrB,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAClB,IAAI,CAON;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,SAAS,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,EAChE,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAWvC;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,SAAS,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,EACpE,WAAW,EAAE,SAAS,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,EACvE,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC,EAC1B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,aAAa,EAClB,MAAM,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,GACnC,OAAO,CAAC,IAAI,CAAC,CAgCf;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,SAAS,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAC9D,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAWvC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ru Создает пустой контейнер для конвейеров плагинов.
|
|
3
|
+
* @en Creates an empty container for plugin pipelines.
|
|
4
|
+
*/
|
|
5
|
+
export function createPipelines() {
|
|
6
|
+
return {
|
|
7
|
+
request: [],
|
|
8
|
+
responseMutators: [],
|
|
9
|
+
responseSideEffects: [],
|
|
10
|
+
error: [],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* @ru Вставляет хук в массив с сохранением сортировки по убыванию приоритета (деревья поиска тут избыточны).
|
|
15
|
+
* @en Inserts a hook into the array maintaining descending priority order.
|
|
16
|
+
*/
|
|
17
|
+
export function insertHookSorted(list, hook) {
|
|
18
|
+
const len = list.length;
|
|
19
|
+
let i = 0;
|
|
20
|
+
while (i < len && list[i].priority >= hook.priority) {
|
|
21
|
+
i++;
|
|
22
|
+
}
|
|
23
|
+
list.splice(i, 0, hook);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* @ru Выполняет конвейер пред-запроса. Поддерживает short-circuit (ранний возврат ответа).
|
|
27
|
+
* @en Executes the pre-request pipeline. Supports short-circuiting.
|
|
28
|
+
*/
|
|
29
|
+
export async function executeRequestPipeline(hooks, req, ctx) {
|
|
30
|
+
const len = hooks.length;
|
|
31
|
+
if (len === 0)
|
|
32
|
+
return null;
|
|
33
|
+
for (let i = 0; i < len; i++) {
|
|
34
|
+
const shortCircuit = await hooks[i].run(req, ctx);
|
|
35
|
+
if (shortCircuit) {
|
|
36
|
+
return shortCircuit;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* @ru Выполняет конвейер пост-ответа. Разделен на мутаторы (последовательно) и сайд-эффекты (в фоне).
|
|
43
|
+
* @en Executes the post-response pipeline. Split into mutators (sequential) and side-effects (background).
|
|
44
|
+
*/
|
|
45
|
+
export async function executeResponsePipeline(mutators, sideEffects, res, req, ctx, logger) {
|
|
46
|
+
// 1. Запуск фоновых сайд-эффектов (Background Phase) - Fire and Forget безопасно для основного потока
|
|
47
|
+
const seLen = sideEffects.length;
|
|
48
|
+
if (seLen > 0) {
|
|
49
|
+
for (let i = 0; i < seLen; i++) {
|
|
50
|
+
const effect = sideEffects[i];
|
|
51
|
+
try {
|
|
52
|
+
const promise = effect.run(res, req, ctx);
|
|
53
|
+
if (promise && typeof promise.catch === "function") {
|
|
54
|
+
promise.catch((err) => logger?.("warn", `Background hook ${effect.name} crashed: ${err instanceof Error ? err.message : String(err)}`));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
logger?.("warn", `Sync background hook ${effect.name} crashed: ${err instanceof Error ? err.message : String(err)}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// 2. Запуск мутаторов ответа (Mutator Phase) - Изменяют объект ответа последовательно
|
|
63
|
+
const mutLen = mutators.length;
|
|
64
|
+
if (mutLen > 0) {
|
|
65
|
+
for (let i = 0; i < mutLen; i++) {
|
|
66
|
+
await mutators[i].run(res, req, ctx);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* @ru Выполняет конвейер перехвата ошибок. Первый вернувший HttpResponse плагин прерывает панику.
|
|
72
|
+
* @en Executes the error interception pipeline. First plugin to return HttpResponse stops the panic.
|
|
73
|
+
*/
|
|
74
|
+
export async function executeErrorPipeline(hooks, error, req, ctx) {
|
|
75
|
+
const len = hooks.length;
|
|
76
|
+
if (len === 0)
|
|
77
|
+
return null;
|
|
78
|
+
for (let i = 0; i < len; i++) {
|
|
79
|
+
const recovered = await hooks[i].run(error, req, ctx);
|
|
80
|
+
if (recovered) {
|
|
81
|
+
return recovered;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/utils/pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { HttpResponse, HyperTransport, StreamResponse } from "@hyperttp/types";
|
|
2
|
+
type TransportResponse = Awaited<ReturnType<HyperTransport["execute"]>>;
|
|
3
|
+
/**
|
|
4
|
+
* @ru Высокопроизводительный глубокий клон тела ответа. Безопасно пропускает стримы и буферы без мутации рантайма.
|
|
5
|
+
* @en High-performance deep clone for response payloads. Safely bypasses streams and buffers to prevent runtime state mutations.
|
|
6
|
+
* @param body - Targeted data or stream context to clone.
|
|
7
|
+
*/
|
|
8
|
+
export declare const cloneBodyFast: <T>(body: T) => T;
|
|
9
|
+
/**
|
|
10
|
+
* @ru Контекстный обработчик для создания независимого изолированного клона объекта HttpResponse.
|
|
11
|
+
* @en Contextual execution handler to generate an isolated deep clone of the HttpResponse instance.
|
|
12
|
+
*/
|
|
13
|
+
export declare function responseCloneHandler<T>(this: HttpResponse<T>): HttpResponse<T>;
|
|
14
|
+
/**
|
|
15
|
+
* @ru Быстрый маппинг сырого низкоуровневого ответа сетевого транспорта в плоский объект Hyperttp.
|
|
16
|
+
* @en Fast mapping from raw low-level network transport response into flat Hyperttp object layouts.
|
|
17
|
+
* @param rawResponse - Target instance returned by a transport executor.
|
|
18
|
+
*/
|
|
19
|
+
export declare const mapResponseFast: (rawResponse: TransportResponse) => {
|
|
20
|
+
status: number;
|
|
21
|
+
headers: Record<string, string | string[]>;
|
|
22
|
+
body: import("@hyperttp/types").TransportResponsePayload;
|
|
23
|
+
url: string;
|
|
24
|
+
clone: typeof responseCloneHandler;
|
|
25
|
+
json: <T = unknown>() => Promise<T>;
|
|
26
|
+
text: () => Promise<string>;
|
|
27
|
+
dump: () => Promise<void>;
|
|
28
|
+
data: null;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* @ru Быстрый маппинг сырого ответа транспорта в специализированный объект потокового ответа StreamResponse.
|
|
32
|
+
* @en Fast mapping from raw transport context into a specialized streaming response StreamResponse layout.
|
|
33
|
+
* @param rawResponse - Target instance returned by a transport executor.
|
|
34
|
+
*/
|
|
35
|
+
export declare const mapStreamFast: (rawResponse: TransportResponse) => StreamResponse<unknown>;
|
|
36
|
+
/**
|
|
37
|
+
* @ru Zero-allocation слияние заголовков. Полностью избегает вызовов `Object.keys()` и выделения массивов в куче.
|
|
38
|
+
* @en Zero-allocation headers merging layout. Completely avoids `Object.keys()` overhead and heavy heap array operations.
|
|
39
|
+
* @param base - Primary dictionary containing foundational header values.
|
|
40
|
+
* @param override - High-priority map containing overrides or additions.
|
|
41
|
+
*/
|
|
42
|
+
export declare const mergeHeadersFast: (base: Record<string, string | string[]>, override?: Record<string, string | string[]>) => Record<string, string | string[]>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../src/utils/response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,cAAc,EACf,MAAM,iBAAiB,CAAC;AAEzB,KAAK,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,MAAM,CAAC,KAAG,CAsB1C,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GACpB,YAAY,CAAC,CAAC,CAAC,CAWjB;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,aAAa,iBAAiB;;;;;;;;;;CAU5D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,aAAa,GACxB,aAAa,iBAAiB,KAC7B,cAAc,CAAC,OAAO,CAKvB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EACvC,WAAW,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,KAC3C,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CASlC,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ru Высокопроизводительный глубокий клон тела ответа. Безопасно пропускает стримы и буферы без мутации рантайма.
|
|
3
|
+
* @en High-performance deep clone for response payloads. Safely bypasses streams and buffers to prevent runtime state mutations.
|
|
4
|
+
* @param body - Targeted data or stream context to clone.
|
|
5
|
+
*/
|
|
6
|
+
export const cloneBodyFast = (body) => {
|
|
7
|
+
if (typeof body !== "object" || body === null)
|
|
8
|
+
return body;
|
|
9
|
+
const obj = body;
|
|
10
|
+
if (body instanceof Uint8Array ||
|
|
11
|
+
typeof obj.pipe === "function" ||
|
|
12
|
+
typeof obj.getReader === "function") {
|
|
13
|
+
return body;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
return structuredClone(body);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(JSON.stringify(body));
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return { ...body };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* @ru Контекстный обработчик для создания независимого изолированного клона объекта HttpResponse.
|
|
29
|
+
* @en Contextual execution handler to generate an isolated deep clone of the HttpResponse instance.
|
|
30
|
+
*/
|
|
31
|
+
export function responseCloneHandler() {
|
|
32
|
+
return {
|
|
33
|
+
status: this.status,
|
|
34
|
+
headers: { ...this.headers },
|
|
35
|
+
body: cloneBodyFast(this.body),
|
|
36
|
+
url: this.url,
|
|
37
|
+
clone: responseCloneHandler,
|
|
38
|
+
json: this.json,
|
|
39
|
+
text: this.text,
|
|
40
|
+
dump: this.dump,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* @ru Быстрый маппинг сырого низкоуровневого ответа сетевого транспорта в плоский объект Hyperttp.
|
|
45
|
+
* @en Fast mapping from raw low-level network transport response into flat Hyperttp object layouts.
|
|
46
|
+
* @param rawResponse - Target instance returned by a transport executor.
|
|
47
|
+
*/
|
|
48
|
+
export const mapResponseFast = (rawResponse) => ({
|
|
49
|
+
status: rawResponse.status,
|
|
50
|
+
headers: rawResponse.headers,
|
|
51
|
+
body: rawResponse.body,
|
|
52
|
+
url: rawResponse.url ?? "",
|
|
53
|
+
clone: responseCloneHandler,
|
|
54
|
+
json: rawResponse.json,
|
|
55
|
+
text: rawResponse.text,
|
|
56
|
+
dump: rawResponse.dump,
|
|
57
|
+
data: null,
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* @ru Быстрый маппинг сырого ответа транспорта в специализированный объект потокового ответа StreamResponse.
|
|
61
|
+
* @en Fast mapping from raw transport context into a specialized streaming response StreamResponse layout.
|
|
62
|
+
* @param rawResponse - Target instance returned by a transport executor.
|
|
63
|
+
*/
|
|
64
|
+
export const mapStreamFast = (rawResponse) => ({
|
|
65
|
+
status: rawResponse.status,
|
|
66
|
+
headers: rawResponse.headers,
|
|
67
|
+
body: rawResponse.body,
|
|
68
|
+
url: rawResponse.url ?? "",
|
|
69
|
+
});
|
|
70
|
+
/**
|
|
71
|
+
* @ru Zero-allocation слияние заголовков. Полностью избегает вызовов `Object.keys()` и выделения массивов в куче.
|
|
72
|
+
* @en Zero-allocation headers merging layout. Completely avoids `Object.keys()` overhead and heavy heap array operations.
|
|
73
|
+
* @param base - Primary dictionary containing foundational header values.
|
|
74
|
+
* @param override - High-priority map containing overrides or additions.
|
|
75
|
+
*/
|
|
76
|
+
export const mergeHeadersFast = (base, override) => {
|
|
77
|
+
if (!override)
|
|
78
|
+
return base;
|
|
79
|
+
for (const key in override) {
|
|
80
|
+
if (Object.prototype.hasOwnProperty.call(override, key)) {
|
|
81
|
+
return { ...base, ...override };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return base;
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/utils/response.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAI,IAAO,EAAK,EAAE;IAC7C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAE3D,MAAM,GAAG,GAAG,IAA+B,CAAC;IAE5C,IACE,IAAI,YAAY,UAAU;QAC1B,OAAO,GAAG,CAAC,IAAI,KAAK,UAAU;QAC9B,OAAO,GAAG,CAAC,SAAS,KAAK,UAAU,EACnC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAM,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAGlC,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE;QAC5B,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;QAC9B,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,WAA8B,EAAE,EAAE,CAAC,CAAC;IAClE,MAAM,EAAE,WAAW,CAAC,MAAM;IAC1B,OAAO,EAAE,WAAW,CAAC,OAAO;IAC5B,IAAI,EAAE,WAAW,CAAC,IAAI;IACtB,GAAG,EAAE,WAAW,CAAC,GAAG,IAAI,EAAE;IAC1B,KAAK,EAAE,oBAAoB;IAC3B,IAAI,EAAE,WAAW,CAAC,IAAI;IACtB,IAAI,EAAE,WAAW,CAAC,IAAI;IACtB,IAAI,EAAE,WAAW,CAAC,IAAI;IACtB,IAAI,EAAE,IAAI;CACX,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,WAA8B,EACL,EAAE,CAAC,CAAC;IAC7B,MAAM,EAAE,WAAW,CAAC,MAAM;IAC1B,OAAO,EAAE,WAAW,CAAC,OAAO;IAC5B,IAAI,EAAE,WAAW,CAAC,IAAI;IACtB,GAAG,EAAE,WAAW,CAAC,GAAG,IAAI,EAAE;CAC3B,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,IAAuC,EACvC,QAA4C,EACT,EAAE;IACrC,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;YACxD,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { RetryOptions } from "@hyperttp/types";
|
|
2
|
+
export declare function calcDelay(attempt: number, retryOptions: RetryOptions): number;
|
|
3
|
+
export declare function drainBody(body: unknown): Promise<void>;
|
|
4
|
+
export declare function shouldRetry(status: number, retryOptions: RetryOptions): boolean;
|
|
5
|
+
//# sourceMappingURL=retryUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retryUtils.d.ts","sourceRoot":"","sources":["../../src/utils/retryUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAIpD,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,GAAG,MAAM,CAK7E;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB5D;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,GACzB,OAAO,CAQT"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const DEFAULT_RETRY_STATUS_CODES = [502, 503, 504];
|
|
2
|
+
export function calcDelay(attempt, retryOptions) {
|
|
3
|
+
const { baseDelay = 1000, maxDelay = 10000, jitter = true } = retryOptions;
|
|
4
|
+
const base = Math.min(baseDelay * 2 ** attempt, maxDelay);
|
|
5
|
+
return jitter ? base * (0.75 + Math.random() * 0.5) : base;
|
|
6
|
+
}
|
|
7
|
+
export async function drainBody(body) {
|
|
8
|
+
if (!body || typeof body !== "object")
|
|
9
|
+
return;
|
|
10
|
+
try {
|
|
11
|
+
const stream = body;
|
|
12
|
+
if (typeof stream.dump === "function") {
|
|
13
|
+
await stream.dump();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (typeof stream.resume === "function") {
|
|
17
|
+
stream.resume();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (typeof stream.destroy === "function") {
|
|
21
|
+
stream.destroy();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
//
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function shouldRetry(status, retryOptions) {
|
|
29
|
+
const codes = retryOptions.retryStatusCodes;
|
|
30
|
+
if (codes && codes.length > 0) {
|
|
31
|
+
return codes.includes(status);
|
|
32
|
+
}
|
|
33
|
+
return DEFAULT_RETRY_STATUS_CODES.includes(status);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=retryUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retryUtils.js","sourceRoot":"","sources":["../../src/utils/retryUtils.ts"],"names":[],"mappings":"AAEA,MAAM,0BAA0B,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEnD,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,YAA0B;IACnE,MAAM,EAAE,SAAS,GAAG,IAAI,EAAE,QAAQ,GAAG,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,YAAY,CAAC;IAE3E,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,IAAI,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC1D,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAa;IAC3C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO;IAE9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAA+B,CAAC;QAE/C,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACtC,MAAO,MAAM,CAAC,IAA4B,EAAE,CAAC;YAC7C,OAAO;QACT,CAAC;QAED,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACvC,MAAM,CAAC,MAAqB,EAAE,CAAC;YAChC,OAAO;QACT,CAAC;QAED,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;YACxC,MAAM,CAAC,OAAsB,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,EAAE;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,MAAc,EACd,YAA0B;IAE1B,MAAM,KAAK,GAAG,YAAY,CAAC,gBAAgB,CAAC;IAE5C,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,0BAA0B,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { Agent } from "undici";
|
|
2
|
-
import type { RetryOptions } from "../types/retry.js";
|
|
3
|
-
import type { LogLevel, ResponseType } from "../types/http.js";
|
|
4
|
-
import type { RequestMetrics } from "../types/metrics.js";
|
|
5
|
-
export type LowLevelResponse = {
|
|
6
|
-
status: number;
|
|
7
|
-
headers: Record<string, string | string[] | undefined>;
|
|
8
|
-
body: unknown;
|
|
9
|
-
url: string;
|
|
10
|
-
};
|
|
11
|
-
export interface InterceptorRequestConfig {
|
|
12
|
-
url: string;
|
|
13
|
-
method: string;
|
|
14
|
-
headers: Record<string, string | string[]>;
|
|
15
|
-
body: string | Buffer | undefined;
|
|
16
|
-
}
|
|
17
|
-
export interface DynamicInterceptor {
|
|
18
|
-
applyRequest(config: InterceptorRequestConfig): Promise<InterceptorRequestConfig>;
|
|
19
|
-
applyResponse(response: LowLevelResponse): Promise<LowLevelResponse>;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* @en Low-level request executor responsible for handling the actual HTTP lifecycle.
|
|
23
|
-
* @ru Низкоуровневый исполнитель запросов, отвечающий за полный цикл HTTP-жизни.
|
|
24
|
-
*/
|
|
25
|
-
export declare class RequestExecutor {
|
|
26
|
-
private agent;
|
|
27
|
-
private options;
|
|
28
|
-
private readonly redirectStatusCodes;
|
|
29
|
-
constructor(agent: Agent, options: {
|
|
30
|
-
timeout: number;
|
|
31
|
-
maxRetries: number;
|
|
32
|
-
followRedirects: boolean;
|
|
33
|
-
maxRedirects: number;
|
|
34
|
-
retryOptions: RetryOptions;
|
|
35
|
-
verbose?: boolean;
|
|
36
|
-
logger?: (level: LogLevel, message: string, meta?: unknown) => void;
|
|
37
|
-
});
|
|
38
|
-
/**
|
|
39
|
-
* @en Executes a raw HTTP request.
|
|
40
|
-
* @ru Выполняет "сырой" HTTP-запрос.
|
|
41
|
-
*/
|
|
42
|
-
execute(method: string, url: string, headers: Record<string, string | string[]>, body: string | Buffer | undefined, signal?: AbortSignal, metrics?: RequestMetrics, interceptors?: DynamicInterceptor, meta?: {
|
|
43
|
-
responseType?: ResponseType;
|
|
44
|
-
}): Promise<LowLevelResponse>;
|
|
45
|
-
get verbose(): boolean;
|
|
46
|
-
/**
|
|
47
|
-
* @en Calculates the delay for the next retry attempt using exponential backoff.
|
|
48
|
-
* @ru Вычисляет задержку для следующей попытки повтора.
|
|
49
|
-
*/
|
|
50
|
-
private calcDelay;
|
|
51
|
-
private sleep;
|
|
52
|
-
/**
|
|
53
|
-
* @en Ensures that the response body stream is properly closed to prevent memory leaks.
|
|
54
|
-
* @ru Гарантирует, что поток тела ответа корректно закрыт.
|
|
55
|
-
*/
|
|
56
|
-
private drainBody;
|
|
57
|
-
/**
|
|
58
|
-
* @en Checks if the status code should trigger a retry attempt.
|
|
59
|
-
* @ru Проверяет, должен ли данный статус-код вызывать повтор запроса.
|
|
60
|
-
*/
|
|
61
|
-
private shouldRetry;
|
|
62
|
-
private executeCore;
|
|
63
|
-
}
|
|
64
|
-
//# sourceMappingURL=RequestExecutor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RequestExecutor.d.ts","sourceRoot":"","sources":["../../src/Core/RequestExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAU,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC3C,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,CACV,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,wBAAwB,CAAC,CAAC;IACrC,aAAa,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACtE;AAkBD;;;GAGG;AACH,qBAAa,eAAe;IAIxB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,OAAO;IAJjB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsC;gBAGhE,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,eAAe,EAAE,OAAO,CAAC;QACzB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,YAAY,CAAC;QAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;KACrE;IAGH;;;OAGG;IACU,OAAO,CAClB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAC1C,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EACjC,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,kBAAkB,EACjC,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,YAAY,CAAA;KAAE,GACrC,OAAO,CAAC,gBAAgB,CAAC;IAc5B,IAAW,OAAO,IAAI,OAAO,CAE5B;IAED;;;OAGG;IACH,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,KAAK;IAIb;;;OAGG;YACW,SAAS;IAqBvB;;;OAGG;IACH,OAAO,CAAC,WAAW;YAQL,WAAW;CAsL1B"}
|