kinetex 1.3.0 → 1.4.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/README.md +246 -9
- package/dist/browser/kinetex.esm.js +38 -22
- package/dist/browser/kinetex.js +2545 -550
- package/dist/browser/kinetex.min.js +38 -22
- package/dist/cjs/aws-sigv4.js +133 -19
- package/dist/cjs/cache.js +49 -7
- package/dist/cjs/circuit-breaker.js +45 -3
- package/dist/cjs/client.js +387 -104
- package/dist/cjs/cookie-parser.js +103 -5
- package/dist/cjs/cookie-store.js +125 -28
- package/dist/cjs/core.js +465 -66
- package/dist/cjs/dedup.js +49 -11
- package/dist/cjs/digest.js +160 -24
- package/dist/cjs/graphql.js +164 -24
- package/dist/cjs/headers.js +303 -45
- package/dist/cjs/interceptors.js +221 -7
- package/dist/cjs/lifecycle.js +89 -40
- package/dist/cjs/logging.js +168 -15
- package/dist/cjs/mod.js +3 -2
- package/dist/cjs/pagination.js +247 -22
- package/dist/cjs/progress.js +177 -27
- package/dist/cjs/proxy.js +412 -0
- package/dist/cjs/response.js +316 -47
- package/dist/cjs/socks5.js +131 -15
- package/dist/cjs/sse.js +173 -43
- package/dist/cjs/url.js +191 -45
- package/dist/cjs/utils.js +222 -48
- package/dist/cjs/ws.js +19 -10
- package/dist/esm/aws-sigv4.js +133 -19
- package/dist/esm/aws-sigv4.js.map +1 -1
- package/dist/esm/cache.js +49 -7
- package/dist/esm/cache.js.map +1 -1
- package/dist/esm/circuit-breaker.js +45 -3
- package/dist/esm/circuit-breaker.js.map +1 -1
- package/dist/esm/client.js +387 -104
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/cookie-parser.js +103 -5
- package/dist/esm/cookie-parser.js.map +1 -1
- package/dist/esm/cookie-store.js +125 -28
- package/dist/esm/cookie-store.js.map +1 -1
- package/dist/esm/core.js +465 -66
- package/dist/esm/core.js.map +1 -1
- package/dist/esm/dedup.js +49 -11
- package/dist/esm/dedup.js.map +1 -1
- package/dist/esm/digest.js +160 -24
- package/dist/esm/digest.js.map +1 -1
- package/dist/esm/graphql.js +164 -24
- package/dist/esm/graphql.js.map +1 -1
- package/dist/esm/headers.js +303 -45
- package/dist/esm/headers.js.map +1 -1
- package/dist/esm/interceptors.js +221 -7
- package/dist/esm/interceptors.js.map +1 -1
- package/dist/esm/lifecycle.js +89 -40
- package/dist/esm/lifecycle.js.map +1 -1
- package/dist/esm/logging.js +168 -15
- package/dist/esm/logging.js.map +1 -1
- package/dist/esm/mod.js +3 -2
- package/dist/esm/mod.js.map +1 -1
- package/dist/esm/pagination.js +247 -22
- package/dist/esm/pagination.js.map +1 -1
- package/dist/esm/progress.js +177 -27
- package/dist/esm/progress.js.map +1 -1
- package/dist/esm/proxy.js +413 -0
- package/dist/esm/proxy.js.map +1 -0
- package/dist/esm/response.js +316 -47
- package/dist/esm/response.js.map +1 -1
- package/dist/esm/socks5.js +131 -15
- package/dist/esm/socks5.js.map +1 -1
- package/dist/esm/sse.js +173 -43
- package/dist/esm/sse.js.map +1 -1
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/url.js +191 -45
- package/dist/esm/url.js.map +1 -1
- package/dist/esm/utils.js +222 -48
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/ws.js +19 -10
- package/dist/esm/ws.js.map +1 -1
- package/dist/types/aws-sigv4.d.ts.map +1 -1
- package/dist/types/cache.d.ts +19 -1
- package/dist/types/cache.d.ts.map +1 -1
- package/dist/types/circuit-breaker.d.ts +14 -1
- package/dist/types/circuit-breaker.d.ts.map +1 -1
- package/dist/types/client.d.ts +69 -11
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/cookie-parser.d.ts +0 -17
- package/dist/types/cookie-parser.d.ts.map +1 -1
- package/dist/types/cookie-store.d.ts.map +1 -1
- package/dist/types/core.d.ts +103 -25
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/dedup.d.ts.map +1 -1
- package/dist/types/digest.d.ts +17 -37
- package/dist/types/digest.d.ts.map +1 -1
- package/dist/types/graphql.d.ts.map +1 -1
- package/dist/types/headers.d.ts +45 -27
- package/dist/types/headers.d.ts.map +1 -1
- package/dist/types/interceptors.d.ts +102 -0
- package/dist/types/interceptors.d.ts.map +1 -1
- package/dist/types/lifecycle.d.ts +19 -2
- package/dist/types/lifecycle.d.ts.map +1 -1
- package/dist/types/logging.d.ts +22 -3
- package/dist/types/logging.d.ts.map +1 -1
- package/dist/types/mod.d.ts +5 -3
- package/dist/types/mod.d.ts.map +1 -1
- package/dist/types/pagination.d.ts +0 -25
- package/dist/types/pagination.d.ts.map +1 -1
- package/dist/types/progress.d.ts +1 -1
- package/dist/types/progress.d.ts.map +1 -1
- package/dist/types/proxy.d.ts +50 -0
- package/dist/types/proxy.d.ts.map +1 -0
- package/dist/types/response.d.ts +7 -1
- package/dist/types/response.d.ts.map +1 -1
- package/dist/types/socks5.d.ts.map +1 -1
- package/dist/types/sse.d.ts.map +1 -1
- package/dist/types/types.d.ts +114 -3
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/url.d.ts +0 -14
- package/dist/types/url.d.ts.map +1 -1
- package/dist/types/utils.d.ts.map +1 -1
- package/dist/types/ws.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* §14 HTTP(S) CONNECT PROXY TUNNELING
|
|
3
|
+
*
|
|
4
|
+
* Establishes a TCP tunnel to a target host through an HTTP/HTTPS proxy using
|
|
5
|
+
* the `CONNECT` method (RFC 9110 §9.3.6), then optionally wraps that socket in
|
|
6
|
+
* TLS to the target.
|
|
7
|
+
*
|
|
8
|
+
* The tunnel is how an HTTP proxy must be used for HTTPS: the client sends
|
|
9
|
+
* only the CONNECT request line to the proxy, and from there the proxy is a
|
|
10
|
+
* blind byte relay. The target's certificate is therefore validated end to
|
|
11
|
+
* end against the target's own name — the proxy never terminates TLS, so it
|
|
12
|
+
* cannot impersonate the target without the CA store rejecting it.
|
|
13
|
+
*
|
|
14
|
+
* This module is Node-only by construction: it imports `node:net` and
|
|
15
|
+
* `node:tls`. Other runtimes route through their own `fetch` and must use a
|
|
16
|
+
* proxy-capable dispatcher instead.
|
|
17
|
+
*
|
|
18
|
+
* @module
|
|
19
|
+
*/
|
|
20
|
+
import { KinetexError } from "./types.js";
|
|
21
|
+
const DEFAULT_CONNECT_TIMEOUT_MS = 30_000;
|
|
22
|
+
/** Maximum CONNECT response head we will buffer before giving up. */
|
|
23
|
+
const MAX_HEAD_BYTES = 64 * 1024;
|
|
24
|
+
/**
|
|
25
|
+
* True when the proxy URL names a SOCKS proxy, which needs a different
|
|
26
|
+
* mechanism entirely (`createSocks5Tunnel` in `kinetex/socks5`).
|
|
27
|
+
*/
|
|
28
|
+
function isSocksProxy(url) {
|
|
29
|
+
return /^socks5h?:/i.test(url);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Build the `Proxy-Authorization` header value for Basic proxy auth.
|
|
33
|
+
*
|
|
34
|
+
* Uses the same encoding as the client's HTTP Basic auth. Returns `undefined`
|
|
35
|
+
* when no username was supplied — an empty username is still a deliberate
|
|
36
|
+
* (if unusual) credential, so it is encoded rather than skipped.
|
|
37
|
+
*/
|
|
38
|
+
function proxyAuthHeader(proxy) {
|
|
39
|
+
if (proxy.username === undefined)
|
|
40
|
+
return undefined;
|
|
41
|
+
const raw = `${proxy.username}:${proxy.password ?? ""}`;
|
|
42
|
+
const bytes = new TextEncoder().encode(raw);
|
|
43
|
+
let binary = "";
|
|
44
|
+
for (const b of bytes)
|
|
45
|
+
binary += String.fromCharCode(b);
|
|
46
|
+
const b64 = typeof globalThis.btoa === "function"
|
|
47
|
+
? globalThis.btoa(binary)
|
|
48
|
+
: // Node without btoa (or a non-Latin1 username) — encode explicitly.
|
|
49
|
+
Buffer.from(bytes).toString("base64");
|
|
50
|
+
return `Basic ${b64}`;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Parse a `CONNECT` response head.
|
|
54
|
+
*
|
|
55
|
+
* @returns The numeric status code, or `null` when the head is incomplete.
|
|
56
|
+
*/
|
|
57
|
+
function parseConnectStatus(head) {
|
|
58
|
+
const statusLine = head.split("\r\n", 1)[0] ?? "";
|
|
59
|
+
const match = /^HTTP\/1\.[01] (\d{3})(?: (.*))?$/.exec(statusLine);
|
|
60
|
+
if (!match)
|
|
61
|
+
return null;
|
|
62
|
+
return { status: Number(match[1]), reason: match[2] ?? "" };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Open a socket to a target host through an HTTP(S) proxy via `CONNECT`.
|
|
66
|
+
*
|
|
67
|
+
* Returns a socket connected to the **target** — already TLS-wrapped when the
|
|
68
|
+
* target is `https:`. The caller owns it and decides whether to pool it.
|
|
69
|
+
*
|
|
70
|
+
* @param proxy - Proxy URL and optional Basic credentials.
|
|
71
|
+
* @param target - Fully-resolved target URL.
|
|
72
|
+
* @param options - CA, timeout, and abort configuration.
|
|
73
|
+
* @returns A socket tunneled to the target.
|
|
74
|
+
* @throws {KinetexError} `EVALIDATION` for a SOCKS proxy or a malformed proxy
|
|
75
|
+
* URL, `EPROXYAUTH` when the proxy demands credentials, `EPROXY` for any
|
|
76
|
+
* other non-2xx CONNECT response, `ETIMEOUT` if the proxy never answers,
|
|
77
|
+
* `EABORT` if `signal` fires, and `ENETWORK` for socket/TLS failures.
|
|
78
|
+
*/
|
|
79
|
+
export async function connectThroughProxy(proxy, target, options = {}) {
|
|
80
|
+
// Built conditionally: `exactOptionalPropertyTypes` forbids passing an
|
|
81
|
+
// explicit `undefined` for an optional property.
|
|
82
|
+
const errMeta = options.request !== undefined ? { request: options.request } : {};
|
|
83
|
+
if (isSocksProxy(proxy.url)) {
|
|
84
|
+
throw new KinetexError(`proxy url "${proxy.url}" is a SOCKS proxy, which needs a different mechanism. ` +
|
|
85
|
+
"Use createSocks5Tunnel() from kinetex/socks5 and supply your own fetch over the tunnel.", "EVALIDATION", errMeta);
|
|
86
|
+
}
|
|
87
|
+
let proxyUrl;
|
|
88
|
+
try {
|
|
89
|
+
proxyUrl = new URL(proxy.url);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
throw new KinetexError(`proxy url "${proxy.url}" is not a valid URL`, "EVALIDATION", {
|
|
93
|
+
...errMeta,
|
|
94
|
+
cause: err,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
if (proxyUrl.protocol !== "http:" && proxyUrl.protocol !== "https:") {
|
|
98
|
+
throw new KinetexError(`proxy url scheme "${proxyUrl.protocol}" is not supported; use http:, https:, socks5: or socks5h:`, "EVALIDATION", errMeta);
|
|
99
|
+
}
|
|
100
|
+
const net = await import("node:net");
|
|
101
|
+
const tls = await import("node:tls");
|
|
102
|
+
const proxyPort = proxyUrl.port
|
|
103
|
+
? Number(proxyUrl.port)
|
|
104
|
+
: proxyUrl.protocol === "https:"
|
|
105
|
+
? 443
|
|
106
|
+
: 80;
|
|
107
|
+
const targetPort = target.port ? Number(target.port) : target.protocol === "https:" ? 443 : 80;
|
|
108
|
+
const authority = `${target.hostname}:${targetPort}`;
|
|
109
|
+
const timeoutMs = options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;
|
|
110
|
+
// ── 1. TCP (or TLS-to-proxy) connection to the proxy itself ───────────────
|
|
111
|
+
const baseSocket = proxyUrl.protocol === "https:"
|
|
112
|
+
? await openTlsSocket(tls, {
|
|
113
|
+
host: proxyUrl.hostname,
|
|
114
|
+
port: proxyPort,
|
|
115
|
+
servername: proxyUrl.hostname,
|
|
116
|
+
...(options.ca !== undefined ? { ca: options.ca } : {}),
|
|
117
|
+
}, timeoutMs, options.signal, errMeta, `proxy ${proxyUrl.host}`)
|
|
118
|
+
: await openTcpSocket(net, { host: proxyUrl.hostname, port: proxyPort }, timeoutMs, options.signal, errMeta, `proxy ${proxyUrl.host}`);
|
|
119
|
+
// ── 2. CONNECT handshake ─────────────────────────────────────────────────
|
|
120
|
+
const auth = proxyAuthHeader(proxy);
|
|
121
|
+
const connectLines = [
|
|
122
|
+
`CONNECT ${authority} HTTP/1.1`,
|
|
123
|
+
`Host: ${authority}`,
|
|
124
|
+
// RFC 9110 §9.3.6: proxies that support persistent tunnels are expected to
|
|
125
|
+
// treat a tunnel as still-open even without this, but sending it is what
|
|
126
|
+
// every real client does and some proxies misbehave without it.
|
|
127
|
+
"Proxy-Connection: Keep-Alive",
|
|
128
|
+
...(auth !== undefined ? [`Proxy-Authorization: ${auth}`] : []),
|
|
129
|
+
"",
|
|
130
|
+
"",
|
|
131
|
+
];
|
|
132
|
+
baseSocket.write(connectLines.join("\r\n"));
|
|
133
|
+
let head = "";
|
|
134
|
+
// TCP does not preserve write boundaries. A proxy that splits the 200 head
|
|
135
|
+
// across two writes and puts the target's first bytes in the second
|
|
136
|
+
// delivers the head terminator and the start of the tunnelled stream in a
|
|
137
|
+
// single read, so the tail is kept and put back rather than discarded --
|
|
138
|
+
// dropping it silently truncates the message the caller is about to read.
|
|
139
|
+
//
|
|
140
|
+
// The head is therefore read in PAUSED mode -- `on("readable")` plus
|
|
141
|
+
// `read()` -- and never with `on("data")`. `on("data")` switches the stream
|
|
142
|
+
// to flowing mode, and removing the last `data` listener does NOT switch it
|
|
143
|
+
// back, so a flowing socket with nothing attached silently DISCARDS the
|
|
144
|
+
// bytes after the head terminator. `unshift()` alone does not recover them
|
|
145
|
+
// either: a later `on("data")` sets `state.flowing = true` before calling
|
|
146
|
+
// `resume()`, and `resume()` only restarts the flow when flowing was
|
|
147
|
+
// previously false, so the socket stalls with the tail still buffered and
|
|
148
|
+
// the caller waits forever. Reading paused leaves the flow state unset, so
|
|
149
|
+
// whichever consumer comes next -- `on("data")`, `pipe()`, or
|
|
150
|
+
// `tls.connect({ socket })` -- starts the flow and sees the tail.
|
|
151
|
+
const headResult = await new Promise((resolve) => {
|
|
152
|
+
// Pull every buffered chunk into `head`; a null read means the buffer is
|
|
153
|
+
// drained and `readable` will fire again when more arrives.
|
|
154
|
+
const drain = () => {
|
|
155
|
+
for (;;) {
|
|
156
|
+
const chunk = baseSocket.read();
|
|
157
|
+
if (chunk === null)
|
|
158
|
+
return;
|
|
159
|
+
head += chunk.toString("latin1");
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
const onReadable = () => {
|
|
163
|
+
drain();
|
|
164
|
+
const end = head.indexOf("\r\n\r\n");
|
|
165
|
+
if (end === -1) {
|
|
166
|
+
if (head.length > MAX_HEAD_BYTES) {
|
|
167
|
+
cleanup();
|
|
168
|
+
resolve({
|
|
169
|
+
ok: false,
|
|
170
|
+
err: new KinetexError("Proxy sent an oversized CONNECT response", "EPROXY", errMeta),
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
cleanup();
|
|
176
|
+
const parsed = parseConnectStatus(head.slice(0, end));
|
|
177
|
+
if (!parsed) {
|
|
178
|
+
resolve({
|
|
179
|
+
ok: false,
|
|
180
|
+
err: new KinetexError(`Proxy returned a malformed CONNECT response: ${JSON.stringify(head.slice(0, end).split("\r\n", 1)[0] ?? "")}`, "EPROXY", errMeta),
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
// RFC 9110 section 9.3.6: any 2xx switches the proxy to tunnel mode.
|
|
185
|
+
// Only 200 was accepted, so a proxy answering 201 or 204 was reported
|
|
186
|
+
// as a refusal.
|
|
187
|
+
if (parsed.status >= 200 && parsed.status < 300) {
|
|
188
|
+
// Put the tunnel bytes back in front of the buffered stream before
|
|
189
|
+
// handing the socket on. latin1 round-trips the bytes exactly, which
|
|
190
|
+
// is how `head` was built.
|
|
191
|
+
const tail = head.slice(end + 4);
|
|
192
|
+
if (tail.length > 0)
|
|
193
|
+
baseSocket.unshift(Buffer.from(tail, "latin1"));
|
|
194
|
+
resolve({ ok: true });
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (parsed.status === 407) {
|
|
198
|
+
// Deliberately does not echo credentials back to the caller.
|
|
199
|
+
resolve({
|
|
200
|
+
ok: false,
|
|
201
|
+
err: new KinetexError("Proxy requires authentication (407). Set `username`/`password` on the proxy config, " +
|
|
202
|
+
"or embed them in the proxy URL.", "EPROXY", errMeta),
|
|
203
|
+
});
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
resolve({
|
|
207
|
+
ok: false,
|
|
208
|
+
err: new KinetexError(`Proxy refused CONNECT to ${authority}: ${parsed.status} ${parsed.reason}`.trim(), "EPROXY", errMeta),
|
|
209
|
+
});
|
|
210
|
+
};
|
|
211
|
+
const onError = (e) => {
|
|
212
|
+
cleanup();
|
|
213
|
+
resolve({
|
|
214
|
+
ok: false,
|
|
215
|
+
err: new KinetexError(`Proxy connection failed: ${e.message}`, "ENETWORK", {
|
|
216
|
+
...errMeta,
|
|
217
|
+
cause: e,
|
|
218
|
+
}),
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
// A proxy that closes the connection mid-handshake delivers a clean FIN,
|
|
222
|
+
// not a reset — so no `error` event fires and the socket simply ends.
|
|
223
|
+
// Without this the request would sit here until the connect timeout
|
|
224
|
+
// expired: 30s by default, for a proxy that is already gone.
|
|
225
|
+
const onClosedEarly = () => {
|
|
226
|
+
cleanup();
|
|
227
|
+
resolve({
|
|
228
|
+
ok: false,
|
|
229
|
+
err: new KinetexError(`Proxy closed the connection before answering CONNECT for ${authority}`, "EPROXY", errMeta),
|
|
230
|
+
});
|
|
231
|
+
};
|
|
232
|
+
const onTimeout = () => {
|
|
233
|
+
cleanup();
|
|
234
|
+
baseSocket.destroy();
|
|
235
|
+
resolve({
|
|
236
|
+
ok: false,
|
|
237
|
+
err: new KinetexError(`Proxy did not respond to CONNECT for ${authority} within ${timeoutMs}ms`, "ETIMEOUT", errMeta),
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
const onAbort = () => {
|
|
241
|
+
cleanup();
|
|
242
|
+
baseSocket.destroy();
|
|
243
|
+
resolve({
|
|
244
|
+
ok: false,
|
|
245
|
+
err: new KinetexError("Proxy connection aborted", "EABORT", errMeta),
|
|
246
|
+
});
|
|
247
|
+
};
|
|
248
|
+
const timer = setTimeout(onTimeout, timeoutMs);
|
|
249
|
+
if (typeof timer.unref === "function") {
|
|
250
|
+
timer.unref();
|
|
251
|
+
}
|
|
252
|
+
function cleanup() {
|
|
253
|
+
clearTimeout(timer);
|
|
254
|
+
baseSocket.off("readable", onReadable);
|
|
255
|
+
baseSocket.off("error", onError);
|
|
256
|
+
baseSocket.off("end", onClosedEarly);
|
|
257
|
+
baseSocket.off("close", onClosedEarly);
|
|
258
|
+
baseSocket.off("timeout", onTimeout);
|
|
259
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
260
|
+
}
|
|
261
|
+
baseSocket.on("readable", onReadable);
|
|
262
|
+
baseSocket.once("error", onError);
|
|
263
|
+
baseSocket.once("end", onClosedEarly);
|
|
264
|
+
baseSocket.once("close", onClosedEarly);
|
|
265
|
+
baseSocket.setTimeout(timeoutMs, onTimeout);
|
|
266
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
267
|
+
// Data may already be buffered (the request write above and the reply
|
|
268
|
+
// can cross), and `readable` does not fire for bytes that arrived before
|
|
269
|
+
// the listener was attached.
|
|
270
|
+
drain();
|
|
271
|
+
});
|
|
272
|
+
if (!headResult.ok) {
|
|
273
|
+
baseSocket.destroy();
|
|
274
|
+
throw headResult.err;
|
|
275
|
+
}
|
|
276
|
+
// ── 3. TLS to the target through the tunnel ───────────────────────────────
|
|
277
|
+
if (target.protocol !== "https:") {
|
|
278
|
+
// Clear the handshake listeners' timeout; the socket now belongs to the
|
|
279
|
+
// caller and its own timeout policy.
|
|
280
|
+
baseSocket.setTimeout(0);
|
|
281
|
+
return baseSocket;
|
|
282
|
+
}
|
|
283
|
+
return await new Promise((resolve, reject) => {
|
|
284
|
+
// The CONNECT handshake is over and its timeout/abort listeners are torn
|
|
285
|
+
// down, but the TLS handshake to the target has not happened yet. A peer
|
|
286
|
+
// that accepts the tunnel and then says nothing -- a black-holed target,
|
|
287
|
+
// or a proxy that relays to nothing -- would otherwise wait forever, so
|
|
288
|
+
// the same timeout and abort cover this step too.
|
|
289
|
+
const onTunnelTimeout = () => {
|
|
290
|
+
done();
|
|
291
|
+
baseSocket.destroy();
|
|
292
|
+
reject(new KinetexError(`TLS handshake through proxy to ${target.hostname} did not complete within ${timeoutMs}ms`, "ETIMEOUT", errMeta));
|
|
293
|
+
};
|
|
294
|
+
const onTunnelAbort = () => {
|
|
295
|
+
done();
|
|
296
|
+
baseSocket.destroy();
|
|
297
|
+
reject(new KinetexError("Proxy connection aborted", "EABORT", errMeta));
|
|
298
|
+
};
|
|
299
|
+
const tunnelTimer = setTimeout(onTunnelTimeout, timeoutMs);
|
|
300
|
+
if (typeof tunnelTimer.unref === "function") {
|
|
301
|
+
tunnelTimer.unref();
|
|
302
|
+
}
|
|
303
|
+
options.signal?.addEventListener("abort", onTunnelAbort, { once: true });
|
|
304
|
+
function done() {
|
|
305
|
+
clearTimeout(tunnelTimer);
|
|
306
|
+
options.signal?.removeEventListener("abort", onTunnelAbort);
|
|
307
|
+
}
|
|
308
|
+
const secure = tls.connect({
|
|
309
|
+
socket: baseSocket,
|
|
310
|
+
servername: options.servername ?? target.hostname,
|
|
311
|
+
...(options.ca !== undefined ? { ca: options.ca } : {}),
|
|
312
|
+
},
|
|
313
|
+
// `rejectUnauthorized` is left at its default (true), so a peer that
|
|
314
|
+
// fails verification emits `error` rather than reaching this callback.
|
|
315
|
+
// Verification therefore cannot be bypassed here, and the callback
|
|
316
|
+
// only ever runs for a verified handshake.
|
|
317
|
+
() => {
|
|
318
|
+
done();
|
|
319
|
+
baseSocket.setTimeout(0);
|
|
320
|
+
resolve(secure);
|
|
321
|
+
});
|
|
322
|
+
secure.once("error", (e) => {
|
|
323
|
+
done();
|
|
324
|
+
baseSocket.destroy();
|
|
325
|
+
reject(new KinetexError(`TLS handshake through proxy failed for ${target.hostname}: ${e.message}`, "ENETWORK", { ...errMeta, cause: e }));
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
/** Open a plain TCP socket, rejecting on error/timeout/abort. */
|
|
330
|
+
async function openTcpSocket(net, opts, timeoutMs, signal, errMeta, what) {
|
|
331
|
+
return await new Promise((resolve, reject) => {
|
|
332
|
+
const socket = net.connect({ host: opts.host, port: opts.port });
|
|
333
|
+
const onError = (e) => {
|
|
334
|
+
cleanup();
|
|
335
|
+
reject(new KinetexError(`Cannot reach ${what}: ${e.message}`, "ENETWORK", {
|
|
336
|
+
...errMeta,
|
|
337
|
+
cause: e,
|
|
338
|
+
}));
|
|
339
|
+
};
|
|
340
|
+
const timer = setTimeout(() => {
|
|
341
|
+
cleanup();
|
|
342
|
+
socket.destroy();
|
|
343
|
+
reject(new KinetexError(`Connecting to ${what} timed out`, "ETIMEOUT", errMeta));
|
|
344
|
+
}, timeoutMs);
|
|
345
|
+
if (typeof timer.unref === "function") {
|
|
346
|
+
timer.unref();
|
|
347
|
+
}
|
|
348
|
+
const onAbort = () => {
|
|
349
|
+
cleanup();
|
|
350
|
+
socket.destroy();
|
|
351
|
+
reject(new KinetexError("Proxy connection aborted", "EABORT", errMeta));
|
|
352
|
+
};
|
|
353
|
+
function cleanup() {
|
|
354
|
+
clearTimeout(timer);
|
|
355
|
+
socket.off("error", onError);
|
|
356
|
+
signal?.removeEventListener("abort", onAbort);
|
|
357
|
+
}
|
|
358
|
+
socket.once("error", onError);
|
|
359
|
+
socket.once("connect", () => {
|
|
360
|
+
cleanup();
|
|
361
|
+
resolve(socket);
|
|
362
|
+
});
|
|
363
|
+
if (signal?.aborted)
|
|
364
|
+
onAbort();
|
|
365
|
+
else
|
|
366
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
/** Open a TLS socket to an HTTPS proxy itself. */
|
|
370
|
+
async function openTlsSocket(tls, opts, timeoutMs, signal, errMeta, what) {
|
|
371
|
+
return await new Promise((resolve, reject) => {
|
|
372
|
+
const socket = tls.connect({
|
|
373
|
+
host: opts.host,
|
|
374
|
+
port: opts.port,
|
|
375
|
+
servername: opts.servername,
|
|
376
|
+
...(opts.ca !== undefined ? { ca: opts.ca } : {}),
|
|
377
|
+
}, () => {
|
|
378
|
+
cleanup();
|
|
379
|
+
resolve(socket);
|
|
380
|
+
});
|
|
381
|
+
const onError = (e) => {
|
|
382
|
+
cleanup();
|
|
383
|
+
reject(new KinetexError(`Cannot reach ${what}: ${e.message}`, "ENETWORK", {
|
|
384
|
+
...errMeta,
|
|
385
|
+
cause: e,
|
|
386
|
+
}));
|
|
387
|
+
};
|
|
388
|
+
const timer = setTimeout(() => {
|
|
389
|
+
cleanup();
|
|
390
|
+
socket.destroy();
|
|
391
|
+
reject(new KinetexError(`Connecting to ${what} timed out`, "ETIMEOUT", errMeta));
|
|
392
|
+
}, timeoutMs);
|
|
393
|
+
if (typeof timer.unref === "function") {
|
|
394
|
+
timer.unref();
|
|
395
|
+
}
|
|
396
|
+
const onAbort = () => {
|
|
397
|
+
cleanup();
|
|
398
|
+
socket.destroy();
|
|
399
|
+
reject(new KinetexError("Proxy connection aborted", "EABORT", errMeta));
|
|
400
|
+
};
|
|
401
|
+
function cleanup() {
|
|
402
|
+
clearTimeout(timer);
|
|
403
|
+
socket.off("error", onError);
|
|
404
|
+
signal?.removeEventListener("abort", onAbort);
|
|
405
|
+
}
|
|
406
|
+
socket.once("error", onError);
|
|
407
|
+
if (signal?.aborted)
|
|
408
|
+
onAbort();
|
|
409
|
+
else
|
|
410
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
//# sourceMappingURL=proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAiB1C,MAAM,0BAA0B,GAAG,MAAM,CAAC;AAE1C,qEAAqE;AACrE,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,CAAC;AAEjC;;;GAGG;AACH,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,KAAkB;IACzC,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACnD,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;IACxD,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACxD,MAAM,GAAG,GACP,OAAO,UAAU,CAAC,IAAI,KAAK,UAAU;QACnC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QACzB,CAAC,CAAC,oEAAoE;YACpE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5C,OAAO,SAAS,GAAG,EAAE,CAAC;AACxB,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,IAAY;IACtC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAClD,MAAM,KAAK,GAAG,mCAAmC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACnE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAAkB,EAClB,MAAW,EACX,UAA+B,EAAE;IAEjC,uEAAuE;IACvE,iDAAiD;IACjD,MAAM,OAAO,GACX,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEpE,IAAI,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,YAAY,CACpB,cAAc,KAAK,CAAC,GAAG,yDAAyD;YAC9E,yFAAyF,EAC3F,aAAa,EACb,OAAO,CACR,CAAC;IACJ,CAAC;IAED,IAAI,QAAa,CAAC;IAClB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,YAAY,CAAC,cAAc,KAAK,CAAC,GAAG,sBAAsB,EAAE,aAAa,EAAE;YACnF,GAAG,OAAO;YACV,KAAK,EAAE,GAAG;SACX,CAAC,CAAC;IACL,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,KAAK,OAAO,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACpE,MAAM,IAAI,YAAY,CACpB,qBAAqB,QAAQ,CAAC,QAAQ,4DAA4D,EAClG,aAAa,EACb,OAAO,CACR,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IAErC,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI;QAC7B,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC,CAAC,QAAQ,CAAC,QAAQ,KAAK,QAAQ;YAC9B,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/F,MAAM,SAAS,GAAG,GAAG,MAAM,CAAC,QAAQ,IAAI,UAAU,EAAE,CAAC;IACrD,MAAM,SAAS,GAAG,OAAO,CAAC,gBAAgB,IAAI,0BAA0B,CAAC;IAEzE,6EAA6E;IAC7E,MAAM,UAAU,GACd,QAAQ,CAAC,QAAQ,KAAK,QAAQ;QAC5B,CAAC,CAAC,MAAM,aAAa,CACjB,GAAG,EACH;YACE,IAAI,EAAE,QAAQ,CAAC,QAAQ;YACvB,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,QAAQ,CAAC,QAAQ;YAC7B,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxD,EACD,SAAS,EACT,OAAO,CAAC,MAAM,EACd,OAAO,EACP,SAAS,QAAQ,CAAC,IAAI,EAAE,CACzB;QACH,CAAC,CAAC,MAAM,aAAa,CACjB,GAAG,EACH,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,EAC5C,SAAS,EACT,OAAO,CAAC,MAAM,EACd,OAAO,EACP,SAAS,QAAQ,CAAC,IAAI,EAAE,CACzB,CAAC;IAER,4EAA4E;IAC5E,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,YAAY,GAAG;QACnB,WAAW,SAAS,WAAW;QAC/B,SAAS,SAAS,EAAE;QACpB,2EAA2E;QAC3E,yEAAyE;QACzE,gEAAgE;QAChE,8BAA8B;QAC9B,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,EAAE;QACF,EAAE;KACH,CAAC;IACF,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAE5C,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,2EAA2E;IAC3E,oEAAoE;IACpE,0EAA0E;IAC1E,yEAAyE;IACzE,0EAA0E;IAC1E,EAAE;IACF,qEAAqE;IACrE,4EAA4E;IAC5E,4EAA4E;IAC5E,wEAAwE;IACxE,2EAA2E;IAC3E,0EAA0E;IAC1E,qEAAqE;IACrE,0EAA0E;IAC1E,2EAA2E;IAC3E,8DAA8D;IAC9D,kEAAkE;IAClE,MAAM,UAAU,GAAG,MAAM,IAAI,OAAO,CAClC,CAAC,OAAO,EAAE,EAAE;QACV,yEAAyE;QACzE,4DAA4D;QAC5D,MAAM,KAAK,GAAG,GAAS,EAAE;YACvB,SAAS,CAAC;gBACR,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAmB,CAAC;gBACjD,IAAI,KAAK,KAAK,IAAI;oBAAE,OAAO;gBAC3B,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnC,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,UAAU,GAAG,GAAS,EAAE;YAC5B,KAAK,EAAE,CAAC;YACR,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACrC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;gBACf,IAAI,IAAI,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;oBACjC,OAAO,EAAE,CAAC;oBACV,OAAO,CAAC;wBACN,EAAE,EAAE,KAAK;wBACT,GAAG,EAAE,IAAI,YAAY,CAAC,0CAA0C,EAAE,QAAQ,EAAE,OAAO,CAAC;qBACrF,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO;YACT,CAAC;YAED,OAAO,EAAE,CAAC;YACV,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACtD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,CAAC;oBACN,EAAE,EAAE,KAAK;oBACT,GAAG,EAAE,IAAI,YAAY,CACnB,gDAAgD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAC9G,QAAQ,EACR,OAAO,CACR;iBACF,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,qEAAqE;YACrE,sEAAsE;YACtE,gBAAgB;YAChB,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBAChD,mEAAmE;gBACnE,qEAAqE;gBACrE,2BAA2B;gBAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;gBACjC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;oBAAE,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;gBACrE,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtB,OAAO;YACT,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC1B,6DAA6D;gBAC7D,OAAO,CAAC;oBACN,EAAE,EAAE,KAAK;oBACT,GAAG,EAAE,IAAI,YAAY,CACnB,sFAAsF;wBACpF,iCAAiC,EACnC,QAAQ,EACR,OAAO,CACR;iBACF,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YACD,OAAO,CAAC;gBACN,EAAE,EAAE,KAAK;gBACT,GAAG,EAAE,IAAI,YAAY,CACnB,4BAA4B,SAAS,KAAK,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EACjF,QAAQ,EACR,OAAO,CACR;aACF,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,CAAC,CAAQ,EAAQ,EAAE;YACjC,OAAO,EAAE,CAAC;YACV,OAAO,CAAC;gBACN,EAAE,EAAE,KAAK;gBACT,GAAG,EAAE,IAAI,YAAY,CAAC,4BAA4B,CAAC,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE;oBACzE,GAAG,OAAO;oBACV,KAAK,EAAE,CAAC;iBACT,CAAC;aACH,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,yEAAyE;QACzE,sEAAsE;QACtE,oEAAoE;QACpE,6DAA6D;QAC7D,MAAM,aAAa,GAAG,GAAS,EAAE;YAC/B,OAAO,EAAE,CAAC;YACV,OAAO,CAAC;gBACN,EAAE,EAAE,KAAK;gBACT,GAAG,EAAE,IAAI,YAAY,CACnB,4DAA4D,SAAS,EAAE,EACvE,QAAQ,EACR,OAAO,CACR;aACF,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,MAAM,SAAS,GAAG,GAAS,EAAE;YAC3B,OAAO,EAAE,CAAC;YACV,UAAU,CAAC,OAAO,EAAE,CAAC;YACrB,OAAO,CAAC;gBACN,EAAE,EAAE,KAAK;gBACT,GAAG,EAAE,IAAI,YAAY,CACnB,wCAAwC,SAAS,WAAW,SAAS,IAAI,EACzE,UAAU,EACV,OAAO,CACR;aACF,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,OAAO,EAAE,CAAC;YACV,UAAU,CAAC,OAAO,EAAE,CAAC;YACrB,OAAO,CAAC;gBACN,EAAE,EAAE,KAAK;gBACT,GAAG,EAAE,IAAI,YAAY,CAAC,0BAA0B,EAAE,QAAQ,EAAE,OAAO,CAAC;aACrE,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC/C,IAAI,OAAQ,KAA2C,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YAC5E,KAA0C,CAAC,KAAK,EAAE,CAAC;QACtD,CAAC;QAED,SAAS,OAAO;YACd,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YACvC,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACjC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;YACrC,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YACvC,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YACrC,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxD,CAAC;QAED,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACtC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClC,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QACtC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QACxC,UAAU,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC5C,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,sEAAsE;QACtE,yEAAyE;QACzE,6BAA6B;QAC7B,KAAK,EAAE,CAAC;IACV,CAAC,CACF,CAAC;IAEF,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC;QACnB,UAAU,CAAC,OAAO,EAAE,CAAC;QACrB,MAAM,UAAU,CAAC,GAAG,CAAC;IACvB,CAAC;IAED,6EAA6E;IAC7E,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,wEAAwE;QACxE,qCAAqC;QACrC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACzB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,MAAM,IAAI,OAAO,CAA+B,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACzE,yEAAyE;QACzE,yEAAyE;QACzE,yEAAyE;QACzE,wEAAwE;QACxE,kDAAkD;QAClD,MAAM,eAAe,GAAG,GAAS,EAAE;YACjC,IAAI,EAAE,CAAC;YACP,UAAU,CAAC,OAAO,EAAE,CAAC;YACrB,MAAM,CACJ,IAAI,YAAY,CACd,kCAAkC,MAAM,CAAC,QAAQ,4BAA4B,SAAS,IAAI,EAC1F,UAAU,EACV,OAAO,CACR,CACF,CAAC;QACJ,CAAC,CAAC;QACF,MAAM,aAAa,GAAG,GAAS,EAAE;YAC/B,IAAI,EAAE,CAAC;YACP,UAAU,CAAC,OAAO,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,YAAY,CAAC,0BAA0B,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1E,CAAC,CAAC;QAEF,MAAM,WAAW,GAAG,UAAU,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;QAC3D,IAAI,OAAQ,WAAiD,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YAClF,WAAgD,CAAC,KAAK,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAEzE,SAAS,IAAI;YACX,YAAY,CAAC,WAAW,CAAC,CAAC;YAC1B,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CACxB;YACE,MAAM,EAAE,UAAU;YAClB,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,QAAQ;YACjD,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxD;QACD,qEAAqE;QACrE,uEAAuE;QACvE,mEAAmE;QACnE,2CAA2C;QAC3C,GAAG,EAAE;YACH,IAAI,EAAE,CAAC;YACP,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YACzB,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CACF,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE;YAChC,IAAI,EAAE,CAAC;YACP,UAAU,CAAC,OAAO,EAAE,CAAC;YACrB,MAAM,CACJ,IAAI,YAAY,CACd,0CAA0C,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,EACzE,UAAU,EACV,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CACzB,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,iEAAiE;AACjE,KAAK,UAAU,aAAa,CAC1B,GAA8B,EAC9B,IAAoC,EACpC,SAAiB,EACjB,MAAsC,EACtC,OAAe,EACf,IAAY;IAEZ,OAAO,MAAM,IAAI,OAAO,CAA4B,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtE,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACjE,MAAM,OAAO,GAAG,CAAC,CAAQ,EAAQ,EAAE;YACjC,OAAO,EAAE,CAAC;YACV,MAAM,CACJ,IAAI,YAAY,CAAC,gBAAgB,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE;gBACjE,GAAG,OAAO;gBACV,KAAK,EAAE,CAAC;aACT,CAAC,CACH,CAAC;QACJ,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,OAAO,EAAE,CAAC;YACV,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,YAAY,CAAC,iBAAiB,IAAI,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QACnF,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,IAAI,OAAQ,KAA2C,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YAC5E,KAA0C,CAAC,KAAK,EAAE,CAAC;QACtD,CAAC;QACD,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,OAAO,EAAE,CAAC;YACV,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,YAAY,CAAC,0BAA0B,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1E,CAAC,CAAC;QACF,SAAS,OAAO;YACd,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;YAC1B,OAAO,EAAE,CAAC;YACV,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QACH,IAAI,MAAM,EAAE,OAAO;YAAE,OAAO,EAAE,CAAC;;YAC1B,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,kDAAkD;AAClD,KAAK,UAAU,aAAa,CAC1B,GAA8B,EAC9B,IAAgF,EAChF,SAAiB,EACjB,MAAsC,EACtC,OAAe,EACf,IAAY;IAEZ,OAAO,MAAM,IAAI,OAAO,CAA+B,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACzE,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CACxB;YACE,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClD,EACD,GAAG,EAAE;YACH,OAAO,EAAE,CAAC;YACV,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CACF,CAAC;QACF,MAAM,OAAO,GAAG,CAAC,CAAQ,EAAQ,EAAE;YACjC,OAAO,EAAE,CAAC;YACV,MAAM,CACJ,IAAI,YAAY,CAAC,gBAAgB,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE;gBACjE,GAAG,OAAO;gBACV,KAAK,EAAE,CAAC;aACT,CAAC,CACH,CAAC;QACJ,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,OAAO,EAAE,CAAC;YACV,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,YAAY,CAAC,iBAAiB,IAAI,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QACnF,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,IAAI,OAAQ,KAA2C,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YAC5E,KAA0C,CAAC,KAAK,EAAE,CAAC;QACtD,CAAC;QACD,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,OAAO,EAAE,CAAC;YACV,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,YAAY,CAAC,0BAA0B,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1E,CAAC,CAAC;QACF,SAAS,OAAO;YACd,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9B,IAAI,MAAM,EAAE,OAAO;YAAE,OAAO,EAAE,CAAC;;YAC1B,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC"}
|