@hyperttp/core 1.4.7 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Core/HyperCore.d.ts +3 -15
- package/Core/HyperCore.d.ts.map +1 -1
- package/Core/HyperCore.js +2 -576
- package/Core/HyperCore.js.map +7 -1
- package/Core/RequestBuilder.d.ts +11 -0
- package/Core/RequestBuilder.d.ts.map +1 -0
- package/Core/RequestBuilder.js +2 -0
- package/Core/RequestBuilder.js.map +7 -0
- package/Core/index.js +2 -2
- package/Core/index.js.map +7 -1
- package/README.md +30 -0
- package/defaultConfig.d.ts.map +1 -1
- package/defaultConfig.js +2 -20
- package/defaultConfig.js.map +7 -1
- package/index.js +2 -3
- package/index.js.map +7 -1
- package/package.json +1 -1
- package/transports/browser.d.ts.map +1 -1
- package/transports/browser.js +2 -113
- package/transports/browser.js.map +7 -1
- package/transports/manager.d.ts +0 -33
- package/transports/manager.d.ts.map +1 -1
- package/transports/manager.js +7 -349
- package/transports/manager.js.map +7 -1
- package/transports/node.d.ts +1 -0
- package/transports/node.d.ts.map +1 -1
- package/transports/node.js +2 -380
- package/transports/node.js.map +7 -1
- package/utils/errors.d.ts +0 -11
- package/utils/errors.d.ts.map +1 -1
- package/utils/errors.js +2 -53
- package/utils/errors.js.map +7 -1
- package/utils/merge.js +2 -29
- package/utils/merge.js.map +7 -1
- package/utils/normalize.d.ts +12 -7
- package/utils/normalize.d.ts.map +1 -1
- package/utils/normalize.js +2 -285
- package/utils/normalize.js.map +7 -1
- package/utils/pipeline.js +2 -193
- package/utils/pipeline.js.map +7 -1
- package/utils/response.d.ts +0 -14
- package/utils/response.d.ts.map +1 -1
- package/utils/response.js +2 -389
- package/utils/response.js.map +7 -1
- package/utils/retryUtils.js +2 -55
- package/utils/retryUtils.js.map +7 -1
package/utils/normalize.d.ts
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import type { Method, RequestBodyData } from "@hyperttp/types";
|
|
2
2
|
type NormalizedHeaders = Record<string, string | string[]>;
|
|
3
|
-
/**
|
|
4
|
-
* @ru Нормализует HTTP-метод в верхний регистр с кэшированием.
|
|
5
|
-
* @en Normalizes HTTP method to uppercase with caching.
|
|
6
|
-
* @param method - The HTTP method string (e.g., 'get', 'POST').
|
|
7
|
-
* @returns The normalized HTTP method in uppercase.
|
|
8
|
-
*/
|
|
9
|
-
export declare function normalizeMethod(method: string): Method;
|
|
10
3
|
/**
|
|
11
4
|
* @ru Извлекает URL из объекта запроса или строки.
|
|
12
5
|
* Поддерживает различные форматы: строка, объект с полем `url`, `_url`, или `scheme/host/path`.
|
|
@@ -48,5 +41,17 @@ export declare function normalizeHeaders(headers: unknown): NormalizedHeaders;
|
|
|
48
41
|
* @returns The body for methods that support it, or undefined for GET/HEAD.
|
|
49
42
|
*/
|
|
50
43
|
export declare function normalizeBody(method: Method, body: RequestBodyData | undefined): RequestBodyData | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* @ru Сериализует тело запроса для транспорта: plain objects → JSON,
|
|
46
|
+
* URLSearchParams → string, pass-through для остальных типов.
|
|
47
|
+
* Мутирует headers, выставляя content-type если не задан.
|
|
48
|
+
* @en Serializes request body for transport: plain objects → JSON,
|
|
49
|
+
* URLSearchParams → string, pass-through for other types.
|
|
50
|
+
* Mutates headers, setting content-type if not already set.
|
|
51
|
+
* @param body - The request body to normalize.
|
|
52
|
+
* @param headers - The request headers (mutated in place).
|
|
53
|
+
* @returns The transport-ready body.
|
|
54
|
+
*/
|
|
55
|
+
export declare function normalizeBodyForTransport(body: RequestBodyData, headers: Record<string, string | string[]>): RequestBodyData;
|
|
51
56
|
export {};
|
|
52
57
|
//# sourceMappingURL=normalize.d.ts.map
|
package/utils/normalize.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/utils/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE/D,KAAK,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/utils/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE/D,KAAK,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;AAkG3D;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAwBjD;AAoED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,iBAAiB,CAmDpE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,eAAe,GAAG,SAAS,GAChC,eAAe,GAAG,SAAS,CAE7B;AAWD;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GACzC,eAAe,CA8BjB"}
|
package/utils/normalize.js
CHANGED
|
@@ -1,285 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* Использует `Object.create(null)` для быстрого доступа без прототипа.
|
|
4
|
-
* @en Map of headers that should contain only a single value (not an array).
|
|
5
|
-
* Uses `Object.create(null)` for fast prototype-less access.
|
|
6
|
-
*/
|
|
7
|
-
const SINGLE_VALUE_HEADERS = Object.create(null);
|
|
8
|
-
for (const h of [
|
|
9
|
-
"content-type",
|
|
10
|
-
"content-length",
|
|
11
|
-
"content-encoding",
|
|
12
|
-
"content-disposition",
|
|
13
|
-
"host",
|
|
14
|
-
"authorization",
|
|
15
|
-
"proxy-authorization",
|
|
16
|
-
"user-agent",
|
|
17
|
-
"referer",
|
|
18
|
-
"origin",
|
|
19
|
-
"location",
|
|
20
|
-
"etag",
|
|
21
|
-
"last-modified",
|
|
22
|
-
]) {
|
|
23
|
-
SINGLE_VALUE_HEADERS[h] = 1;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* @ru Кэш нормализованных HTTP-методов для избежания повторных вызовов `toUpperCase()`.
|
|
27
|
-
* @en Cache of normalized HTTP methods to avoid repeated `toUpperCase()` calls.
|
|
28
|
-
*/
|
|
29
|
-
const METHOD_CACHE = {
|
|
30
|
-
get: "GET",
|
|
31
|
-
GET: "GET",
|
|
32
|
-
post: "POST",
|
|
33
|
-
POST: "POST",
|
|
34
|
-
put: "PUT",
|
|
35
|
-
PUT: "PUT",
|
|
36
|
-
delete: "DELETE",
|
|
37
|
-
DELETE: "DELETE",
|
|
38
|
-
patch: "PATCH",
|
|
39
|
-
PATCH: "PATCH",
|
|
40
|
-
head: "HEAD",
|
|
41
|
-
HEAD: "HEAD",
|
|
42
|
-
options: "OPTIONS",
|
|
43
|
-
OPTIONS: "OPTIONS",
|
|
44
|
-
};
|
|
45
|
-
/**
|
|
46
|
-
* @ru Кэш для нормализации ключей заголовков (lowercase).
|
|
47
|
-
* Ограничен размером HEADER_CACHE_LIMIT для предотвращения утечек памяти.
|
|
48
|
-
* @en Cache for header key normalization (lowercase).
|
|
49
|
-
* Limited by HEADER_CACHE_LIMIT to prevent memory leaks.
|
|
50
|
-
*/
|
|
51
|
-
const HEADER_CACHE_LIMIT = 2048;
|
|
52
|
-
const HEADER_KEY_CACHE = Object.create(null);
|
|
53
|
-
/**
|
|
54
|
-
* @ru Список наиболее распространённых HTTP-заголовков для предзаполнения кэша.
|
|
55
|
-
* @en List of most common HTTP headers for cache pre-population.
|
|
56
|
-
*/
|
|
57
|
-
const COMMON_HEADERS = [
|
|
58
|
-
"accept",
|
|
59
|
-
"accept-encoding",
|
|
60
|
-
"accept-language",
|
|
61
|
-
"authorization",
|
|
62
|
-
"cache-control",
|
|
63
|
-
"connection",
|
|
64
|
-
"content-encoding",
|
|
65
|
-
"content-length",
|
|
66
|
-
"content-type",
|
|
67
|
-
"cookie",
|
|
68
|
-
"date",
|
|
69
|
-
"etag",
|
|
70
|
-
"host",
|
|
71
|
-
"if-modified-since",
|
|
72
|
-
"if-none-match",
|
|
73
|
-
"keep-alive",
|
|
74
|
-
"location",
|
|
75
|
-
"origin",
|
|
76
|
-
"pragma",
|
|
77
|
-
"proxy-authorization",
|
|
78
|
-
"referer",
|
|
79
|
-
"sec-ch-ua",
|
|
80
|
-
"server",
|
|
81
|
-
"set-cookie",
|
|
82
|
-
"transfer-encoding",
|
|
83
|
-
"user-agent",
|
|
84
|
-
"x-forwarded-for",
|
|
85
|
-
"x-requested-with",
|
|
86
|
-
];
|
|
87
|
-
for (let i = 0; i < COMMON_HEADERS.length; i++) {
|
|
88
|
-
const lower = COMMON_HEADERS[i];
|
|
89
|
-
HEADER_KEY_CACHE[lower] = lower;
|
|
90
|
-
}
|
|
91
|
-
let cacheSize = COMMON_HEADERS.length;
|
|
92
|
-
/**
|
|
93
|
-
* @ru Быстрая нормализация ключа заголовка в нижний регистр с кэшированием.
|
|
94
|
-
* @en Fast header key normalization to lowercase with caching.
|
|
95
|
-
* @param key - The header key to normalize.
|
|
96
|
-
* @returns The lowercase version of the key.
|
|
97
|
-
*/
|
|
98
|
-
function fastLowercaseKey(key) {
|
|
99
|
-
const cached = HEADER_KEY_CACHE[key];
|
|
100
|
-
if (cached !== undefined)
|
|
101
|
-
return cached;
|
|
102
|
-
const lower = key.toLowerCase();
|
|
103
|
-
if (cacheSize < HEADER_CACHE_LIMIT) {
|
|
104
|
-
HEADER_KEY_CACHE[key] = lower;
|
|
105
|
-
cacheSize++;
|
|
106
|
-
}
|
|
107
|
-
return lower;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* @ru Нормализует HTTP-метод в верхний регистр с кэшированием.
|
|
111
|
-
* @en Normalizes HTTP method to uppercase with caching.
|
|
112
|
-
* @param method - The HTTP method string (e.g., 'get', 'POST').
|
|
113
|
-
* @returns The normalized HTTP method in uppercase.
|
|
114
|
-
*/
|
|
115
|
-
export function normalizeMethod(method) {
|
|
116
|
-
const cached = METHOD_CACHE[method];
|
|
117
|
-
return cached !== undefined ? cached : method.toUpperCase();
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* @ru Извлекает URL из объекта запроса или строки.
|
|
121
|
-
* Поддерживает различные форматы: строка, объект с полем `url`, `_url`, или `scheme/host/path`.
|
|
122
|
-
* @en Extracts URL from a request object or string.
|
|
123
|
-
* Supports various formats: string, object with `url`, `_url`, or `scheme/host/path` fields.
|
|
124
|
-
* @param req - The request object or URL string.
|
|
125
|
-
* @returns The extracted URL string.
|
|
126
|
-
* @throws Error if URL is missing in the request.
|
|
127
|
-
*/
|
|
128
|
-
export function normalizeUrl(req) {
|
|
129
|
-
if (typeof req === "string")
|
|
130
|
-
return req;
|
|
131
|
-
if (req && typeof req === "object") {
|
|
132
|
-
const r = req;
|
|
133
|
-
const url = r.url;
|
|
134
|
-
if (typeof url === "string")
|
|
135
|
-
return url;
|
|
136
|
-
if (url != null)
|
|
137
|
-
return String(url);
|
|
138
|
-
const u = r._url;
|
|
139
|
-
if (typeof u === "string")
|
|
140
|
-
return u;
|
|
141
|
-
if (u != null)
|
|
142
|
-
return String(u);
|
|
143
|
-
const scheme = r.scheme;
|
|
144
|
-
const host = r.host;
|
|
145
|
-
const path = r.path;
|
|
146
|
-
if (typeof scheme === "string" && typeof host === "string" && typeof path === "string") {
|
|
147
|
-
return `${scheme}://${host}${path}`;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
throw new Error("URL missing in request");
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* @ru Добавляет значение заголовка к нормализованному объекту заголовков.
|
|
154
|
-
* Учитывает специальные правила для `set-cookie`, `cookie`, и других заголовков.
|
|
155
|
-
* @en Appends a header value to the normalized headers object.
|
|
156
|
-
* Accounts for special rules for `set-cookie`, `cookie`, and other headers.
|
|
157
|
-
* @param out - The normalized headers object to modify.
|
|
158
|
-
* @param lowerKey - The lowercase header key.
|
|
159
|
-
* @param value - The header value to append.
|
|
160
|
-
*/
|
|
161
|
-
function appendHeader(out, lowerKey, value) {
|
|
162
|
-
if (SINGLE_VALUE_HEADERS[lowerKey] === 1) {
|
|
163
|
-
out[lowerKey] = value;
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
const existing = out[lowerKey];
|
|
167
|
-
if (existing === undefined) {
|
|
168
|
-
out[lowerKey] = lowerKey === "set-cookie" ? [value] : value;
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
if (lowerKey === "set-cookie") {
|
|
172
|
-
if (Array.isArray(existing)) {
|
|
173
|
-
existing.push(value);
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
out[lowerKey] = [existing, value];
|
|
177
|
-
}
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
if (lowerKey === "cookie" || lowerKey === "cookie2") {
|
|
181
|
-
out[lowerKey] = existing + "; " + value;
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
out[lowerKey] = existing + ", " + value;
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* @ru Добавляет сырое значение заголовка к нормализованному объекту.
|
|
188
|
-
* Обрабатывает массивы значений и преобразует нестроковые значения в строки.
|
|
189
|
-
* @en Appends a raw header value to the normalized headers object.
|
|
190
|
-
* Handles arrays of values and converts non-string values to strings.
|
|
191
|
-
* @param out - The normalized headers object to modify.
|
|
192
|
-
* @param lower - The lowercase header key.
|
|
193
|
-
* @param raw - The raw header value (string, array, or other).
|
|
194
|
-
*/
|
|
195
|
-
function appendRawValue(out, lower, raw) {
|
|
196
|
-
if (raw === undefined || raw === null)
|
|
197
|
-
return;
|
|
198
|
-
if (Array.isArray(raw)) {
|
|
199
|
-
const len = raw.length;
|
|
200
|
-
for (let i = 0; i < len; i++) {
|
|
201
|
-
const item = raw[i];
|
|
202
|
-
if (item !== undefined && item !== null) {
|
|
203
|
-
appendHeader(out, lower, typeof item === "string" ? item : String(item));
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
appendHeader(out, lower, typeof raw === "string" ? raw : String(raw));
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* @ru Нормализует заголовки запроса в единый формат с ключами в нижнем регистре.
|
|
212
|
-
* Поддерживает различные входные форматы: объект, массив пар, плоский массив.
|
|
213
|
-
*
|
|
214
|
-
* Специальные правила:
|
|
215
|
-
* - `set-cookie` всегда хранится как массив
|
|
216
|
-
* - `cookie`/`cookie2` объединяются через `; `
|
|
217
|
-
* - Остальные множественные заголовки объединяются через `, `
|
|
218
|
-
* - Заголовки из SINGLE_VALUE_HEADERS перезаписываются (не объединяются)
|
|
219
|
-
*
|
|
220
|
-
* @en Normalizes request headers into a unified format with lowercase keys.
|
|
221
|
-
* Supports various input formats: object, array of pairs, flat array.
|
|
222
|
-
*
|
|
223
|
-
* Special rules:
|
|
224
|
-
* - `set-cookie` is always stored as an array
|
|
225
|
-
* - `cookie`/`cookie2` are joined with `; `
|
|
226
|
-
* - Other multiple headers are joined with `, `
|
|
227
|
-
* - Headers from SINGLE_VALUE_HEADERS are overwritten (not merged)
|
|
228
|
-
*
|
|
229
|
-
* @param headers - The headers to normalize (object, array of pairs, or flat array).
|
|
230
|
-
* @returns Normalized headers object with lowercase keys.
|
|
231
|
-
*/
|
|
232
|
-
export function normalizeHeaders(headers) {
|
|
233
|
-
const out = Object.create(null);
|
|
234
|
-
if (!headers || typeof headers !== "object")
|
|
235
|
-
return out;
|
|
236
|
-
if (!Array.isArray(headers)) {
|
|
237
|
-
for (const key in headers) {
|
|
238
|
-
const val = headers[key];
|
|
239
|
-
if (val !== undefined && val !== null) {
|
|
240
|
-
appendRawValue(out, fastLowercaseKey(key), val);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
return out;
|
|
244
|
-
}
|
|
245
|
-
const len = headers.length;
|
|
246
|
-
if (len === 0)
|
|
247
|
-
return out;
|
|
248
|
-
if (Array.isArray(headers[0])) {
|
|
249
|
-
for (let i = 0; i < len; i++) {
|
|
250
|
-
const pair = headers[i];
|
|
251
|
-
if (!Array.isArray(pair))
|
|
252
|
-
continue;
|
|
253
|
-
const key = pair[0];
|
|
254
|
-
if (typeof key !== "string" || key.length === 0)
|
|
255
|
-
continue;
|
|
256
|
-
const rawValue = pair[1];
|
|
257
|
-
if (rawValue === undefined || rawValue === null)
|
|
258
|
-
continue;
|
|
259
|
-
appendHeader(out, fastLowercaseKey(key), typeof rawValue === "string" ? rawValue : String(rawValue));
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
else {
|
|
263
|
-
for (let i = 0; i < len; i += 2) {
|
|
264
|
-
const key = headers[i];
|
|
265
|
-
if (typeof key !== "string" || key.length === 0)
|
|
266
|
-
continue;
|
|
267
|
-
const rawValue = headers[i + 1];
|
|
268
|
-
if (rawValue === undefined || rawValue === null)
|
|
269
|
-
continue;
|
|
270
|
-
appendHeader(out, fastLowercaseKey(key), typeof rawValue === "string" ? rawValue : String(rawValue));
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
return out;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* @ru Нормализует тело запроса, удаляя его для методов GET и HEAD.
|
|
277
|
-
* @en Normalizes request body by removing it for GET and HEAD methods.
|
|
278
|
-
* @param method - The HTTP method.
|
|
279
|
-
* @param body - The request body data.
|
|
280
|
-
* @returns The body for methods that support it, or undefined for GET/HEAD.
|
|
281
|
-
*/
|
|
282
|
-
export function normalizeBody(method, body) {
|
|
283
|
-
return method === "GET" || method === "HEAD" ? undefined : body;
|
|
284
|
-
}
|
|
285
|
-
//# sourceMappingURL=normalize.js.map
|
|
1
|
+
"use strict";const p=Object.create(null);for(const n of["content-type","content-length","content-encoding","content-disposition","host","authorization","proxy-authorization","user-agent","referer","origin","location","etag","last-modified"])p[n]=1;const y=2048,a=Object.create(null),s=["accept","accept-encoding","accept-language","authorization","cache-control","connection","content-encoding","content-length","content-type","cookie","date","etag","host","if-modified-since","if-none-match","keep-alive","location","origin","pragma","proxy-authorization","referer","sec-ch-ua","server","set-cookie","transfer-encoding","user-agent","x-forwarded-for","x-requested-with"];for(let n=0;n<s.length;n++){const t=s[n];a[t]=t}let l=s.length;function u(n){const t=a[n];if(t!==void 0)return t;const e=n.toLowerCase();return l<y&&(a[n]=e,l++),e}export function normalizeUrl(n){if(typeof n=="string")return n;if(n&&typeof n=="object"){const t=n,e=t.url;if(typeof e=="string")return e;if(e!=null)return String(e);const i=t._url;if(typeof i=="string")return i;if(i!=null)return String(i);const r=t.scheme,o=t.host,c=t.path;if(typeof r=="string"&&typeof o=="string"&&typeof c=="string")return`${r}://${o}${c}`}throw new Error("URL missing in request")}function f(n,t,e){if(e=e.replace(/[\r\n]/g,""),p[t]===1){n[t]=e;return}const i=n[t];if(i===void 0){n[t]=t==="set-cookie"?[e]:e;return}if(t==="set-cookie"){Array.isArray(i)?i.push(e):n[t]=[i,e];return}if(t==="cookie"||t==="cookie2"){n[t]=i+"; "+e;return}n[t]=i+", "+e}function d(n,t,e){if(e!=null){if(Array.isArray(e)){const i=e.length;for(let r=0;r<i;r++){const o=e[r];o!=null&&f(n,t,typeof o=="string"?o:String(o))}return}f(n,t,typeof e=="string"?e:String(e))}}export function normalizeHeaders(n){const t=Object.create(null);if(!n||typeof n!="object")return t;if(!Array.isArray(n)){for(const i in n){const r=n[i];r!=null&&d(t,u(i),r)}return t}const e=n.length;if(e===0)return t;if(Array.isArray(n[0]))for(let i=0;i<e;i++){const r=n[i];if(!Array.isArray(r))continue;const o=r[0];if(typeof o!="string"||o.length===0)continue;const c=r[1];c!=null&&f(t,u(o),typeof c=="string"?c:String(c))}else for(let i=0;i<e;i+=2){const r=n[i];if(typeof r!="string"||r.length===0)continue;const o=n[i+1];o!=null&&f(t,u(r),typeof o=="string"?o:String(o))}return t}export function normalizeBody(n,t){return n==="GET"||n==="HEAD"?void 0:t}function g(n){const t=n["content-type"];if(typeof t=="string")return t;if(Array.isArray(t))return t[0]}export function normalizeBodyForTransport(n,t){return n==null?n:typeof URLSearchParams<"u"&&n instanceof URLSearchParams?(g(t)||(t["content-type"]="application/x-www-form-urlencoded"),n.toString()):typeof n=="object"&&n!==null&&!(n instanceof Uint8Array)&&!(n instanceof ArrayBuffer)&&!(typeof ArrayBuffer<"u"&&ArrayBuffer.isView?.(n))&&!(typeof URLSearchParams<"u"&&n instanceof URLSearchParams)&&!(typeof FormData<"u"&&n instanceof FormData)&&!(typeof Blob<"u"&&n instanceof Blob)&&!(typeof ReadableStream<"u"&&n instanceof ReadableStream)&&!("pipe"in n&&typeof n.pipe=="function")?(g(t)||(t["content-type"]="application/json"),JSON.stringify(n)):n}
|
|
2
|
+
//# sourceMappingURL=normalize.js.map
|
package/utils/normalize.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/normalize.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Method, RequestBodyData } from \"@hyperttp/types\";\n\ntype NormalizedHeaders = Record<string, string | string[]>;\n\n/**\n * @ru \u041A\u0430\u0440\u0442\u0430 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u043E\u0432, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u0434\u043E\u043B\u0436\u043D\u044B \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442\u044C \u0442\u043E\u043B\u044C\u043A\u043E \u043E\u0434\u043D\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 (\u043D\u0435 \u043C\u0430\u0441\u0441\u0438\u0432).\n * \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442 `Object.create(null)` \u0434\u043B\u044F \u0431\u044B\u0441\u0442\u0440\u043E\u0433\u043E \u0434\u043E\u0441\u0442\u0443\u043F\u0430 \u0431\u0435\u0437 \u043F\u0440\u043E\u0442\u043E\u0442\u0438\u043F\u0430.\n * @en Map of headers that should contain only a single value (not an array).\n * Uses `Object.create(null)` for fast prototype-less access.\n */\nconst SINGLE_VALUE_HEADERS: Record<string, 1> = Object.create(null);\nfor (const h of [\n \"content-type\",\n \"content-length\",\n \"content-encoding\",\n \"content-disposition\",\n \"host\",\n \"authorization\",\n \"proxy-authorization\",\n \"user-agent\",\n \"referer\",\n \"origin\",\n \"location\",\n \"etag\",\n \"last-modified\",\n] as const) {\n SINGLE_VALUE_HEADERS[h] = 1;\n}\n\n\n\n/**\n * @ru \u041A\u044D\u0448 \u0434\u043B\u044F \u043D\u043E\u0440\u043C\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u0438 \u043A\u043B\u044E\u0447\u0435\u0439 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u043E\u0432 (lowercase).\n * \u041E\u0433\u0440\u0430\u043D\u0438\u0447\u0435\u043D \u0440\u0430\u0437\u043C\u0435\u0440\u043E\u043C HEADER_CACHE_LIMIT \u0434\u043B\u044F \u043F\u0440\u0435\u0434\u043E\u0442\u0432\u0440\u0430\u0449\u0435\u043D\u0438\u044F \u0443\u0442\u0435\u0447\u0435\u043A \u043F\u0430\u043C\u044F\u0442\u0438.\n * @en Cache for header key normalization (lowercase).\n * Limited by HEADER_CACHE_LIMIT to prevent memory leaks.\n */\nconst HEADER_CACHE_LIMIT = 2048;\nconst HEADER_KEY_CACHE: Record<string, string> = Object.create(null);\n\n/**\n * @ru \u0421\u043F\u0438\u0441\u043E\u043A \u043D\u0430\u0438\u0431\u043E\u043B\u0435\u0435 \u0440\u0430\u0441\u043F\u0440\u043E\u0441\u0442\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0445 HTTP-\u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u043E\u0432 \u0434\u043B\u044F \u043F\u0440\u0435\u0434\u0437\u0430\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u044F \u043A\u044D\u0448\u0430.\n * @en List of most common HTTP headers for cache pre-population.\n */\nconst COMMON_HEADERS = [\n \"accept\",\n \"accept-encoding\",\n \"accept-language\",\n \"authorization\",\n \"cache-control\",\n \"connection\",\n \"content-encoding\",\n \"content-length\",\n \"content-type\",\n \"cookie\",\n \"date\",\n \"etag\",\n \"host\",\n \"if-modified-since\",\n \"if-none-match\",\n \"keep-alive\",\n \"location\",\n \"origin\",\n \"pragma\",\n \"proxy-authorization\",\n \"referer\",\n \"sec-ch-ua\",\n \"server\",\n \"set-cookie\",\n \"transfer-encoding\",\n \"user-agent\",\n \"x-forwarded-for\",\n \"x-requested-with\",\n] as const;\n\nfor (let i = 0; i < COMMON_HEADERS.length; i++) {\n const lower = COMMON_HEADERS[i]!;\n HEADER_KEY_CACHE[lower] = lower;\n}\n\nlet cacheSize = COMMON_HEADERS.length;\n\n/**\n * @ru \u0411\u044B\u0441\u0442\u0440\u0430\u044F \u043D\u043E\u0440\u043C\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u044F \u043A\u043B\u044E\u0447\u0430 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430 \u0432 \u043D\u0438\u0436\u043D\u0438\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u0441 \u043A\u044D\u0448\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435\u043C.\n * @en Fast header key normalization to lowercase with caching.\n * @param key - The header key to normalize.\n * @returns The lowercase version of the key.\n */\nfunction fastLowercaseKey(key: string): string {\n const cached = HEADER_KEY_CACHE[key];\n if (cached !== undefined) return cached;\n\n const lower = key.toLowerCase();\n if (cacheSize < HEADER_CACHE_LIMIT) {\n HEADER_KEY_CACHE[key] = lower;\n cacheSize++;\n }\n return lower;\n}\n\n/**\n * @ru \u0418\u0437\u0432\u043B\u0435\u043A\u0430\u0435\u0442 URL \u0438\u0437 \u043E\u0431\u044A\u0435\u043A\u0442\u0430 \u0437\u0430\u043F\u0440\u043E\u0441\u0430 \u0438\u043B\u0438 \u0441\u0442\u0440\u043E\u043A\u0438.\n * \u041F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u043B\u0438\u0447\u043D\u044B\u0435 \u0444\u043E\u0440\u043C\u0430\u0442\u044B: \u0441\u0442\u0440\u043E\u043A\u0430, \u043E\u0431\u044A\u0435\u043A\u0442 \u0441 \u043F\u043E\u043B\u0435\u043C `url`, `_url`, \u0438\u043B\u0438 `scheme/host/path`.\n * @en Extracts URL from a request object or string.\n * Supports various formats: string, object with `url`, `_url`, or `scheme/host/path` fields.\n * @param req - The request object or URL string.\n * @returns The extracted URL string.\n * @throws Error if URL is missing in the request.\n */\nexport function normalizeUrl(req: unknown): string {\n if (typeof req === \"string\") return req;\n\n if (req && typeof req === \"object\") {\n const r = req as Record<string, unknown>;\n\n const url = r.url;\n if (typeof url === \"string\") return url;\n if (url != null) return String(url);\n\n const u = r._url;\n if (typeof u === \"string\") return u;\n if (u != null) return String(u);\n\n const scheme = r.scheme;\n const host = r.host;\n const path = r.path;\n\n if (typeof scheme === \"string\" && typeof host === \"string\" && typeof path === \"string\") {\n return `${scheme}://${host}${path}`;\n }\n }\n\n throw new Error(\"URL missing in request\");\n}\n\n/**\n * @ru \u0414\u043E\u0431\u0430\u0432\u043B\u044F\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430 \u043A \u043D\u043E\u0440\u043C\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u043D\u043D\u043E\u043C\u0443 \u043E\u0431\u044A\u0435\u043A\u0442\u0443 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u043E\u0432.\n * \u0423\u0447\u0438\u0442\u044B\u0432\u0430\u0435\u0442 \u0441\u043F\u0435\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u0434\u043B\u044F `set-cookie`, `cookie`, \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u043E\u0432.\n * @en Appends a header value to the normalized headers object.\n * Accounts for special rules for `set-cookie`, `cookie`, and other headers.\n * @param out - The normalized headers object to modify.\n * @param lowerKey - The lowercase header key.\n * @param value - The header value to append.\n */\nfunction appendHeader(out: NormalizedHeaders, lowerKey: string, value: string): void {\n value = value.replace(/[\\r\\n]/g, \"\");\n if (SINGLE_VALUE_HEADERS[lowerKey] === 1) {\n out[lowerKey] = value;\n return;\n }\n\n const existing = out[lowerKey];\n\n if (existing === undefined) {\n out[lowerKey] = lowerKey === \"set-cookie\" ? [value] : value;\n return;\n }\n\n if (lowerKey === \"set-cookie\") {\n if (Array.isArray(existing)) {\n existing.push(value);\n } else {\n out[lowerKey] = [existing, value];\n }\n return;\n }\n\n if (lowerKey === \"cookie\" || lowerKey === \"cookie2\") {\n out[lowerKey] = existing + \"; \" + value;\n return;\n }\n\n out[lowerKey] = existing + \", \" + value;\n}\n\n/**\n * @ru \u0414\u043E\u0431\u0430\u0432\u043B\u044F\u0435\u0442 \u0441\u044B\u0440\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430 \u043A \u043D\u043E\u0440\u043C\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u043D\u043D\u043E\u043C\u0443 \u043E\u0431\u044A\u0435\u043A\u0442\u0443.\n * \u041E\u0431\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u0435\u0442 \u043C\u0430\u0441\u0441\u0438\u0432\u044B \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0438 \u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u043D\u0435\u0441\u0442\u0440\u043E\u043A\u043E\u0432\u044B\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u0432 \u0441\u0442\u0440\u043E\u043A\u0438.\n * @en Appends a raw header value to the normalized headers object.\n * Handles arrays of values and converts non-string values to strings.\n * @param out - The normalized headers object to modify.\n * @param lower - The lowercase header key.\n * @param raw - The raw header value (string, array, or other).\n */\nfunction appendRawValue(out: NormalizedHeaders, lower: string, raw: unknown): void {\n if (raw === undefined || raw === null) return;\n\n if (Array.isArray(raw)) {\n const len = raw.length;\n for (let i = 0; i < len; i++) {\n const item = raw[i];\n if (item !== undefined && item !== null) {\n appendHeader(out, lower, typeof item === \"string\" ? item : String(item));\n }\n }\n return;\n }\n\n appendHeader(out, lower, typeof raw === \"string\" ? raw : String(raw));\n}\n\n/**\n * @ru \u041D\u043E\u0440\u043C\u0430\u043B\u0438\u0437\u0443\u0435\u0442 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0438 \u0437\u0430\u043F\u0440\u043E\u0441\u0430 \u0432 \u0435\u0434\u0438\u043D\u044B\u0439 \u0444\u043E\u0440\u043C\u0430\u0442 \u0441 \u043A\u043B\u044E\u0447\u0430\u043C\u0438 \u0432 \u043D\u0438\u0436\u043D\u0435\u043C \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0435.\n * \u041F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u043B\u0438\u0447\u043D\u044B\u0435 \u0432\u0445\u043E\u0434\u043D\u044B\u0435 \u0444\u043E\u0440\u043C\u0430\u0442\u044B: \u043E\u0431\u044A\u0435\u043A\u0442, \u043C\u0430\u0441\u0441\u0438\u0432 \u043F\u0430\u0440, \u043F\u043B\u043E\u0441\u043A\u0438\u0439 \u043C\u0430\u0441\u0441\u0438\u0432.\n *\n * \u0421\u043F\u0435\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u0430:\n * - `set-cookie` \u0432\u0441\u0435\u0433\u0434\u0430 \u0445\u0440\u0430\u043D\u0438\u0442\u0441\u044F \u043A\u0430\u043A \u043C\u0430\u0441\u0441\u0438\u0432\n * - `cookie`/`cookie2` \u043E\u0431\u044A\u0435\u0434\u0438\u043D\u044F\u044E\u0442\u0441\u044F \u0447\u0435\u0440\u0435\u0437 `; `\n * - \u041E\u0441\u0442\u0430\u043B\u044C\u043D\u044B\u0435 \u043C\u043D\u043E\u0436\u0435\u0441\u0442\u0432\u0435\u043D\u043D\u044B\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0438 \u043E\u0431\u044A\u0435\u0434\u0438\u043D\u044F\u044E\u0442\u0441\u044F \u0447\u0435\u0440\u0435\u0437 `, `\n * - \u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0438 \u0438\u0437 SINGLE_VALUE_HEADERS \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0438\u0441\u044B\u0432\u0430\u044E\u0442\u0441\u044F (\u043D\u0435 \u043E\u0431\u044A\u0435\u0434\u0438\u043D\u044F\u044E\u0442\u0441\u044F)\n *\n * @en Normalizes request headers into a unified format with lowercase keys.\n * Supports various input formats: object, array of pairs, flat array.\n *\n * Special rules:\n * - `set-cookie` is always stored as an array\n * - `cookie`/`cookie2` are joined with `; `\n * - Other multiple headers are joined with `, `\n * - Headers from SINGLE_VALUE_HEADERS are overwritten (not merged)\n *\n * @param headers - The headers to normalize (object, array of pairs, or flat array).\n * @returns Normalized headers object with lowercase keys.\n */\nexport function normalizeHeaders(headers: unknown): NormalizedHeaders {\n const out: NormalizedHeaders = Object.create(null);\n if (!headers || typeof headers !== \"object\") return out;\n\n if (!Array.isArray(headers)) {\n for (const key in headers) {\n const val = (headers as Record<string, unknown>)[key];\n if (val !== undefined && val !== null) {\n appendRawValue(out, fastLowercaseKey(key), val);\n }\n }\n return out;\n }\n\n const len = headers.length;\n if (len === 0) return out;\n\n if (Array.isArray(headers[0])) {\n for (let i = 0; i < len; i++) {\n const pair = headers[i];\n if (!Array.isArray(pair)) continue;\n\n const key = pair[0];\n if (typeof key !== \"string\" || key.length === 0) continue;\n\n const rawValue = pair[1];\n if (rawValue === undefined || rawValue === null) continue;\n\n appendHeader(\n out,\n fastLowercaseKey(key),\n typeof rawValue === \"string\" ? rawValue : String(rawValue),\n );\n }\n } else {\n for (let i = 0; i < len; i += 2) {\n const key = headers[i];\n if (typeof key !== \"string\" || key.length === 0) continue;\n\n const rawValue = headers[i + 1];\n if (rawValue === undefined || rawValue === null) continue;\n\n appendHeader(\n out,\n fastLowercaseKey(key),\n typeof rawValue === \"string\" ? rawValue : String(rawValue),\n );\n }\n }\n\n return out;\n}\n\n/**\n * @ru \u041D\u043E\u0440\u043C\u0430\u043B\u0438\u0437\u0443\u0435\u0442 \u0442\u0435\u043B\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0430, \u0443\u0434\u0430\u043B\u044F\u044F \u0435\u0433\u043E \u0434\u043B\u044F \u043C\u0435\u0442\u043E\u0434\u043E\u0432 GET \u0438 HEAD.\n * @en Normalizes request body by removing it for GET and HEAD methods.\n * @param method - The HTTP method.\n * @param body - The request body data.\n * @returns The body for methods that support it, or undefined for GET/HEAD.\n */\nexport function normalizeBody(\n method: Method,\n body: RequestBodyData | undefined,\n): RequestBodyData | undefined {\n return method === \"GET\" || method === \"HEAD\" ? undefined : body;\n}\n\nfunction getContentType(\n headers: Record<string, string | string[]>,\n): string | undefined {\n const ct = headers[\"content-type\"];\n if (typeof ct === \"string\") return ct;\n if (Array.isArray(ct)) return ct[0];\n return undefined;\n}\n\n/**\n * @ru \u0421\u0435\u0440\u0438\u0430\u043B\u0438\u0437\u0443\u0435\u0442 \u0442\u0435\u043B\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0430 \u0434\u043B\u044F \u0442\u0440\u0430\u043D\u0441\u043F\u043E\u0440\u0442\u0430: plain objects \u2192 JSON,\n * URLSearchParams \u2192 string, pass-through \u0434\u043B\u044F \u043E\u0441\u0442\u0430\u043B\u044C\u043D\u044B\u0445 \u0442\u0438\u043F\u043E\u0432.\n * \u041C\u0443\u0442\u0438\u0440\u0443\u0435\u0442 headers, \u0432\u044B\u0441\u0442\u0430\u0432\u043B\u044F\u044F content-type \u0435\u0441\u043B\u0438 \u043D\u0435 \u0437\u0430\u0434\u0430\u043D.\n * @en Serializes request body for transport: plain objects \u2192 JSON,\n * URLSearchParams \u2192 string, pass-through for other types.\n * Mutates headers, setting content-type if not already set.\n * @param body - The request body to normalize.\n * @param headers - The request headers (mutated in place).\n * @returns The transport-ready body.\n */\nexport function normalizeBodyForTransport(\n body: RequestBodyData,\n headers: Record<string, string | string[]>,\n): RequestBodyData {\n if (body == null) return body;\n\n if (typeof URLSearchParams !== \"undefined\" && body instanceof URLSearchParams) {\n if (!getContentType(headers)) {\n headers[\"content-type\"] = \"application/x-www-form-urlencoded\";\n }\n return body.toString();\n }\n\n const isSerializableObject =\n typeof body === \"object\" &&\n body !== null &&\n !(body instanceof Uint8Array) &&\n !(body instanceof ArrayBuffer) &&\n !(typeof ArrayBuffer !== \"undefined\" && ArrayBuffer.isView?.(body)) &&\n !(typeof URLSearchParams !== \"undefined\" && body instanceof URLSearchParams) &&\n !(typeof FormData !== \"undefined\" && body instanceof FormData) &&\n !(typeof Blob !== \"undefined\" && body instanceof Blob) &&\n !(typeof ReadableStream !== \"undefined\" && body instanceof ReadableStream) &&\n !(\"pipe\" in body && typeof (body as any).pipe === \"function\");\n\n if (isSerializableObject) {\n if (!getContentType(headers)) {\n headers[\"content-type\"] = \"application/json\";\n }\n return JSON.stringify(body);\n }\n\n return body;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["SINGLE_VALUE_HEADERS", "h", "HEADER_CACHE_LIMIT", "HEADER_KEY_CACHE", "COMMON_HEADERS", "i", "lower", "cacheSize", "fastLowercaseKey", "key", "cached", "req", "r", "url", "u", "scheme", "host", "path", "appendHeader", "out", "lowerKey", "value", "existing", "appendRawValue", "raw", "len", "item", "headers", "val", "pair", "rawValue", "method", "body", "getContentType", "ct"]
|
|
7
|
+
}
|
package/utils/pipeline.js
CHANGED
|
@@ -1,193 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* @en Creates an empty container for plugin pipelines.
|
|
4
|
-
* @returns An empty pipeline container.
|
|
5
|
-
*/
|
|
6
|
-
export function createPipelines() {
|
|
7
|
-
return {
|
|
8
|
-
request: [],
|
|
9
|
-
responseData: [],
|
|
10
|
-
responseMutators: [],
|
|
11
|
-
responseSideEffects: [],
|
|
12
|
-
error: [],
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* @ru Вставляет хук в массив с сохранением сортировки по убыванию приоритета (деревья поиска тут избыточны).
|
|
17
|
-
* @en Inserts a hook into the array maintaining descending priority order.
|
|
18
|
-
* @param list - Target array to insert into.
|
|
19
|
-
* @param hook - Hook record to insert.
|
|
20
|
-
*/
|
|
21
|
-
export function insertHookSorted(list, hook) {
|
|
22
|
-
const len = list.length;
|
|
23
|
-
let i = 0;
|
|
24
|
-
while (i < len && list[i].priority >= hook.priority) {
|
|
25
|
-
i++;
|
|
26
|
-
}
|
|
27
|
-
list.splice(i, 0, hook);
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* @ru Выполняет конвейер пред-запроса. Поддерживает short-circuit.
|
|
31
|
-
* @en Executes the pre-request pipeline. Supports short-circuiting.
|
|
32
|
-
*/
|
|
33
|
-
export function executeRequestPipeline(hooks, req, ctx) {
|
|
34
|
-
const len = hooks.length;
|
|
35
|
-
if (len === 0)
|
|
36
|
-
return null;
|
|
37
|
-
for (let i = 0; i < len; i++) {
|
|
38
|
-
const hook = hooks[i];
|
|
39
|
-
const res = hook.run(req, ctx);
|
|
40
|
-
if (res !== null && res !== undefined) {
|
|
41
|
-
if (res instanceof Promise) {
|
|
42
|
-
return executeRequestPipelineAsync(hooks, req, ctx, i, res);
|
|
43
|
-
}
|
|
44
|
-
return res;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* @ru Выполняет низкоуровневый конвейер трансформации сырых данных транспорта (фаза DATA).
|
|
51
|
-
* @en Executes low-level transport data transformation pipeline (DATA phase).
|
|
52
|
-
*/
|
|
53
|
-
export function executeResponseDataPipeline(hooks, res, ctx) {
|
|
54
|
-
const len = hooks.length;
|
|
55
|
-
if (len === 0)
|
|
56
|
-
return res;
|
|
57
|
-
let currentRes = res;
|
|
58
|
-
for (let i = 0; i < len; i++) {
|
|
59
|
-
const result = hooks[i].run(currentRes, ctx);
|
|
60
|
-
if (result instanceof Promise) {
|
|
61
|
-
return executeResponseDataPipelineAsync(hooks, ctx, i, result, currentRes);
|
|
62
|
-
}
|
|
63
|
-
if (result != null) {
|
|
64
|
-
currentRes = result;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return currentRes;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* @ru Выполняет конвейер пост-ответа. Разделен на мутаторы и сайд-эффекты.
|
|
71
|
-
* @en Executes the post-response pipeline. Split into mutators and side-effects.
|
|
72
|
-
*/
|
|
73
|
-
export function executeResponsePipeline(mutators, sideEffects, res, req, ctx, logger) {
|
|
74
|
-
const seLen = sideEffects.length;
|
|
75
|
-
if (seLen > 0) {
|
|
76
|
-
for (let i = 0; i < seLen; i++) {
|
|
77
|
-
const effect = sideEffects[i];
|
|
78
|
-
try {
|
|
79
|
-
const promise = effect.run(res, req, ctx);
|
|
80
|
-
if (promise instanceof Promise) {
|
|
81
|
-
safelyAttachSideEffectCatch(promise, effect.name, logger);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch (err) {
|
|
85
|
-
handleSideEffectError(err, effect.name, logger);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
const mutLen = mutators.length;
|
|
90
|
-
if (mutLen > 0) {
|
|
91
|
-
for (let i = 0; i < mutLen; i++) {
|
|
92
|
-
const result = mutators[i].run(res, req, ctx);
|
|
93
|
-
if (result instanceof Promise) {
|
|
94
|
-
return executeMutatorsAsync(mutators, res, req, ctx, i, result);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* @ru Выполняет конвейер перехвата ошибок.
|
|
101
|
-
* @en Executes the error interception pipeline.
|
|
102
|
-
*/
|
|
103
|
-
export function executeErrorPipeline(hooks, error, req, ctx) {
|
|
104
|
-
const len = hooks.length;
|
|
105
|
-
if (len === 0)
|
|
106
|
-
return null;
|
|
107
|
-
for (let i = 0; i < len; i++) {
|
|
108
|
-
const res = hooks[i].run(error, req, ctx);
|
|
109
|
-
if (res instanceof Promise) {
|
|
110
|
-
return executeErrorPipelineAsync(hooks, error, req, ctx, i, res);
|
|
111
|
-
}
|
|
112
|
-
if (res != null)
|
|
113
|
-
return res;
|
|
114
|
-
}
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
async function executeRequestPipelineAsync(hooks, req, ctx, startIndex, initialPromise) {
|
|
118
|
-
const shortCircuit = await initialPromise;
|
|
119
|
-
if (shortCircuit != null)
|
|
120
|
-
return shortCircuit;
|
|
121
|
-
const len = hooks.length;
|
|
122
|
-
for (let i = startIndex + 1; i < len; i++) {
|
|
123
|
-
const res = hooks[i].run(req, ctx);
|
|
124
|
-
if (res instanceof Promise) {
|
|
125
|
-
const asyncRes = await res;
|
|
126
|
-
if (asyncRes != null)
|
|
127
|
-
return asyncRes;
|
|
128
|
-
}
|
|
129
|
-
else if (res != null) {
|
|
130
|
-
return res;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
async function executeResponseDataPipelineAsync(hooks, ctx, startIndex, initialPromise, lastRes) {
|
|
136
|
-
let currentRes = lastRes;
|
|
137
|
-
const firstAsyncResult = await initialPromise;
|
|
138
|
-
if (firstAsyncResult != null) {
|
|
139
|
-
currentRes = firstAsyncResult;
|
|
140
|
-
}
|
|
141
|
-
const len = hooks.length;
|
|
142
|
-
for (let i = startIndex + 1; i < len; i++) {
|
|
143
|
-
const result = hooks[i].run(currentRes, ctx);
|
|
144
|
-
if (result instanceof Promise) {
|
|
145
|
-
const asyncResult = await result;
|
|
146
|
-
if (asyncResult != null) {
|
|
147
|
-
currentRes = asyncResult;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
else if (result != null) {
|
|
151
|
-
currentRes = result;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return currentRes;
|
|
155
|
-
}
|
|
156
|
-
async function executeMutatorsAsync(mutators, res, req, ctx, startIndex, initialPromise) {
|
|
157
|
-
await initialPromise;
|
|
158
|
-
const len = mutators.length;
|
|
159
|
-
for (let i = startIndex + 1; i < len; i++) {
|
|
160
|
-
const result = mutators[i].run(res, req, ctx);
|
|
161
|
-
if (result instanceof Promise) {
|
|
162
|
-
await result;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
async function executeErrorPipelineAsync(hooks, error, req, ctx, startIndex, initialPromise) {
|
|
167
|
-
const recovered = await initialPromise;
|
|
168
|
-
if (recovered != null)
|
|
169
|
-
return recovered;
|
|
170
|
-
const len = hooks.length;
|
|
171
|
-
for (let i = startIndex + 1; i < len; i++) {
|
|
172
|
-
const res = hooks[i].run(error, req, ctx);
|
|
173
|
-
if (res instanceof Promise) {
|
|
174
|
-
const asyncRes = await res;
|
|
175
|
-
if (asyncRes != null)
|
|
176
|
-
return asyncRes;
|
|
177
|
-
}
|
|
178
|
-
else if (res != null) {
|
|
179
|
-
return res;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
function safelyAttachSideEffectCatch(promise, hookName, logger) {
|
|
185
|
-
promise.catch((err) => handleSideEffectError(err, hookName, logger));
|
|
186
|
-
}
|
|
187
|
-
function handleSideEffectError(err, hookName, logger) {
|
|
188
|
-
if (!logger)
|
|
189
|
-
return;
|
|
190
|
-
const errorObject = err instanceof Error ? err : new Error(String(err));
|
|
191
|
-
logger("warn", `Background hook "${hookName}" crashed: ${errorObject.message}`, errorObject);
|
|
192
|
-
}
|
|
193
|
-
//# sourceMappingURL=pipeline.js.map
|
|
1
|
+
"use strict";export function createPipelines(){return{request:[],responseData:[],responseMutators:[],responseSideEffects:[],error:[]}}export function insertHookSorted(e,r){const i=e.length;let n=0;for(;n<i&&e[n].priority>=r.priority;)n++;e.splice(n,0,r)}export function executeRequestPipeline(e,r,i){const n=e.length;if(n===0)return null;for(let c=0;c<n;c++){const t=e[c].run(r,i);if(t!=null)return t instanceof Promise?p(e,r,i,c,t):t}return null}export function executeResponseDataPipeline(e,r,i){const n=e.length;if(n===0)return r;let c=r;for(let s=0;s<n;s++){const t=e[s].run(c,i);if(t instanceof Promise)return y(e,i,s,t,c);t!=null&&(c=t)}return c}export function executeResponsePipeline(e,r,i,n,c,s){const t=r.length;if(t>0)for(let l=0;l<t;l++){const u=r[l];try{const f=u.run(i,n,c);f instanceof Promise&&w(f,u.name,s)}catch(f){a(f,u.name,s)}}const o=e.length;if(o>0)for(let l=0;l<o;l++){const u=e[l].run(i,n,c);if(u instanceof Promise)return P(e,i,n,c,l,u)}}export function executeErrorPipeline(e,r,i,n){const c=e.length;if(c===0)return null;for(let s=0;s<c;s++){const t=e[s].run(r,i,n);if(t instanceof Promise)return h(e,r,i,n,s,t);if(t!=null)return t}return null}async function p(e,r,i,n,c){const s=await c;if(s!=null)return s;const t=e.length;for(let o=n+1;o<t;o++){const l=e[o].run(r,i);if(l instanceof Promise){const u=await l;if(u!=null)return u}else if(l!=null)return l}return null}async function y(e,r,i,n,c){let s=c;const t=await n;t!=null&&(s=t);const o=e.length;for(let l=i+1;l<o;l++){const u=e[l].run(s,r);if(u instanceof Promise){const f=await u;f!=null&&(s=f)}else u!=null&&(s=u)}return s}async function P(e,r,i,n,c,s){await s;const t=e.length;for(let o=c+1;o<t;o++){const l=e[o].run(r,i,n);l instanceof Promise&&await l}}async function h(e,r,i,n,c,s){const t=await s;if(t!=null)return t;const o=e.length;for(let l=c+1;l<o;l++){const u=e[l].run(r,i,n);if(u instanceof Promise){const f=await u;if(f!=null)return f}else if(u!=null)return u}return null}function w(e,r,i){e.catch(n=>a(n,r,i))}function a(e,r,i){const n=e instanceof Error?e:new Error(String(e));i?i("warn",`Background hook "${r}" crashed: ${n.message}`,n):console.warn(`[Hyperttp] Background hook "${r}" crashed:`,n)}
|
|
2
|
+
//# sourceMappingURL=pipeline.js.map
|
package/utils/pipeline.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/pipeline.ts"],
|
|
4
|
+
"sourcesContent": ["import type {\n HyperPlugin,\n PluginContext,\n InternalRequest,\n HttpResponse,\n HyperttpError,\n HttpClientOptions,\n TransportResponse,\n} from \"@hyperttp/types\";\n\n/**\n * @ru \u0421\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u0430 \u0437\u0430\u043F\u0438\u0441\u0438 \u0445\u0443\u043A\u0430 \u0441 \u043C\u0435\u0442\u0430\u0434\u0430\u043D\u043D\u044B\u043C\u0438 \u0434\u043B\u044F \u043E\u043F\u0442\u0438\u043C\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u043A\u0438.\n * @en Hook record structure with metadata for optimization and sorting.\n */\nexport interface HookRecord<T> {\n /** @ru \u0423\u043D\u0438\u043A\u0430\u043B\u044C\u043D\u043E\u0435 \u0438\u043C\u044F \u0445\u0443\u043A\u0430. @en Unique hook name. */\n readonly name: string;\n /** @ru \u041F\u0440\u0438\u043E\u0440\u0438\u0442\u0435\u0442 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u044F (\u0432\u044B\u0448\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u2014 \u0440\u0430\u043D\u044C\u0448\u0435 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435). @en Execution priority (higher value runs earlier). */\n readonly priority: number;\n /** @ru \u0424\u0443\u043D\u043A\u0446\u0438\u044F-\u043E\u0431\u0440\u0430\u0431\u043E\u0442\u0447\u0438\u043A. @en Handler function. */\n readonly run: T;\n}\n\n/**\n * @ru \u041A\u043E\u043D\u0442\u0435\u0439\u043D\u0435\u0440 \u043A\u043E\u043D\u0432\u0435\u0439\u0435\u0440\u043E\u0432 \u0434\u043B\u044F \u0440\u0430\u0437\u043B\u0438\u0447\u043D\u044B\u0445 \u0444\u0430\u0437 \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0438 \u0437\u0430\u043F\u0440\u043E\u0441\u0430/\u043E\u0442\u0432\u0435\u0442\u0430.\n * @en Pipeline container for different request/response processing phases.\n */\nexport interface PipelineContainer {\n /** @ru \u0425\u0443\u043A\u0438, \u0432\u044B\u043F\u043E\u043B\u043D\u044F\u0435\u043C\u044B\u0435 \u043F\u0435\u0440\u0435\u0434 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u043E\u0439 \u0437\u0430\u043F\u0440\u043E\u0441\u0430. @en Hooks executed before sending the request. */\n readonly request: HookRecord<Required<HyperPlugin>[\"onRequest\"]>[];\n /** @ru \u0425\u0443\u043A\u0438, \u043E\u0431\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u044E\u0449\u0438\u0435 \u0441\u044B\u0440\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u0442\u0440\u0430\u043D\u0441\u043F\u043E\u0440\u0442\u0430. @en Hooks processing raw transport data. */\n readonly responseData: HookRecord<Required<HyperPlugin>[\"onResponseData\"]>[];\n /** @ru \u0425\u0443\u043A\u0438, \u043C\u0443\u0442\u0438\u0440\u0443\u044E\u0449\u0438\u0435 \u043E\u0442\u0432\u0435\u0442 (\u043F\u043E\u0441\u043B\u0435\u0434\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u043D\u043E\u0435 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435). @en Hooks that mutate the response (sequential execution). */\n readonly responseMutators: HookRecord<Required<HyperPlugin>[\"onResponse\"]>[];\n /** @ru \u0425\u0443\u043A\u0438 \u0441 \u043F\u043E\u0431\u043E\u0447\u043D\u044B\u043C\u0438 \u044D\u0444\u0444\u0435\u043A\u0442\u0430\u043C\u0438 (\u0432\u044B\u043F\u043E\u043B\u043D\u044F\u044E\u0442\u0441\u044F \u0432 \u0444\u043E\u043D\u0435). @en Side-effect hooks (executed in the background). */\n readonly responseSideEffects: HookRecord<Required<HyperPlugin>[\"onResponse\"]>[];\n /** @ru \u0425\u0443\u043A\u0438 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0430 \u043E\u0448\u0438\u0431\u043E\u043A. @en Error interception hooks. */\n readonly error: HookRecord<Required<HyperPlugin>[\"onError\"]>[];\n}\n\n/**\n * @ru \u0421\u043E\u0437\u0434\u0430\u0451\u0442 \u043F\u0443\u0441\u0442\u043E\u0439 \u043A\u043E\u043D\u0442\u0435\u0439\u043D\u0435\u0440 \u0434\u043B\u044F \u043A\u043E\u043D\u0432\u0435\u0439\u0435\u0440\u043E\u0432 \u043F\u043B\u0430\u0433\u0438\u043D\u043E\u0432.\n * @en Creates an empty container for plugin pipelines.\n * @returns An empty pipeline container.\n */\nexport function createPipelines(): PipelineContainer {\n return {\n request: [],\n responseData: [],\n responseMutators: [],\n responseSideEffects: [],\n error: [],\n };\n}\n\n/**\n * @ru \u0412\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u0442 \u0445\u0443\u043A \u0432 \u043C\u0430\u0441\u0441\u0438\u0432 \u0441 \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0435\u043C \u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u043A\u0438 \u043F\u043E \u0443\u0431\u044B\u0432\u0430\u043D\u0438\u044E \u043F\u0440\u0438\u043E\u0440\u0438\u0442\u0435\u0442\u0430 (\u0434\u0435\u0440\u0435\u0432\u044C\u044F \u043F\u043E\u0438\u0441\u043A\u0430 \u0442\u0443\u0442 \u0438\u0437\u0431\u044B\u0442\u043E\u0447\u043D\u044B).\n * @en Inserts a hook into the array maintaining descending priority order.\n * @param list - Target array to insert into.\n * @param hook - Hook record to insert.\n */\nexport function insertHookSorted<T>(list: HookRecord<T>[], hook: HookRecord<T>): void {\n const len = list.length;\n let i = 0;\n while (i < len && list[i]!.priority >= hook.priority) {\n i++;\n }\n list.splice(i, 0, hook);\n}\n\n/**\n * @ru \u0412\u044B\u043F\u043E\u043B\u043D\u044F\u0435\u0442 \u043A\u043E\u043D\u0432\u0435\u0439\u0435\u0440 \u043F\u0440\u0435\u0434-\u0437\u0430\u043F\u0440\u043E\u0441\u0430. \u041F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 short-circuit.\n * @en Executes the pre-request pipeline. Supports short-circuiting.\n */\nexport function executeRequestPipeline(\n hooks: readonly HookRecord<Required<HyperPlugin>[\"onRequest\"]>[],\n req: InternalRequest,\n ctx: PluginContext,\n): Promise<HttpResponse<unknown> | null> | HttpResponse<unknown> | null {\n const len = hooks.length;\n if (len === 0) return null;\n for (let i = 0; i < len; i++) {\n const hook = hooks[i]!;\n const res = hook.run(req, ctx);\n if (res !== null && res !== undefined) {\n if (res instanceof Promise) {\n return executeRequestPipelineAsync(hooks, req, ctx, i, res);\n }\n return res;\n }\n }\n return null;\n}\n\n/**\n * @ru \u0412\u044B\u043F\u043E\u043B\u043D\u044F\u0435\u0442 \u043D\u0438\u0437\u043A\u043E\u0443\u0440\u043E\u0432\u043D\u0435\u0432\u044B\u0439 \u043A\u043E\u043D\u0432\u0435\u0439\u0435\u0440 \u0442\u0440\u0430\u043D\u0441\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u0438 \u0441\u044B\u0440\u044B\u0445 \u0434\u0430\u043D\u043D\u044B\u0445 \u0442\u0440\u0430\u043D\u0441\u043F\u043E\u0440\u0442\u0430 (\u0444\u0430\u0437\u0430 DATA).\n * @en Executes low-level transport data transformation pipeline (DATA phase).\n */\nexport function executeResponseDataPipeline(\n hooks: readonly HookRecord<Required<HyperPlugin>[\"onResponseData\"]>[],\n res: TransportResponse,\n ctx: PluginContext,\n): Promise<TransportResponse> | TransportResponse {\n const len = hooks.length;\n if (len === 0) return res;\n let currentRes = res;\n for (let i = 0; i < len; i++) {\n const result = hooks[i]!.run(currentRes, ctx);\n if (result instanceof Promise) {\n return executeResponseDataPipelineAsync(hooks, ctx, i, result, currentRes);\n }\n if (result != null) {\n currentRes = result;\n }\n }\n return currentRes;\n}\n\n/**\n * @ru \u0412\u044B\u043F\u043E\u043B\u043D\u044F\u0435\u0442 \u043A\u043E\u043D\u0432\u0435\u0439\u0435\u0440 \u043F\u043E\u0441\u0442-\u043E\u0442\u0432\u0435\u0442\u0430. \u0420\u0430\u0437\u0434\u0435\u043B\u0435\u043D \u043D\u0430 \u043C\u0443\u0442\u0430\u0442\u043E\u0440\u044B \u0438 \u0441\u0430\u0439\u0434-\u044D\u0444\u0444\u0435\u043A\u0442\u044B.\n * @en Executes the post-response pipeline. Split into mutators and side-effects.\n */\nexport function executeResponsePipeline(\n mutators: readonly HookRecord<Required<HyperPlugin>[\"onResponse\"]>[],\n sideEffects: readonly HookRecord<Required<HyperPlugin>[\"onResponse\"]>[],\n res: HttpResponse<unknown>,\n req: InternalRequest,\n ctx: PluginContext,\n logger?: HttpClientOptions[\"logger\"],\n): Promise<void> | void {\n const seLen = sideEffects.length;\n if (seLen > 0) {\n for (let i = 0; i < seLen; i++) {\n const effect = sideEffects[i]!;\n try {\n const promise = effect.run(res, req, ctx);\n if (promise instanceof Promise) {\n safelyAttachSideEffectCatch(promise, effect.name, logger);\n }\n } catch (err) {\n handleSideEffectError(err, effect.name, logger);\n }\n }\n }\n const mutLen = mutators.length;\n if (mutLen > 0) {\n for (let i = 0; i < mutLen; i++) {\n const result = mutators[i]!.run(res, req, ctx);\n if (result instanceof Promise) {\n return executeMutatorsAsync(mutators, res, req, ctx, i, result);\n }\n }\n }\n}\n\n/**\n * @ru \u0412\u044B\u043F\u043E\u043B\u043D\u044F\u0435\u0442 \u043A\u043E\u043D\u0432\u0435\u0439\u0435\u0440 \u043F\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0430 \u043E\u0448\u0438\u0431\u043E\u043A.\n * @en Executes the error interception pipeline.\n */\nexport function executeErrorPipeline(\n hooks: readonly HookRecord<Required<HyperPlugin>[\"onError\"]>[],\n error: HyperttpError,\n req: InternalRequest,\n ctx: PluginContext,\n): Promise<HttpResponse<unknown> | null> | HttpResponse<unknown> | null {\n const len = hooks.length;\n if (len === 0) return null;\n for (let i = 0; i < len; i++) {\n const res = hooks[i]!.run(error, req, ctx);\n if (res instanceof Promise) {\n return executeErrorPipelineAsync(hooks, error, req, ctx, i, res);\n }\n if (res != null) return res;\n }\n return null;\n}\n\nasync function executeRequestPipelineAsync(\n hooks: readonly HookRecord<Required<HyperPlugin>[\"onRequest\"]>[],\n req: InternalRequest,\n ctx: PluginContext,\n startIndex: number,\n initialPromise: Promise<HttpResponse<unknown> | void>,\n): Promise<HttpResponse<unknown> | null> {\n const shortCircuit = await initialPromise;\n if (shortCircuit != null) return shortCircuit;\n const len = hooks.length;\n for (let i = startIndex + 1; i < len; i++) {\n const res = hooks[i]!.run(req, ctx);\n if (res instanceof Promise) {\n const asyncRes = await res;\n if (asyncRes != null) return asyncRes;\n } else if (res != null) {\n return res;\n }\n }\n return null;\n}\n\nasync function executeResponseDataPipelineAsync(\n hooks: readonly HookRecord<Required<HyperPlugin>[\"onResponseData\"]>[],\n ctx: PluginContext,\n startIndex: number,\n initialPromise: Promise<TransportResponse | void>,\n lastRes: TransportResponse,\n): Promise<TransportResponse> {\n let currentRes = lastRes;\n const firstAsyncResult = await initialPromise;\n if (firstAsyncResult != null) {\n currentRes = firstAsyncResult;\n }\n const len = hooks.length;\n for (let i = startIndex + 1; i < len; i++) {\n const result = hooks[i]!.run(currentRes, ctx);\n if (result instanceof Promise) {\n const asyncResult = await result;\n if (asyncResult != null) {\n currentRes = asyncResult;\n }\n } else if (result != null) {\n currentRes = result;\n }\n }\n return currentRes;\n}\n\nasync function executeMutatorsAsync(\n mutators: readonly HookRecord<Required<HyperPlugin>[\"onResponse\"]>[],\n res: HttpResponse<unknown>,\n req: InternalRequest,\n ctx: PluginContext,\n startIndex: number,\n initialPromise: Promise<unknown>,\n): Promise<void> {\n await initialPromise;\n const len = mutators.length;\n for (let i = startIndex + 1; i < len; i++) {\n const result = mutators[i]!.run(res, req, ctx);\n if (result instanceof Promise) {\n await result;\n }\n }\n}\n\nasync function executeErrorPipelineAsync(\n hooks: readonly HookRecord<Required<HyperPlugin>[\"onError\"]>[],\n error: HyperttpError,\n req: InternalRequest,\n ctx: PluginContext,\n startIndex: number,\n initialPromise: Promise<HttpResponse<unknown> | void>,\n): Promise<HttpResponse<unknown> | null> {\n const recovered = await initialPromise;\n if (recovered != null) return recovered;\n const len = hooks.length;\n for (let i = startIndex + 1; i < len; i++) {\n const res = hooks[i]!.run(error, req, ctx);\n if (res instanceof Promise) {\n const asyncRes = await res;\n if (asyncRes != null) return asyncRes;\n } else if (res != null) {\n return res;\n }\n }\n return null;\n}\n\nfunction safelyAttachSideEffectCatch(\n promise: Promise<unknown>,\n hookName: string,\n logger?: HttpClientOptions[\"logger\"],\n): void {\n promise.catch((err) => handleSideEffectError(err, hookName, logger));\n}\n\nfunction handleSideEffectError(\n err: unknown,\n hookName: string,\n logger?: HttpClientOptions[\"logger\"],\n): void {\n const errorObject = err instanceof Error ? err : new Error(String(err));\n if (logger) {\n logger(\"warn\", `Background hook \"${hookName}\" crashed: ${errorObject.message}`, errorObject);\n } else {\n console.warn(`[Hyperttp] Background hook \"${hookName}\" crashed:`, errorObject);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["list", "hook", "len", "i", "hooks", "req", "ctx", "res", "executeRequestPipelineAsync", "currentRes", "result", "executeResponseDataPipelineAsync", "mutators", "sideEffects", "logger", "seLen", "effect", "promise", "safelyAttachSideEffectCatch", "err", "handleSideEffectError", "mutLen", "executeMutatorsAsync", "error", "executeErrorPipelineAsync", "startIndex", "initialPromise", "shortCircuit", "asyncRes", "lastRes", "firstAsyncResult", "asyncResult", "recovered", "hookName", "errorObject"]
|
|
7
|
+
}
|