@dbx-tools/lakebox 0.0.0-stage → 0.9.131

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.
@@ -0,0 +1,489 @@
1
+ import { PassThrough } from "node:stream";
2
+ import { StringDecoder } from "node:string_decoder";
3
+ import { errorUtils, log } from "@dbx-tools/shared-core";
4
+ import { createPool } from "generic-pool";
5
+ const logger = log.logger("lakebox:ssh-transport");
6
+ /** Maximum authenticated resources maintained by each SSH operation pool. */
7
+ export const SSH_POOL_MAX = 10;
8
+ /** Live SSH command that streams output and awaits to its numeric exit code. */
9
+ export class SshCommand {
10
+ command;
11
+ args;
12
+ [Symbol.toStringTag] = "SshCommand";
13
+ /** Live standard output decoded as UTF-8 strings. */
14
+ stdout;
15
+ /** Live standard error decoded as UTF-8 strings. */
16
+ stderr;
17
+ /** Completed result with captured output, timing, and timeout metadata. */
18
+ result;
19
+ /** Numeric exit code after completion. */
20
+ exitCode;
21
+ startedAt = Date.now();
22
+ stdoutStream = new PassThrough();
23
+ stderrStream = new PassThrough();
24
+ stdoutDecoder = new StringDecoder("utf8");
25
+ stderrDecoder = new StringDecoder("utf8");
26
+ abortController = new AbortController();
27
+ completion;
28
+ resolveCompletion;
29
+ rejectCompletion;
30
+ cancelBackend;
31
+ cancellation;
32
+ stdoutText = "";
33
+ stderrText = "";
34
+ settled = false;
35
+ timedOut = false;
36
+ /** Creates a command and schedules its asynchronous setup and execution. */
37
+ constructor(command, args, options, start) {
38
+ this.command = command;
39
+ this.args = args;
40
+ this.stdoutStream.setEncoding("utf8");
41
+ this.stderrStream.setEncoding("utf8");
42
+ this.stdout = this.stdoutStream;
43
+ this.stderr = this.stderrStream;
44
+ this.completion = new Promise((resolve, reject) => {
45
+ this.resolveCompletion = resolve;
46
+ this.rejectCompletion = reject;
47
+ });
48
+ this.result = this.completion.then((exitCode) => ({
49
+ success: exitCode === 0 && !this.timedOut,
50
+ exitCode,
51
+ stdout: this.stdoutText,
52
+ stderr: this.stderrText,
53
+ executionTimeMs: Date.now() - this.startedAt,
54
+ ...(this.timedOut ? { timedOut: true } : {}),
55
+ command: this.command,
56
+ args: [...this.args],
57
+ }));
58
+ void this.completion.catch(() => undefined);
59
+ void this.result.catch(() => undefined);
60
+ const externalAbort = () => {
61
+ void this.cancel().catch(() => undefined);
62
+ };
63
+ if (options.signal?.aborted)
64
+ externalAbort();
65
+ else
66
+ options.signal?.addEventListener("abort", externalAbort, { once: true });
67
+ const timeout = setTimeout(() => {
68
+ this.timedOut = true;
69
+ void this.cancel(124).catch(() => undefined);
70
+ }, options.timeoutMs);
71
+ timeout.unref?.();
72
+ const cleanup = () => {
73
+ clearTimeout(timeout);
74
+ options.signal?.removeEventListener("abort", externalAbort);
75
+ };
76
+ void this.completion.then(cleanup, cleanup);
77
+ queueMicrotask(() => {
78
+ if (this.settled)
79
+ return;
80
+ void start({
81
+ signal: this.abortController.signal,
82
+ stdout: (chunk) => this.writeOutput("stdout", chunk),
83
+ stderr: (chunk) => this.writeOutput("stderr", chunk),
84
+ setCancel: (cancel) => {
85
+ this.cancelBackend = cancel;
86
+ if (this.abortController.signal.aborted) {
87
+ void this.invokeCancel().catch(() => undefined);
88
+ }
89
+ },
90
+ follow: (command) => this.follow(command),
91
+ }).then((exitCode) => this.finish(exitCode), (error) => this.fail(error));
92
+ });
93
+ }
94
+ /** Cancel the command once. Caller cancellation resolves with exit code 130. */
95
+ cancel(exitCode = 130) {
96
+ if (this.settled)
97
+ return this.cancellation ?? Promise.resolve();
98
+ if (!this.abortController.signal.aborted)
99
+ this.abortController.abort();
100
+ const cancellation = this.invokeCancel();
101
+ this.finish(exitCode);
102
+ return cancellation;
103
+ }
104
+ then(onfulfilled, onrejected) {
105
+ return this.completion.then(onfulfilled, onrejected);
106
+ }
107
+ catch(onrejected) {
108
+ return this.completion.catch(onrejected);
109
+ }
110
+ finally(onfinally) {
111
+ return this.completion.finally(onfinally ?? undefined);
112
+ }
113
+ invokeCancel() {
114
+ if (this.cancellation)
115
+ return this.cancellation;
116
+ if (!this.cancelBackend)
117
+ return Promise.resolve();
118
+ const cancelBackend = this.cancelBackend;
119
+ this.cancellation = Promise.resolve()
120
+ .then(() => cancelBackend())
121
+ .then(() => undefined);
122
+ void this.cancellation.catch(() => undefined);
123
+ return this.cancellation;
124
+ }
125
+ writeOutput(stream, chunk) {
126
+ if (this.settled)
127
+ return;
128
+ const decoder = stream === "stdout" ? this.stdoutDecoder : this.stderrDecoder;
129
+ const value = decoder.write(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
130
+ if (!value)
131
+ return;
132
+ if (stream === "stdout") {
133
+ this.stdoutText += value;
134
+ this.stdoutStream.write(value);
135
+ }
136
+ else {
137
+ this.stderrText += value;
138
+ this.stderrStream.write(value);
139
+ }
140
+ }
141
+ async follow(command) {
142
+ this.cancelBackend = () => command.cancel();
143
+ if (this.abortController.signal.aborted) {
144
+ void this.invokeCancel().catch(() => undefined);
145
+ }
146
+ const stdout = this.pipe(command.stdout, (chunk) => this.writeOutput("stdout", chunk));
147
+ const stderr = this.pipe(command.stderr, (chunk) => this.writeOutput("stderr", chunk));
148
+ const exitCode = await command;
149
+ await Promise.all([stdout, stderr]);
150
+ return exitCode;
151
+ }
152
+ async pipe(stream, write) {
153
+ for await (const chunk of stream)
154
+ write(chunk);
155
+ }
156
+ finish(exitCode) {
157
+ if (this.settled)
158
+ return;
159
+ this.settled = true;
160
+ this.exitCode = exitCode;
161
+ this.closeOutput();
162
+ this.resolveCompletion(exitCode);
163
+ }
164
+ fail(error) {
165
+ if (this.settled)
166
+ return;
167
+ this.settled = true;
168
+ this.closeOutput();
169
+ this.rejectCompletion(error);
170
+ }
171
+ closeOutput() {
172
+ const stdoutRemainder = this.stdoutDecoder.end();
173
+ const stderrRemainder = this.stderrDecoder.end();
174
+ if (stdoutRemainder) {
175
+ this.stdoutText += stdoutRemainder;
176
+ this.stdoutStream.write(stdoutRemainder);
177
+ }
178
+ if (stderrRemainder) {
179
+ this.stderrText += stderrRemainder;
180
+ this.stderrStream.write(stderrRemainder);
181
+ }
182
+ this.stdoutStream.end();
183
+ this.stderrStream.end();
184
+ }
185
+ }
186
+ /**
187
+ * Exclusive, single-operation SSH resource pool.
188
+ *
189
+ * The command pool keeps one authenticated resource warm. Forwarding uses a
190
+ * separate zero-minimum pool so long-lived WebSockets cannot consume the warm
191
+ * command connection. Every borrowed resource is destroyed after its command
192
+ * or forwarded stream because the Databricks Russh gateway may accept only one
193
+ * operation during a connection's lifetime.
194
+ */
195
+ export class PooledSshTransport {
196
+ lifecycle;
197
+ commandPool;
198
+ forwardingPool;
199
+ activeResources = new Map();
200
+ seededResources = [];
201
+ lastCreateError;
202
+ starting;
203
+ closing;
204
+ closed = false;
205
+ constructor(lifecycle, options = {}) {
206
+ this.lifecycle = lifecycle;
207
+ const factory = {
208
+ create: async () => {
209
+ try {
210
+ const resource = this.seededResources.shift() ?? (await lifecycle.create());
211
+ this.lastCreateError = undefined;
212
+ return resource;
213
+ }
214
+ catch (error) {
215
+ this.lastCreateError = error;
216
+ throw error;
217
+ }
218
+ },
219
+ destroy: (resource) => lifecycle.destroy(resource),
220
+ validate: async (resource) => {
221
+ try {
222
+ return await lifecycle.test(resource);
223
+ }
224
+ catch {
225
+ return false;
226
+ }
227
+ },
228
+ };
229
+ const defaults = {
230
+ max: options.max ?? SSH_POOL_MAX,
231
+ acquireTimeoutMillis: options.acquireTimeoutMillis ?? 15_000,
232
+ idleTimeoutMillis: options.idleTimeoutMillis ?? 30_000,
233
+ evictionRunIntervalMillis: options.evictionRunIntervalMillis ?? 10_000,
234
+ numTestsPerEvictionRun: options.numTestsPerEvictionRun ?? 3,
235
+ testOnBorrow: true,
236
+ autostart: false,
237
+ };
238
+ this.commandPool = createPool(factory, { ...defaults, min: 1 });
239
+ this.forwardingPool = createPool(factory, { ...defaults, min: 0 });
240
+ }
241
+ /** Starts both pools and waits until one tested command resource is warm. */
242
+ start() {
243
+ if (this.closed)
244
+ return Promise.reject(new Error(`${this.kind} SSH transport is closed`));
245
+ if (this.starting)
246
+ return this.starting;
247
+ this.starting = this.startPools();
248
+ void this.starting
249
+ .catch(() => this.close())
250
+ .catch((error) => logger.warn("failed to close SSH transport after startup failure", {
251
+ kind: this.kind,
252
+ error: errorUtils.toError(error),
253
+ }));
254
+ return this.starting;
255
+ }
256
+ async startPools() {
257
+ if (this.closed)
258
+ throw new Error(`${this.kind} SSH transport is closed`);
259
+ const resource = await this.lifecycle.create();
260
+ if (this.closed) {
261
+ await this.lifecycle.destroy(resource);
262
+ throw new Error(`${this.kind} SSH transport is closed`);
263
+ }
264
+ this.seededResources.push(resource);
265
+ this.commandPool.start();
266
+ this.forwardingPool.start();
267
+ try {
268
+ const resource = await this.commandPool.acquire();
269
+ await this.commandPool.release(resource);
270
+ }
271
+ catch (error) {
272
+ throw this.lastCreateError ?? error;
273
+ }
274
+ }
275
+ async run(script, execution) {
276
+ const resource = await this.acquire(this.commandPool);
277
+ try {
278
+ if (execution.signal.aborted)
279
+ return 130;
280
+ return await this.runWithResource(resource, script, execution);
281
+ }
282
+ finally {
283
+ await this.destroy(this.commandPool, resource);
284
+ }
285
+ }
286
+ async connect(remoteHost, remotePort) {
287
+ const first = await this.acquire(this.forwardingPool);
288
+ try {
289
+ return await this.connectWithBorrowedResource(first, remoteHost, remotePort);
290
+ }
291
+ catch (error) {
292
+ await this.destroy(this.forwardingPool, first);
293
+ if (this.closed)
294
+ throw error;
295
+ }
296
+ const retry = await this.acquire(this.forwardingPool);
297
+ try {
298
+ return await this.connectWithBorrowedResource(retry, remoteHost, remotePort);
299
+ }
300
+ catch (error) {
301
+ await this.destroy(this.forwardingPool, retry);
302
+ throw error;
303
+ }
304
+ }
305
+ async close() {
306
+ if (this.closing)
307
+ return this.closing;
308
+ this.closed = true;
309
+ this.closing = this.closePools();
310
+ return this.closing;
311
+ }
312
+ async connectWithBorrowedResource(resource, remoteHost, remotePort) {
313
+ const stream = await this.connectWithResource(resource, remoteHost, remotePort);
314
+ let disposed = false;
315
+ const dispose = () => {
316
+ if (disposed)
317
+ return;
318
+ disposed = true;
319
+ void this.destroy(this.forwardingPool, resource);
320
+ };
321
+ stream.once("close", dispose);
322
+ stream.once("error", dispose);
323
+ if (stream.destroyed)
324
+ dispose();
325
+ return stream;
326
+ }
327
+ async acquire(pool) {
328
+ if (this.closed)
329
+ throw new Error(`${this.kind} SSH transport is closed`);
330
+ let resource;
331
+ try {
332
+ resource = await pool.acquire();
333
+ }
334
+ catch (error) {
335
+ throw this.lastCreateError ?? error;
336
+ }
337
+ this.activeResources.set(resource, pool);
338
+ if (this.closed) {
339
+ await this.destroy(pool, resource);
340
+ throw new Error(`${this.kind} SSH transport is closed`);
341
+ }
342
+ return resource;
343
+ }
344
+ async destroy(pool, resource) {
345
+ if (this.activeResources.get(resource) !== pool)
346
+ return;
347
+ this.activeResources.delete(resource);
348
+ try {
349
+ await pool.destroy(resource);
350
+ }
351
+ catch (error) {
352
+ logger.warn("failed to destroy pooled SSH resource", {
353
+ kind: this.kind,
354
+ error: errorUtils.toError(error),
355
+ });
356
+ }
357
+ }
358
+ async closePools() {
359
+ await this.starting?.catch(() => undefined);
360
+ const commandDrain = this.commandPool.drain();
361
+ const forwardingDrain = this.forwardingPool.drain();
362
+ await Promise.all([...this.activeResources].map(([resource, pool]) => this.destroy(pool, resource)));
363
+ await Promise.all([commandDrain, forwardingDrain]);
364
+ await Promise.all([this.commandPool.clear(), this.forwardingPool.clear()]);
365
+ }
366
+ }
367
+ /**
368
+ * Select one SSH transport from resolved policy and keep it for the session.
369
+ * Auto prefers native OpenSSH and otherwise selects ssh2.
370
+ */
371
+ export async function createSshTransport(options, overrides = {}) {
372
+ const factories = { ...defaultSshTransportFactories, ...overrides };
373
+ const sshCommand = options.sshCommand ?? "ssh";
374
+ const transportMode = options.transport ?? "auto";
375
+ if (transportMode === "ssh2") {
376
+ return factories.createSsh2(options);
377
+ }
378
+ const openSshSupported = await factories.supportsOpenSsh(sshCommand);
379
+ if (transportMode === "openssh" && !openSshSupported) {
380
+ throw new Error("Native OpenSSH with SOCKS5 forwarding is unavailable");
381
+ }
382
+ if (openSshSupported) {
383
+ return factories.createOpenSsh(options, sshCommand);
384
+ }
385
+ if (transportMode !== "auto") {
386
+ throw new Error(`Unsupported SSH transport: ${transportMode}`);
387
+ }
388
+ return factories.createSsh2(options);
389
+ }
390
+ const defaultSshTransportFactories = {
391
+ supportsOpenSsh: async (command) => {
392
+ const { supportsNativeOpenSsh } = await import("./_ssh_openssh.js");
393
+ return supportsNativeOpenSsh(command);
394
+ },
395
+ createOpenSsh: async (options, command) => {
396
+ const { OpenSshTransport } = await import("./_ssh_openssh.js");
397
+ const transport = new OpenSshTransport(options, command);
398
+ try {
399
+ await transport.start();
400
+ return transport;
401
+ }
402
+ catch (error) {
403
+ await transport.close();
404
+ throw error;
405
+ }
406
+ },
407
+ createSsh2: async (options) => {
408
+ const { Ssh2Transport } = await import("./_ssh_ssh2.js");
409
+ const transport = new Ssh2Transport(options);
410
+ try {
411
+ await transport.start();
412
+ return transport;
413
+ }
414
+ catch (error) {
415
+ await transport.close();
416
+ throw error;
417
+ }
418
+ },
419
+ };
420
+ /** @internal Builds a remote command after clearing inherited machine credentials. */
421
+ export function sshCommandScript(command, args, cwd, env, identity) {
422
+ assertSafeSshEnvironment(env);
423
+ const root = identity.kind === "root";
424
+ const home = root ? "/root" : identity.home;
425
+ const name = root ? "root" : identity.name;
426
+ const workingDirectory = cwd ?? home;
427
+ const invocation = [command, ...scrubLoginShellCommand(command, args)].map(shellQuote).join(" ");
428
+ const environment = Object.entries({
429
+ HOME: home,
430
+ USER: name,
431
+ LOGNAME: name,
432
+ SHELL: "/bin/bash",
433
+ PWD: workingDirectory,
434
+ PATH: root
435
+ ? "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
436
+ : `${home}/.local/bin:/usr/local/bin:/usr/bin:/bin`,
437
+ DATABRICKS_CONFIG_FILE: "/dev/null",
438
+ ...env,
439
+ })
440
+ .map(([key, value]) => `${environmentName(key)}=${shellQuote(value)}`)
441
+ .join(" ");
442
+ const run = `cd -- ${shellQuote(workingDirectory)} && ${invocation}`;
443
+ const sudoArgs = root ? ["-n", "-H"] : ["-n", "-H", "-u", name];
444
+ const switched = ["sudo", ...sudoArgs, "--", "env", "-i"].map(shellQuote).join(" ");
445
+ return `${SSH_AUTH_ENVIRONMENT_SCRUB}\nexec ${switched} ${environment} '/bin/sh' '-c' ${shellQuote(run)} </dev/null`;
446
+ }
447
+ function scrubLoginShellCommand(command, args) {
448
+ const executable = command.split("/").at(-1);
449
+ if (!executable || !["sh", "bash", "zsh"].includes(executable) || args[0] !== "-lc") {
450
+ return args;
451
+ }
452
+ const [flags, script, ...rest] = args;
453
+ if (script === undefined)
454
+ return args;
455
+ return [flags, `${SSH_AUTH_ENVIRONMENT_SCRUB}\n${script}`, ...rest];
456
+ }
457
+ const SSH_AUTH_ENVIRONMENT_SCRUB = `for __dbx_tools_name in $(env | sed -n 's/^\\([A-Za-z_][A-Za-z0-9_]*\\)=.*/\\1/p'); do
458
+ case "$__dbx_tools_name" in
459
+ DATABRICKS_*|SSH_AUTH_SOCK)
460
+ unset "$__dbx_tools_name"
461
+ ;;
462
+ esac
463
+ done
464
+ export DATABRICKS_CONFIG_FILE=/dev/null`;
465
+ function assertSafeSshEnvironment(env) {
466
+ for (const name of Object.keys(env ?? {})) {
467
+ if (name === "HOME" ||
468
+ name === "USER" ||
469
+ name === "LOGNAME" ||
470
+ name === "SHELL" ||
471
+ name === "PWD" ||
472
+ name === "PATH" ||
473
+ name.startsWith("SUDO_") ||
474
+ name.startsWith("DATABRICKS_") ||
475
+ name === "SSH_AUTH_SOCK") {
476
+ throw new Error("SSH environment overlays cannot replace the Lakebox identity or restore Databricks or SSH agent credentials.");
477
+ }
478
+ }
479
+ }
480
+ function shellQuote(value) {
481
+ return `'${value.replaceAll("'", "'\\''")}'`;
482
+ }
483
+ function environmentName(value) {
484
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
485
+ throw new Error(`Invalid SSH environment variable name: ${value}`);
486
+ }
487
+ return value;
488
+ }
489
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX3NzaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9fc3NoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQThCLE1BQU0sYUFBYSxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRXpELE9BQU8sRUFBRSxVQUFVLEVBQXlDLE1BQU0sY0FBYyxDQUFDO0FBSWpGLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsdUJBQXVCLENBQUMsQ0FBQztBQUNuRCw2RUFBNkU7QUFDN0UsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztBQWlCL0IsZ0ZBQWdGO0FBQ2hGLE1BQU0sT0FBTyxVQUFVO0lBNkJWO0lBQ0E7SUE3QkYsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsWUFBWSxDQUFDO0lBQzdDLHFEQUFxRDtJQUM1QyxNQUFNLENBQW1DO0lBQ2xELG9EQUFvRDtJQUMzQyxNQUFNLENBQW1DO0lBQ2xELDJFQUEyRTtJQUNsRSxNQUFNLENBQWdDO0lBQy9DLDBDQUEwQztJQUMxQyxRQUFRLENBQXFCO0lBRVosU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN2QixZQUFZLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztJQUNqQyxZQUFZLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztJQUNqQyxhQUFhLEdBQUcsSUFBSSxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUMsYUFBYSxHQUFHLElBQUksYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFDLGVBQWUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO0lBQ3hDLFVBQVUsQ0FBa0I7SUFDckMsaUJBQWlCLENBQThCO0lBQy9DLGdCQUFnQixDQUE0QjtJ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LEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQ3RFLENBQUM7QUFFRCxNQUFNLDBCQUEwQixHQUFHOzs7Ozs7O3dDQU9LLENBQUM7QUFFekMsU0FBUyx3QkFBd0IsQ0FBQyxHQUFpRDtJQUNqRixLQUFLLE1BQU0sSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDMUMsSUFDRSxJQUFJLEtBQUssTUFBTTtZQUNmLElBQUksS0FBSyxNQUFNO1lBQ2YsSUFBSSxLQUFLLFNBQVM7WUFDbEIsSUFBSSxLQUFLLE9BQU87WUFDaEIsSUFBSSxLQUFLLEtBQUs7WUFDZCxJQUFJLEtBQUssTUFBTTtZQUNmLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO1lBQ3hCLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDO1lBQzlCLElBQUksS0FBSyxlQUFlLEVBQ3hCLENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUNiLDhHQUE4RyxDQUMvRyxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsS0FBYTtJQUMvQixPQUFPLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQztBQUMvQyxDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsS0FBYTtJQUNwQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDNUMsTUFBTSxJQUFJLEtBQUssQ0FBQywwQ0FBMEMsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFzc1Rocm91Z2gsIHR5cGUgRHVwbGV4LCB0eXBlIFJlYWRhYmxlIH0gZnJvbSBcIm5vZGU6c3RyZWFtXCI7XG5pbXBvcnQgeyBTdHJpbmdEZWNvZGVyIH0gZnJvbSBcIm5vZGU6c3RyaW5nX2RlY29kZXJcIjtcbmltcG9ydCB7IGVycm9yVXRpbHMsIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IExha2Vib3hDb21tYW5kUmVzdWx0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWxha2Vib3hcIjtcbmltcG9ydCB7IGNyZWF0ZVBvb2wsIHR5cGUgRmFjdG9yeSwgdHlwZSBPcHRpb25zLCB0eXBlIFBvb2wgfSBmcm9tIFwiZ2VuZXJpYy1wb29sXCI7XG5pbXBvcnQgdHlwZSB7IENsaWVudCBhcyBTc2gyQ2xpZW50IH0gZnJvbSBcInNzaDJcIjtcbmltcG9ydCB0eXBlIHsgU3NoMlBhdGNoTW9kZSwgU3NoVHJhbnNwb3J0TW9kZSB9IGZyb20gXCIuL3RyYW5zcG9ydC50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwibGFrZWJveDpzc2gtdHJhbnNwb3J0XCIpO1xuLyoqIE1heGltdW0gYXV0aGVudGljYXRlZCByZXNvdXJjZXMgbWFpbnRhaW5lZCBieSBlYWNoIFNTSCBvcGVyYXRpb24gcG9vbC4gKi9cbmV4cG9ydCBjb25zdCBTU0hfUE9PTF9NQVggPSAxMDtcblxuLyoqIE9uZSBjb21tYW5kIGV4ZWN1dGlvbiByZXF1ZXN0IGFmdGVyIHRoZSByZW1vdGUgc2hlbGwgc2NyaXB0IGlzIGFzc2VtYmxlZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NoRXhlY3V0aW9uT3B0aW9ucyB7XG4gIHRpbWVvdXRNczogbnVtYmVyO1xuICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbn1cblxuLyoqIFRyYW5zcG9ydCBjYWxsYmFja3Mgb3duZWQgYnkgb25lIGxpdmUgU1NIIGNvbW1hbmQuICovXG5leHBvcnQgaW50ZXJmYWNlIFNzaENvbW1hbmRFeGVjdXRpb24ge1xuICByZWFkb25seSBzaWduYWw6IEFib3J0U2lnbmFsO1xuICBzdGRvdXQoY2h1bms6IEJ1ZmZlciB8IHN0cmluZyk6IHZvaWQ7XG4gIHN0ZGVycihjaHVuazogQnVmZmVyIHwgc3RyaW5nKTogdm9pZDtcbiAgc2V0Q2FuY2VsKGNhbmNlbDogKCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4pOiB2b2lkO1xuICBmb2xsb3coY29tbWFuZDogU3NoQ29tbWFuZCk6IFByb21pc2U8bnVtYmVyPjtcbn1cblxuLyoqIExpdmUgU1NIIGNvbW1hbmQgdGhhdCBzdHJlYW1zIG91dHB1dCBhbmQgYXdhaXRzIHRvIGl0cyBudW1lcmljIGV4aXQgY29kZS4gKi9cbmV4cG9ydCBjbGFzcyBTc2hDb21tYW5kIGltcGxlbWVudHMgUHJvbWlzZTxudW1iZXI+IHtcbiAgcmVhZG9ubHkgW1N5bWJvbC50b1N0cmluZ1RhZ10gPSBcIlNzaENvbW1hbmRcIjtcbiAgLyoqIExpdmUgc3RhbmRhcmQgb3V0cHV0IGRlY29kZWQgYXMgVVRGLTggc3RyaW5ncy4gKi9cbiAgcmVhZG9ubHkgc3Rkb3V0OiBSZWFkYWJsZSAmIEFzeW5jSXRlcmFibGU8c3RyaW5nPjtcbiAgLyoqIExpdmUgc3RhbmRhcmQgZXJyb3IgZGVjb2RlZCBhcyBVVEYtOCBzdHJpbmdzLiAqL1xuICByZWFkb25seSBzdGRlcnI6IFJlYWRhYmxlICYgQXN5bmNJdGVyYWJsZTxzdHJpbmc+O1xuICAvKiogQ29tcGxldGVkIHJlc3VsdCB3aXRoIGNhcHR1cmVkIG91dHB1dCwgdGltaW5nLCBhbmQgdGltZW91dCBtZXRhZGF0YS4gKi9cbiAgcmVhZG9ubHkgcmVzdWx0OiBQcm9taXNlPExha2Vib3hDb21tYW5kUmVzdWx0PjtcbiAgLyoqIE51bWVyaWMgZXhpdCBjb2RlIGFmdGVyIGNvbXBsZXRpb24uICovXG4gIGV4aXRDb2RlOiBudW1iZXIgfCB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBzdGFydGVkQXQgPSBEYXRlLm5vdygpO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0ZG91dFN0cmVhbSA9IG5ldyBQYXNzVGhyb3VnaCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0ZGVyclN0cmVhbSA9IG5ldyBQYXNzVGhyb3VnaCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0ZG91dERlY29kZXIgPSBuZXcgU3RyaW5nRGVjb2RlcihcInV0ZjhcIik7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3RkZXJyRGVjb2RlciA9IG5ldyBTdHJpbmdEZWNvZGVyKFwidXRmOFwiKTtcbiAgcHJpdmF0ZSByZWFkb25seSBhYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29tcGxldGlvbjogUHJvbWlzZTxudW1iZXI+O1xuICBwcml2YXRlIHJlc29sdmVDb21wbGV0aW9uITogKGV4aXRDb2RlOiBudW1iZXIpID0+IHZvaWQ7XG4gIHByaXZhdGUgcmVqZWN0Q29tcGxldGlvbiE6IChlcnJvcjogdW5rbm93bikgPT4gdm9pZDtcbiAgcHJpdmF0ZSBjYW5jZWxCYWNrZW5kPzogKCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG4gIHByaXZhdGUgY2FuY2VsbGF0aW9uPzogUHJvbWlzZTx2b2lkPjtcbiAgcHJpdmF0ZSBzdGRvdXRUZXh0ID0gXCJcIjtcbiAgcHJpdmF0ZSBzdGRlcnJUZXh0ID0gXCJcIjtcbiAgcHJpdmF0ZSBzZXR0bGVkID0gZmFsc2U7XG4gIHByaXZhdGUgdGltZWRPdXQgPSBmYWxzZTtcblxuICAvKiogQ3JlYXRlcyBhIGNvbW1hbmQgYW5kIHNjaGVkdWxlcyBpdHMgYXN5bmNocm9ub3VzIHNldHVwIGFuZCBleGVjdXRpb24uICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IGNvbW1hbmQ6IHN0cmluZyxcbiAgICByZWFkb25seSBhcmdzOiByZWFkb25seSBzdHJpbmdbXSxcbiAgICBvcHRpb25zOiBTc2hFeGVjdXRpb25PcHRpb25zLFxuICAgIHN0YXJ0OiAoZXhlY3V0aW9uOiBTc2hDb21tYW5kRXhlY3V0aW9uKSA9PiBQcm9taXNlPG51bWJlcj4sXG4gICkge1xuICAgIHRoaXMuc3Rkb3V0U3RyZWFtLnNldEVuY29kaW5nKFwidXRmOFwiKTtcbiAgICB0aGlzLnN0ZGVyclN0cmVhbS5zZXRFbmNvZGluZyhcInV0ZjhcIik7XG4gICAgdGhpcy5zdGRvdXQgPSB0aGlzLnN0ZG91dFN0cmVhbSBhcyBSZWFkYWJsZSAmIEFzeW5jSXRlcmFibGU8c3RyaW5nPjtcbiAgICB0aGlzLnN0ZGVyciA9IHRoaXMuc3RkZXJyU3RyZWFtIGFzIFJlYWRhYmxlICYgQXN5bmNJdGVyYWJsZTxzdHJpbmc+O1xuICAgIHRoaXMuY29tcGxldGlvbiA9IG5ldyBQcm9taXNlPG51bWJlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5yZXNvbHZlQ29tcGxldGlvbiA9IHJlc29sdmU7XG4gICAgICB0aGlzLnJlamVjdENvbXBsZXRpb24gPSByZWplY3Q7XG4gICAgfSk7XG4gICAgdGhpcy5yZXN1bHQgPSB0aGlzLmNvbXBsZXRpb24udGhlbigoZXhpdENvZGUpID0+ICh7XG4gICAgICBzdWNjZXNzOiBleGl0Q29kZSA9PT0gMCAmJiAhdGhpcy50aW1lZE91dCxcbiAgICAgIGV4aXRDb2RlLFxuICAgICAgc3Rkb3V0OiB0aGlzLnN0ZG91dFRleHQsXG4gICAgICBzdGRlcnI6IHRoaXMuc3RkZXJyVGV4dCxcbiAgICAgIGV4ZWN1dGlvblRpbWVNczogRGF0ZS5ub3coKSAtIHRoaXMuc3RhcnRlZEF0LFxuICAgICAgLi4uKHRoaXMudGltZWRPdXQgPyB7IHRpbWVkT3V0OiB0cnVlIH0gOiB7fSksXG4gICAgICBjb21tYW5kOiB0aGlzLmNvbW1hbmQsXG4gICAgICBhcmdzOiBbLi4udGhpcy5hcmdzXSxcbiAgICB9KSk7XG4gICAgdm9pZCB0aGlzLmNvbXBsZXRpb24uY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB2b2lkIHRoaXMucmVzdWx0LmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG5cbiAgICBjb25zdCBleHRlcm5hbEFib3J0ID0gKCkgPT4ge1xuICAgICAgdm9pZCB0aGlzLmNhbmNlbCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfTtcbiAgICBpZiAob3B0aW9ucy5zaWduYWw/LmFib3J0ZWQpIGV4dGVybmFsQWJvcnQoKTtcbiAgICBlbHNlIG9wdGlvbnMuc2lnbmFsPy5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgZXh0ZXJuYWxBYm9ydCwgeyBvbmNlOiB0cnVlIH0pO1xuICAgIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMudGltZWRPdXQgPSB0cnVlO1xuICAgICAgdm9pZCB0aGlzLmNhbmNlbCgxMjQpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfSwgb3B0aW9ucy50aW1lb3V0TXMpO1xuICAgIHRpbWVvdXQudW5yZWY/LigpO1xuICAgIGNvbnN0IGNsZWFudXAgPSAoKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICBvcHRpb25zLnNpZ25hbD8ucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIGV4dGVybmFsQWJvcnQpO1xuICAgIH07XG4gICAgdm9pZCB0aGlzLmNvbXBsZXRpb24udGhlbihjbGVhbnVwLCBjbGVhbnVwKTtcblxuICAgIHF1ZXVlTWljcm90YXNrKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLnNldHRsZWQpIHJldHVybjtcbiAgICAgIHZvaWQgc3RhcnQoe1xuICAgICAgICBzaWduYWw6IHRoaXMuYWJvcnRDb250cm9sbGVyLnNpZ25hbCxcbiAgICAgICAgc3Rkb3V0OiAoY2h1bmspID0+IHRoaXMud3JpdGVPdXRwdXQoXCJzdGRvdXRcIiwgY2h1bmspLFxuICAgICAgICBzdGRlcnI6IChjaHVuaykgPT4gdGhpcy53cml0ZU91dHB1dChcInN0ZGVyclwiLCBjaHVuayksXG4gICAgICAgIHNldENhbmNlbDogKGNhbmNlbCkgPT4ge1xuICAgICAgICAgIHRoaXMuY2FuY2VsQmFja2VuZCA9IGNhbmNlbDtcbiAgICAgICAgICBpZiAodGhpcy5hYm9ydENvbnRyb2xsZXIuc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgICAgICAgIHZvaWQgdGhpcy5pbnZva2VDYW5jZWwoKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZm9sbG93OiAoY29tbWFuZCkgPT4gdGhpcy5mb2xsb3coY29tbWFuZCksXG4gICAgICB9KS50aGVuKFxuICAgICAgICAoZXhpdENvZGUpID0+IHRoaXMuZmluaXNoKGV4aXRDb2RlKSxcbiAgICAgICAgKGVycm9yKSA9PiB0aGlzLmZhaWwoZXJyb3IpLFxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBDYW5jZWwgdGhlIGNvbW1hbmQgb25jZS4gQ2FsbGVyIGNhbmNlbGxhdGlvbiByZXNvbHZlcyB3aXRoIGV4aXQgY29kZSAxMzAuICovXG4gIGNhbmNlbChleGl0Q29kZSA9IDEzMCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLnNldHRsZWQpIHJldHVybiB0aGlzLmNhbmNlbGxhdGlvbiA/PyBQcm9taXNlLnJlc29sdmUoKTtcbiAgICBpZiAoIXRoaXMuYWJvcnRDb250cm9sbGVyLnNpZ25hbC5hYm9ydGVkKSB0aGlzLmFib3J0Q29udHJvbGxlci5hYm9ydCgpO1xuICAgIGNvbnN0IGNhbmNlbGxhdGlvbiA9IHRoaXMuaW52b2tlQ2FuY2VsKCk7XG4gICAgdGhpcy5maW5pc2goZXhpdENvZGUpO1xuICAgIHJldHVybiBjYW5jZWxsYXRpb247XG4gIH1cblxuICB0aGVuPFRSZXN1bHQxID0gbnVtYmVyLCBUUmVzdWx0MiA9IG5ldmVyPihcbiAgICBvbmZ1bGZpbGxlZD86ICgodmFsdWU6IG51bWJlcikgPT4gVFJlc3VsdDEgfCBQcm9taXNlTGlrZTxUUmVzdWx0MT4pIHwgbnVsbCxcbiAgICBvbnJlamVjdGVkPzogKChyZWFzb246IHVua25vd24pID0+IFRSZXN1bHQyIHwgUHJvbWlzZUxpa2U8VFJlc3VsdDI+KSB8IG51bGwsXG4gICk6IFByb21pc2U8VFJlc3VsdDEgfCBUUmVzdWx0Mj4ge1xuICAgIHJldHVybiB0aGlzLmNvbXBsZXRpb24udGhlbihvbmZ1bGZpbGxlZCwgb25yZWplY3RlZCk7XG4gIH1cblxuICBjYXRjaDxUUmVzdWx0ID0gbmV2ZXI+KFxuICAgIG9ucmVqZWN0ZWQ/OiAoKHJlYXNvbjogdW5rbm93bikgPT4gVFJlc3VsdCB8IFByb21pc2VMaWtlPFRSZXN1bHQ+KSB8IG51bGwsXG4gICk6IFByb21pc2U8bnVtYmVyIHwgVFJlc3VsdD4ge1xuICAgIHJldHVybiB0aGlzLmNvbXBsZXRpb24uY2F0Y2gob25yZWplY3RlZCk7XG4gIH1cblxuICBmaW5hbGx5KG9uZmluYWxseT86ICgoKSA9PiB2b2lkKSB8IG51bGwpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIHJldHVybiB0aGlzLmNvbXBsZXRpb24uZmluYWxseShvbmZpbmFsbHkgPz8gdW5kZWZpbmVkKTtcbiAgfVxuXG4gIHByaXZhdGUgaW52b2tlQ2FuY2VsKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmNhbmNlbGxhdGlvbikgcmV0dXJuIHRoaXMuY2FuY2VsbGF0aW9uO1xuICAgIGlmICghdGhpcy5jYW5jZWxCYWNrZW5kKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgY29uc3QgY2FuY2VsQmFja2VuZCA9IHRoaXMuY2FuY2VsQmFja2VuZDtcbiAgICB0aGlzLmNhbmNlbGxhdGlvbiA9IFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAudGhlbigoKSA9PiBjYW5jZWxCYWNrZW5kKCkpXG4gICAgICAudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIHZvaWQgdGhpcy5jYW5jZWxsYXRpb24uY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICByZXR1cm4gdGhpcy5jYW5jZWxsYXRpb247XG4gIH1cblxuICBwcml2YXRlIHdyaXRlT3V0cHV0KHN0cmVhbTogXCJzdGRvdXRcIiB8IFwic3RkZXJyXCIsIGNodW5rOiBCdWZmZXIgfCBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZXR0bGVkKSByZXR1cm47XG4gICAgY29uc3QgZGVjb2RlciA9IHN0cmVhbSA9PT0gXCJzdGRvdXRcIiA/IHRoaXMuc3Rkb3V0RGVjb2RlciA6IHRoaXMuc3RkZXJyRGVjb2RlcjtcbiAgICBjb25zdCB2YWx1ZSA9IGRlY29kZXIud3JpdGUodHlwZW9mIGNodW5rID09PSBcInN0cmluZ1wiID8gQnVmZmVyLmZyb20oY2h1bmspIDogY2h1bmspO1xuICAgIGlmICghdmFsdWUpIHJldHVybjtcbiAgICBpZiAoc3RyZWFtID09PSBcInN0ZG91dFwiKSB7XG4gICAgICB0aGlzLnN0ZG91dFRleHQgKz0gdmFsdWU7XG4gICAgICB0aGlzLnN0ZG91dFN0cmVhbS53cml0ZSh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc3RkZXJyVGV4dCArPSB2YWx1ZTtcbiAgICAgIHRoaXMuc3RkZXJyU3RyZWFtLndyaXRlKHZhbHVlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZvbGxvdyhjb21tYW5kOiBTc2hDb21tYW5kKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICB0aGlzLmNhbmNlbEJhY2tlbmQgPSAoKSA9PiBjb21tYW5kLmNhbmNlbCgpO1xuICAgIGlmICh0aGlzLmFib3J0Q29udHJvbGxlci5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgdm9pZCB0aGlzLmludm9rZUNhbmNlbCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIGNvbnN0IHN0ZG91dCA9IHRoaXMucGlwZShjb21tYW5kLnN0ZG91dCwgKGNodW5rKSA9PiB0aGlzLndyaXRlT3V0cHV0KFwic3Rkb3V0XCIsIGNodW5rKSk7XG4gICAgY29uc3Qgc3RkZXJyID0gdGhpcy5waXBlKGNvbW1hbmQuc3RkZXJyLCAoY2h1bmspID0+IHRoaXMud3JpdGVPdXRwdXQoXCJzdGRlcnJcIiwgY2h1bmspKTtcbiAgICBjb25zdCBleGl0Q29kZSA9IGF3YWl0IGNvbW1hbmQ7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoW3N0ZG91dCwgc3RkZXJyXSk7XG4gICAgcmV0dXJuIGV4aXRDb2RlO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwaXBlKHN0cmVhbTogQXN5bmNJdGVyYWJsZTxzdHJpbmc+LCB3cml0ZTogKGNodW5rOiBzdHJpbmcpID0+IHZvaWQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgYXdhaXQgKGNvbnN0IGNodW5rIG9mIHN0cmVhbSkgd3JpdGUoY2h1bmspO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5pc2goZXhpdENvZGU6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh0aGlzLnNldHRsZWQpIHJldHVybjtcbiAgICB0aGlzLnNldHRsZWQgPSB0cnVlO1xuICAgIHRoaXMuZXhpdENvZGUgPSBleGl0Q29kZTtcbiAgICB0aGlzLmNsb3NlT3V0cHV0KCk7XG4gICAgdGhpcy5yZXNvbHZlQ29tcGxldGlvbihleGl0Q29kZSk7XG4gIH1cblxuICBwcml2YXRlIGZhaWwoZXJyb3I6IHVua25vd24pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZXR0bGVkKSByZXR1cm47XG4gICAgdGhpcy5zZXR0bGVkID0gdHJ1ZTtcbiAgICB0aGlzLmNsb3NlT3V0cHV0KCk7XG4gICAgdGhpcy5yZWplY3RDb21wbGV0aW9uKGVycm9yKTtcbiAgfVxuXG4gIHByaXZhdGUgY2xvc2VPdXRwdXQoKTogdm9pZCB7XG4gICAgY29uc3Qgc3Rkb3V0UmVtYWluZGVyID0gdGhpcy5zdGRvdXREZWNvZGVyLmVuZCgpO1xuICAgIGNvbnN0IHN0ZGVyclJlbWFpbmRlciA9IHRoaXMuc3RkZXJyRGVjb2Rlci5lbmQoKTtcbiAgICBpZiAoc3Rkb3V0UmVtYWluZGVyKSB7XG4gICAgICB0aGlzLnN0ZG91dFRleHQgKz0gc3Rkb3V0UmVtYWluZGVyO1xuICAgICAgdGhpcy5zdGRvdXRTdHJlYW0ud3JpdGUoc3Rkb3V0UmVtYWluZGVyKTtcbiAgICB9XG4gICAgaWYgKHN0ZGVyclJlbWFpbmRlcikge1xuICAgICAgdGhpcy5zdGRlcnJUZXh0ICs9IHN0ZGVyclJlbWFpbmRlcjtcbiAgICAgIHRoaXMuc3RkZXJyU3RyZWFtLndyaXRlKHN0ZGVyclJlbWFpbmRlcik7XG4gICAgfVxuICAgIHRoaXMuc3Rkb3V0U3RyZWFtLmVuZCgpO1xuICAgIHRoaXMuc3RkZXJyU3RyZWFtLmVuZCgpO1xuICB9XG59XG5cbi8qKiBDb25uZWN0aW9uIGRldGFpbHMgc2hhcmVkIGJ5IG5hdGl2ZSBPcGVuU1NIIGFuZCB0aGUgZ3VhcmRlZCBzc2gyIGZhbGxiYWNrLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTc2hUcmFuc3BvcnRPcHRpb25zIHtcbiAgaG9zdDogc3RyaW5nO1xuICBjb25uZWN0SG9zdDogc3RyaW5nO1xuICBwb3J0OiBudW1iZXI7XG4gIHVzZXJuYW1lOiBzdHJpbmc7XG4gIHByaXZhdGVLZXlQYXRoOiBzdHJpbmc7XG4gIGtub3duSG9zdHNQYXRoOiBzdHJpbmc7XG4gIGNvbm5lY3RUaW1lb3V0TXM6IG51bWJlcjtcbiAgc3NoMkNsaWVudDogU3NoMkNsaWVudDtcbiAgY3JlYXRlU3NoMkNvbW1hbmRDbGllbnQ6ICgpID0+IFByb21pc2U8U3NoMkNsaWVudD47XG4gIHRyYW5zcG9ydD86IFNzaFRyYW5zcG9ydE1vZGU7XG4gIHNzaDJQYXRjaD86IFNzaDJQYXRjaE1vZGU7XG4gIHNzaENvbW1hbmQ/OiBzdHJpbmc7XG59XG5cbi8qKiBTZWxlY3RlZCBjb21tYW5kIGFuZCByZW1vdGUgVENQIHRyYW5zcG9ydCBmb3Igb25lIHZlcmlmaWVkIFNTSCBnYXRld2F5LiAqL1xuZXhwb3J0IGludGVyZmFjZSBTc2hUcmFuc3BvcnQge1xuICByZWFkb25seSBraW5kOiBcIm9wZW5zc2hcIiB8IFwic3NoMlwiO1xuICBydW4oc2NyaXB0OiBzdHJpbmcsIGV4ZWN1dGlvbjogU3NoQ29tbWFuZEV4ZWN1dGlvbik6IFByb21pc2U8bnVtYmVyPjtcbiAgY29ubmVjdChyZW1vdGVIb3N0OiBzdHJpbmcsIHJlbW90ZVBvcnQ6IG51bWJlcik6IFByb21pc2U8RHVwbGV4PjtcbiAgY2xvc2UoKTogUHJvbWlzZTx2b2lkPjtcbn1cblxuLyoqIEFzeW5jIGxpZmVjeWNsZSB1c2VkIGJ5IGJvdGggbmF0aXZlIE9wZW5TU0ggYW5kIHNzaDIgY29ubmVjdGlvbiBwb29scy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NoUmVzb3VyY2VMaWZlY3ljbGU8VD4ge1xuICBjcmVhdGUoKTogUHJvbWlzZTxUPjtcbiAgZGVzdHJveShyZXNvdXJjZTogVCk6IFByb21pc2U8dm9pZD47XG4gIHRlc3QocmVzb3VyY2U6IFQpOiBQcm9taXNlPGJvb2xlYW4+O1xufVxuXG4vKiogT3B0aW9uYWwgcG9vbCBvdmVycmlkZXMgdXNlZCBieSB0cmFuc3BvcnQgdGVzdHMgYW5kIGNvbnN0cmFpbmVkIHJ1bnRpbWVzLiAqL1xuZXhwb3J0IHR5cGUgU3NoUG9vbE9wdGlvbnMgPSBQaWNrPFxuICBPcHRpb25zLFxuICB8IFwibWF4XCJcbiAgfCBcImFjcXVpcmVUaW1lb3V0TWlsbGlzXCJcbiAgfCBcImlkbGVUaW1lb3V0TWlsbGlzXCJcbiAgfCBcImV2aWN0aW9uUnVuSW50ZXJ2YWxNaWxsaXNcIlxuICB8IFwibnVtVGVzdHNQZXJFdmljdGlvblJ1blwiXG4+O1xuXG4vKipcbiAqIEV4Y2x1c2l2ZSwgc2luZ2xlLW9wZXJhdGlvbiBTU0ggcmVzb3VyY2UgcG9vbC5cbiAqXG4gKiBUaGUgY29tbWFuZCBwb29sIGtlZXBzIG9uZSBhdXRoZW50aWNhdGVkIHJlc291cmNlIHdhcm0uIEZvcndhcmRpbmcgdXNlcyBhXG4gKiBzZXBhcmF0ZSB6ZXJvLW1pbmltdW0gcG9vbCBzbyBsb25nLWxpdmVkIFdlYlNvY2tldHMgY2Fubm90IGNvbnN1bWUgdGhlIHdhcm1cbiAqIGNvbW1hbmQgY29ubmVjdGlvbi4gRXZlcnkgYm9ycm93ZWQgcmVzb3VyY2UgaXMgZGVzdHJveWVkIGFmdGVyIGl0cyBjb21tYW5kXG4gKiBvciBmb3J3YXJkZWQgc3RyZWFtIGJlY2F1c2UgdGhlIERhdGFicmlja3MgUnVzc2ggZ2F0ZXdheSBtYXkgYWNjZXB0IG9ubHkgb25lXG4gKiBvcGVyYXRpb24gZHVyaW5nIGEgY29ubmVjdGlvbidzIGxpZmV0aW1lLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUG9vbGVkU3NoVHJhbnNwb3J0PFQ+IGltcGxlbWVudHMgU3NoVHJhbnNwb3J0IHtcbiAgYWJzdHJhY3QgcmVhZG9ubHkga2luZDogXCJvcGVuc3NoXCIgfCBcInNzaDJcIjtcblxuICBwcml2YXRlIHJlYWRvbmx5IGNvbW1hbmRQb29sOiBQb29sPFQ+O1xuICBwcml2YXRlIHJlYWRvbmx5IGZvcndhcmRpbmdQb29sOiBQb29sPFQ+O1xuICBwcml2YXRlIHJlYWRvbmx5IGFjdGl2ZVJlc291cmNlcyA9IG5ldyBNYXA8VCwgUG9vbDxUPj4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBzZWVkZWRSZXNvdXJjZXM6IFRbXSA9IFtdO1xuICBwcml2YXRlIGxhc3RDcmVhdGVFcnJvcjogdW5rbm93bjtcbiAgcHJpdmF0ZSBzdGFydGluZz86IFByb21pc2U8dm9pZD47XG4gIHByaXZhdGUgY2xvc2luZz86IFByb21pc2U8dm9pZD47XG4gIHByaXZhdGUgY2xvc2VkID0gZmFsc2U7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbGlmZWN5Y2xlOiBTc2hSZXNvdXJjZUxpZmVjeWNsZTxUPixcbiAgICBvcHRpb25zOiBTc2hQb29sT3B0aW9ucyA9IHt9LFxuICApIHtcbiAgICBjb25zdCBmYWN0b3J5OiBGYWN0b3J5PFQ+ID0ge1xuICAgICAgY3JlYXRlOiBhc3luYyAoKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzb3VyY2UgPSB0aGlzLnNlZWRlZFJlc291cmNlcy5zaGlmdCgpID8/IChhd2FpdCBsaWZlY3ljbGUuY3JlYXRlKCkpO1xuICAgICAgICAgIHRoaXMubGFzdENyZWF0ZUVycm9yID0gdW5kZWZpbmVkO1xuICAgICAgICAgIHJldHVybiByZXNvdXJjZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICB0aGlzLmxhc3RDcmVhdGVFcnJvciA9IGVycm9yO1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZGVzdHJveTogKHJlc291cmNlKSA9PiBsaWZlY3ljbGUuZGVzdHJveShyZXNvdXJjZSksXG4gICAgICB2YWxpZGF0ZTogYXN5bmMgKHJlc291cmNlKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IGxpZmVjeWNsZS50ZXN0KHJlc291cmNlKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH07XG4gICAgY29uc3QgZGVmYXVsdHM6IE9wdGlvbnMgPSB7XG4gICAgICBtYXg6IG9wdGlvbnMubWF4ID8/IFNTSF9QT09MX01BWCxcbiAgICAgIGFjcXVpcmVUaW1lb3V0TWlsbGlzOiBvcHRpb25zLmFjcXVpcmVUaW1lb3V0TWlsbGlzID8/IDE1XzAwMCxcbiAgICAgIGlkbGVUaW1lb3V0TWlsbGlzOiBvcHRpb25zLmlkbGVUaW1lb3V0TWlsbGlzID8/IDMwXzAwMCxcbiAgICAgIGV2aWN0aW9uUnVuSW50ZXJ2YWxNaWxsaXM6IG9wdGlvbnMuZXZpY3Rpb25SdW5JbnRlcnZhbE1pbGxpcyA/PyAxMF8wMDAsXG4gICAgICBudW1UZXN0c1BlckV2aWN0aW9uUnVuOiBvcHRpb25zLm51bVRlc3RzUGVyRXZpY3Rpb25SdW4gPz8gMyxcbiAgICAgIHRlc3RPbkJvcnJvdzogdHJ1ZSxcbiAgICAgIGF1dG9zdGFydDogZmFsc2UsXG4gICAgfTtcbiAgICB0aGlzLmNvbW1hbmRQb29sID0gY3JlYXRlUG9vbChmYWN0b3J5LCB7IC4uLmRlZmF1bHRzLCBtaW46IDEgfSk7XG4gICAgdGhpcy5mb3J3YXJkaW5nUG9vbCA9IGNyZWF0ZVBvb2woZmFjdG9yeSwgeyAuLi5kZWZhdWx0cywgbWluOiAwIH0pO1xuICB9XG5cbiAgLyoqIFN0YXJ0cyBib3RoIHBvb2xzIGFuZCB3YWl0cyB1bnRpbCBvbmUgdGVzdGVkIGNvbW1hbmQgcmVzb3VyY2UgaXMgd2FybS4gKi9cbiAgc3RhcnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2xvc2VkKSByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKGAke3RoaXMua2luZH0gU1NIIHRyYW5zcG9ydCBpcyBjbG9zZWRgKSk7XG4gICAgaWYgKHRoaXMuc3RhcnRpbmcpIHJldHVybiB0aGlzLnN0YXJ0aW5nO1xuICAgIHRoaXMuc3RhcnRpbmcgPSB0aGlzLnN0YXJ0UG9vbHMoKTtcbiAgICB2b2lkIHRoaXMuc3RhcnRpbmdcbiAgICAgIC5jYXRjaCgoKSA9PiB0aGlzLmNsb3NlKCkpXG4gICAgICAuY2F0Y2goKGVycm9yKSA9PlxuICAgICAgICBsb2dnZXIud2FybihcImZhaWxlZCB0byBjbG9zZSBTU0ggdHJhbnNwb3J0IGFmdGVyIHN0YXJ0dXAgZmFpbHVyZVwiLCB7XG4gICAgICAgICAga2luZDogdGhpcy5raW5kLFxuICAgICAgICAgIGVycm9yOiBlcnJvclV0aWxzLnRvRXJyb3IoZXJyb3IpLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc3RhcnRpbmc7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHN0YXJ0UG9vbHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2xvc2VkKSB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5raW5kfSBTU0ggdHJhbnNwb3J0IGlzIGNsb3NlZGApO1xuICAgIGNvbnN0IHJlc291cmNlID0gYXdhaXQgdGhpcy5saWZlY3ljbGUuY3JlYXRlKCk7XG4gICAgaWYgKHRoaXMuY2xvc2VkKSB7XG4gICAgICBhd2FpdCB0aGlzLmxpZmVjeWNsZS5kZXN0cm95KHJlc291cmNlKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLmtpbmR9IFNTSCB0cmFuc3BvcnQgaXMgY2xvc2VkYCk7XG4gICAgfVxuICAgIHRoaXMuc2VlZGVkUmVzb3VyY2VzLnB1c2gocmVzb3VyY2UpO1xuICAgIHRoaXMuY29tbWFuZFBvb2wuc3RhcnQoKTtcbiAgICB0aGlzLmZvcndhcmRpbmdQb29sLnN0YXJ0KCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc291cmNlID0gYXdhaXQgdGhpcy5jb21tYW5kUG9vbC5hY3F1aXJlKCk7XG4gICAgICBhd2FpdCB0aGlzLmNvbW1hbmRQb29sLnJlbGVhc2UocmVzb3VyY2UpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyB0aGlzLmxhc3RDcmVhdGVFcnJvciA/PyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICBhc3luYyBydW4oc2NyaXB0OiBzdHJpbmcsIGV4ZWN1dGlvbjogU3NoQ29tbWFuZEV4ZWN1dGlvbik6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgcmVzb3VyY2UgPSBhd2FpdCB0aGlzLmFjcXVpcmUodGhpcy5jb21tYW5kUG9vbCk7XG4gICAgdHJ5IHtcbiAgICAgIGlmIChleGVjdXRpb24uc2lnbmFsLmFib3J0ZWQpIHJldHVybiAxMzA7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5ydW5XaXRoUmVzb3VyY2UocmVzb3VyY2UsIHNjcmlwdCwgZXhlY3V0aW9uKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgdGhpcy5kZXN0cm95KHRoaXMuY29tbWFuZFBvb2wsIHJlc291cmNlKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjb25uZWN0KHJlbW90ZUhvc3Q6IHN0cmluZywgcmVtb3RlUG9ydDogbnVtYmVyKTogUHJvbWlzZTxEdXBsZXg+IHtcbiAgICBjb25zdCBmaXJzdCA9IGF3YWl0IHRoaXMuYWNxdWlyZSh0aGlzLmZvcndhcmRpbmdQb29sKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY29ubmVjdFdpdGhCb3Jyb3dlZFJlc291cmNlKGZpcnN0LCByZW1vdGVIb3N0LCByZW1vdGVQb3J0KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgYXdhaXQgdGhpcy5kZXN0cm95KHRoaXMuZm9yd2FyZGluZ1Bvb2wsIGZpcnN0KTtcbiAgICAgIGlmICh0aGlzLmNsb3NlZCkgdGhyb3cgZXJyb3I7XG4gICAgfVxuICAgIGNvbnN0IHJldHJ5ID0gYXdhaXQgdGhpcy5hY3F1aXJlKHRoaXMuZm9yd2FyZGluZ1Bvb2wpO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5jb25uZWN0V2l0aEJvcnJvd2VkUmVzb3VyY2UocmV0cnksIHJlbW90ZUhvc3QsIHJlbW90ZVBvcnQpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3kodGhpcy5mb3J3YXJkaW5nUG9vbCwgcmV0cnkpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgY2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2xvc2luZykgcmV0dXJuIHRoaXMuY2xvc2luZztcbiAgICB0aGlzLmNsb3NlZCA9IHRydWU7XG4gICAgdGhpcy5jbG9zaW5nID0gdGhpcy5jbG9zZVBvb2xzKCk7XG4gICAgcmV0dXJuIHRoaXMuY2xvc2luZztcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBydW5XaXRoUmVzb3VyY2UoXG4gICAgcmVzb3VyY2U6IFQsXG4gICAgc2NyaXB0OiBzdHJpbmcsXG4gICAgZXhlY3V0aW9uOiBTc2hDb21tYW5kRXhlY3V0aW9uLFxuICApOiBQcm9taXNlPG51bWJlcj47XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGNvbm5lY3RXaXRoUmVzb3VyY2UoXG4gICAgcmVzb3VyY2U6IFQsXG4gICAgcmVtb3RlSG9zdDogc3RyaW5nLFxuICAgIHJlbW90ZVBvcnQ6IG51bWJlcixcbiAgKTogUHJvbWlzZTxEdXBsZXg+O1xuXG4gIHByaXZhdGUgYXN5bmMgY29ubmVjdFdpdGhCb3Jyb3dlZFJlc291cmNlKFxuICAgIHJlc291cmNlOiBULFxuICAgIHJlbW90ZUhvc3Q6IHN0cmluZyxcbiAgICByZW1vdGVQb3J0OiBudW1iZXIsXG4gICk6IFByb21pc2U8RHVwbGV4PiB7XG4gICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgdGhpcy5jb25uZWN0V2l0aFJlc291cmNlKHJlc291cmNlLCByZW1vdGVIb3N0LCByZW1vdGVQb3J0KTtcbiAgICBsZXQgZGlzcG9zZWQgPSBmYWxzZTtcbiAgICBjb25zdCBkaXNwb3NlID0gKCkgPT4ge1xuICAgICAgaWYgKGRpc3Bvc2VkKSByZXR1cm47XG4gICAgICBkaXNwb3NlZCA9IHRydWU7XG4gICAgICB2b2lkIHRoaXMuZGVzdHJveSh0aGlzLmZvcndhcmRpbmdQb29sLCByZXNvdXJjZSk7XG4gICAgfTtcbiAgICBzdHJlYW0ub25jZShcImNsb3NlXCIsIGRpc3Bvc2UpO1xuICAgIHN0cmVhbS5vbmNlKFwiZXJyb3JcIiwgZGlzcG9zZSk7XG4gICAgaWYgKHN0cmVhbS5kZXN0cm95ZWQpIGRpc3Bvc2UoKTtcbiAgICByZXR1cm4gc3RyZWFtO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBhY3F1aXJlKHBvb2w6IFBvb2w8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICBpZiAodGhpcy5jbG9zZWQpIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLmtpbmR9IFNTSCB0cmFuc3BvcnQgaXMgY2xvc2VkYCk7XG4gICAgbGV0IHJlc291cmNlOiBUO1xuICAgIHRyeSB7XG4gICAgICByZXNvdXJjZSA9IGF3YWl0IHBvb2wuYWNxdWlyZSgpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyB0aGlzLmxhc3RDcmVhdGVFcnJvciA/PyBlcnJvcjtcbiAgICB9XG4gICAgdGhpcy5hY3RpdmVSZXNvdXJjZXMuc2V0KHJlc291cmNlLCBwb29sKTtcbiAgICBpZiAodGhpcy5jbG9zZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMuZGVzdHJveShwb29sLCByZXNvdXJjZSk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5raW5kfSBTU0ggdHJhbnNwb3J0IGlzIGNsb3NlZGApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzb3VyY2U7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRlc3Ryb3kocG9vbDogUG9vbDxUPiwgcmVzb3VyY2U6IFQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5hY3RpdmVSZXNvdXJjZXMuZ2V0KHJlc291cmNlKSAhPT0gcG9vbCkgcmV0dXJuO1xuICAgIHRoaXMuYWN0aXZlUmVzb3VyY2VzLmRlbGV0ZShyZXNvdXJjZSk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHBvb2wuZGVzdHJveShyZXNvdXJjZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKFwiZmFpbGVkIHRvIGRlc3Ryb3kgcG9vbGVkIFNTSCByZXNvdXJjZVwiLCB7XG4gICAgICAgIGtpbmQ6IHRoaXMua2luZCxcbiAgICAgICAgZXJyb3I6IGVycm9yVXRpbHMudG9FcnJvcihlcnJvciksXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNsb3NlUG9vbHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5zdGFydGluZz8uY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICBjb25zdCBjb21tYW5kRHJhaW4gPSB0aGlzLmNvbW1hbmRQb29sLmRyYWluKCk7XG4gICAgY29uc3QgZm9yd2FyZGluZ0RyYWluID0gdGhpcy5mb3J3YXJkaW5nUG9vbC5kcmFpbigpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgWy4uLnRoaXMuYWN0aXZlUmVzb3VyY2VzXS5tYXAoKFtyZXNvdXJjZSwgcG9vbF0pID0+IHRoaXMuZGVzdHJveShwb29sLCByZXNvdXJjZSkpLFxuICAgICk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoW2NvbW1hbmREcmFpbiwgZm9yd2FyZGluZ0RyYWluXSk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoW3RoaXMuY29tbWFuZFBvb2wuY2xlYXIoKSwgdGhpcy5mb3J3YXJkaW5nUG9vbC5jbGVhcigpXSk7XG4gIH1cbn1cblxuLyoqIEluamVjdGFibGUgdHJhbnNwb3J0IGNvbnN0cnVjdG9ycyB1c2VkIHRvIGlzb2xhdGUgcG9saWN5IHNlbGVjdGlvbiBpbiB0ZXN0cy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NoVHJhbnNwb3J0RmFjdG9yaWVzIHtcbiAgc3VwcG9ydHNPcGVuU3NoKGNvbW1hbmQ6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj47XG4gIGNyZWF0ZU9wZW5Tc2gob3B0aW9uczogU3NoVHJhbnNwb3J0T3B0aW9ucywgY29tbWFuZDogc3RyaW5nKTogUHJvbWlzZTxTc2hUcmFuc3BvcnQ+O1xuICBjcmVhdGVTc2gyKG9wdGlvbnM6IFNzaFRyYW5zcG9ydE9wdGlvbnMpOiBQcm9taXNlPFNzaFRyYW5zcG9ydD47XG59XG5cbi8qKlxuICogU2VsZWN0IG9uZSBTU0ggdHJhbnNwb3J0IGZyb20gcmVzb2x2ZWQgcG9saWN5IGFuZCBrZWVwIGl0IGZvciB0aGUgc2Vzc2lvbi5cbiAqIEF1dG8gcHJlZmVycyBuYXRpdmUgT3BlblNTSCBhbmQgb3RoZXJ3aXNlIHNlbGVjdHMgc3NoMi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVNzaFRyYW5zcG9ydChcbiAgb3B0aW9uczogU3NoVHJhbnNwb3J0T3B0aW9ucyxcbiAgb3ZlcnJpZGVzOiBQYXJ0aWFsPFNzaFRyYW5zcG9ydEZhY3Rvcmllcz4gPSB7fSxcbik6IFByb21pc2U8U3NoVHJhbnNwb3J0PiB7XG4gIGNvbnN0IGZhY3RvcmllcyA9IHsgLi4uZGVmYXVsdFNzaFRyYW5zcG9ydEZhY3RvcmllcywgLi4ub3ZlcnJpZGVzIH07XG4gIGNvbnN0IHNzaENvbW1hbmQgPSBvcHRpb25zLnNzaENvbW1hbmQgPz8gXCJzc2hcIjtcbiAgY29uc3QgdHJhbnNwb3J0TW9kZSA9IG9wdGlvbnMudHJhbnNwb3J0ID8/IFwiYXV0b1wiO1xuICBpZiAodHJhbnNwb3J0TW9kZSA9PT0gXCJzc2gyXCIpIHtcbiAgICByZXR1cm4gZmFjdG9yaWVzLmNyZWF0ZVNzaDIob3B0aW9ucyk7XG4gIH1cbiAgY29uc3Qgb3BlblNzaFN1cHBvcnRlZCA9IGF3YWl0IGZhY3Rvcmllcy5zdXBwb3J0c09wZW5Tc2goc3NoQ29tbWFuZCk7XG4gIGlmICh0cmFuc3BvcnRNb2RlID09PSBcIm9wZW5zc2hcIiAmJiAhb3BlblNzaFN1cHBvcnRlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIk5hdGl2ZSBPcGVuU1NIIHdpdGggU09DS1M1IGZvcndhcmRpbmcgaXMgdW5hdmFpbGFibGVcIik7XG4gIH1cbiAgaWYgKG9wZW5Tc2hTdXBwb3J0ZWQpIHtcbiAgICByZXR1cm4gZmFjdG9yaWVzLmNyZWF0ZU9wZW5Tc2gob3B0aW9ucywgc3NoQ29tbWFuZCk7XG4gIH1cbiAgaWYgKHRyYW5zcG9ydE1vZGUgIT09IFwiYXV0b1wiKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBTU0ggdHJhbnNwb3J0OiAke3RyYW5zcG9ydE1vZGV9YCk7XG4gIH1cbiAgcmV0dXJuIGZhY3Rvcmllcy5jcmVhdGVTc2gyKG9wdGlvbnMpO1xufVxuXG5jb25zdCBkZWZhdWx0U3NoVHJhbnNwb3J0RmFjdG9yaWVzOiBTc2hUcmFuc3BvcnRGYWN0b3JpZXMgPSB7XG4gIHN1cHBvcnRzT3BlblNzaDogYXN5bmMgKGNvbW1hbmQpID0+IHtcbiAgICBjb25zdCB7IHN1cHBvcnRzTmF0aXZlT3BlblNzaCB9ID0gYXdhaXQgaW1wb3J0KFwiLi9fc3NoX29wZW5zc2gudHNcIik7XG4gICAgcmV0dXJuIHN1cHBvcnRzTmF0aXZlT3BlblNzaChjb21tYW5kKTtcbiAgfSxcbiAgY3JlYXRlT3BlblNzaDogYXN5bmMgKG9wdGlvbnMsIGNvbW1hbmQpID0+IHtcbiAgICBjb25zdCB7IE9wZW5Tc2hUcmFuc3BvcnQgfSA9IGF3YWl0IGltcG9ydChcIi4vX3NzaF9vcGVuc3NoLnRzXCIpO1xuICAgIGNvbnN0IHRyYW5zcG9ydCA9IG5ldyBPcGVuU3NoVHJhbnNwb3J0KG9wdGlvbnMsIGNvbW1hbmQpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0cmFuc3BvcnQuc3RhcnQoKTtcbiAgICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGF3YWl0IHRyYW5zcG9ydC5jbG9zZSgpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9LFxuICBjcmVhdGVTc2gyOiBhc3luYyAob3B0aW9ucykgPT4ge1xuICAgIGNvbnN0IHsgU3NoMlRyYW5zcG9ydCB9ID0gYXdhaXQgaW1wb3J0KFwiLi9fc3NoX3NzaDIudHNcIik7XG4gICAgY29uc3QgdHJhbnNwb3J0ID0gbmV3IFNzaDJUcmFuc3BvcnQob3B0aW9ucyk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRyYW5zcG9ydC5zdGFydCgpO1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgYXdhaXQgdHJhbnNwb3J0LmNsb3NlKCk7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH0sXG59O1xuXG4vKipcbiAqIEFjY291bnQgdGhhdCBydW5zIG9uZSByZW1vdGUgY29tbWFuZC5cbiAqXG4gKiBgdXNlcmAgdGFyZ2V0cyBhIGxvY2tlZCwgbm9uLXN1ZG8gTGFrZWJveCBhY2NvdW50LiBgcm9vdGAgaXMgcmVzZXJ2ZWQgZm9yXG4gKiBmaXhlZCBwYWNrYWdlLW93bmVkIGJvb3RzdHJhcCBzY3JpcHRzIGFuZCBpcyBuZXZlciByZWFjaGFibGUgZnJvbSBSRVNULFxuICogYWdlbnQgdG9vbHMsIG9yIHNlcnZpY2UgZGVmaW5pdGlvbnMuXG4gKi9cbmV4cG9ydCB0eXBlIFNzaENvbW1hbmRJZGVudGl0eSA9IHsga2luZDogXCJ1c2VyXCI7IG5hbWU6IHN0cmluZzsgaG9tZTogc3RyaW5nIH0gfCB7IGtpbmQ6IFwicm9vdFwiIH07XG5cbi8qKiBAaW50ZXJuYWwgQnVpbGRzIGEgcmVtb3RlIGNvbW1hbmQgYWZ0ZXIgY2xlYXJpbmcgaW5oZXJpdGVkIG1hY2hpbmUgY3JlZGVudGlhbHMuICovXG5leHBvcnQgZnVuY3Rpb24gc3NoQ29tbWFuZFNjcmlwdChcbiAgY29tbWFuZDogc3RyaW5nLFxuICBhcmdzOiBzdHJpbmdbXSxcbiAgY3dkOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIGVudjogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IHVuZGVmaW5lZCxcbiAgaWRlbnRpdHk6IFNzaENvbW1hbmRJZGVudGl0eSxcbik6IHN0cmluZyB7XG4gIGFzc2VydFNhZmVTc2hFbnZpcm9ubWVudChlbnYpO1xuICBjb25zdCByb290ID0gaWRlbnRpdHkua2luZCA9PT0gXCJyb290XCI7XG4gIGNvbnN0IGhvbWUgPSByb290ID8gXCIvcm9vdFwiIDogaWRlbnRpdHkuaG9tZTtcbiAgY29uc3QgbmFtZSA9IHJvb3QgPyBcInJvb3RcIiA6IGlkZW50aXR5Lm5hbWU7XG4gIGNvbnN0IHdvcmtpbmdEaXJlY3RvcnkgPSBjd2QgPz8gaG9tZTtcbiAgY29uc3QgaW52b2NhdGlvbiA9IFtjb21tYW5kLCAuLi5zY3J1YkxvZ2luU2hlbGxDb21tYW5kKGNvbW1hbmQsIGFyZ3MpXS5tYXAoc2hlbGxRdW90ZSkuam9pbihcIiBcIik7XG4gIGNvbnN0IGVudmlyb25tZW50ID0gT2JqZWN0LmVudHJpZXMoe1xuICAgIEhPTUU6IGhvbWUsXG4gICAgVVNFUjogbmFtZSxcbiAgICBMT0dOQU1FOiBuYW1lLFxuICAgIFNIRUxMOiBcIi9iaW4vYmFzaFwiLFxuICAgIFBXRDogd29ya2luZ0RpcmVjdG9yeSxcbiAgICBQQVRIOiByb290XG4gICAgICA/IFwiL3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluXCJcbiAgICAgIDogYCR7aG9tZX0vLmxvY2FsL2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2JpbjovYmluYCxcbiAgICBEQVRBQlJJQ0tTX0NPTkZJR19GSUxFOiBcIi9kZXYvbnVsbFwiLFxuICAgIC4uLmVudixcbiAgfSlcbiAgICAubWFwKChba2V5LCB2YWx1ZV0pID0+IGAke2Vudmlyb25tZW50TmFtZShrZXkpfT0ke3NoZWxsUXVvdGUodmFsdWUpfWApXG4gICAgLmpvaW4oXCIgXCIpO1xuICBjb25zdCBydW4gPSBgY2QgLS0gJHtzaGVsbFF1b3RlKHdvcmtpbmdEaXJlY3RvcnkpfSAmJiAke2ludm9jYXRpb259YDtcbiAgY29uc3Qgc3Vkb0FyZ3MgPSByb290ID8gW1wiLW5cIiwgXCItSFwiXSA6IFtcIi1uXCIsIFwiLUhcIiwgXCItdVwiLCBuYW1lXTtcbiAgY29uc3Qgc3dpdGNoZWQgPSBbXCJzdWRvXCIsIC4uLnN1ZG9BcmdzLCBcIi0tXCIsIFwiZW52XCIsIFwiLWlcIl0ubWFwKHNoZWxsUXVvdGUpLmpvaW4oXCIgXCIpO1xuICByZXR1cm4gYCR7U1NIX0FVVEhfRU5WSVJPTk1FTlRfU0NSVUJ9XFxuZXhlYyAke3N3aXRjaGVkfSAke2Vudmlyb25tZW50fSAnL2Jpbi9zaCcgJy1jJyAke3NoZWxsUXVvdGUocnVuKX0gPC9kZXYvbnVsbGA7XG59XG5cbmZ1bmN0aW9uIHNjcnViTG9naW5TaGVsbENvbW1hbmQoY29tbWFuZDogc3RyaW5nLCBhcmdzOiBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgY29uc3QgZXhlY3V0YWJsZSA9IGNvbW1hbmQuc3BsaXQoXCIvXCIpLmF0KC0xKTtcbiAgaWYgKCFleGVjdXRhYmxlIHx8ICFbXCJzaFwiLCBcImJhc2hcIiwgXCJ6c2hcIl0uaW5jbHVkZXMoZXhlY3V0YWJsZSkgfHwgYXJnc1swXSAhPT0gXCItbGNcIikge1xuICAgIHJldHVybiBhcmdzO1xuICB9XG4gIGNvbnN0IFtmbGFncywgc2NyaXB0LCAuLi5yZXN0XSA9IGFyZ3M7XG4gIGlmIChzY3JpcHQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGFyZ3M7XG4gIHJldHVybiBbZmxhZ3MsIGAke1NTSF9BVVRIX0VOVklST05NRU5UX1NDUlVCfVxcbiR7c2NyaXB0fWAsIC4uLnJlc3RdO1xufVxuXG5jb25zdCBTU0hfQVVUSF9FTlZJUk9OTUVOVF9TQ1JVQiA9IGBmb3IgX19kYnhfdG9vbHNfbmFtZSBpbiAkKGVudiB8IHNlZCAtbiAncy9eXFxcXChbQS1aYS16X11bQS1aYS16MC05X10qXFxcXCk9LiovXFxcXDEvcCcpOyBkb1xuICBjYXNlIFwiJF9fZGJ4X3Rvb2xzX25hbWVcIiBpblxuICAgIERBVEFCUklDS1NfKnxTU0hfQVVUSF9TT0NLKVxuICAgICAgdW5zZXQgXCIkX19kYnhfdG9vbHNfbmFtZVwiXG4gICAgICA7O1xuICBlc2FjXG5kb25lXG5leHBvcnQgREFUQUJSSUNLU19DT05GSUdfRklMRT0vZGV2L251bGxgO1xuXG5mdW5jdGlvbiBhc3NlcnRTYWZlU3NoRW52aXJvbm1lbnQoZW52OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PiB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmtleXMoZW52ID8/IHt9KSkge1xuICAgIGlmIChcbiAgICAgIG5hbWUgPT09IFwiSE9NRVwiIHx8XG4gICAgICBuYW1lID09PSBcIlVTRVJcIiB8fFxuICAgICAgbmFtZSA9PT0gXCJMT0dOQU1FXCIgfHxcbiAgICAgIG5hbWUgPT09IFwiU0hFTExcIiB8fFxuICAgICAgbmFtZSA9PT0gXCJQV0RcIiB8fFxuICAgICAgbmFtZSA9PT0gXCJQQVRIXCIgfHxcbiAgICAgIG5hbWUuc3RhcnRzV2l0aChcIlNVRE9fXCIpIHx8XG4gICAgICBuYW1lLnN0YXJ0c1dpdGgoXCJEQVRBQlJJQ0tTX1wiKSB8fFxuICAgICAgbmFtZSA9PT0gXCJTU0hfQVVUSF9TT0NLXCJcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJTU0ggZW52aXJvbm1lbnQgb3ZlcmxheXMgY2Fubm90IHJlcGxhY2UgdGhlIExha2Vib3ggaWRlbnRpdHkgb3IgcmVzdG9yZSBEYXRhYnJpY2tzIG9yIFNTSCBhZ2VudCBjcmVkZW50aWFscy5cIixcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHNoZWxsUXVvdGUodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJyR7dmFsdWUucmVwbGFjZUFsbChcIidcIiwgXCInXFxcXCcnXCIpfSdgO1xufVxuXG5mdW5jdGlvbiBlbnZpcm9ubWVudE5hbWUodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICghL15bQS1aYS16X11bQS1aYS16MC05X10qJC8udGVzdCh2YWx1ZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgU1NIIGVudmlyb25tZW50IHZhcmlhYmxlIG5hbWU6ICR7dmFsdWV9YCk7XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufVxuIl19
@@ -0,0 +1,18 @@
1
+ import type { Duplex } from "node:stream";
2
+ import { PooledSshTransport, type SshCommandExecution, type SshPoolOptions, type SshResourceLifecycle, type SshTransportOptions } from "./_ssh.ts";
3
+ /** One authenticated native OpenSSH ControlMaster resource. */
4
+ export interface OpenSshResource {
5
+ run(script: string, execution: SshCommandExecution): Promise<number>;
6
+ connect(remoteHost: string, remotePort: number): Promise<Duplex>;
7
+ test(): Promise<boolean>;
8
+ close(): Promise<void>;
9
+ }
10
+ /** Exclusive native OpenSSH ControlMaster pool. */
11
+ export declare class OpenSshTransport extends PooledSshTransport<OpenSshResource> {
12
+ readonly kind: "openssh";
13
+ constructor(options: SshTransportOptions, command: string, poolOptions?: SshPoolOptions, lifecycle?: SshResourceLifecycle<OpenSshResource>);
14
+ protected runWithResource(resource: OpenSshResource, script: string, execution: SshCommandExecution): Promise<number>;
15
+ protected connectWithResource(resource: OpenSshResource, remoteHost: string, remotePort: number): Promise<Duplex>;
16
+ }
17
+ /** Return whether an executable is OpenSSH and accepts dynamic SOCKS5 forwarding. */
18
+ export declare function supportsNativeOpenSsh(command?: string): Promise<boolean>;