@dbx-tools/lakebox 0.9.153 → 0.9.157
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/index.ts +7 -3
- package/lib/index.d.ts +7 -3
- package/lib/index.js +7 -4
- package/lib/src/_ssh_openssh.d.ts +1 -1
- package/lib/src/_ssh_openssh.js +13 -13
- package/lib/src/_ssh_ssh2.d.ts +1 -1
- package/lib/src/_ssh_ssh2.js +2 -2
- package/lib/src/key-store.js +3 -3
- package/lib/src/lifecycle.js +3 -3
- package/lib/src/rest.js +4 -4
- package/lib/src/session.d.ts +2 -3
- package/lib/src/session.js +6 -7
- package/lib/src/ssh.js +489 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -53
- package/src/_ssh_openssh.ts +13 -13
- package/src/_ssh_ssh2.ts +1 -1
- package/src/key-store.ts +2 -2
- package/src/lifecycle.ts +2 -2
- package/src/rest.ts +3 -3
- package/src/session.ts +5 -7
- package/src/{_ssh.ts → ssh.ts} +3 -3
- package/lib/src/_ssh.js +0 -489
- /package/lib/src/{_ssh.d.ts → ssh.d.ts} +0 -0
package/lib/src/ssh.js
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
import { PassThrough } from "node:stream";
|
|
2
|
+
import { StringDecoder } from "node:string_decoder";
|
|
3
|
+
import { log, toError } 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: 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: 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3NoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NzaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUE4QixNQUFNLGFBQWEsQ0FBQztBQUN0RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUV0RCxPQUFPLEVBQUUsVUFBVSxFQUF5QyxNQUFNLGNBQWMsQ0FBQztBQUlqRixNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLHVCQUF1QixDQUFDLENBQUM7QUFDbkQsNkVBQTZFO0FBQzdFLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxFQUFFLENBQUM7QUFpQi9CLGdGQUFnRjtBQUNoRixNQUFNLE9BQU8sVUFBVTtJQTZCVjtJQUNBO0lBN0JGLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFHLFlBQVksQ0FBQztJQUM3QyxxREFBcUQ7SUFDNUMsTUFBTSxDQUFtQztJQUNsRCxvREFBb0Q7SUFDM0MsTUFBTSxDQUFtQztJQUNsRCwyRUFBMkU7SUFDbEUsTUFBTSxDQUFnQztJQUMvQywwQ0FBMEM7SUFDMUMsUUFBUSxDQUFxQjtJQUVaLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDdkIsWUFBWSxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7SUFDakMsWUFBWSxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7SUFDakMsYUFBYSxHQUFHLElBQUksYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFDLGFBQWEsR0FBRyxJQUFJLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMxQyxlQUFlLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztJQUN4QyxVQUFVLENBQWtCO0lBQ3JDLGlCQUFpQixDQUE4QjtJQUMvQyxnQkFBZ0IsQ0FBNEI7SUFD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QUFDLENBQUM7QUFDdEUsQ0FBQztBQUVELE1BQU0sMEJBQTBCLEdBQUc7Ozs7Ozs7d0NBT0ssQ0FBQztBQUV6QyxTQUFTLHdCQUF3QixDQUFDLEdBQWlEO0lBQ2pGLEtBQUssTUFBTSxJQUFJLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUMxQyxJQUNFLElBQUksS0FBSyxNQUFNO1lBQ2YsSUFBSSxLQUFLLE1BQU07WUFDZixJQUFJLEtBQUssU0FBUztZQUNsQixJQUFJLEtBQUssT0FBTztZQUNoQixJQUFJLEtBQUssS0FBSztZQUNkLElBQUksS0FBSyxNQUFNO1lBQ2YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUM7WUFDeEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUM7WUFDOUIsSUFBSSxLQUFLLGVBQWUsRUFDeEIsQ0FBQztZQUNELE1BQU0sSUFBSSxLQUFLLENBQ2IsOEdBQThHLENBQy9HLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLFVBQVUsQ0FBQyxLQUFhO0lBQy9CLE9BQU8sSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDO0FBQy9DLENBQUM7QUFFRCxTQUFTLGVBQWUsQ0FBQyxLQUFhO0lBQ3BDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUM1QyxNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ3JFLENBQUM7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXNzVGhyb3VnaCwgdHlwZSBEdXBsZXgsIHR5cGUgUmVhZGFibGUgfSBmcm9tIFwibm9kZTpzdHJlYW1cIjtcbmltcG9ydCB7IFN0cmluZ0RlY29kZXIgfSBmcm9tIFwibm9kZTpzdHJpbmdfZGVjb2RlclwiO1xuaW1wb3J0IHsgbG9nLCB0b0Vycm9yIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHsgTGFrZWJveENvbW1hbmRSZXN1bHQgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtbGFrZWJveFwiO1xuaW1wb3J0IHsgY3JlYXRlUG9vbCwgdHlwZSBGYWN0b3J5LCB0eXBlIE9wdGlvbnMsIHR5cGUgUG9vbCB9IGZyb20gXCJnZW5lcmljLXBvb2xcIjtcbmltcG9ydCB0eXBlIHsgQ2xpZW50IGFzIFNzaDJDbGllbnQgfSBmcm9tIFwic3NoMlwiO1xuaW1wb3J0IHR5cGUgeyBTc2gyUGF0Y2hNb2RlLCBTc2hUcmFuc3BvcnRNb2RlIH0gZnJvbSBcIi4vdHJhbnNwb3J0LnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJsYWtlYm94OnNzaC10cmFuc3BvcnRcIik7XG4vKiogTWF4aW11bSBhdXRoZW50aWNhdGVkIHJlc291cmNlcyBtYWludGFpbmVkIGJ5IGVhY2ggU1NIIG9wZXJhdGlvbiBwb29sLiAqL1xuZXhwb3J0IGNvbnN0IFNTSF9QT09MX01BWCA9IDEwO1xuXG4vKiogT25lIGNvbW1hbmQgZXhlY3V0aW9uIHJlcXVlc3QgYWZ0ZXIgdGhlIHJlbW90ZSBzaGVsbCBzY3JpcHQgaXMgYXNzZW1ibGVkLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTc2hFeGVjdXRpb25PcHRpb25zIHtcbiAgdGltZW91dE1zOiBudW1iZXI7XG4gIHNpZ25hbD86IEFib3J0U2lnbmFsO1xufVxuXG4vKiogVHJhbnNwb3J0IGNhbGxiYWNrcyBvd25lZCBieSBvbmUgbGl2ZSBTU0ggY29tbWFuZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NoQ29tbWFuZEV4ZWN1dGlvbiB7XG4gIHJlYWRvbmx5IHNpZ25hbDogQWJvcnRTaWduYWw7XG4gIHN0ZG91dChjaHVuazogQnVmZmVyIHwgc3RyaW5nKTogdm9pZDtcbiAgc3RkZXJyKGNodW5rOiBCdWZmZXIgfCBzdHJpbmcpOiB2b2lkO1xuICBzZXRDYW5jZWwoY2FuY2VsOiAoKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPik6IHZvaWQ7XG4gIGZvbGxvdyhjb21tYW5kOiBTc2hDb21tYW5kKTogUHJvbWlzZTxudW1iZXI+O1xufVxuXG4vKiogTGl2ZSBTU0ggY29tbWFuZCB0aGF0IHN0cmVhbXMgb3V0cHV0IGFuZCBhd2FpdHMgdG8gaXRzIG51bWVyaWMgZXhpdCBjb2RlLiAqL1xuZXhwb3J0IGNsYXNzIFNzaENvbW1hbmQgaW1wbGVtZW50cyBQcm9taXNlPG51bWJlcj4ge1xuICByZWFkb25seSBbU3ltYm9sLnRvU3RyaW5nVGFnXSA9IFwiU3NoQ29tbWFuZFwiO1xuICAvKiogTGl2ZSBzdGFuZGFyZCBvdXRwdXQgZGVjb2RlZCBhcyBVVEYtOCBzdHJpbmdzLiAqL1xuICByZWFkb25seSBzdGRvdXQ6IFJlYWRhYmxlICYgQXN5bmNJdGVyYWJsZTxzdHJpbmc+O1xuICAvKiogTGl2ZSBzdGFuZGFyZCBlcnJvciBkZWNvZGVkIGFzIFVURi04IHN0cmluZ3MuICovXG4gIHJlYWRvbmx5IHN0ZGVycjogUmVhZGFibGUgJiBBc3luY0l0ZXJhYmxlPHN0cmluZz47XG4gIC8qKiBDb21wbGV0ZWQgcmVzdWx0IHdpdGggY2FwdHVyZWQgb3V0cHV0LCB0aW1pbmcsIGFuZCB0aW1lb3V0IG1ldGFkYXRhLiAqL1xuICByZWFkb25seSByZXN1bHQ6IFByb21pc2U8TGFrZWJveENvbW1hbmRSZXN1bHQ+O1xuICAvKiogTnVtZXJpYyBleGl0IGNvZGUgYWZ0ZXIgY29tcGxldGlvbi4gKi9cbiAgZXhpdENvZGU6IG51bWJlciB8IHVuZGVmaW5lZDtcblxuICBwcml2YXRlIHJlYWRvbmx5IHN0YXJ0ZWRBdCA9IERhdGUubm93KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3Rkb3V0U3RyZWFtID0gbmV3IFBhc3NUaHJvdWdoKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3RkZXJyU3RyZWFtID0gbmV3IFBhc3NUaHJvdWdoKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3Rkb3V0RGVjb2RlciA9IG5ldyBTdHJpbmdEZWNvZGVyKFwidXRmOFwiKTtcbiAgcHJpdmF0ZSByZWFkb25seSBzdGRlcnJEZWNvZGVyID0gbmV3IFN0cmluZ0RlY29kZXIoXCJ1dGY4XCIpO1xuICBwcml2YXRlIHJlYWRvbmx5IGFib3J0Q29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgcHJpdmF0ZSByZWFkb25seSBjb21wbGV0aW9uOiBQcm9taXNlPG51bWJlcj47XG4gIHByaXZhdGUgcmVzb2x2ZUNvbXBsZXRpb24hOiAoZXhpdENvZGU6IG51bWJlcikgPT4gdm9pZDtcbiAgcHJpdmF0ZSByZWplY3RDb21wbGV0aW9uITogKGVycm9yOiB1bmtub3duKSA9PiB2b2lkO1xuICBwcml2YXRlIGNhbmNlbEJhY2tlbmQ/OiAoKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPjtcbiAgcHJpdmF0ZSBjYW5jZWxsYXRpb24/OiBQcm9taXNlPHZvaWQ+O1xuICBwcml2YXRlIHN0ZG91dFRleHQgPSBcIlwiO1xuICBwcml2YXRlIHN0ZGVyclRleHQgPSBcIlwiO1xuICBwcml2YXRlIHNldHRsZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSB0aW1lZE91dCA9IGZhbHNlO1xuXG4gIC8qKiBDcmVhdGVzIGEgY29tbWFuZCBhbmQgc2NoZWR1bGVzIGl0cyBhc3luY2hyb25vdXMgc2V0dXAgYW5kIGV4ZWN1dGlvbi4gKi9cbiAgY29uc3RydWN0b3IoXG4gICAgcmVhZG9ubHkgY29tbWFuZDogc3RyaW5nLFxuICAgIHJlYWRvbmx5IGFyZ3M6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICAgIG9wdGlvbnM6IFNzaEV4ZWN1dGlvbk9wdGlvbnMsXG4gICAgc3RhcnQ6IChleGVjdXRpb246IFNzaENvbW1hbmRFeGVjdXRpb24pID0+IFByb21pc2U8bnVtYmVyPixcbiAgKSB7XG4gICAgdGhpcy5zdGRvdXRTdHJlYW0uc2V0RW5jb2RpbmcoXCJ1dGY4XCIpO1xuICAgIHRoaXMuc3RkZXJyU3RyZWFtLnNldEVuY29kaW5nKFwidXRmOFwiKTtcbiAgICB0aGlzLnN0ZG91dCA9IHRoaXMuc3Rkb3V0U3RyZWFtIGFzIFJlYWRhYmxlICYgQXN5bmNJdGVyYWJsZTxzdHJpbmc+O1xuICAgIHRoaXMuc3RkZXJyID0gdGhpcy5zdGRlcnJTdHJlYW0gYXMgUmVhZGFibGUgJiBBc3luY0l0ZXJhYmxlPHN0cmluZz47XG4gICAgdGhpcy5jb21wbGV0aW9uID0gbmV3IFByb21pc2U8bnVtYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLnJlc29sdmVDb21wbGV0aW9uID0gcmVzb2x2ZTtcbiAgICAgIHRoaXMucmVqZWN0Q29tcGxldGlvbiA9IHJlamVjdDtcbiAgICB9KTtcbiAgICB0aGlzLnJlc3VsdCA9IHRoaXMuY29tcGxldGlvbi50aGVuKChleGl0Q29kZSkgPT4gKHtcbiAgICAgIHN1Y2Nlc3M6IGV4aXRDb2RlID09PSAwICYmICF0aGlzLnRpbWVkT3V0LFxuICAgICAgZXhpdENvZGUsXG4gICAgICBzdGRvdXQ6IHRoaXMuc3Rkb3V0VGV4dCxcbiAgICAgIHN0ZGVycjogdGhpcy5zdGRlcnJUZXh0LFxuICAgICAgZXhlY3V0aW9uVGltZU1zOiBEYXRlLm5vdygpIC0gdGhpcy5zdGFydGVkQXQsXG4gICAgICAuLi4odGhpcy50aW1lZE91dCA/IHsgdGltZWRPdXQ6IHRydWUgfSA6IHt9KSxcbiAgICAgIGNvbW1hbmQ6IHRoaXMuY29tbWFuZCxcbiAgICAgIGFyZ3M6IFsuLi50aGlzLmFyZ3NdLFxuICAgIH0pKTtcbiAgICB2b2lkIHRoaXMuY29tcGxldGlvbi5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgIHZvaWQgdGhpcy5yZXN1bHQuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcblxuICAgIGNvbnN0IGV4dGVybmFsQWJvcnQgPSAoKSA9PiB7XG4gICAgICB2b2lkIHRoaXMuY2FuY2VsKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9O1xuICAgIGlmIChvcHRpb25zLnNpZ25hbD8uYWJvcnRlZCkgZXh0ZXJuYWxBYm9ydCgpO1xuICAgIGVsc2Ugb3B0aW9ucy5zaWduYWw/LmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBleHRlcm5hbEFib3J0LCB7IG9uY2U6IHRydWUgfSk7XG4gICAgY29uc3QgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy50aW1lZE91dCA9IHRydWU7XG4gICAgICB2b2lkIHRoaXMuY2FuY2VsKDEyNCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9LCBvcHRpb25zLnRpbWVvdXRNcyk7XG4gICAgdGltZW91dC51bnJlZj8uKCk7XG4gICAgY29uc3QgY2xlYW51cCA9ICgpID0+IHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIG9wdGlvbnMuc2lnbmFsPy5yZW1vdmVFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgZXh0ZXJuYWxBYm9ydCk7XG4gICAgfTtcbiAgICB2b2lkIHRoaXMuY29tcGxldGlvbi50aGVuKGNsZWFudXAsIGNsZWFudXApO1xuXG4gICAgcXVldWVNaWNyb3Rhc2soKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuc2V0dGxlZCkgcmV0dXJuO1xuICAgICAgdm9pZCBzdGFydCh7XG4gICAgICAgIHNpZ25hbDogdGhpcy5hYm9ydENvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgICBzdGRvdXQ6IChjaHVuaykgPT4gdGhpcy53cml0ZU91dHB1dChcInN0ZG91dFwiLCBjaHVuayksXG4gICAgICAgIHN0ZGVycjogKGNodW5rKSA9PiB0aGlzLndyaXRlT3V0cHV0KFwic3RkZXJyXCIsIGNodW5rKSxcbiAgICAgICAgc2V0Q2FuY2VsOiAoY2FuY2VsKSA9PiB7XG4gICAgICAgICAgdGhpcy5jYW5jZWxCYWNrZW5kID0gY2FuY2VsO1xuICAgICAgICAgIGlmICh0aGlzLmFib3J0Q29udHJvbGxlci5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgICAgICAgdm9pZCB0aGlzLmludm9rZUNhbmNlbCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBmb2xsb3c6IChjb21tYW5kKSA9PiB0aGlzLmZvbGxvdyhjb21tYW5kKSxcbiAgICAgIH0pLnRoZW4oXG4gICAgICAgIChleGl0Q29kZSkgPT4gdGhpcy5maW5pc2goZXhpdENvZGUpLFxuICAgICAgICAoZXJyb3IpID0+IHRoaXMuZmFpbChlcnJvciksXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqIENhbmNlbCB0aGUgY29tbWFuZCBvbmNlLiBDYWxsZXIgY2FuY2VsbGF0aW9uIHJlc29sdmVzIHdpdGggZXhpdCBjb2RlIDEzMC4gKi9cbiAgY2FuY2VsKGV4aXRDb2RlID0gMTMwKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuc2V0dGxlZCkgcmV0dXJuIHRoaXMuY2FuY2VsbGF0aW9uID8/IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIGlmICghdGhpcy5hYm9ydENvbnRyb2xsZXIuc2lnbmFsLmFib3J0ZWQpIHRoaXMuYWJvcnRDb250cm9sbGVyLmFib3J0KCk7XG4gICAgY29uc3QgY2FuY2VsbGF0aW9uID0gdGhpcy5pbnZva2VDYW5jZWwoKTtcbiAgICB0aGlzLmZpbmlzaChleGl0Q29kZSk7XG4gICAgcmV0dXJuIGNhbmNlbGxhdGlvbjtcbiAgfVxuXG4gIHRoZW48VFJlc3VsdDEgPSBudW1iZXIsIFRSZXN1bHQyID0gbmV2ZXI+KFxuICAgIG9uZnVsZmlsbGVkPzogKCh2YWx1ZTogbnVtYmVyKSA9PiBUUmVzdWx0MSB8IFByb21pc2VMaWtlPFRSZXN1bHQxPikgfCBudWxsLFxuICAgIG9ucmVqZWN0ZWQ/OiAoKHJlYXNvbjogdW5rbm93bikgPT4gVFJlc3VsdDIgfCBQcm9taXNlTGlrZTxUUmVzdWx0Mj4pIHwgbnVsbCxcbiAgKTogUHJvbWlzZTxUUmVzdWx0MSB8IFRSZXN1bHQyPiB7XG4gICAgcmV0dXJuIHRoaXMuY29tcGxldGlvbi50aGVuKG9uZnVsZmlsbGVkLCBvbnJlamVjdGVkKTtcbiAgfVxuXG4gIGNhdGNoPFRSZXN1bHQgPSBuZXZlcj4oXG4gICAgb25yZWplY3RlZD86ICgocmVhc29uOiB1bmtub3duKSA9PiBUUmVzdWx0IHwgUHJvbWlzZUxpa2U8VFJlc3VsdD4pIHwgbnVsbCxcbiAgKTogUHJvbWlzZTxudW1iZXIgfCBUUmVzdWx0PiB7XG4gICAgcmV0dXJuIHRoaXMuY29tcGxldGlvbi5jYXRjaChvbnJlamVjdGVkKTtcbiAgfVxuXG4gIGZpbmFsbHkob25maW5hbGx5PzogKCgpID0+IHZvaWQpIHwgbnVsbCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgcmV0dXJuIHRoaXMuY29tcGxldGlvbi5maW5hbGx5KG9uZmluYWxseSA/PyB1bmRlZmluZWQpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnZva2VDYW5jZWwoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2FuY2VsbGF0aW9uKSByZXR1cm4gdGhpcy5jYW5jZWxsYXRpb247XG4gICAgaWYgKCF0aGlzLmNhbmNlbEJhY2tlbmQpIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICBjb25zdCBjYW5jZWxCYWNrZW5kID0gdGhpcy5jYW5jZWxCYWNrZW5kO1xuICAgIHRoaXMuY2FuY2VsbGF0aW9uID0gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgIC50aGVuKCgpID0+IGNhbmNlbEJhY2tlbmQoKSlcbiAgICAgIC50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgdm9pZCB0aGlzLmNhbmNlbGxhdGlvbi5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgIHJldHVybiB0aGlzLmNhbmNlbGxhdGlvbjtcbiAgfVxuXG4gIHByaXZhdGUgd3JpdGVPdXRwdXQoc3RyZWFtOiBcInN0ZG91dFwiIHwgXCJzdGRlcnJcIiwgY2h1bms6IEJ1ZmZlciB8IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLnNldHRsZWQpIHJldHVybjtcbiAgICBjb25zdCBkZWNvZGVyID0gc3RyZWFtID09PSBcInN0ZG91dFwiID8gdGhpcy5zdGRvdXREZWNvZGVyIDogdGhpcy5zdGRlcnJEZWNvZGVyO1xuICAgIGNvbnN0IHZhbHVlID0gZGVjb2Rlci53cml0ZSh0eXBlb2YgY2h1bmsgPT09IFwic3RyaW5nXCIgPyBCdWZmZXIuZnJvbShjaHVuaykgOiBjaHVuayk7XG4gICAgaWYgKCF2YWx1ZSkgcmV0dXJuO1xuICAgIGlmIChzdHJlYW0gPT09IFwic3Rkb3V0XCIpIHtcbiAgICAgIHRoaXMuc3Rkb3V0VGV4dCArPSB2YWx1ZTtcbiAgICAgIHRoaXMuc3Rkb3V0U3RyZWFtLndyaXRlKHZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zdGRlcnJUZXh0ICs9IHZhbHVlO1xuICAgICAgdGhpcy5zdGRlcnJTdHJlYW0ud3JpdGUodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZm9sbG93KGNvbW1hbmQ6IFNzaENvbW1hbmQpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIHRoaXMuY2FuY2VsQmFja2VuZCA9ICgpID0+IGNvbW1hbmQuY2FuY2VsKCk7XG4gICAgaWYgKHRoaXMuYWJvcnRDb250cm9sbGVyLnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICB2b2lkIHRoaXMuaW52b2tlQ2FuY2VsKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgY29uc3Qgc3Rkb3V0ID0gdGhpcy5waXBlKGNvbW1hbmQuc3Rkb3V0LCAoY2h1bmspID0+IHRoaXMud3JpdGVPdXRwdXQoXCJzdGRvdXRcIiwgY2h1bmspKTtcbiAgICBjb25zdCBzdGRlcnIgPSB0aGlzLnBpcGUoY29tbWFuZC5zdGRlcnIsIChjaHVuaykgPT4gdGhpcy53cml0ZU91dHB1dChcInN0ZGVyclwiLCBjaHVuaykpO1xuICAgIGNvbnN0IGV4aXRDb2RlID0gYXdhaXQgY29tbWFuZDtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbc3Rkb3V0LCBzdGRlcnJdKTtcbiAgICByZXR1cm4gZXhpdENvZGU7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHBpcGUoc3RyZWFtOiBBc3luY0l0ZXJhYmxlPHN0cmluZz4sIHdyaXRlOiAoY2h1bms6IHN0cmluZykgPT4gdm9pZCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGZvciBhd2FpdCAoY29uc3QgY2h1bmsgb2Ygc3RyZWFtKSB3cml0ZShjaHVuayk7XG4gIH1cblxuICBwcml2YXRlIGZpbmlzaChleGl0Q29kZTogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2V0dGxlZCkgcmV0dXJuO1xuICAgIHRoaXMuc2V0dGxlZCA9IHRydWU7XG4gICAgdGhpcy5leGl0Q29kZSA9IGV4aXRDb2RlO1xuICAgIHRoaXMuY2xvc2VPdXRwdXQoKTtcbiAgICB0aGlzLnJlc29sdmVDb21wbGV0aW9uKGV4aXRDb2RlKTtcbiAgfVxuXG4gIHByaXZhdGUgZmFpbChlcnJvcjogdW5rbm93bik6IHZvaWQge1xuICAgIGlmICh0aGlzLnNldHRsZWQpIHJldHVybjtcbiAgICB0aGlzLnNldHRsZWQgPSB0cnVlO1xuICAgIHRoaXMuY2xvc2VPdXRwdXQoKTtcbiAgICB0aGlzLnJlamVjdENvbXBsZXRpb24oZXJyb3IpO1xuICB9XG5cbiAgcHJpdmF0ZSBjbG9zZU91dHB1dCgpOiB2b2lkIHtcbiAgICBjb25zdCBzdGRvdXRSZW1haW5kZXIgPSB0aGlzLnN0ZG91dERlY29kZXIuZW5kKCk7XG4gICAgY29uc3Qgc3RkZXJyUmVtYWluZGVyID0gdGhpcy5zdGRlcnJEZWNvZGVyLmVuZCgpO1xuICAgIGlmIChzdGRvdXRSZW1haW5kZXIpIHtcbiAgICAgIHRoaXMuc3Rkb3V0VGV4dCArPSBzdGRvdXRSZW1haW5kZXI7XG4gICAgICB0aGlzLnN0ZG91dFN0cmVhbS53cml0ZShzdGRvdXRSZW1haW5kZXIpO1xuICAgIH1cbiAgICBpZiAoc3RkZXJyUmVtYWluZGVyKSB7XG4gICAgICB0aGlzLnN0ZGVyclRleHQgKz0gc3RkZXJyUmVtYWluZGVyO1xuICAgICAgdGhpcy5zdGRlcnJTdHJlYW0ud3JpdGUoc3RkZXJyUmVtYWluZGVyKTtcbiAgICB9XG4gICAgdGhpcy5zdGRvdXRTdHJlYW0uZW5kKCk7XG4gICAgdGhpcy5zdGRlcnJTdHJlYW0uZW5kKCk7XG4gIH1cbn1cblxuLyoqIENvbm5lY3Rpb24gZGV0YWlscyBzaGFyZWQgYnkgbmF0aXZlIE9wZW5TU0ggYW5kIHRoZSBndWFyZGVkIHNzaDIgZmFsbGJhY2suICovXG5leHBvcnQgaW50ZXJmYWNlIFNzaFRyYW5zcG9ydE9wdGlvbnMge1xuICBob3N0OiBzdHJpbmc7XG4gIGNvbm5lY3RIb3N0OiBzdHJpbmc7XG4gIHBvcnQ6IG51bWJlcjtcbiAgdXNlcm5hbWU6IHN0cmluZztcbiAgcHJpdmF0ZUtleVBhdGg6IHN0cmluZztcbiAga25vd25Ib3N0c1BhdGg6IHN0cmluZztcbiAgY29ubmVjdFRpbWVvdXRNczogbnVtYmVyO1xuICBzc2gyQ2xpZW50OiBTc2gyQ2xpZW50O1xuICBjcmVhdGVTc2gyQ29tbWFuZENsaWVudDogKCkgPT4gUHJvbWlzZTxTc2gyQ2xpZW50PjtcbiAgdHJhbnNwb3J0PzogU3NoVHJhbnNwb3J0TW9kZTtcbiAgc3NoMlBhdGNoPzogU3NoMlBhdGNoTW9kZTtcbiAgc3NoQ29tbWFuZD86IHN0cmluZztcbn1cblxuLyoqIFNlbGVjdGVkIGNvbW1hbmQgYW5kIHJlbW90ZSBUQ1AgdHJhbnNwb3J0IGZvciBvbmUgdmVyaWZpZWQgU1NIIGdhdGV3YXkuICovXG5leHBvcnQgaW50ZXJmYWNlIFNzaFRyYW5zcG9ydCB7XG4gIHJlYWRvbmx5IGtpbmQ6IFwib3BlbnNzaFwiIHwgXCJzc2gyXCI7XG4gIHJ1bihzY3JpcHQ6IHN0cmluZywgZXhlY3V0aW9uOiBTc2hDb21tYW5kRXhlY3V0aW9uKTogUHJvbWlzZTxudW1iZXI+O1xuICBjb25uZWN0KHJlbW90ZUhvc3Q6IHN0cmluZywgcmVtb3RlUG9ydDogbnVtYmVyKTogUHJvbWlzZTxEdXBsZXg+O1xuICBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+O1xufVxuXG4vKiogQXN5bmMgbGlmZWN5Y2xlIHVzZWQgYnkgYm90aCBuYXRpdmUgT3BlblNTSCBhbmQgc3NoMiBjb25uZWN0aW9uIHBvb2xzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTc2hSZXNvdXJjZUxpZmVjeWNsZTxUPiB7XG4gIGNyZWF0ZSgpOiBQcm9taXNlPFQ+O1xuICBkZXN0cm95KHJlc291cmNlOiBUKTogUHJvbWlzZTx2b2lkPjtcbiAgdGVzdChyZXNvdXJjZTogVCk6IFByb21pc2U8Ym9vbGVhbj47XG59XG5cbi8qKiBPcHRpb25hbCBwb29sIG92ZXJyaWRlcyB1c2VkIGJ5IHRyYW5zcG9ydCB0ZXN0cyBhbmQgY29uc3RyYWluZWQgcnVudGltZXMuICovXG5leHBvcnQgdHlwZSBTc2hQb29sT3B0aW9ucyA9IFBpY2s8XG4gIE9wdGlvbnMsXG4gIHwgXCJtYXhcIlxuICB8IFwiYWNxdWlyZVRpbWVvdXRNaWxsaXNcIlxuICB8IFwiaWRsZVRpbWVvdXRNaWxsaXNcIlxuICB8IFwiZXZpY3Rpb25SdW5JbnRlcnZhbE1pbGxpc1wiXG4gIHwgXCJudW1UZXN0c1BlckV2aWN0aW9uUnVuXCJcbj47XG5cbi8qKlxuICogRXhjbHVzaXZlLCBzaW5nbGUtb3BlcmF0aW9uIFNTSCByZXNvdXJjZSBwb29sLlxuICpcbiAqIFRoZSBjb21tYW5kIHBvb2wga2VlcHMgb25lIGF1dGhlbnRpY2F0ZWQgcmVzb3VyY2Ugd2FybS4gRm9yd2FyZGluZyB1c2VzIGFcbiAqIHNlcGFyYXRlIHplcm8tbWluaW11bSBwb29sIHNvIGxvbmctbGl2ZWQgV2ViU29ja2V0cyBjYW5ub3QgY29uc3VtZSB0aGUgd2FybVxuICogY29tbWFuZCBjb25uZWN0aW9uLiBFdmVyeSBib3Jyb3dlZCByZXNvdXJjZSBpcyBkZXN0cm95ZWQgYWZ0ZXIgaXRzIGNvbW1hbmRcbiAqIG9yIGZvcndhcmRlZCBzdHJlYW0gYmVjYXVzZSB0aGUgRGF0YWJyaWNrcyBSdXNzaCBnYXRld2F5IG1heSBhY2NlcHQgb25seSBvbmVcbiAqIG9wZXJhdGlvbiBkdXJpbmcgYSBjb25uZWN0aW9uJ3MgbGlmZXRpbWUuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBQb29sZWRTc2hUcmFuc3BvcnQ8VD4gaW1wbGVtZW50cyBTc2hUcmFuc3BvcnQge1xuICBhYnN0cmFjdCByZWFkb25seSBraW5kOiBcIm9wZW5zc2hcIiB8IFwic3NoMlwiO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgY29tbWFuZFBvb2w6IFBvb2w8VD47XG4gIHByaXZhdGUgcmVhZG9ubHkgZm9yd2FyZGluZ1Bvb2w6IFBvb2w8VD47XG4gIHByaXZhdGUgcmVhZG9ubHkgYWN0aXZlUmVzb3VyY2VzID0gbmV3IE1hcDxULCBQb29sPFQ+PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHNlZWRlZFJlc291cmNlczogVFtdID0gW107XG4gIHByaXZhdGUgbGFzdENyZWF0ZUVycm9yOiB1bmtub3duO1xuICBwcml2YXRlIHN0YXJ0aW5nPzogUHJvbWlzZTx2b2lkPjtcbiAgcHJpdmF0ZSBjbG9zaW5nPzogUHJvbWlzZTx2b2lkPjtcbiAgcHJpdmF0ZSBjbG9zZWQgPSBmYWxzZTtcblxuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBsaWZlY3ljbGU6IFNzaFJlc291cmNlTGlmZWN5Y2xlPFQ+LFxuICAgIG9wdGlvbnM6IFNzaFBvb2xPcHRpb25zID0ge30sXG4gICkge1xuICAgIGNvbnN0IGZhY3Rvcnk6IEZhY3Rvcnk8VD4gPSB7XG4gICAgICBjcmVhdGU6IGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXNvdXJjZSA9IHRoaXMuc2VlZGVkUmVzb3VyY2VzLnNoaWZ0KCkgPz8gKGF3YWl0IGxpZmVjeWNsZS5jcmVhdGUoKSk7XG4gICAgICAgICAgdGhpcy5sYXN0Q3JlYXRlRXJyb3IgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgcmV0dXJuIHJlc291cmNlO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHRoaXMubGFzdENyZWF0ZUVycm9yID0gZXJyb3I7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBkZXN0cm95OiAocmVzb3VyY2UpID0+IGxpZmVjeWNsZS5kZXN0cm95KHJlc291cmNlKSxcbiAgICAgIHZhbGlkYXRlOiBhc3luYyAocmVzb3VyY2UpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgbGlmZWN5Y2xlLnRlc3QocmVzb3VyY2UpO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfTtcbiAgICBjb25zdCBkZWZhdWx0czogT3B0aW9ucyA9IHtcbiAgICAgIG1heDogb3B0aW9ucy5tYXggPz8gU1NIX1BPT0xfTUFYLFxuICAgICAgYWNxdWlyZVRpbWVvdXRNaWxsaXM6IG9wdGlvbnMuYWNxdWlyZVRpbWVvdXRNaWxsaXMgPz8gMTVfMDAwLFxuICAgICAgaWRsZVRpbWVvdXRNaWxsaXM6IG9wdGlvbnMuaWRsZVRpbWVvdXRNaWxsaXMgPz8gMzBfMDAwLFxuICAgICAgZXZpY3Rpb25SdW5JbnRlcnZhbE1pbGxpczogb3B0aW9ucy5ldmljdGlvblJ1bkludGVydmFsTWlsbGlzID8/IDEwXzAwMCxcbiAgICAgIG51bVRlc3RzUGVyRXZpY3Rpb25SdW46IG9wdGlvbnMubnVtVGVzdHNQZXJFdmljdGlvblJ1biA/PyAzLFxuICAgICAgdGVzdE9uQm9ycm93OiB0cnVlLFxuICAgICAgYXV0b3N0YXJ0OiBmYWxzZSxcbiAgICB9O1xuICAgIHRoaXMuY29tbWFuZFBvb2wgPSBjcmVhdGVQb29sKGZhY3RvcnksIHsgLi4uZGVmYXVsdHMsIG1pbjogMSB9KTtcbiAgICB0aGlzLmZvcndhcmRpbmdQb29sID0gY3JlYXRlUG9vbChmYWN0b3J5LCB7IC4uLmRlZmF1bHRzLCBtaW46IDAgfSk7XG4gIH1cblxuICAvKiogU3RhcnRzIGJvdGggcG9vbHMgYW5kIHdhaXRzIHVudGlsIG9uZSB0ZXN0ZWQgY29tbWFuZCByZXNvdXJjZSBpcyB3YXJtLiAqL1xuICBzdGFydCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5jbG9zZWQpIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoYCR7dGhpcy5raW5kfSBTU0ggdHJhbnNwb3J0IGlzIGNsb3NlZGApKTtcbiAgICBpZiAodGhpcy5zdGFydGluZykgcmV0dXJuIHRoaXMuc3RhcnRpbmc7XG4gICAgdGhpcy5zdGFydGluZyA9IHRoaXMuc3RhcnRQb29scygpO1xuICAgIHZvaWQgdGhpcy5zdGFydGluZ1xuICAgICAgLmNhdGNoKCgpID0+IHRoaXMuY2xvc2UoKSlcbiAgICAgIC5jYXRjaCgoZXJyb3IpID0+XG4gICAgICAgIGxvZ2dlci53YXJuKFwiZmFpbGVkIHRvIGNsb3NlIFNTSCB0cmFuc3BvcnQgYWZ0ZXIgc3RhcnR1cCBmYWlsdXJlXCIsIHtcbiAgICAgICAgICBraW5kOiB0aGlzLmtpbmQsXG4gICAgICAgICAgZXJyb3I6IHRvRXJyb3IoZXJyb3IpLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc3RhcnRpbmc7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHN0YXJ0UG9vbHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2xvc2VkKSB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5raW5kfSBTU0ggdHJhbnNwb3J0IGlzIGNsb3NlZGApO1xuICAgIGNvbnN0IHJlc291cmNlID0gYXdhaXQgdGhpcy5saWZlY3ljbGUuY3JlYXRlKCk7XG4gICAgaWYgKHRoaXMuY2xvc2VkKSB7XG4gICAgICBhd2FpdCB0aGlzLmxpZmVjeWNsZS5kZXN0cm95KHJlc291cmNlKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLmtpbmR9IFNTSCB0cmFuc3BvcnQgaXMgY2xvc2VkYCk7XG4gICAgfVxuICAgIHRoaXMuc2VlZGVkUmVzb3VyY2VzLnB1c2gocmVzb3VyY2UpO1xuICAgIHRoaXMuY29tbWFuZFBvb2wuc3RhcnQoKTtcbiAgICB0aGlzLmZvcndhcmRpbmdQb29sLnN0YXJ0KCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc291cmNlID0gYXdhaXQgdGhpcy5jb21tYW5kUG9vbC5hY3F1aXJlKCk7XG4gICAgICBhd2FpdCB0aGlzLmNvbW1hbmRQb29sLnJlbGVhc2UocmVzb3VyY2UpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyB0aGlzLmxhc3RDcmVhdGVFcnJvciA/PyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICBhc3luYyBydW4oc2NyaXB0OiBzdHJpbmcsIGV4ZWN1dGlvbjogU3NoQ29tbWFuZEV4ZWN1dGlvbik6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgcmVzb3VyY2UgPSBhd2FpdCB0aGlzLmFjcXVpcmUodGhpcy5jb21tYW5kUG9vbCk7XG4gICAgdHJ5IHtcbiAgICAgIGlmIChleGVjdXRpb24uc2lnbmFsLmFib3J0ZWQpIHJldHVybiAxMzA7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5ydW5XaXRoUmVzb3VyY2UocmVzb3VyY2UsIHNjcmlwdCwgZXhlY3V0aW9uKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgdGhpcy5kZXN0cm95KHRoaXMuY29tbWFuZFBvb2wsIHJlc291cmNlKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjb25uZWN0KHJlbW90ZUhvc3Q6IHN0cmluZywgcmVtb3RlUG9ydDogbnVtYmVyKTogUHJvbWlzZTxEdXBsZXg+IHtcbiAgICBjb25zdCBmaXJzdCA9IGF3YWl0IHRoaXMuYWNxdWlyZSh0aGlzLmZvcndhcmRpbmdQb29sKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY29ubmVjdFdpdGhCb3Jyb3dlZFJlc291cmNlKGZpcnN0LCByZW1vdGVIb3N0LCByZW1vdGVQb3J0KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgYXdhaXQgdGhpcy5kZXN0cm95KHRoaXMuZm9yd2FyZGluZ1Bvb2wsIGZpcnN0KTtcbiAgICAgIGlmICh0aGlzLmNsb3NlZCkgdGhyb3cgZXJyb3I7XG4gICAgfVxuICAgIGNvbnN0IHJldHJ5ID0gYXdhaXQgdGhpcy5hY3F1aXJlKHRoaXMuZm9yd2FyZGluZ1Bvb2wpO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5jb25uZWN0V2l0aEJvcnJvd2VkUmVzb3VyY2UocmV0cnksIHJlbW90ZUhvc3QsIHJlbW90ZVBvcnQpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3kodGhpcy5mb3J3YXJkaW5nUG9vbCwgcmV0cnkpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgY2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2xvc2luZykgcmV0dXJuIHRoaXMuY2xvc2luZztcbiAgICB0aGlzLmNsb3NlZCA9IHRydWU7XG4gICAgdGhpcy5jbG9zaW5nID0gdGhpcy5jbG9zZVBvb2xzKCk7XG4gICAgcmV0dXJuIHRoaXMuY2xvc2luZztcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBydW5XaXRoUmVzb3VyY2UoXG4gICAgcmVzb3VyY2U6IFQsXG4gICAgc2NyaXB0OiBzdHJpbmcsXG4gICAgZXhlY3V0aW9uOiBTc2hDb21tYW5kRXhlY3V0aW9uLFxuICApOiBQcm9taXNlPG51bWJlcj47XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGNvbm5lY3RXaXRoUmVzb3VyY2UoXG4gICAgcmVzb3VyY2U6IFQsXG4gICAgcmVtb3RlSG9zdDogc3RyaW5nLFxuICAgIHJlbW90ZVBvcnQ6IG51bWJlcixcbiAgKTogUHJvbWlzZTxEdXBsZXg+O1xuXG4gIHByaXZhdGUgYXN5bmMgY29ubmVjdFdpdGhCb3Jyb3dlZFJlc291cmNlKFxuICAgIHJlc291cmNlOiBULFxuICAgIHJlbW90ZUhvc3Q6IHN0cmluZyxcbiAgICByZW1vdGVQb3J0OiBudW1iZXIsXG4gICk6IFByb21pc2U8RHVwbGV4PiB7XG4gICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgdGhpcy5jb25uZWN0V2l0aFJlc291cmNlKHJlc291cmNlLCByZW1vdGVIb3N0LCByZW1vdGVQb3J0KTtcbiAgICBsZXQgZGlzcG9zZWQgPSBmYWxzZTtcbiAgICBjb25zdCBkaXNwb3NlID0gKCkgPT4ge1xuICAgICAgaWYgKGRpc3Bvc2VkKSByZXR1cm47XG4gICAgICBkaXNwb3NlZCA9IHRydWU7XG4gICAgICB2b2lkIHRoaXMuZGVzdHJveSh0aGlzLmZvcndhcmRpbmdQb29sLCByZXNvdXJjZSk7XG4gICAgfTtcbiAgICBzdHJlYW0ub25jZShcImNsb3NlXCIsIGRpc3Bvc2UpO1xuICAgIHN0cmVhbS5vbmNlKFwiZXJyb3JcIiwgZGlzcG9zZSk7XG4gICAgaWYgKHN0cmVhbS5kZXN0cm95ZWQpIGRpc3Bvc2UoKTtcbiAgICByZXR1cm4gc3RyZWFtO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBhY3F1aXJlKHBvb2w6IFBvb2w8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICBpZiAodGhpcy5jbG9zZWQpIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLmtpbmR9IFNTSCB0cmFuc3BvcnQgaXMgY2xvc2VkYCk7XG4gICAgbGV0IHJlc291cmNlOiBUO1xuICAgIHRyeSB7XG4gICAgICByZXNvdXJjZSA9IGF3YWl0IHBvb2wuYWNxdWlyZSgpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyB0aGlzLmxhc3RDcmVhdGVFcnJvciA/PyBlcnJvcjtcbiAgICB9XG4gICAgdGhpcy5hY3RpdmVSZXNvdXJjZXMuc2V0KHJlc291cmNlLCBwb29sKTtcbiAgICBpZiAodGhpcy5jbG9zZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMuZGVzdHJveShwb29sLCByZXNvdXJjZSk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5raW5kfSBTU0ggdHJhbnNwb3J0IGlzIGNsb3NlZGApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzb3VyY2U7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRlc3Ryb3kocG9vbDogUG9vbDxUPiwgcmVzb3VyY2U6IFQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5hY3RpdmVSZXNvdXJjZXMuZ2V0KHJlc291cmNlKSAhPT0gcG9vbCkgcmV0dXJuO1xuICAgIHRoaXMuYWN0aXZlUmVzb3VyY2VzLmRlbGV0ZShyZXNvdXJjZSk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHBvb2wuZGVzdHJveShyZXNvdXJjZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKFwiZmFpbGVkIHRvIGRlc3Ryb3kgcG9vbGVkIFNTSCByZXNvdXJjZVwiLCB7XG4gICAgICAgIGtpbmQ6IHRoaXMua2luZCxcbiAgICAgICAgZXJyb3I6IHRvRXJyb3IoZXJyb3IpLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjbG9zZVBvb2xzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuc3RhcnRpbmc/LmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgY29uc3QgY29tbWFuZERyYWluID0gdGhpcy5jb21tYW5kUG9vbC5kcmFpbigpO1xuICAgIGNvbnN0IGZvcndhcmRpbmdEcmFpbiA9IHRoaXMuZm9yd2FyZGluZ1Bvb2wuZHJhaW4oKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIFsuLi50aGlzLmFjdGl2ZVJlc291cmNlc10ubWFwKChbcmVzb3VyY2UsIHBvb2xdKSA9PiB0aGlzLmRlc3Ryb3kocG9vbCwgcmVzb3VyY2UpKSxcbiAgICApO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFtjb21tYW5kRHJhaW4sIGZvcndhcmRpbmdEcmFpbl0pO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFt0aGlzLmNvbW1hbmRQb29sLmNsZWFyKCksIHRoaXMuZm9yd2FyZGluZ1Bvb2wuY2xlYXIoKV0pO1xuICB9XG59XG5cbi8qKiBJbmplY3RhYmxlIHRyYW5zcG9ydCBjb25zdHJ1Y3RvcnMgdXNlZCB0byBpc29sYXRlIHBvbGljeSBzZWxlY3Rpb24gaW4gdGVzdHMuICovXG5leHBvcnQgaW50ZXJmYWNlIFNzaFRyYW5zcG9ydEZhY3RvcmllcyB7XG4gIHN1cHBvcnRzT3BlblNzaChjb21tYW5kOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+O1xuICBjcmVhdGVPcGVuU3NoKG9wdGlvbnM6IFNzaFRyYW5zcG9ydE9wdGlvbnMsIGNvbW1hbmQ6IHN0cmluZyk6IFByb21pc2U8U3NoVHJhbnNwb3J0PjtcbiAgY3JlYXRlU3NoMihvcHRpb25zOiBTc2hUcmFuc3BvcnRPcHRpb25zKTogUHJvbWlzZTxTc2hUcmFuc3BvcnQ+O1xufVxuXG4vKipcbiAqIFNlbGVjdCBvbmUgU1NIIHRyYW5zcG9ydCBmcm9tIHJlc29sdmVkIHBvbGljeSBhbmQga2VlcCBpdCBmb3IgdGhlIHNlc3Npb24uXG4gKiBBdXRvIHByZWZlcnMgbmF0aXZlIE9wZW5TU0ggYW5kIG90aGVyd2lzZSBzZWxlY3RzIHNzaDIuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVTc2hUcmFuc3BvcnQoXG4gIG9wdGlvbnM6IFNzaFRyYW5zcG9ydE9wdGlvbnMsXG4gIG92ZXJyaWRlczogUGFydGlhbDxTc2hUcmFuc3BvcnRGYWN0b3JpZXM+ID0ge30sXG4pOiBQcm9taXNlPFNzaFRyYW5zcG9ydD4ge1xuICBjb25zdCBmYWN0b3JpZXMgPSB7IC4uLmRlZmF1bHRTc2hUcmFuc3BvcnRGYWN0b3JpZXMsIC4uLm92ZXJyaWRlcyB9O1xuICBjb25zdCBzc2hDb21tYW5kID0gb3B0aW9ucy5zc2hDb21tYW5kID8/IFwic3NoXCI7XG4gIGNvbnN0IHRyYW5zcG9ydE1vZGUgPSBvcHRpb25zLnRyYW5zcG9ydCA/PyBcImF1dG9cIjtcbiAgaWYgKHRyYW5zcG9ydE1vZGUgPT09IFwic3NoMlwiKSB7XG4gICAgcmV0dXJuIGZhY3Rvcmllcy5jcmVhdGVTc2gyKG9wdGlvbnMpO1xuICB9XG4gIGNvbnN0IG9wZW5Tc2hTdXBwb3J0ZWQgPSBhd2FpdCBmYWN0b3JpZXMuc3VwcG9ydHNPcGVuU3NoKHNzaENvbW1hbmQpO1xuICBpZiAodHJhbnNwb3J0TW9kZSA9PT0gXCJvcGVuc3NoXCIgJiYgIW9wZW5Tc2hTdXBwb3J0ZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJOYXRpdmUgT3BlblNTSCB3aXRoIFNPQ0tTNSBmb3J3YXJkaW5nIGlzIHVuYXZhaWxhYmxlXCIpO1xuICB9XG4gIGlmIChvcGVuU3NoU3VwcG9ydGVkKSB7XG4gICAgcmV0dXJuIGZhY3Rvcmllcy5jcmVhdGVPcGVuU3NoKG9wdGlvbnMsIHNzaENvbW1hbmQpO1xuICB9XG4gIGlmICh0cmFuc3BvcnRNb2RlICE9PSBcImF1dG9cIikge1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgU1NIIHRyYW5zcG9ydDogJHt0cmFuc3BvcnRNb2RlfWApO1xuICB9XG4gIHJldHVybiBmYWN0b3JpZXMuY3JlYXRlU3NoMihvcHRpb25zKTtcbn1cblxuY29uc3QgZGVmYXVsdFNzaFRyYW5zcG9ydEZhY3RvcmllczogU3NoVHJhbnNwb3J0RmFjdG9yaWVzID0ge1xuICBzdXBwb3J0c09wZW5Tc2g6IGFzeW5jIChjb21tYW5kKSA9PiB7XG4gICAgY29uc3QgeyBzdXBwb3J0c05hdGl2ZU9wZW5Tc2ggfSA9IGF3YWl0IGltcG9ydChcIi4vX3NzaF9vcGVuc3NoLnRzXCIpO1xuICAgIHJldHVybiBzdXBwb3J0c05hdGl2ZU9wZW5Tc2goY29tbWFuZCk7XG4gIH0sXG4gIGNyZWF0ZU9wZW5Tc2g6IGFzeW5jIChvcHRpb25zLCBjb21tYW5kKSA9PiB7XG4gICAgY29uc3QgeyBPcGVuU3NoVHJhbnNwb3J0IH0gPSBhd2FpdCBpbXBvcnQoXCIuL19zc2hfb3BlbnNzaC50c1wiKTtcbiAgICBjb25zdCB0cmFuc3BvcnQgPSBuZXcgT3BlblNzaFRyYW5zcG9ydChvcHRpb25zLCBjb21tYW5kKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdHJhbnNwb3J0LnN0YXJ0KCk7XG4gICAgICByZXR1cm4gdHJhbnNwb3J0O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCB0cmFuc3BvcnQuY2xvc2UoKTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfSxcbiAgY3JlYXRlU3NoMjogYXN5bmMgKG9wdGlvbnMpID0+IHtcbiAgICBjb25zdCB7IFNzaDJUcmFuc3BvcnQgfSA9IGF3YWl0IGltcG9ydChcIi4vX3NzaF9zc2gyLnRzXCIpO1xuICAgIGNvbnN0IHRyYW5zcG9ydCA9IG5ldyBTc2gyVHJhbnNwb3J0KG9wdGlvbnMpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0cmFuc3BvcnQuc3RhcnQoKTtcbiAgICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGF3YWl0IHRyYW5zcG9ydC5jbG9zZSgpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9LFxufTtcblxuLyoqXG4gKiBBY2NvdW50IHRoYXQgcnVucyBvbmUgcmVtb3RlIGNvbW1hbmQuXG4gKlxuICogYHVzZXJgIHRhcmdldHMgYSBsb2NrZWQsIG5vbi1zdWRvIExha2Vib3ggYWNjb3VudC4gYHJvb3RgIGlzIHJlc2VydmVkIGZvclxuICogZml4ZWQgcGFja2FnZS1vd25lZCBib290c3RyYXAgc2NyaXB0cyBhbmQgaXMgbmV2ZXIgcmVhY2hhYmxlIGZyb20gUkVTVCxcbiAqIGFnZW50IHRvb2xzLCBvciBzZXJ2aWNlIGRlZmluaXRpb25zLlxuICovXG5leHBvcnQgdHlwZSBTc2hDb21tYW5kSWRlbnRpdHkgPSB7IGtpbmQ6IFwidXNlclwiOyBuYW1lOiBzdHJpbmc7IGhvbWU6IHN0cmluZyB9IHwgeyBraW5kOiBcInJvb3RcIiB9O1xuXG4vKiogQGludGVybmFsIEJ1aWxkcyBhIHJlbW90ZSBjb21tYW5kIGFmdGVyIGNsZWFyaW5nIGluaGVyaXRlZCBtYWNoaW5lIGNyZWRlbnRpYWxzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNzaENvbW1hbmRTY3JpcHQoXG4gIGNvbW1hbmQ6IHN0cmluZyxcbiAgYXJnczogc3RyaW5nW10sXG4gIGN3ZDogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBlbnY6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCB1bmRlZmluZWQsXG4gIGlkZW50aXR5OiBTc2hDb21tYW5kSWRlbnRpdHksXG4pOiBzdHJpbmcge1xuICBhc3NlcnRTYWZlU3NoRW52aXJvbm1lbnQoZW52KTtcbiAgY29uc3Qgcm9vdCA9IGlkZW50aXR5LmtpbmQgPT09IFwicm9vdFwiO1xuICBjb25zdCBob21lID0gcm9vdCA/IFwiL3Jvb3RcIiA6IGlkZW50aXR5LmhvbWU7XG4gIGNvbnN0IG5hbWUgPSByb290ID8gXCJyb290XCIgOiBpZGVudGl0eS5uYW1lO1xuICBjb25zdCB3b3JraW5nRGlyZWN0b3J5ID0gY3dkID8/IGhvbWU7XG4gIGNvbnN0IGludm9jYXRpb24gPSBbY29tbWFuZCwgLi4uc2NydWJMb2dpblNoZWxsQ29tbWFuZChjb21tYW5kLCBhcmdzKV0ubWFwKHNoZWxsUXVvdGUpLmpvaW4oXCIgXCIpO1xuICBjb25zdCBlbnZpcm9ubWVudCA9IE9iamVjdC5lbnRyaWVzKHtcbiAgICBIT01FOiBob21lLFxuICAgIFVTRVI6IG5hbWUsXG4gICAgTE9HTkFNRTogbmFtZSxcbiAgICBTSEVMTDogXCIvYmluL2Jhc2hcIixcbiAgICBQV0Q6IHdvcmtpbmdEaXJlY3RvcnksXG4gICAgUEFUSDogcm9vdFxuICAgICAgPyBcIi91c3IvbG9jYWwvc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL3NiaW46L3Vzci9iaW46L3NiaW46L2JpblwiXG4gICAgICA6IGAke2hvbWV9Ly5sb2NhbC9iaW46L3Vzci9sb2NhbC9iaW46L3Vzci9iaW46L2JpbmAsXG4gICAgREFUQUJSSUNLU19DT05GSUdfRklMRTogXCIvZGV2L251bGxcIixcbiAgICAuLi5lbnYsXG4gIH0pXG4gICAgLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBgJHtlbnZpcm9ubWVudE5hbWUoa2V5KX09JHtzaGVsbFF1b3RlKHZhbHVlKX1gKVxuICAgIC5qb2luKFwiIFwiKTtcbiAgY29uc3QgcnVuID0gYGNkIC0tICR7c2hlbGxRdW90ZSh3b3JraW5nRGlyZWN0b3J5KX0gJiYgJHtpbnZvY2F0aW9ufWA7XG4gIGNvbnN0IHN1ZG9BcmdzID0gcm9vdCA/IFtcIi1uXCIsIFwiLUhcIl0gOiBbXCItblwiLCBcIi1IXCIsIFwiLXVcIiwgbmFtZV07XG4gIGNvbnN0IHN3aXRjaGVkID0gW1wic3Vkb1wiLCAuLi5zdWRvQXJncywgXCItLVwiLCBcImVudlwiLCBcIi1pXCJdLm1hcChzaGVsbFF1b3RlKS5qb2luKFwiIFwiKTtcbiAgcmV0dXJuIGAke1NTSF9BVVRIX0VOVklST05NRU5UX1NDUlVCfVxcbmV4ZWMgJHtzd2l0Y2hlZH0gJHtlbnZpcm9ubWVudH0gJy9iaW4vc2gnICctYycgJHtzaGVsbFF1b3RlKHJ1bil9IDwvZGV2L251bGxgO1xufVxuXG5mdW5jdGlvbiBzY3J1YkxvZ2luU2hlbGxDb21tYW5kKGNvbW1hbmQ6IHN0cmluZywgYXJnczogc3RyaW5nW10pOiBzdHJpbmdbXSB7XG4gIGNvbnN0IGV4ZWN1dGFibGUgPSBjb21tYW5kLnNwbGl0KFwiL1wiKS5hdCgtMSk7XG4gIGlmICghZXhlY3V0YWJsZSB8fCAhW1wic2hcIiwgXCJiYXNoXCIsIFwienNoXCJdLmluY2x1ZGVzKGV4ZWN1dGFibGUpIHx8IGFyZ3NbMF0gIT09IFwiLWxjXCIpIHtcbiAgICByZXR1cm4gYXJncztcbiAgfVxuICBjb25zdCBbZmxhZ3MsIHNjcmlwdCwgLi4ucmVzdF0gPSBhcmdzO1xuICBpZiAoc2NyaXB0ID09PSB1bmRlZmluZWQpIHJldHVybiBhcmdzO1xuICByZXR1cm4gW2ZsYWdzLCBgJHtTU0hfQVVUSF9FTlZJUk9OTUVOVF9TQ1JVQn1cXG4ke3NjcmlwdH1gLCAuLi5yZXN0XTtcbn1cblxuY29uc3QgU1NIX0FVVEhfRU5WSVJPTk1FTlRfU0NSVUIgPSBgZm9yIF9fZGJ4X3Rvb2xzX25hbWUgaW4gJChlbnYgfCBzZWQgLW4gJ3MvXlxcXFwoW0EtWmEtel9dW0EtWmEtejAtOV9dKlxcXFwpPS4qL1xcXFwxL3AnKTsgZG9cbiAgY2FzZSBcIiRfX2RieF90b29sc19uYW1lXCIgaW5cbiAgICBEQVRBQlJJQ0tTXyp8U1NIX0FVVEhfU09DSylcbiAgICAgIHVuc2V0IFwiJF9fZGJ4X3Rvb2xzX25hbWVcIlxuICAgICAgOztcbiAgZXNhY1xuZG9uZVxuZXhwb3J0IERBVEFCUklDS1NfQ09ORklHX0ZJTEU9L2Rldi9udWxsYDtcblxuZnVuY3Rpb24gYXNzZXJ0U2FmZVNzaEVudmlyb25tZW50KGVudjogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgc3RyaW5nPj4gfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5rZXlzKGVudiA/PyB7fSkpIHtcbiAgICBpZiAoXG4gICAgICBuYW1lID09PSBcIkhPTUVcIiB8fFxuICAgICAgbmFtZSA9PT0gXCJVU0VSXCIgfHxcbiAgICAgIG5hbWUgPT09IFwiTE9HTkFNRVwiIHx8XG4gICAgICBuYW1lID09PSBcIlNIRUxMXCIgfHxcbiAgICAgIG5hbWUgPT09IFwiUFdEXCIgfHxcbiAgICAgIG5hbWUgPT09IFwiUEFUSFwiIHx8XG4gICAgICBuYW1lLnN0YXJ0c1dpdGgoXCJTVURPX1wiKSB8fFxuICAgICAgbmFtZS5zdGFydHNXaXRoKFwiREFUQUJSSUNLU19cIikgfHxcbiAgICAgIG5hbWUgPT09IFwiU1NIX0FVVEhfU09DS1wiXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiU1NIIGVudmlyb25tZW50IG92ZXJsYXlzIGNhbm5vdCByZXBsYWNlIHRoZSBMYWtlYm94IGlkZW50aXR5IG9yIHJlc3RvcmUgRGF0YWJyaWNrcyBvciBTU0ggYWdlbnQgY3JlZGVudGlhbHMuXCIsXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBzaGVsbFF1b3RlKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCcke3ZhbHVlLnJlcGxhY2VBbGwoXCInXCIsIFwiJ1xcXFwnJ1wiKX0nYDtcbn1cblxuZnVuY3Rpb24gZW52aXJvbm1lbnROYW1lKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoIS9eW0EtWmEtel9dW0EtWmEtejAtOV9dKiQvLnRlc3QodmFsdWUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIFNTSCBlbnZpcm9ubWVudCB2YXJpYWJsZSBuYW1lOiAke3ZhbHVlfWApO1xuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cbiJdfQ==
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/
|
|
1
|
+
{"root":["../src/_ssh_openssh.ts","../src/_ssh_ssh2.ts","../src/key-store.ts","../src/lifecycle.ts","../src/rest.ts","../src/session.ts","../src/ssh.ts","../src/transport.ts","../index.ts"],"version":"5.9.3"}
|