@dbx-tools/auth 0.9.31 → 0.9.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -97
- package/index.ts +8 -26
- package/lib/index.d.ts +8 -26
- package/lib/index.js +6 -22
- package/lib/src/{databricks-cli.d.ts → _databricks-cli.d.ts} +3 -7
- package/lib/src/_databricks-cli.js +172 -0
- package/lib/src/_errors.d.ts +5 -0
- package/lib/src/_errors.js +10 -0
- package/lib/src/{lifecycle.d.ts → _lifecycle.d.ts} +5 -5
- package/lib/src/_lifecycle.js +214 -0
- package/lib/src/_logging.d.ts +1 -1
- package/lib/src/_logging.js +2 -2
- package/lib/src/{personal-access-token.d.ts → _personal-access-token.d.ts} +1 -1
- package/lib/src/_personal-access-token.js +30 -0
- package/lib/src/_profile-config.d.ts +43 -0
- package/lib/src/_profile-config.js +443 -0
- package/lib/src/{service-principal.d.ts → _service-principal.d.ts} +1 -1
- package/lib/src/_service-principal.js +69 -0
- package/lib/src/{storage.d.ts → _storage.d.ts} +4 -6
- package/lib/src/_storage.js +94 -0
- package/lib/src/_types.d.ts +40 -0
- package/lib/src/_types.js +2 -0
- package/lib/src/client.d.ts +30 -0
- package/lib/src/client.js +223 -0
- package/lib/src/config.d.ts +36 -0
- package/lib/src/config.js +15 -0
- package/lib/src/profile.d.ts +11 -0
- package/lib/src/profile.js +21 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +34 -10
- package/src/{databricks-cli.ts → _databricks-cli.ts} +20 -109
- package/src/_errors.ts +11 -0
- package/src/{lifecycle.ts → _lifecycle.ts} +24 -48
- package/src/_logging.ts +2 -2
- package/src/{personal-access-token.ts → _personal-access-token.ts} +1 -1
- package/src/_profile-config.ts +545 -0
- package/src/{service-principal.ts → _service-principal.ts} +2 -2
- package/src/_storage.ts +109 -0
- package/src/_types.ts +45 -0
- package/src/client.ts +291 -0
- package/src/config.ts +44 -0
- package/src/profile.ts +33 -0
- package/lib/exports.d.ts +0 -2
- package/lib/exports.js +0 -3
- package/lib/src/_profile-core.d.ts +0 -28
- package/lib/src/_profile-core.js +0 -216
- package/lib/src/_profile.d.ts +0 -15
- package/lib/src/_profile.js +0 -236
- package/lib/src/databricks-auth.d.ts +0 -11
- package/lib/src/databricks-auth.js +0 -314
- package/lib/src/databricks-cli.js +0 -239
- package/lib/src/errors.d.ts +0 -7
- package/lib/src/errors.js +0 -14
- package/lib/src/generated/databricks-cli-assets.json +0 -33
- package/lib/src/http-client.d.ts +0 -23
- package/lib/src/http-client.js +0 -116
- package/lib/src/lifecycle.js +0 -229
- package/lib/src/node-storage.d.ts +0 -20
- package/lib/src/node-storage.js +0 -207
- package/lib/src/personal-access-token.js +0 -30
- package/lib/src/service-principal.js +0 -69
- package/lib/src/storage.js +0 -98
- package/lib/src/types.d.ts +0 -157
- package/lib/src/types.js +0 -67
- package/src/_profile-core.ts +0 -258
- package/src/_profile.ts +0 -319
- package/src/databricks-auth.ts +0 -416
- package/src/errors.ts +0 -16
- package/src/generated/databricks-cli-assets.json +0 -33
- package/src/http-client.ts +0 -147
- package/src/node-storage.ts +0 -230
- package/src/storage.ts +0 -104
- package/src/types.ts +0 -188
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import { homedir } from "node:os";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import * as bin from "@dbx-tools/core/bin";
|
|
4
|
-
import * as exec from "@dbx-tools/core/exec";
|
|
5
|
-
import * as stringUtils from "@dbx-tools/shared-core/string-utils";
|
|
6
|
-
import cliAssets from "./generated/databricks-cli-assets.json" with { type: "json" };
|
|
7
|
-
import { authLogger, failureMetadata, tokenMetadata } from "./_logging.js";
|
|
8
|
-
import { AuthError } from "./errors.js";
|
|
9
|
-
const resolutionCache = new Map();
|
|
10
|
-
const logger = authLogger("cli");
|
|
11
|
-
/** Resolve a compatible Databricks CLI, installing the pinned build asset when needed. */
|
|
12
|
-
export function resolveDatabricksCli(environment = process.env, options = {}) {
|
|
13
|
-
const candidate = stringValue(environment.DATABRICKS_CLI_PATH) ?? "databricks";
|
|
14
|
-
const key = `${candidate}\0${homedir()}\0${process.platform}\0${process.arch}\0${options.install !== false}`;
|
|
15
|
-
const cached = resolutionCache.get(key);
|
|
16
|
-
if (cached) {
|
|
17
|
-
logger.debug("reused Databricks CLI resolution", {
|
|
18
|
-
candidate,
|
|
19
|
-
install: options.install !== false,
|
|
20
|
-
});
|
|
21
|
-
return cached;
|
|
22
|
-
}
|
|
23
|
-
logger.debug("resolving Databricks CLI", {
|
|
24
|
-
candidate,
|
|
25
|
-
install: options.install !== false,
|
|
26
|
-
platform: process.platform,
|
|
27
|
-
arch: process.arch,
|
|
28
|
-
minimumVersion: cliAssets.minimumVersion,
|
|
29
|
-
});
|
|
30
|
-
const resolved = resolveDatabricksCliUncached(candidate, options.install !== false).catch((error) => {
|
|
31
|
-
resolutionCache.delete(key);
|
|
32
|
-
throw error;
|
|
33
|
-
});
|
|
34
|
-
resolutionCache.set(key, resolved);
|
|
35
|
-
return resolved;
|
|
36
|
-
}
|
|
37
|
-
/** Clear cached CLI resolution, primarily after installation or environment changes. */
|
|
38
|
-
export function resetDatabricksCliResolution() {
|
|
39
|
-
resolutionCache.clear();
|
|
40
|
-
logger.debug("cleared Databricks CLI resolution cache");
|
|
41
|
-
}
|
|
42
|
-
async function resolveDatabricksCliUncached(candidate, install) {
|
|
43
|
-
if (await compatibleDatabricksCli(candidate)) {
|
|
44
|
-
logger.debug("selected installed Databricks CLI", { executable: candidate });
|
|
45
|
-
return candidate;
|
|
46
|
-
}
|
|
47
|
-
const managed = managedExecutable();
|
|
48
|
-
if (await compatibleDatabricksCli(managed)) {
|
|
49
|
-
logger.debug("selected managed Databricks CLI", { executable: managed });
|
|
50
|
-
return managed;
|
|
51
|
-
}
|
|
52
|
-
if (!install) {
|
|
53
|
-
logger.debug("compatible Databricks CLI unavailable and installation disabled");
|
|
54
|
-
return undefined;
|
|
55
|
-
}
|
|
56
|
-
const asset = platformAsset();
|
|
57
|
-
if (!asset) {
|
|
58
|
-
logger.debug("no managed Databricks CLI asset for platform", {
|
|
59
|
-
platform: process.platform,
|
|
60
|
-
arch: process.arch,
|
|
61
|
-
});
|
|
62
|
-
return undefined;
|
|
63
|
-
}
|
|
64
|
-
const root = join(homedir(), ".databricks");
|
|
65
|
-
const binDir = join(root, "bin");
|
|
66
|
-
const executable = managedExecutableName();
|
|
67
|
-
const installed = await bin.ensure("databricks", asset, {
|
|
68
|
-
autoUnpackage: true,
|
|
69
|
-
destination: { root, binDir, path: join(binDir, executable) },
|
|
70
|
-
minVersion: cliAssets.minimumVersion,
|
|
71
|
-
selector: ({ source }) => join(source, executable),
|
|
72
|
-
versionParser: (output) => {
|
|
73
|
-
const version = bin.parseVersion(output);
|
|
74
|
-
return version === cliAssets.version ? version : undefined;
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
logger.debug("ensured managed Databricks CLI", {
|
|
78
|
-
executable: installed.path,
|
|
79
|
-
version: cliAssets.version,
|
|
80
|
-
});
|
|
81
|
-
return installed.path;
|
|
82
|
-
}
|
|
83
|
-
function managedExecutable() {
|
|
84
|
-
return join(homedir(), ".databricks", "bin", managedExecutableName());
|
|
85
|
-
}
|
|
86
|
-
function managedExecutableName() {
|
|
87
|
-
return process.platform === "win32" ? "databricks.exe" : "databricks";
|
|
88
|
-
}
|
|
89
|
-
async function compatibleDatabricksCli(executable) {
|
|
90
|
-
try {
|
|
91
|
-
const result = await runProcess(executable, ["--version"], {}, 10_000);
|
|
92
|
-
if (result.exitCode !== 0) {
|
|
93
|
-
logger.debug("Databricks CLI version probe failed", {
|
|
94
|
-
executable,
|
|
95
|
-
exitCode: result.exitCode,
|
|
96
|
-
});
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
const version = bin.parseVersion(result);
|
|
100
|
-
const compatible = version !== undefined && bin.isVersionAtLeast(version, cliAssets.minimumVersion);
|
|
101
|
-
logger.debug("probed Databricks CLI version", {
|
|
102
|
-
executable,
|
|
103
|
-
version: version ?? "unknown",
|
|
104
|
-
minimumVersion: cliAssets.minimumVersion,
|
|
105
|
-
compatible,
|
|
106
|
-
});
|
|
107
|
-
return compatible;
|
|
108
|
-
}
|
|
109
|
-
catch (cause) {
|
|
110
|
-
logger.debug("Databricks CLI version probe unavailable", {
|
|
111
|
-
executable,
|
|
112
|
-
error: failureMetadata(cause),
|
|
113
|
-
});
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function platformAsset() {
|
|
118
|
-
const key = `${process.platform}-${process.arch}`;
|
|
119
|
-
return cliAssets.assets[key];
|
|
120
|
-
}
|
|
121
|
-
/** Run interactive Databricks CLI login for one profile. */
|
|
122
|
-
export async function databricksCliLogin(profile, timeoutMs, executable = process.env.DATABRICKS_CLI_PATH ?? "databricks", environment = {}) {
|
|
123
|
-
logger.debug("starting Databricks CLI login", { profile, executable, timeoutMs });
|
|
124
|
-
const result = await runProcess(executable, ["auth", "login", "--profile", profile, "--timeout", `${Math.ceil(timeoutMs / 1000)}s`], environment);
|
|
125
|
-
if (result.exitCode !== 0)
|
|
126
|
-
throw new AuthError("cli", result.stderr || `databricks auth login exited ${result.exitCode}`);
|
|
127
|
-
logger.debug("Databricks CLI login completed", { profile, executable });
|
|
128
|
-
}
|
|
129
|
-
/** Request one profile token from the Databricks CLI. */
|
|
130
|
-
export async function databricksCliToken(profile, forceRefresh = false, executable = process.env.DATABRICKS_CLI_PATH ?? "databricks", environment = {}) {
|
|
131
|
-
logger.debug("requesting Databricks CLI token", { profile, executable, forceRefresh });
|
|
132
|
-
const args = ["auth", "token", "--profile", profile, "--output", "json"];
|
|
133
|
-
if (forceRefresh)
|
|
134
|
-
args.push("--force-refresh");
|
|
135
|
-
const result = await runProcess(executable, args, environment);
|
|
136
|
-
if (result.exitCode !== 0)
|
|
137
|
-
throw new AuthError("cli", result.stderr || `databricks auth token exited ${result.exitCode}`);
|
|
138
|
-
let value;
|
|
139
|
-
try {
|
|
140
|
-
value = JSON.parse(result.stdout ?? "");
|
|
141
|
-
}
|
|
142
|
-
catch (cause) {
|
|
143
|
-
throw new AuthError("cli", "Databricks CLI token output was not JSON", { cause });
|
|
144
|
-
}
|
|
145
|
-
const accessToken = stringValue(value.access_token ?? value.accessToken);
|
|
146
|
-
if (!accessToken)
|
|
147
|
-
throw new AuthError("cli", "Databricks CLI token output had no access token");
|
|
148
|
-
const token = {
|
|
149
|
-
accessToken,
|
|
150
|
-
tokenType: stringValue(value.token_type ?? value.tokenType) ?? "Bearer",
|
|
151
|
-
...(stringValue(value.refresh_token ?? value.refreshToken)
|
|
152
|
-
? { refreshToken: stringValue(value.refresh_token ?? value.refreshToken) }
|
|
153
|
-
: {}),
|
|
154
|
-
...(stringValue(value.expiry ?? value.expires_at)
|
|
155
|
-
? { expiry: stringValue(value.expiry ?? value.expires_at) }
|
|
156
|
-
: {}),
|
|
157
|
-
scopes: Array.isArray(value.scopes)
|
|
158
|
-
? value.scopes.filter((scope) => typeof scope === "string")
|
|
159
|
-
: [],
|
|
160
|
-
};
|
|
161
|
-
logger.debug("received Databricks CLI token", {
|
|
162
|
-
profile,
|
|
163
|
-
forceRefresh,
|
|
164
|
-
token: tokenMetadata(token),
|
|
165
|
-
});
|
|
166
|
-
return token;
|
|
167
|
-
}
|
|
168
|
-
async function runProcess(command, args, environment, timeoutMs) {
|
|
169
|
-
const controller = timeoutMs === undefined ? undefined : new AbortController();
|
|
170
|
-
const timeout = controller ? setTimeout(() => controller.abort(), timeoutMs) : undefined;
|
|
171
|
-
try {
|
|
172
|
-
return await exec.spawn(command, args, {
|
|
173
|
-
env: { ...process.env, ...environment },
|
|
174
|
-
stdin: "ignore",
|
|
175
|
-
stdout: "capture",
|
|
176
|
-
stderr: "capture",
|
|
177
|
-
signal: controller?.signal,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
finally {
|
|
181
|
-
if (timeout)
|
|
182
|
-
clearTimeout(timeout);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
/** Provider that lazily delegates U2M credentials to the Databricks CLI. */
|
|
186
|
-
export class DatabricksCliProvider {
|
|
187
|
-
profile;
|
|
188
|
-
executableOrResolver;
|
|
189
|
-
environment;
|
|
190
|
-
resolution;
|
|
191
|
-
constructor(profile, executableOrResolver = () => resolveDatabricksCli(), environment = {}) {
|
|
192
|
-
this.profile = profile;
|
|
193
|
-
this.executableOrResolver = executableOrResolver;
|
|
194
|
-
this.environment = environment;
|
|
195
|
-
}
|
|
196
|
-
async authenticate(_timeoutMs) {
|
|
197
|
-
return databricksCliToken(this.profile, false, await this.resolveExecutable(), this.environment);
|
|
198
|
-
}
|
|
199
|
-
async login(timeoutMs) {
|
|
200
|
-
const executable = await this.resolveExecutable();
|
|
201
|
-
await databricksCliLogin(this.profile, timeoutMs, executable, this.environment);
|
|
202
|
-
return databricksCliToken(this.profile, false, executable, this.environment);
|
|
203
|
-
}
|
|
204
|
-
async refresh(_token) {
|
|
205
|
-
return databricksCliToken(this.profile, true, await this.resolveExecutable(), this.environment);
|
|
206
|
-
}
|
|
207
|
-
canAuthenticateSilently() {
|
|
208
|
-
return true;
|
|
209
|
-
}
|
|
210
|
-
resolveExecutable() {
|
|
211
|
-
if (typeof this.executableOrResolver === "string") {
|
|
212
|
-
logger.debug("using configured Databricks CLI executable", {
|
|
213
|
-
profile: this.profile,
|
|
214
|
-
executable: this.executableOrResolver,
|
|
215
|
-
});
|
|
216
|
-
return Promise.resolve(this.executableOrResolver);
|
|
217
|
-
}
|
|
218
|
-
if (this.resolution) {
|
|
219
|
-
logger.debug("reused provider CLI resolution", { profile: this.profile });
|
|
220
|
-
return this.resolution;
|
|
221
|
-
}
|
|
222
|
-
logger.debug("resolving provider CLI lazily", { profile: this.profile });
|
|
223
|
-
this.resolution = this.executableOrResolver()
|
|
224
|
-
.then((executable) => {
|
|
225
|
-
if (!executable)
|
|
226
|
-
throw new AuthError("cli", "Databricks CLI is unavailable on this platform");
|
|
227
|
-
return executable;
|
|
228
|
-
})
|
|
229
|
-
.catch((error) => {
|
|
230
|
-
this.resolution = undefined;
|
|
231
|
-
throw error;
|
|
232
|
-
});
|
|
233
|
-
return this.resolution;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
function stringValue(value) {
|
|
237
|
-
return stringUtils.trimToNull(value) ?? undefined;
|
|
238
|
-
}
|
|
239
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWJyaWNrcy1jbGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGF0YWJyaWNrcy1jbGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNsQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRWpDLE9BQU8sS0FBSyxHQUFHLE1BQU0scUJBQXFCLENBQUM7QUFDM0MsT0FBTyxLQUFLLElBQUksTUFBTSxzQkFBc0IsQ0FBQztBQUM3QyxPQUFPLEtBQUssV0FBVyxNQUFNLHFDQUFxQyxDQUFDO0FBRW5FLE9BQU8sU0FBUyxNQUFNLHdDQUF3QyxDQUFDLE9BQU8sSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBQ3JGLE9BQU8sRUFBRSxVQUFVLEVBQUUsZUFBZSxFQUFFLGFBQWEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBR3hDLE1BQU0sZUFBZSxHQUFHLElBQUksR0FBRyxFQUF1QyxDQUFDO0FBQ3ZFLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQWVqQywwRkFBMEY7QUFDMUYsTUFBTSxVQUFVLG9CQUFvQixDQUNsQyxjQUE0RCxPQUFPLENBQUMsR0FBRyxFQUN2RSxVQUEwQyxFQUFFO0lBRTVDLE1BQU0sU0FBUyxHQUFHLFdBQVcsQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQUMsSUFBSSxZQUFZLENBQUM7SUFDL0UsTUFBTSxHQUFHLEdBQUcsR0FBRyxTQUFTLEtBQUssT0FBTyxFQUFFLEtBQUssT0FBTyxDQUFDLFFBQVEsS0FBSyxPQUFPLENBQUMsSUFBSSxLQUFLLE9BQU8sQ0FBQyxPQUFPLEtBQUssS0FBSyxFQUFFLENBQUM7SUFDN0csTUFBTSxNQUFNLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJ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QUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSSxTQUFTLENBQUM7QUFDcEQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGhvbWVkaXIgfSBmcm9tIFwibm9kZTpvc1wiO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJub2RlOnBhdGhcIjtcblxuaW1wb3J0ICogYXMgYmluIGZyb20gXCJAZGJ4LXRvb2xzL2NvcmUvYmluXCI7XG5pbXBvcnQgKiBhcyBleGVjIGZyb20gXCJAZGJ4LXRvb2xzL2NvcmUvZXhlY1wiO1xuaW1wb3J0ICogYXMgc3RyaW5nVXRpbHMgZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmUvc3RyaW5nLXV0aWxzXCI7XG5cbmltcG9ydCBjbGlBc3NldHMgZnJvbSBcIi4vZ2VuZXJhdGVkL2RhdGFicmlja3MtY2xpLWFzc2V0cy5qc29uXCIgd2l0aCB7IHR5cGU6IFwianNvblwiIH07XG5pbXBvcnQgeyBhdXRoTG9nZ2VyLCBmYWlsdXJlTWV0YWRhdGEsIHRva2VuTWV0YWRhdGEgfSBmcm9tIFwiLi9fbG9nZ2luZy50c1wiO1xuaW1wb3J0IHsgQXV0aEVycm9yIH0gZnJvbSBcIi4vZXJyb3JzLnRzXCI7XG5pbXBvcnQgdHlwZSB7IFRva2VuLCBUb2tlblByb3ZpZGVyIH0gZnJvbSBcIi4vdHlwZXMudHNcIjtcblxuY29uc3QgcmVzb2x1dGlvbkNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPj4oKTtcbmNvbnN0IGxvZ2dlciA9IGF1dGhMb2dnZXIoXCJjbGlcIik7XG5cbmludGVyZmFjZSBEYXRhYnJpY2tzQ2xpQXNzZXQge1xuICByZWFkb25seSB1cmw6IHN0cmluZztcbiAgcmVhZG9ubHkgc2hhMjU2OiBzdHJpbmc7XG59XG5cbi8qKiBEZWZlcnJlZCBEYXRhYnJpY2tzIENMSSBsb29rdXAgdXNlZCBieSBVMk0gdG9rZW4gYWNxdWlzaXRpb24uICovXG5leHBvcnQgdHlwZSBEYXRhYnJpY2tzQ2xpUmVzb2x2ZXIgPSAoKSA9PiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD47XG5cbi8qKiBDb250cm9scyB3aGV0aGVyIENMSSByZXNvbHV0aW9uIG1heSBpbnN0YWxsIHRoZSBwaW5uZWQgbWFuYWdlZCBleGVjdXRhYmxlLiAqL1xuZXhwb3J0IGludGVyZmFjZSBEYXRhYnJpY2tzQ2xpUmVzb2x1dGlvbk9wdGlvbnMge1xuICBpbnN0YWxsPzogYm9vbGVhbjtcbn1cblxuLyoqIFJlc29sdmUgYSBjb21wYXRpYmxlIERhdGFicmlja3MgQ0xJLCBpbnN0YWxsaW5nIHRoZSBwaW5uZWQgYnVpbGQgYXNzZXQgd2hlbiBuZWVkZWQuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZURhdGFicmlja3NDbGkoXG4gIGVudmlyb25tZW50OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+PiA9IHByb2Nlc3MuZW52LFxuICBvcHRpb25zOiBEYXRhYnJpY2tzQ2xpUmVzb2x1dGlvbk9wdGlvbnMgPSB7fSxcbik6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IGNhbmRpZGF0ZSA9IHN0cmluZ1ZhbHVlKGVudmlyb25tZW50LkRBVEFCUklDS1NfQ0xJX1BBVEgpID8/IFwiZGF0YWJyaWNrc1wiO1xuICBjb25zdCBrZXkgPSBgJHtjYW5kaWRhdGV9XFwwJHtob21lZGlyKCl9XFwwJHtwcm9jZXNzLnBsYXRmb3JtfVxcMCR7cHJvY2Vzcy5hcmNofVxcMCR7b3B0aW9ucy5pbnN0YWxsICE9PSBmYWxzZX1gO1xuICBjb25zdCBjYWNoZWQgPSByZXNvbHV0aW9uQ2FjaGUuZ2V0KGtleSk7XG4gIGlmIChjYWNoZWQpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJyZXVzZWQgRGF0YWJyaWNrcyBDTEkgcmVzb2x1dGlvblwiLCB7XG4gICAgICBjYW5kaWRhdGUsXG4gICAgICBpbnN0YWxsOiBvcHRpb25zLmluc3RhbGwgIT09IGZhbHNlLFxuICAgIH0pO1xuICAgIHJldHVybiBjYWNoZWQ7XG4gIH1cbiAgbG9nZ2VyLmRlYnVnKFwicmVzb2x2aW5nIERhdGFicmlja3MgQ0xJXCIsIHtcbiAgICBjYW5kaWRhdGUsXG4gICAgaW5zdGFsbDogb3B0aW9ucy5pbnN0YWxsICE9PSBmYWxzZSxcbiAgICBwbGF0Zm9ybTogcHJvY2Vzcy5wbGF0Zm9ybSxcbiAgICBhcmNoOiBwcm9jZXNzLmFyY2gsXG4gICAgbWluaW11bVZlcnNpb246IGNsaUFzc2V0cy5taW5pbXVtVmVyc2lvbixcbiAgfSk7XG4gIGNvbnN0IHJlc29sdmVkID0gcmVzb2x2ZURhdGFicmlja3NDbGlVbmNhY2hlZChjYW5kaWRhdGUsIG9wdGlvbnMuaW5zdGFsbCAhPT0gZmFsc2UpLmNhdGNoKFxuICAgIChlcnJvcikgPT4ge1xuICAgICAgcmVzb2x1dGlvbkNhY2hlLmRlbGV0ZShrZXkpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfSxcbiAgKTtcbiAgcmVzb2x1dGlvbkNhY2hlLnNldChrZXksIHJlc29sdmVkKTtcbiAgcmV0dXJuIHJlc29sdmVkO1xufVxuXG4vKiogQ2xlYXIgY2FjaGVkIENMSSByZXNvbHV0aW9uLCBwcmltYXJpbHkgYWZ0ZXIgaW5zdGFsbGF0aW9uIG9yIGVudmlyb25tZW50IGNoYW5nZXMuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzZXREYXRhYnJpY2tzQ2xpUmVzb2x1dGlvbigpOiB2b2lkIHtcbiAgcmVzb2x1dGlvbkNhY2hlLmNsZWFyKCk7XG4gIGxvZ2dlci5kZWJ1ZyhcImNsZWFyZWQgRGF0YWJyaWNrcyBDTEkgcmVzb2x1dGlvbiBjYWNoZVwiKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZURhdGFicmlja3NDbGlVbmNhY2hlZChcbiAgY2FuZGlkYXRlOiBzdHJpbmcsXG4gIGluc3RhbGw6IGJvb2xlYW4sXG4pOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICBpZiAoYXdhaXQgY29tcGF0aWJsZURhdGFicmlja3NDbGkoY2FuZGlkYXRlKSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcInNlbGVjdGVkIGluc3RhbGxlZCBEYXRhYnJpY2tzIENMSVwiLCB7IGV4ZWN1dGFibGU6IGNhbmRpZGF0ZSB9KTtcbiAgICByZXR1cm4gY2FuZGlkYXRlO1xuICB9XG4gIGNvbnN0IG1hbmFnZWQgPSBtYW5hZ2VkRXhlY3V0YWJsZSgpO1xuICBpZiAoYXdhaXQgY29tcGF0aWJsZURhdGFicmlja3NDbGkobWFuYWdlZCkpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJzZWxlY3RlZCBtYW5hZ2VkIERhdGFicmlja3MgQ0xJXCIsIHsgZXhlY3V0YWJsZTogbWFuYWdlZCB9KTtcbiAgICByZXR1cm4gbWFuYWdlZDtcbiAgfVxuICBpZiAoIWluc3RhbGwpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJjb21wYXRpYmxlIERhdGFicmlja3MgQ0xJIHVuYXZhaWxhYmxlIGFuZCBpbnN0YWxsYXRpb24gZGlzYWJsZWRcIik7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICBjb25zdCBhc3NldCA9IHBsYXRmb3JtQXNzZXQoKTtcbiAgaWYgKCFhc3NldCkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcIm5vIG1hbmFnZWQgRGF0YWJyaWNrcyBDTEkgYXNzZXQgZm9yIHBsYXRmb3JtXCIsIHtcbiAgICAgIHBsYXRmb3JtOiBwcm9jZXNzLnBsYXRmb3JtLFxuICAgICAgYXJjaDogcHJvY2Vzcy5hcmNoLFxuICAgIH0pO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgY29uc3Qgcm9vdCA9IGpvaW4oaG9tZWRpcigpLCBcIi5kYXRhYnJpY2tzXCIpO1xuICBjb25zdCBiaW5EaXIgPSBqb2luKHJvb3QsIFwiYmluXCIpO1xuICBjb25zdCBleGVjdXRhYmxlID0gbWFuYWdlZEV4ZWN1dGFibGVOYW1lKCk7XG4gIGNvbnN0IGluc3RhbGxlZCA9IGF3YWl0IGJpbi5lbnN1cmUoXCJkYXRhYnJpY2tzXCIsIGFzc2V0LCB7XG4gICAgYXV0b1VucGFja2FnZTogdHJ1ZSxcbiAgICBkZXN0aW5hdGlvbjogeyByb290LCBiaW5EaXIsIHBhdGg6IGpvaW4oYmluRGlyLCBleGVjdXRhYmxlKSB9LFxuICAgIG1pblZlcnNpb246IGNsaUFzc2V0cy5taW5pbXVtVmVyc2lvbixcbiAgICBzZWxlY3RvcjogKHsgc291cmNlIH0pID0+IGpvaW4oc291cmNlLCBleGVjdXRhYmxlKSxcbiAgICB2ZXJzaW9uUGFyc2VyOiAob3V0cHV0KSA9PiB7XG4gICAgICBjb25zdCB2ZXJzaW9uID0gYmluLnBhcnNlVmVyc2lvbihvdXRwdXQpO1xuICAgICAgcmV0dXJuIHZlcnNpb24gPT09IGNsaUFzc2V0cy52ZXJzaW9uID8gdmVyc2lvbiA6IHVuZGVmaW5lZDtcbiAgICB9LFxuICB9KTtcbiAgbG9nZ2VyLmRlYnVnKFwiZW5zdXJlZCBtYW5hZ2VkIERhdGFicmlja3MgQ0xJXCIsIHtcbiAgICBleGVjdXRhYmxlOiBpbnN0YWxsZWQucGF0aCxcbiAgICB2ZXJzaW9uOiBjbGlBc3NldHMudmVyc2lvbixcbiAgfSk7XG4gIHJldHVybiBpbnN0YWxsZWQucGF0aDtcbn1cblxuZnVuY3Rpb24gbWFuYWdlZEV4ZWN1dGFibGUoKTogc3RyaW5nIHtcbiAgcmV0dXJuIGpvaW4oaG9tZWRpcigpLCBcIi5kYXRhYnJpY2tzXCIsIFwiYmluXCIsIG1hbmFnZWRFeGVjdXRhYmxlTmFtZSgpKTtcbn1cblxuZnVuY3Rpb24gbWFuYWdlZEV4ZWN1dGFibGVOYW1lKCk6IHN0cmluZyB7XG4gIHJldHVybiBwcm9jZXNzLnBsYXRmb3JtID09PSBcIndpbjMyXCIgPyBcImRhdGFicmlja3MuZXhlXCIgOiBcImRhdGFicmlja3NcIjtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY29tcGF0aWJsZURhdGFicmlja3NDbGkoZXhlY3V0YWJsZTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnVuUHJvY2VzcyhleGVjdXRhYmxlLCBbXCItLXZlcnNpb25cIl0sIHt9LCAxMF8wMDApO1xuICAgIGlmIChyZXN1bHQuZXhpdENvZGUgIT09IDApIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcIkRhdGFicmlja3MgQ0xJIHZlcnNpb24gcHJvYmUgZmFpbGVkXCIsIHtcbiAgICAgICAgZXhlY3V0YWJsZSxcbiAgICAgICAgZXhpdENvZGU6IHJlc3VsdC5leGl0Q29kZSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCB2ZXJzaW9uID0gYmluLnBhcnNlVmVyc2lvbihyZXN1bHQpO1xuICAgIGNvbnN0IGNvbXBhdGlibGUgPVxuICAgICAgdmVyc2lvbiAhPT0gdW5kZWZpbmVkICYmIGJpbi5pc1ZlcnNpb25BdExlYXN0KHZlcnNpb24sIGNsaUFzc2V0cy5taW5pbXVtVmVyc2lvbik7XG4gICAgbG9nZ2VyLmRlYnVnKFwicHJvYmVkIERhdGFicmlja3MgQ0xJIHZlcnNpb25cIiwge1xuICAgICAgZXhlY3V0YWJsZSxcbiAgICAgIHZlcnNpb246IHZlcnNpb24gPz8gXCJ1bmtub3duXCIsXG4gICAgICBtaW5pbXVtVmVyc2lvbjogY2xpQXNzZXRzLm1pbmltdW1WZXJzaW9uLFxuICAgICAgY29tcGF0aWJsZSxcbiAgICB9KTtcbiAgICByZXR1cm4gY29tcGF0aWJsZTtcbiAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJEYXRhYnJpY2tzIENMSSB2ZXJzaW9uIHByb2JlIHVuYXZhaWxhYmxlXCIsIHtcbiAgICAgIGV4ZWN1dGFibGUsXG4gICAgICBlcnJvcjogZmFpbHVyZU1ldGFkYXRhKGNhdXNlKSxcbiAgICB9KTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuZnVuY3Rpb24gcGxhdGZvcm1Bc3NldCgpOiBEYXRhYnJpY2tzQ2xpQXNzZXQgfCB1bmRlZmluZWQge1xuICBjb25zdCBrZXkgPSBgJHtwcm9jZXNzLnBsYXRmb3JtfS0ke3Byb2Nlc3MuYXJjaH1gIGFzIGtleW9mIHR5cGVvZiBjbGlBc3NldHMuYXNzZXRzO1xuICByZXR1cm4gY2xpQXNzZXRzLmFzc2V0c1trZXldO1xufVxuXG4vKiogUnVuIGludGVyYWN0aXZlIERhdGFicmlja3MgQ0xJIGxvZ2luIGZvciBvbmUgcHJvZmlsZS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkYXRhYnJpY2tzQ2xpTG9naW4oXG4gIHByb2ZpbGU6IHN0cmluZyxcbiAgdGltZW91dE1zOiBudW1iZXIsXG4gIGV4ZWN1dGFibGUgPSBwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0NMSV9QQVRIID8/IFwiZGF0YWJyaWNrc1wiLFxuICBlbnZpcm9ubWVudDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9LFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGxvZ2dlci5kZWJ1ZyhcInN0YXJ0aW5nIERhdGFicmlja3MgQ0xJIGxvZ2luXCIsIHsgcHJvZmlsZSwgZXhlY3V0YWJsZSwgdGltZW91dE1zIH0pO1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCBydW5Qcm9jZXNzKFxuICAgIGV4ZWN1dGFibGUsXG4gICAgW1wiYXV0aFwiLCBcImxvZ2luXCIsIFwiLS1wcm9maWxlXCIsIHByb2ZpbGUsIFwiLS10aW1lb3V0XCIsIGAke01hdGguY2VpbCh0aW1lb3V0TXMgLyAxMDAwKX1zYF0sXG4gICAgZW52aXJvbm1lbnQsXG4gICk7XG4gIGlmIChyZXN1bHQuZXhpdENvZGUgIT09IDApXG4gICAgdGhyb3cgbmV3IEF1dGhFcnJvcihcImNsaVwiLCByZXN1bHQuc3RkZXJyIHx8IGBkYXRhYnJpY2tzIGF1dGggbG9naW4gZXhpdGVkICR7cmVzdWx0LmV4aXRDb2RlfWApO1xuICBsb2dnZXIuZGVidWcoXCJEYXRhYnJpY2tzIENMSSBsb2dpbiBjb21wbGV0ZWRcIiwgeyBwcm9maWxlLCBleGVjdXRhYmxlIH0pO1xufVxuXG4vKiogUmVxdWVzdCBvbmUgcHJvZmlsZSB0b2tlbiBmcm9tIHRoZSBEYXRhYnJpY2tzIENMSS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkYXRhYnJpY2tzQ2xpVG9rZW4oXG4gIHByb2ZpbGU6IHN0cmluZyxcbiAgZm9yY2VSZWZyZXNoID0gZmFsc2UsXG4gIGV4ZWN1dGFibGUgPSBwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0NMSV9QQVRIID8/IFwiZGF0YWJyaWNrc1wiLFxuICBlbnZpcm9ubWVudDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9LFxuKTogUHJvbWlzZTxUb2tlbj4ge1xuICBsb2dnZXIuZGVidWcoXCJyZXF1ZXN0aW5nIERhdGFicmlja3MgQ0xJIHRva2VuXCIsIHsgcHJvZmlsZSwgZXhlY3V0YWJsZSwgZm9yY2VSZWZyZXNoIH0pO1xuICBjb25zdCBhcmdzID0gW1wiYXV0aFwiLCBcInRva2VuXCIsIFwiLS1wcm9maWxlXCIsIHByb2ZpbGUsIFwiLS1vdXRwdXRcIiwgXCJqc29uXCJdO1xuICBpZiAoZm9yY2VSZWZyZXNoKSBhcmdzLnB1c2goXCItLWZvcmNlLXJlZnJlc2hcIik7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJ1blByb2Nlc3MoZXhlY3V0YWJsZSwgYXJncywgZW52aXJvbm1lbnQpO1xuICBpZiAocmVzdWx0LmV4aXRDb2RlICE9PSAwKVxuICAgIHRocm93IG5ldyBBdXRoRXJyb3IoXCJjbGlcIiwgcmVzdWx0LnN0ZGVyciB8fCBgZGF0YWJyaWNrcyBhdXRoIHRva2VuIGV4aXRlZCAke3Jlc3VsdC5leGl0Q29kZX1gKTtcbiAgbGV0IHZhbHVlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgdHJ5IHtcbiAgICB2YWx1ZSA9IEpTT04ucGFyc2UocmVzdWx0LnN0ZG91dCA/PyBcIlwiKSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICB0aHJvdyBuZXcgQXV0aEVycm9yKFwiY2xpXCIsIFwiRGF0YWJyaWNrcyBDTEkgdG9rZW4gb3V0cHV0IHdhcyBub3QgSlNPTlwiLCB7IGNhdXNlIH0pO1xuICB9XG4gIGNvbnN0IGFjY2Vzc1Rva2VuID0gc3RyaW5nVmFsdWUodmFsdWUuYWNjZXNzX3Rva2VuID8/IHZhbHVlLmFjY2Vzc1Rva2VuKTtcbiAgaWYgKCFhY2Nlc3NUb2tlbikgdGhyb3cgbmV3IEF1dGhFcnJvcihcImNsaVwiLCBcIkRhdGFicmlja3MgQ0xJIHRva2VuIG91dHB1dCBoYWQgbm8gYWNjZXNzIHRva2VuXCIpO1xuICBjb25zdCB0b2tlbiA9IHtcbiAgICBhY2Nlc3NUb2tlbixcbiAgICB0b2tlblR5cGU6IHN0cmluZ1ZhbHVlKHZhbHVlLnRva2VuX3R5cGUgPz8gdmFsdWUudG9rZW5UeXBlKSA/PyBcIkJlYXJlclwiLFxuICAgIC4uLihzdHJpbmdWYWx1ZSh2YWx1ZS5yZWZyZXNoX3Rva2VuID8/IHZhbHVlLnJlZnJlc2hUb2tlbilcbiAgICAgID8geyByZWZyZXNoVG9rZW46IHN0cmluZ1ZhbHVlKHZhbHVlLnJlZnJlc2hfdG9rZW4gPz8gdmFsdWUucmVmcmVzaFRva2VuKSB9XG4gICAgICA6IHt9KSxcbiAgICAuLi4oc3RyaW5nVmFsdWUodmFsdWUuZXhwaXJ5ID8/IHZhbHVlLmV4cGlyZXNfYXQpXG4gICAgICA/IHsgZXhwaXJ5OiBzdHJpbmdWYWx1ZSh2YWx1ZS5leHBpcnkgPz8gdmFsdWUuZXhwaXJlc19hdCkgfVxuICAgICAgOiB7fSksXG4gICAgc2NvcGVzOiBBcnJheS5pc0FycmF5KHZhbHVlLnNjb3BlcylcbiAgICAgID8gdmFsdWUuc2NvcGVzLmZpbHRlcigoc2NvcGUpOiBzY29wZSBpcyBzdHJpbmcgPT4gdHlwZW9mIHNjb3BlID09PSBcInN0cmluZ1wiKVxuICAgICAgOiBbXSxcbiAgfTtcbiAgbG9nZ2VyLmRlYnVnKFwicmVjZWl2ZWQgRGF0YWJyaWNrcyBDTEkgdG9rZW5cIiwge1xuICAgIHByb2ZpbGUsXG4gICAgZm9yY2VSZWZyZXNoLFxuICAgIHRva2VuOiB0b2tlbk1ldGFkYXRhKHRva2VuKSxcbiAgfSk7XG4gIHJldHVybiB0b2tlbjtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcnVuUHJvY2VzcyhcbiAgY29tbWFuZDogc3RyaW5nLFxuICBhcmdzOiBzdHJpbmdbXSxcbiAgZW52aXJvbm1lbnQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4gIHRpbWVvdXRNcz86IG51bWJlcixcbik6IFByb21pc2U8eyBleGl0Q29kZTogbnVtYmVyOyBzdGRvdXQ6IHN0cmluZzsgc3RkZXJyOiBzdHJpbmcgfT4ge1xuICBjb25zdCBjb250cm9sbGVyID0gdGltZW91dE1zID09PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIGNvbnN0IHRpbWVvdXQgPSBjb250cm9sbGVyID8gc2V0VGltZW91dCgoKSA9PiBjb250cm9sbGVyLmFib3J0KCksIHRpbWVvdXRNcykgOiB1bmRlZmluZWQ7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IGV4ZWMuc3Bhd24oY29tbWFuZCwgYXJncywge1xuICAgICAgZW52OiB7IC4uLnByb2Nlc3MuZW52LCAuLi5lbnZpcm9ubWVudCB9LFxuICAgICAgc3RkaW46IFwiaWdub3JlXCIsXG4gICAgICBzdGRvdXQ6IFwiY2FwdHVyZVwiLFxuICAgICAgc3RkZXJyOiBcImNhcHR1cmVcIixcbiAgICAgIHNpZ25hbDogY29udHJvbGxlcj8uc2lnbmFsLFxuICAgIH0pO1xuICB9IGZpbmFsbHkge1xuICAgIGlmICh0aW1lb3V0KSBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gIH1cbn1cblxuLyoqIFByb3ZpZGVyIHRoYXQgbGF6aWx5IGRlbGVnYXRlcyBVMk0gY3JlZGVudGlhbHMgdG8gdGhlIERhdGFicmlja3MgQ0xJLiAqL1xuZXhwb3J0IGNsYXNzIERhdGFicmlja3NDbGlQcm92aWRlciBpbXBsZW1lbnRzIFRva2VuUHJvdmlkZXIge1xuICBwcml2YXRlIHJlc29sdXRpb24/OiBQcm9taXNlPHN0cmluZz47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBwcm9maWxlOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBleGVjdXRhYmxlT3JSZXNvbHZlcjogc3RyaW5nIHwgRGF0YWJyaWNrc0NsaVJlc29sdmVyID0gKCkgPT5cbiAgICAgIHJlc29sdmVEYXRhYnJpY2tzQ2xpKCksXG4gICAgcHJpdmF0ZSByZWFkb25seSBlbnZpcm9ubWVudDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9LFxuICApIHt9XG5cbiAgYXN5bmMgYXV0aGVudGljYXRlKF90aW1lb3V0TXM6IG51bWJlcik6IFByb21pc2U8VG9rZW4+IHtcbiAgICByZXR1cm4gZGF0YWJyaWNrc0NsaVRva2VuKFxuICAgICAgdGhpcy5wcm9maWxlLFxuICAgICAgZmFsc2UsXG4gICAgICBhd2FpdCB0aGlzLnJlc29sdmVFeGVjdXRhYmxlKCksXG4gICAgICB0aGlzLmVudmlyb25tZW50LFxuICAgICk7XG4gIH1cblxuICBhc3luYyBsb2dpbih0aW1lb3V0TXM6IG51bWJlcik6IFByb21pc2U8VG9rZW4+IHtcbiAgICBjb25zdCBleGVjdXRhYmxlID0gYXdhaXQgdGhpcy5yZXNvbHZlRXhlY3V0YWJsZSgpO1xuICAgIGF3YWl0IGRhdGFicmlja3NDbGlMb2dpbih0aGlzLnByb2ZpbGUsIHRpbWVvdXRNcywgZXhlY3V0YWJsZSwgdGhpcy5lbnZpcm9ubWVudCk7XG4gICAgcmV0dXJuIGRhdGFicmlja3NDbGlUb2tlbih0aGlzLnByb2ZpbGUsIGZhbHNlLCBleGVjdXRhYmxlLCB0aGlzLmVudmlyb25tZW50KTtcbiAgfVxuXG4gIGFzeW5jIHJlZnJlc2goX3Rva2VuOiBUb2tlbik6IFByb21pc2U8VG9rZW4+IHtcbiAgICByZXR1cm4gZGF0YWJyaWNrc0NsaVRva2VuKHRoaXMucHJvZmlsZSwgdHJ1ZSwgYXdhaXQgdGhpcy5yZXNvbHZlRXhlY3V0YWJsZSgpLCB0aGlzLmVudmlyb25tZW50KTtcbiAgfVxuXG4gIGNhbkF1dGhlbnRpY2F0ZVNpbGVudGx5KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlRXhlY3V0YWJsZSgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGlmICh0eXBlb2YgdGhpcy5leGVjdXRhYmxlT3JSZXNvbHZlciA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgbG9nZ2VyLmRlYnVnKFwidXNpbmcgY29uZmlndXJlZCBEYXRhYnJpY2tzIENMSSBleGVjdXRhYmxlXCIsIHtcbiAgICAgICAgcHJvZmlsZTogdGhpcy5wcm9maWxlLFxuICAgICAgICBleGVjdXRhYmxlOiB0aGlzLmV4ZWN1dGFibGVPclJlc29sdmVyLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuZXhlY3V0YWJsZU9yUmVzb2x2ZXIpO1xuICAgIH1cbiAgICBpZiAodGhpcy5yZXNvbHV0aW9uKSB7XG4gICAgICBsb2dnZXIuZGVidWcoXCJyZXVzZWQgcHJvdmlkZXIgQ0xJIHJlc29sdXRpb25cIiwgeyBwcm9maWxlOiB0aGlzLnByb2ZpbGUgfSk7XG4gICAgICByZXR1cm4gdGhpcy5yZXNvbHV0aW9uO1xuICAgIH1cbiAgICBsb2dnZXIuZGVidWcoXCJyZXNvbHZpbmcgcHJvdmlkZXIgQ0xJIGxhemlseVwiLCB7IHByb2ZpbGU6IHRoaXMucHJvZmlsZSB9KTtcbiAgICB0aGlzLnJlc29sdXRpb24gPSB0aGlzLmV4ZWN1dGFibGVPclJlc29sdmVyKClcbiAgICAgIC50aGVuKChleGVjdXRhYmxlKSA9PiB7XG4gICAgICAgIGlmICghZXhlY3V0YWJsZSlcbiAgICAgICAgICB0aHJvdyBuZXcgQXV0aEVycm9yKFwiY2xpXCIsIFwiRGF0YWJyaWNrcyBDTEkgaXMgdW5hdmFpbGFibGUgb24gdGhpcyBwbGF0Zm9ybVwiKTtcbiAgICAgICAgcmV0dXJuIGV4ZWN1dGFibGU7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnJlc29sdXRpb24gPSB1bmRlZmluZWQ7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSk7XG4gICAgcmV0dXJuIHRoaXMucmVzb2x1dGlvbjtcbiAgfVxufVxuXG5mdW5jdGlvbiBzdHJpbmdWYWx1ZSh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBzdHJpbmdVdGlscy50cmltVG9OdWxsKHZhbHVlKSA/PyB1bmRlZmluZWQ7XG59XG4iXX0=
|
package/lib/src/errors.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/** Authentication failure with a stable category for callers and language shims. */
|
|
2
|
-
export declare class AuthError extends Error {
|
|
3
|
-
readonly kind: "config" | "oauth" | "storage" | "lock-timeout" | "cli" | "http";
|
|
4
|
-
constructor(kind: "config" | "oauth" | "storage" | "lock-timeout" | "cli" | "http", message: string, options?: ErrorOptions);
|
|
5
|
-
}
|
|
6
|
-
/** Normalize arbitrary failures without erasing their original cause. */
|
|
7
|
-
export declare function authError(kind: AuthError["kind"], message: string, cause?: unknown): AuthError;
|
package/lib/src/errors.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/** Authentication failure with a stable category for callers and language shims. */
|
|
2
|
-
export class AuthError extends Error {
|
|
3
|
-
kind;
|
|
4
|
-
constructor(kind, message, options) {
|
|
5
|
-
super(message, options);
|
|
6
|
-
this.kind = kind;
|
|
7
|
-
this.name = "AuthError";
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
/** Normalize arbitrary failures without erasing their original cause. */
|
|
11
|
-
export function authError(kind, message, cause) {
|
|
12
|
-
return cause instanceof AuthError ? cause : new AuthError(kind, message, { cause });
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Vycm9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxvRkFBb0Y7QUFDcEYsTUFBTSxPQUFPLFNBQVUsU0FBUSxLQUFLO0lBRXZCO0lBRFgsWUFDVyxJQUFzRSxFQUMvRSxPQUFlLEVBQ2YsT0FBc0I7UUFFdEIsS0FBSyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUpmLFNBQUksR0FBSixJQUFJLENBQWtFO1FBSy9FLElBQUksQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFDO0lBQzFCLENBQUM7Q0FDRjtBQUVELHlFQUF5RTtBQUN6RSxNQUFNLFVBQVUsU0FBUyxDQUFDLElBQXVCLEVBQUUsT0FBZSxFQUFFLEtBQWU7SUFDakYsT0FBTyxLQUFLLFlBQVksU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksU0FBUyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0FBQ3RGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiogQXV0aGVudGljYXRpb24gZmFpbHVyZSB3aXRoIGEgc3RhYmxlIGNhdGVnb3J5IGZvciBjYWxsZXJzIGFuZCBsYW5ndWFnZSBzaGltcy4gKi9cbmV4cG9ydCBjbGFzcyBBdXRoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IGtpbmQ6IFwiY29uZmlnXCIgfCBcIm9hdXRoXCIgfCBcInN0b3JhZ2VcIiB8IFwibG9jay10aW1lb3V0XCIgfCBcImNsaVwiIHwgXCJodHRwXCIsXG4gICAgbWVzc2FnZTogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBFcnJvck9wdGlvbnMsXG4gICkge1xuICAgIHN1cGVyKG1lc3NhZ2UsIG9wdGlvbnMpO1xuICAgIHRoaXMubmFtZSA9IFwiQXV0aEVycm9yXCI7XG4gIH1cbn1cblxuLyoqIE5vcm1hbGl6ZSBhcmJpdHJhcnkgZmFpbHVyZXMgd2l0aG91dCBlcmFzaW5nIHRoZWlyIG9yaWdpbmFsIGNhdXNlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGF1dGhFcnJvcihraW5kOiBBdXRoRXJyb3JbXCJraW5kXCJdLCBtZXNzYWdlOiBzdHJpbmcsIGNhdXNlPzogdW5rbm93bik6IEF1dGhFcnJvciB7XG4gIHJldHVybiBjYXVzZSBpbnN0YW5jZW9mIEF1dGhFcnJvciA/IGNhdXNlIDogbmV3IEF1dGhFcnJvcihraW5kLCBtZXNzYWdlLCB7IGNhdXNlIH0pO1xufVxuIl19
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schemaVersion": 1,
|
|
3
|
-
"dbxToolsVersion": "0.9.21",
|
|
4
|
-
"minimumVersion": "0.296.0",
|
|
5
|
-
"version": "1.19.0",
|
|
6
|
-
"publishedAt": "2026-09-30T13:13:22Z",
|
|
7
|
-
"assets": {
|
|
8
|
-
"darwin-arm64": {
|
|
9
|
-
"url": "https://github.com/databricks/cli/releases/download/v1.19.0/databricks_cli_1.19.0_darwin_arm64.tar.gz",
|
|
10
|
-
"sha256": "b84c6a8c623578308a724cdd7181b92b0816c2531564f16f8de7559b2a39f51f"
|
|
11
|
-
},
|
|
12
|
-
"darwin-x64": {
|
|
13
|
-
"url": "https://github.com/databricks/cli/releases/download/v1.19.0/databricks_cli_1.19.0_darwin_amd64.tar.gz",
|
|
14
|
-
"sha256": "d29a5dc1ea7d44d0d892fd4beac05d22daa932982ca6bf98a06d52c95f5ed4cd"
|
|
15
|
-
},
|
|
16
|
-
"linux-arm64": {
|
|
17
|
-
"url": "https://github.com/databricks/cli/releases/download/v1.19.0/databricks_cli_1.19.0_linux_arm64.tar.gz",
|
|
18
|
-
"sha256": "2997ccbda57090ee48bd9282d5cb3a5bef78025db64fd1573fbd7c8726856086"
|
|
19
|
-
},
|
|
20
|
-
"linux-x64": {
|
|
21
|
-
"url": "https://github.com/databricks/cli/releases/download/v1.19.0/databricks_cli_1.19.0_linux_amd64.tar.gz",
|
|
22
|
-
"sha256": "bddf87df3d72b61384da724b40f18ab483a98af742748260097a7bb8154b070e"
|
|
23
|
-
},
|
|
24
|
-
"win32-arm64": {
|
|
25
|
-
"url": "https://github.com/databricks/cli/releases/download/v1.19.0/databricks_cli_1.19.0_windows_arm64.tar.gz",
|
|
26
|
-
"sha256": "c28d098490ea1966230c07585312f8bc66e18d468e34b06319d44e29d61c4602"
|
|
27
|
-
},
|
|
28
|
-
"win32-x64": {
|
|
29
|
-
"url": "https://github.com/databricks/cli/releases/download/v1.19.0/databricks_cli_1.19.0_windows_amd64.tar.gz",
|
|
30
|
-
"sha256": "0ded24a2b001e001c815b9c1c66dc2ef1f6c2e60c64f63c6d9afb8e9fe85afdb"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
package/lib/src/http-client.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { type DatabricksAuthDependencies } from "./databricks-auth.ts";
|
|
2
|
-
import type { AuthClient, DatabricksAuthOptions } from "./types.ts";
|
|
3
|
-
/** Options for one Databricks JSON API request. */
|
|
4
|
-
export interface DatabricksRequestOptions {
|
|
5
|
-
method?: string;
|
|
6
|
-
body?: unknown;
|
|
7
|
-
headers?: Headers | Record<string, string> | [string, string][];
|
|
8
|
-
login?: boolean;
|
|
9
|
-
signal?: AbortSignal;
|
|
10
|
-
}
|
|
11
|
-
/** Dependency-light Databricks JSON client with one rejected-token refresh. */
|
|
12
|
-
export declare class DatabricksClient {
|
|
13
|
-
readonly auth: AuthClient;
|
|
14
|
-
private readonly fetcher;
|
|
15
|
-
private constructor();
|
|
16
|
-
static create(options?: DatabricksAuthOptions, dependencies?: DatabricksAuthDependencies): Promise<DatabricksClient>;
|
|
17
|
-
profile(): string;
|
|
18
|
-
host(): string;
|
|
19
|
-
principal(): string;
|
|
20
|
-
workspaceId(): string | undefined;
|
|
21
|
-
request(path: string, options?: DatabricksRequestOptions): Promise<unknown>;
|
|
22
|
-
private send;
|
|
23
|
-
}
|
package/lib/src/http-client.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { authLogger } from "./_logging.js";
|
|
2
|
-
import { AuthError } from "./errors.js";
|
|
3
|
-
import { createAuthClient } from "./databricks-auth.js";
|
|
4
|
-
import { DEFAULT_ACCESS_TOKEN_HEADER, WORKSPACE_ID_HEADER } from "./types.js";
|
|
5
|
-
const logger = authLogger("http");
|
|
6
|
-
/** Dependency-light Databricks JSON client with one rejected-token refresh. */
|
|
7
|
-
export class DatabricksClient {
|
|
8
|
-
auth;
|
|
9
|
-
fetcher;
|
|
10
|
-
constructor(auth, fetcher) {
|
|
11
|
-
this.auth = auth;
|
|
12
|
-
this.fetcher = fetcher;
|
|
13
|
-
}
|
|
14
|
-
static async create(options = { preferUserToMachine: true }, dependencies = {}) {
|
|
15
|
-
const client = new DatabricksClient(await createAuthClient(options, undefined, dependencies), dependencies.fetch ?? globalThis.fetch);
|
|
16
|
-
logger.debug("created Databricks HTTP client", {
|
|
17
|
-
profile: client.profile(),
|
|
18
|
-
host: client.host(),
|
|
19
|
-
hasWorkspaceId: Boolean(client.workspaceId()),
|
|
20
|
-
});
|
|
21
|
-
return client;
|
|
22
|
-
}
|
|
23
|
-
profile() {
|
|
24
|
-
return this.auth.status().profile;
|
|
25
|
-
}
|
|
26
|
-
host() {
|
|
27
|
-
return this.auth.status().host;
|
|
28
|
-
}
|
|
29
|
-
principal() {
|
|
30
|
-
return this.auth.principal();
|
|
31
|
-
}
|
|
32
|
-
workspaceId() {
|
|
33
|
-
return this.auth.workspaceId();
|
|
34
|
-
}
|
|
35
|
-
async request(path, options = {}) {
|
|
36
|
-
const url = new URL(path, `${this.host().replace(/\/$/, "")}/`).toString();
|
|
37
|
-
const method = options.method ?? (options.body === undefined ? "GET" : "POST");
|
|
38
|
-
const requestUrl = new URL(url);
|
|
39
|
-
logger.debug("sending Databricks API request", {
|
|
40
|
-
method,
|
|
41
|
-
origin: requestUrl.origin,
|
|
42
|
-
path: requestUrl.pathname,
|
|
43
|
-
hasBody: options.body !== undefined,
|
|
44
|
-
login: options.login ?? "auto",
|
|
45
|
-
});
|
|
46
|
-
let authHeaders = await this.auth.authenticate(options.login);
|
|
47
|
-
let response = await this.send(url, method, authHeaders, options);
|
|
48
|
-
logger.debug("received Databricks API response", {
|
|
49
|
-
method,
|
|
50
|
-
path: requestUrl.pathname,
|
|
51
|
-
status: response.status,
|
|
52
|
-
attempt: 1,
|
|
53
|
-
});
|
|
54
|
-
if (response.status === 401) {
|
|
55
|
-
logger.debug("refreshing rejected Databricks API credential", {
|
|
56
|
-
method,
|
|
57
|
-
path: requestUrl.pathname,
|
|
58
|
-
});
|
|
59
|
-
await this.auth.refreshRejectedToken(accessTokenFromHeaders(authHeaders), options.login ?? true);
|
|
60
|
-
authHeaders = await this.auth.authenticate(false);
|
|
61
|
-
response = await this.send(url, method, authHeaders, options);
|
|
62
|
-
logger.debug("received Databricks API response", {
|
|
63
|
-
method,
|
|
64
|
-
path: requestUrl.pathname,
|
|
65
|
-
status: response.status,
|
|
66
|
-
attempt: 2,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
const text = await response.text();
|
|
70
|
-
if (!response.ok)
|
|
71
|
-
throw new AuthError("http", `Databricks API ${path} returned HTTP ${response.status}: ${text}`);
|
|
72
|
-
if (!text) {
|
|
73
|
-
logger.debug("Databricks API response had no body", {
|
|
74
|
-
method,
|
|
75
|
-
path: requestUrl.pathname,
|
|
76
|
-
});
|
|
77
|
-
return undefined;
|
|
78
|
-
}
|
|
79
|
-
try {
|
|
80
|
-
const value = JSON.parse(text);
|
|
81
|
-
logger.debug("parsed Databricks API JSON response", {
|
|
82
|
-
method,
|
|
83
|
-
path: requestUrl.pathname,
|
|
84
|
-
});
|
|
85
|
-
return value;
|
|
86
|
-
}
|
|
87
|
-
catch (cause) {
|
|
88
|
-
throw new AuthError("http", `Databricks API ${path} did not return JSON`, { cause });
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
send(url, method, authHeaders, options) {
|
|
92
|
-
const headers = new Headers(options.headers);
|
|
93
|
-
headers.delete(DEFAULT_ACCESS_TOKEN_HEADER);
|
|
94
|
-
headers.delete(WORKSPACE_ID_HEADER);
|
|
95
|
-
for (const [name, value] of Object.entries(authHeaders))
|
|
96
|
-
headers.set(name, value);
|
|
97
|
-
headers.set("accept", "application/json");
|
|
98
|
-
if (options.body !== undefined)
|
|
99
|
-
headers.set("content-type", "application/json");
|
|
100
|
-
return this.fetcher(url, {
|
|
101
|
-
method,
|
|
102
|
-
headers,
|
|
103
|
-
...(options.body !== undefined ? { body: JSON.stringify(options.body) } : {}),
|
|
104
|
-
signal: options.signal,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
function accessTokenFromHeaders(headers) {
|
|
109
|
-
const authorization = headers[DEFAULT_ACCESS_TOKEN_HEADER];
|
|
110
|
-
const separator = authorization?.indexOf(" ") ?? -1;
|
|
111
|
-
if (separator < 1 || !authorization?.slice(separator + 1).trim()) {
|
|
112
|
-
throw new AuthError("http", "Authentication headers did not contain an access token");
|
|
113
|
-
}
|
|
114
|
-
return authorization.slice(separator + 1).trim();
|
|
115
|
-
}
|
|
116
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC1jbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaHR0cC1jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBbUMsTUFBTSxzQkFBc0IsQ0FBQztBQUV6RixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFOUUsTUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBV2xDLCtFQUErRTtBQUMvRSxNQUFNLE9BQU8sZ0JBQWdCO0lBRWhCO0lBQ1E7SUFGbkIsWUFDVyxJQUFnQixFQUNSLE9BQWdDO1FBRHhDLFNBQUksR0FBSixJQUFJLENBQVk7UUFDUixZQUFPLEdBQVAsT0FBTyxDQUF5QjtJQUNoRCxDQUFDO0lBRUosTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQ2pCLFVBQWlDLEVBQUUsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLEVBQzlELGVBQTJDLEVBQUU7UUFFN0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxnQkFBZ0IsQ0FDakMsTUFBTSxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksQ0FBQyxFQUN4RCxZQUFZLENBQUMsS0FBSyxJQUFJLFVBQVUsQ0FBQyxLQUFLLENBQ3ZDLENBQUM7UUFDRixNQUFNLENBQUMsS0FBSyxDQUFDLGdDQUFnQyxFQUFFO1lBQzdDLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxFQUFFO1lBQ3pCLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxFQUFFO1lBQ25CLGNBQWMsRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQzlDLENBQUMsQ0FBQztRQUNILE9BQU8sTUFBTSxDQUFD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SSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ2xGLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLGtCQUFrQixDQUFDLENBQUM7UUFDMUMsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLFNBQVM7WUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1FBQ2hGLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUU7WUFDdkIsTUFBTTtZQUNOLE9BQU87WUFDUCxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUM3RSxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07U0FDdkIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGO0FBRUQsU0FBUyxzQkFBc0IsQ0FBQyxPQUErQjtJQUM3RCxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsMkJBQTJCLENBQUMsQ0FBQztJQUMzRCxNQUFNLFNBQVMsR0FBRyxhQUFhLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3BELElBQUksU0FBUyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7UUFDakUsTUFBTSxJQUFJLFNBQVMsQ0FBQyxNQUFNLEVBQUUsd0RBQXdELENBQUMsQ0FBQztJQUN4RixDQUFDO0lBQ0QsT0FBTyxhQUFhLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUNuRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgYXV0aExvZ2dlciB9IGZyb20gXCIuL19sb2dnaW5nLnRzXCI7XG5pbXBvcnQgeyBBdXRoRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnMudHNcIjtcbmltcG9ydCB7IGNyZWF0ZUF1dGhDbGllbnQsIHR5cGUgRGF0YWJyaWNrc0F1dGhEZXBlbmRlbmNpZXMgfSBmcm9tIFwiLi9kYXRhYnJpY2tzLWF1dGgudHNcIjtcbmltcG9ydCB0eXBlIHsgQXV0aENsaWVudCwgRGF0YWJyaWNrc0F1dGhPcHRpb25zIH0gZnJvbSBcIi4vdHlwZXMudHNcIjtcbmltcG9ydCB7IERFRkFVTFRfQUNDRVNTX1RPS0VOX0hFQURFUiwgV09SS1NQQUNFX0lEX0hFQURFUiB9IGZyb20gXCIuL3R5cGVzLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGF1dGhMb2dnZXIoXCJodHRwXCIpO1xuXG4vKiogT3B0aW9ucyBmb3Igb25lIERhdGFicmlja3MgSlNPTiBBUEkgcmVxdWVzdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YWJyaWNrc1JlcXVlc3RPcHRpb25zIHtcbiAgbWV0aG9kPzogc3RyaW5nO1xuICBib2R5PzogdW5rbm93bjtcbiAgaGVhZGVycz86IEhlYWRlcnMgfCBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgW3N0cmluZywgc3RyaW5nXVtdO1xuICBsb2dpbj86IGJvb2xlYW47XG4gIHNpZ25hbD86IEFib3J0U2lnbmFsO1xufVxuXG4vKiogRGVwZW5kZW5jeS1saWdodCBEYXRhYnJpY2tzIEpTT04gY2xpZW50IHdpdGggb25lIHJlamVjdGVkLXRva2VuIHJlZnJlc2guICovXG5leHBvcnQgY2xhc3MgRGF0YWJyaWNrc0NsaWVudCB7XG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgcmVhZG9ubHkgYXV0aDogQXV0aENsaWVudCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGZldGNoZXI6IHR5cGVvZiBnbG9iYWxUaGlzLmZldGNoLFxuICApIHt9XG5cbiAgc3RhdGljIGFzeW5jIGNyZWF0ZShcbiAgICBvcHRpb25zOiBEYXRhYnJpY2tzQXV0aE9wdGlvbnMgPSB7IHByZWZlclVzZXJUb01hY2hpbmU6IHRydWUgfSxcbiAgICBkZXBlbmRlbmNpZXM6IERhdGFicmlja3NBdXRoRGVwZW5kZW5jaWVzID0ge30sXG4gICk6IFByb21pc2U8RGF0YWJyaWNrc0NsaWVudD4ge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBEYXRhYnJpY2tzQ2xpZW50KFxuICAgICAgYXdhaXQgY3JlYXRlQXV0aENsaWVudChvcHRpb25zLCB1bmRlZmluZWQsIGRlcGVuZGVuY2llcyksXG4gICAgICBkZXBlbmRlbmNpZXMuZmV0Y2ggPz8gZ2xvYmFsVGhpcy5mZXRjaCxcbiAgICApO1xuICAgIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZWQgRGF0YWJyaWNrcyBIVFRQIGNsaWVudFwiLCB7XG4gICAgICBwcm9maWxlOiBjbGllbnQucHJvZmlsZSgpLFxuICAgICAgaG9zdDogY2xpZW50Lmhvc3QoKSxcbiAgICAgIGhhc1dvcmtzcGFjZUlkOiBCb29sZWFuKGNsaWVudC53b3Jrc3BhY2VJZCgpKSxcbiAgICB9KTtcbiAgICByZXR1cm4gY2xpZW50O1xuICB9XG5cbiAgcHJvZmlsZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmF1dGguc3RhdHVzKCkucHJvZmlsZTtcbiAgfVxuXG4gIGhvc3QoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5hdXRoLnN0YXR1cygpLmhvc3Q7XG4gIH1cblxuICBwcmluY2lwYWwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5hdXRoLnByaW5jaXBhbCgpO1xuICB9XG5cbiAgd29ya3NwYWNlSWQoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5hdXRoLndvcmtzcGFjZUlkKCk7XG4gIH1cblxuICBhc3luYyByZXF1ZXN0KHBhdGg6IHN0cmluZywgb3B0aW9uczogRGF0YWJyaWNrc1JlcXVlc3RPcHRpb25zID0ge30pOiBQcm9taXNlPHVua25vd24+IHtcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHBhdGgsIGAke3RoaXMuaG9zdCgpLnJlcGxhY2UoL1xcLyQvLCBcIlwiKX0vYCkudG9TdHJpbmcoKTtcbiAgICBjb25zdCBtZXRob2QgPSBvcHRpb25zLm1ldGhvZCA/PyAob3B0aW9ucy5ib2R5ID09PSB1bmRlZmluZWQgPyBcIkdFVFwiIDogXCJQT1NUXCIpO1xuICAgIGNvbnN0IHJlcXVlc3RVcmwgPSBuZXcgVVJMKHVybCk7XG4gICAgbG9nZ2VyLmRlYnVnKFwic2VuZGluZyBEYXRhYnJpY2tzIEFQSSByZXF1ZXN0XCIsIHtcbiAgICAgIG1ldGhvZCxcbiAgICAgIG9yaWdpbjogcmVxdWVzdFVybC5vcmlnaW4sXG4gICAgICBwYXRoOiByZXF1ZXN0VXJsLnBhdGhuYW1lLFxuICAgICAgaGFzQm9keTogb3B0aW9ucy5ib2R5ICE9PSB1bmRlZmluZWQsXG4gICAgICBsb2dpbjogb3B0aW9ucy5sb2dpbiA/PyBcImF1dG9cIixcbiAgICB9KTtcbiAgICBsZXQgYXV0aEhlYWRlcnMgPSBhd2FpdCB0aGlzLmF1dGguYXV0aGVudGljYXRlKG9wdGlvbnMubG9naW4pO1xuICAgIGxldCByZXNwb25zZSA9IGF3YWl0IHRoaXMuc2VuZCh1cmwsIG1ldGhvZCwgYXV0aEhlYWRlcnMsIG9wdGlvbnMpO1xuICAgIGxvZ2dlci5kZWJ1ZyhcInJlY2VpdmVkIERhdGFicmlja3MgQVBJIHJlc3BvbnNlXCIsIHtcbiAgICAgIG1ldGhvZCxcbiAgICAgIHBhdGg6IHJlcXVlc3RVcmwucGF0aG5hbWUsXG4gICAgICBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cyxcbiAgICAgIGF0dGVtcHQ6IDEsXG4gICAgfSk7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gNDAxKSB7XG4gICAgICBsb2dnZXIuZGVidWcoXCJyZWZyZXNoaW5nIHJlamVjdGVkIERhdGFicmlja3MgQVBJIGNyZWRlbnRpYWxcIiwge1xuICAgICAgICBtZXRob2QsXG4gICAgICAgIHBhdGg6IHJlcXVlc3RVcmwucGF0aG5hbWUsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHRoaXMuYXV0aC5yZWZyZXNoUmVqZWN0ZWRUb2tlbihcbiAgICAgICAgYWNjZXNzVG9rZW5Gcm9tSGVhZGVycyhhdXRoSGVhZGVycyksXG4gICAgICAgIG9wdGlvbnMubG9naW4gPz8gdHJ1ZSxcbiAgICAgICk7XG4gICAgICBhdXRoSGVhZGVycyA9IGF3YWl0IHRoaXMuYXV0aC5hdXRoZW50aWNhdGUoZmFsc2UpO1xuICAgICAgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnNlbmQodXJsLCBtZXRob2QsIGF1dGhIZWFkZXJzLCBvcHRpb25zKTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcInJlY2VpdmVkIERhdGFicmlja3MgQVBJIHJlc3BvbnNlXCIsIHtcbiAgICAgICAgbWV0aG9kLFxuICAgICAgICBwYXRoOiByZXF1ZXN0VXJsLnBhdGhuYW1lLFxuICAgICAgICBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cyxcbiAgICAgICAgYXR0ZW1wdDogMixcbiAgICAgIH0pO1xuICAgIH1cbiAgICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVzcG9uc2UudGV4dCgpO1xuICAgIGlmICghcmVzcG9uc2Uub2spXG4gICAgICB0aHJvdyBuZXcgQXV0aEVycm9yKFxuICAgICAgICBcImh0dHBcIixcbiAgICAgICAgYERhdGFicmlja3MgQVBJICR7cGF0aH0gcmV0dXJuZWQgSFRUUCAke3Jlc3BvbnNlLnN0YXR1c306ICR7dGV4dH1gLFxuICAgICAgKTtcbiAgICBpZiAoIXRleHQpIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcIkRhdGFicmlja3MgQVBJIHJlc3BvbnNlIGhhZCBubyBib2R5XCIsIHtcbiAgICAgICAgbWV0aG9kLFxuICAgICAgICBwYXRoOiByZXF1ZXN0VXJsLnBhdGhuYW1lLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY29uc3QgdmFsdWUgPSBKU09OLnBhcnNlKHRleHQpO1xuICAgICAgbG9nZ2VyLmRlYnVnKFwicGFyc2VkIERhdGFicmlja3MgQVBJIEpTT04gcmVzcG9uc2VcIiwge1xuICAgICAgICBtZXRob2QsXG4gICAgICAgIHBhdGg6IHJlcXVlc3RVcmwucGF0aG5hbWUsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9IGNhdGNoIChjYXVzZSkge1xuICAgICAgdGhyb3cgbmV3IEF1dGhFcnJvcihcImh0dHBcIiwgYERhdGFicmlja3MgQVBJICR7cGF0aH0gZGlkIG5vdCByZXR1cm4gSlNPTmAsIHsgY2F1c2UgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzZW5kKFxuICAgIHVybDogc3RyaW5nLFxuICAgIG1ldGhvZDogc3RyaW5nLFxuICAgIGF1dGhIZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICAgIG9wdGlvbnM6IERhdGFicmlja3NSZXF1ZXN0T3B0aW9ucyxcbiAgKTogUHJvbWlzZTxSZXNwb25zZT4ge1xuICAgIGNvbnN0IGhlYWRlcnMgPSBuZXcgSGVhZGVycyhvcHRpb25zLmhlYWRlcnMpO1xuICAgIGhlYWRlcnMuZGVsZXRlKERFRkFVTFRfQUNDRVNTX1RPS0VOX0hFQURFUik7XG4gICAgaGVhZGVycy5kZWxldGUoV09SS1NQQUNFX0lEX0hFQURFUik7XG4gICAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGF1dGhIZWFkZXJzKSkgaGVhZGVycy5zZXQobmFtZSwgdmFsdWUpO1xuICAgIGhlYWRlcnMuc2V0KFwiYWNjZXB0XCIsIFwiYXBwbGljYXRpb24vanNvblwiKTtcbiAgICBpZiAob3B0aW9ucy5ib2R5ICE9PSB1bmRlZmluZWQpIGhlYWRlcnMuc2V0KFwiY29udGVudC10eXBlXCIsIFwiYXBwbGljYXRpb24vanNvblwiKTtcbiAgICByZXR1cm4gdGhpcy5mZXRjaGVyKHVybCwge1xuICAgICAgbWV0aG9kLFxuICAgICAgaGVhZGVycyxcbiAgICAgIC4uLihvcHRpb25zLmJvZHkgIT09IHVuZGVmaW5lZCA/IHsgYm9keTogSlNPTi5zdHJpbmdpZnkob3B0aW9ucy5ib2R5KSB9IDoge30pLFxuICAgICAgc2lnbmFsOiBvcHRpb25zLnNpZ25hbCxcbiAgICB9KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBhY2Nlc3NUb2tlbkZyb21IZWFkZXJzKGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pOiBzdHJpbmcge1xuICBjb25zdCBhdXRob3JpemF0aW9uID0gaGVhZGVyc1tERUZBVUxUX0FDQ0VTU19UT0tFTl9IRUFERVJdO1xuICBjb25zdCBzZXBhcmF0b3IgPSBhdXRob3JpemF0aW9uPy5pbmRleE9mKFwiIFwiKSA/PyAtMTtcbiAgaWYgKHNlcGFyYXRvciA8IDEgfHwgIWF1dGhvcml6YXRpb24/LnNsaWNlKHNlcGFyYXRvciArIDEpLnRyaW0oKSkge1xuICAgIHRocm93IG5ldyBBdXRoRXJyb3IoXCJodHRwXCIsIFwiQXV0aGVudGljYXRpb24gaGVhZGVycyBkaWQgbm90IGNvbnRhaW4gYW4gYWNjZXNzIHRva2VuXCIpO1xuICB9XG4gIHJldHVybiBhdXRob3JpemF0aW9uLnNsaWNlKHNlcGFyYXRvciArIDEpLnRyaW0oKTtcbn1cbiJdfQ==
|