@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.
Files changed (73) hide show
  1. package/README.md +49 -97
  2. package/index.ts +8 -26
  3. package/lib/index.d.ts +8 -26
  4. package/lib/index.js +6 -22
  5. package/lib/src/{databricks-cli.d.ts → _databricks-cli.d.ts} +3 -7
  6. package/lib/src/_databricks-cli.js +172 -0
  7. package/lib/src/_errors.d.ts +5 -0
  8. package/lib/src/_errors.js +10 -0
  9. package/lib/src/{lifecycle.d.ts → _lifecycle.d.ts} +5 -5
  10. package/lib/src/_lifecycle.js +214 -0
  11. package/lib/src/_logging.d.ts +1 -1
  12. package/lib/src/_logging.js +2 -2
  13. package/lib/src/{personal-access-token.d.ts → _personal-access-token.d.ts} +1 -1
  14. package/lib/src/_personal-access-token.js +30 -0
  15. package/lib/src/_profile-config.d.ts +43 -0
  16. package/lib/src/_profile-config.js +443 -0
  17. package/lib/src/{service-principal.d.ts → _service-principal.d.ts} +1 -1
  18. package/lib/src/_service-principal.js +69 -0
  19. package/lib/src/{storage.d.ts → _storage.d.ts} +4 -6
  20. package/lib/src/_storage.js +94 -0
  21. package/lib/src/_types.d.ts +40 -0
  22. package/lib/src/_types.js +2 -0
  23. package/lib/src/client.d.ts +30 -0
  24. package/lib/src/client.js +223 -0
  25. package/lib/src/config.d.ts +36 -0
  26. package/lib/src/config.js +15 -0
  27. package/lib/src/profile.d.ts +11 -0
  28. package/lib/src/profile.js +21 -0
  29. package/lib/tsconfig.tsbuildinfo +1 -1
  30. package/package.json +34 -10
  31. package/src/{databricks-cli.ts → _databricks-cli.ts} +20 -109
  32. package/src/_errors.ts +11 -0
  33. package/src/{lifecycle.ts → _lifecycle.ts} +24 -48
  34. package/src/_logging.ts +2 -2
  35. package/src/{personal-access-token.ts → _personal-access-token.ts} +1 -1
  36. package/src/_profile-config.ts +545 -0
  37. package/src/{service-principal.ts → _service-principal.ts} +2 -2
  38. package/src/_storage.ts +109 -0
  39. package/src/_types.ts +45 -0
  40. package/src/client.ts +291 -0
  41. package/src/config.ts +44 -0
  42. package/src/profile.ts +33 -0
  43. package/lib/exports.d.ts +0 -2
  44. package/lib/exports.js +0 -3
  45. package/lib/src/_profile-core.d.ts +0 -28
  46. package/lib/src/_profile-core.js +0 -216
  47. package/lib/src/_profile.d.ts +0 -15
  48. package/lib/src/_profile.js +0 -236
  49. package/lib/src/databricks-auth.d.ts +0 -11
  50. package/lib/src/databricks-auth.js +0 -314
  51. package/lib/src/databricks-cli.js +0 -239
  52. package/lib/src/errors.d.ts +0 -7
  53. package/lib/src/errors.js +0 -14
  54. package/lib/src/generated/databricks-cli-assets.json +0 -33
  55. package/lib/src/http-client.d.ts +0 -23
  56. package/lib/src/http-client.js +0 -116
  57. package/lib/src/lifecycle.js +0 -229
  58. package/lib/src/node-storage.d.ts +0 -20
  59. package/lib/src/node-storage.js +0 -207
  60. package/lib/src/personal-access-token.js +0 -30
  61. package/lib/src/service-principal.js +0 -69
  62. package/lib/src/storage.js +0 -98
  63. package/lib/src/types.d.ts +0 -157
  64. package/lib/src/types.js +0 -67
  65. package/src/_profile-core.ts +0 -258
  66. package/src/_profile.ts +0 -319
  67. package/src/databricks-auth.ts +0 -416
  68. package/src/errors.ts +0 -16
  69. package/src/generated/databricks-cli-assets.json +0 -33
  70. package/src/http-client.ts +0 -147
  71. package/src/node-storage.ts +0 -230
  72. package/src/storage.ts +0 -104
  73. package/src/types.ts +0 -188
@@ -1,314 +0,0 @@
1
- import { homedir } from "node:os";
2
- import { join } from "node:path";
3
- import * as environmentUtils from "@dbx-tools/shared-core/environment-utils";
4
- import { authLogger, tokenMetadata } from "./_logging.js";
5
- import { AuthError } from "./errors.js";
6
- import { DatabricksCliProvider, resolveDatabricksCli } from "./databricks-cli.js";
7
- import { publicToken, TokenLifecycle } from "./lifecycle.js";
8
- import { FileCredentialStore } from "./node-storage.js";
9
- import { DatabricksPersonalAccessTokenProvider } from "./personal-access-token.js";
10
- import { listDatabricksProfiles, machineScopes, resolveConfigFile, resolveDatabricksProfile, } from "./_profile.js";
11
- import { DatabricksServicePrincipalProvider } from "./service-principal.js";
12
- import { MemoryCredentialStore } from "./storage.js";
13
- import { AuthKind, AuthOptions, DEFAULT_ACCESS_TOKEN_HEADER, Storage, TargetKind, WORKSPACE_ID_HEADER, } from "./types.js";
14
- const logger = authLogger("databricks");
15
- /** Persistent Databricks auth facade over the provider-neutral lifecycle. */
16
- class PersistentAuth {
17
- profileValue;
18
- storageValue;
19
- options;
20
- environment;
21
- client;
22
- requestToken;
23
- constructor(profileValue, storageValue, options, environment, client, requestToken) {
24
- this.profileValue = profileValue;
25
- this.storageValue = storageValue;
26
- this.options = options;
27
- this.environment = environment;
28
- this.client = client;
29
- this.requestToken = requestToken;
30
- }
31
- async challenge() {
32
- if (!this.client)
33
- throw new AuthError("oauth", "app_obo uses the current request token and cannot start login");
34
- logger.debug("authentication challenge requested", this.context());
35
- await this.client.login();
36
- logger.debug("authentication challenge completed", this.context());
37
- }
38
- token(login) {
39
- logger.debug("Databricks token requested", {
40
- ...this.context(),
41
- login: login ?? "auto",
42
- source: this.requestToken ? "request" : "lifecycle",
43
- });
44
- return this.requestToken
45
- ? Promise.resolve(publicToken(this.requestToken))
46
- : this.requiredClient().tokenWithLogin(login);
47
- }
48
- async authenticate(login) {
49
- const token = await this.token(login);
50
- const headers = {
51
- [DEFAULT_ACCESS_TOKEN_HEADER]: `${token.tokenType} ${token.accessToken}`,
52
- ...(this.profileValue.workspaceId
53
- ? { [WORKSPACE_ID_HEADER]: this.profileValue.workspaceId }
54
- : {}),
55
- };
56
- logger.debug("generated Databricks authentication headers", {
57
- ...this.context(),
58
- headerNames: Object.keys(headers),
59
- token: tokenMetadata(token),
60
- });
61
- return headers;
62
- }
63
- async authorizationHeaderForUrl(requestUrl, login) {
64
- return (await this.requestHeadersForUrl(requestUrl, login))[DEFAULT_ACCESS_TOKEN_HEADER];
65
- }
66
- async requestHeadersForUrl(requestUrl, login) {
67
- const request = new URL(requestUrl);
68
- const credentialOrigin = new URL(this.profileValue.host).origin;
69
- if (request.origin !== credentialOrigin) {
70
- logger.debug("skipped authentication for different origin", {
71
- ...this.context(),
72
- requestOrigin: request.origin,
73
- credentialOrigin,
74
- });
75
- return {};
76
- }
77
- logger.debug("applying authentication to matching origin", {
78
- ...this.context(),
79
- requestOrigin: request.origin,
80
- });
81
- return this.authenticate(login);
82
- }
83
- forceRefreshToken(login = true) {
84
- logger.debug("Databricks token force refresh requested", { ...this.context(), login });
85
- return this.requestToken
86
- ? Promise.resolve(publicToken(this.requestToken))
87
- : this.requiredClient().forceRefresh(login);
88
- }
89
- refreshRejectedToken(staleAccessToken, login = true) {
90
- logger.debug("Databricks rejected token refresh requested", {
91
- ...this.context(),
92
- login,
93
- requestToken: Boolean(this.requestToken),
94
- });
95
- return this.requestToken
96
- ? Promise.resolve(publicToken(this.requestToken))
97
- : this.requiredClient().refreshRejectedToken(staleAccessToken, login);
98
- }
99
- logout() {
100
- logger.debug("Databricks logout requested", this.context());
101
- return this.client?.logout() ?? Promise.resolve();
102
- }
103
- status() {
104
- return {
105
- profile: this.profileValue.name,
106
- host: this.profileValue.host,
107
- storage: this.storageValue,
108
- };
109
- }
110
- principal() {
111
- return this.profileValue.principal;
112
- }
113
- workspaceId() {
114
- return this.profileValue.workspaceId;
115
- }
116
- authKind() {
117
- return this.profileValue.authKind;
118
- }
119
- profile(name) {
120
- const profile = !name || name === this.profileValue.name
121
- ? this.profileValue
122
- : resolveDatabricksProfile({ ...this.options, profile: name }, this.environment);
123
- return profileSummary(profile);
124
- }
125
- listProfiles(refresh = false) {
126
- return listDatabricksProfiles(this.options.configFile, refresh, this.environment);
127
- }
128
- requiredClient() {
129
- if (!this.client)
130
- throw new AuthError("oauth", "Authentication lifecycle is not available");
131
- return this.client;
132
- }
133
- context() {
134
- return {
135
- profile: this.profileValue.name,
136
- host: this.profileValue.host,
137
- authKind: this.profileValue.authKind,
138
- storage: this.storageValue,
139
- hasWorkspaceId: Boolean(this.profileValue.workspaceId),
140
- };
141
- }
142
- }
143
- /** Create a Databricks authentication client. */
144
- export function createAuthClient(options = { preferUserToMachine: true }, storage = Storage.Auto, dependencies = {}) {
145
- return createPersistentAuth(options, storage, dependencies);
146
- }
147
- /** Resolve a Databricks profile and open built-in credential storage. */
148
- async function createPersistentAuth(options, storage, dependencies) {
149
- const environment = dependencies.environment ?? process.env;
150
- const profile = resolveDatabricksProfile(options, environment);
151
- const inApp = profile.authKind === AuthKind.AppOnBehalfOf ||
152
- profile.authKind === AuthKind.AppServicePrincipal;
153
- const backend = storage === Storage.Auto ? Storage.Memory : storage;
154
- logger.debug("creating persistent Databricks auth", {
155
- profile: profile.name,
156
- host: profile.host,
157
- authKind: profile.authKind,
158
- requestedStorage: storage,
159
- resolvedStorage: backend,
160
- inApp,
161
- });
162
- const store = backend === Storage.Memory
163
- ? new MemoryCredentialStore()
164
- : new FileCredentialStore(options.cacheDir ?? join(homedir(), ".databricks"));
165
- return createPersistentAuthWithStorage(options, store, storage, dependencies, profile);
166
- }
167
- /** Resolve a Databricks profile using caller-owned generic storage. */
168
- async function createPersistentAuthWithStorage(options, store, storage = store.name() === "memory" ? Storage.Memory : Storage.File, dependencies = {}, resolvedProfile) {
169
- const profile = resolvedProfile ?? resolveDatabricksProfile(options, dependencies.environment ?? process.env);
170
- if (profile.authKind === AuthKind.AppOnBehalfOf) {
171
- logger.debug("created request-scoped App OBO authentication", {
172
- profile: profile.name,
173
- host: profile.host,
174
- hasWorkspaceId: Boolean(profile.workspaceId),
175
- });
176
- return new PersistentAuth(profile, Storage.Memory, options, dependencies.environment ?? process.env, undefined, {
177
- accessToken: profile.accessToken,
178
- tokenType: "Bearer",
179
- scopes: [...profile.scopes],
180
- });
181
- }
182
- const provider = await providerFor(profile, options, dependencies);
183
- const client = new TokenLifecycle(profile.cacheKey, provider, store, AuthOptions.create(options.auth));
184
- const persistent = new PersistentAuth(profile, storage === Storage.Auto ? storageFromName(store.name()) : storage, options, dependencies.environment ?? process.env, client);
185
- logger.debug("created persistent authentication lifecycle", {
186
- profile: profile.name,
187
- host: profile.host,
188
- authKind: profile.authKind,
189
- storage: persistent.status().storage,
190
- });
191
- return persistent;
192
- }
193
- async function providerFor(profile, options, dependencies) {
194
- const environment = dependencies.environment ?? process.env;
195
- const inApp = environmentUtils.isDatabricksAppEnv({ ...environment });
196
- switch (profile.authKind) {
197
- case AuthKind.UserToMachine: {
198
- const install = !inApp || options.installCliInApp === true;
199
- logger.debug("selected Databricks CLI provider", {
200
- profile: profile.name,
201
- inApp,
202
- install,
203
- });
204
- return new DatabricksCliProvider(profile.name, () => dependencies.resolveCli
205
- ? dependencies.resolveCli({ install })
206
- : resolveDatabricksCli(environment, { install }), cliEnvironment(profile, resolveConfigFile(options.configFile, environment)));
207
- }
208
- case AuthKind.PersonalAccessToken:
209
- logger.debug("selected personal access token provider", { profile: profile.name });
210
- return new DatabricksPersonalAccessTokenProvider(profile.accessToken);
211
- case AuthKind.MachineToMachine:
212
- case AuthKind.AppServicePrincipal: {
213
- logger.debug("selected service-principal provider", {
214
- profile: profile.name,
215
- authKind: profile.authKind,
216
- target: profile.target,
217
- });
218
- const endpoints = await resolveOAuthEndpoints(profile, dependencies.fetch);
219
- return new DatabricksServicePrincipalProvider({
220
- tokenEndpoint: endpoints.tokenEndpoint,
221
- clientId: profile.clientId,
222
- clientSecret: profile.clientSecret,
223
- scopes: machineScopes(profile.scopes),
224
- ...(profile.groupId ? { groupId: profile.groupId } : {}),
225
- allowInsecureRequests: isLoopbackHttp(profile.host),
226
- fetch: dependencies.fetch,
227
- });
228
- }
229
- case AuthKind.AppOnBehalfOf:
230
- throw new AuthError("config", "App OBO tokens do not use a persistent provider");
231
- }
232
- }
233
- async function resolveOAuthEndpoints(profile, fetcher = globalThis.fetch) {
234
- const host = profile.host.replace(/\/$/, "");
235
- if (profile.target === TargetKind.Account) {
236
- if (!profile.accountId)
237
- throw new AuthError("config", "Account target requires account_id");
238
- const endpoints = {
239
- tokenEndpoint: `${host}/oidc/accounts/${profile.accountId}/v1/token`,
240
- };
241
- logger.debug("resolved account OAuth endpoint", {
242
- profile: profile.name,
243
- tokenOrigin: new URL(endpoints.tokenEndpoint).origin,
244
- });
245
- return endpoints;
246
- }
247
- const discovery = profile.target === TargetKind.Unified
248
- ? `${host}/oidc/accounts/${requiredAccountId(profile)}/.well-known/oauth-authorization-server`
249
- : `${host}/oidc/.well-known/oauth-authorization-server`;
250
- logger.debug("requesting OAuth discovery", {
251
- profile: profile.name,
252
- target: profile.target,
253
- discovery,
254
- });
255
- const response = await fetcher(discovery, { redirect: "manual" });
256
- logger.debug("received OAuth discovery response", {
257
- profile: profile.name,
258
- status: response.status,
259
- });
260
- if (response.status === 404)
261
- throw new AuthError("oauth", `OAuth is not supported at ${discovery}`);
262
- if (!response.ok)
263
- throw new AuthError("oauth", `OAuth discovery returned HTTP ${response.status}`);
264
- const value = (await response.json());
265
- const tokenEndpoint = stringValue(value.token_endpoint);
266
- if (!tokenEndpoint)
267
- throw new AuthError("oauth", "OAuth discovery response is incomplete");
268
- logger.debug("resolved OAuth token endpoint", {
269
- profile: profile.name,
270
- tokenOrigin: new URL(tokenEndpoint).origin,
271
- });
272
- return { tokenEndpoint };
273
- }
274
- function requiredAccountId(profile) {
275
- if (!profile.accountId)
276
- throw new AuthError("config", "Unified target requires account_id");
277
- return profile.accountId;
278
- }
279
- function storageFromName(name) {
280
- return name === "memory" ? Storage.Memory : Storage.File;
281
- }
282
- function profileSummary(profile) {
283
- return {
284
- name: profile.name,
285
- host: profile.host,
286
- ...(profile.accountId ? { accountId: profile.accountId } : {}),
287
- ...(profile.workspaceId ? { workspaceId: profile.workspaceId } : {}),
288
- target: profile.target,
289
- authKind: profile.authKind,
290
- };
291
- }
292
- function isLoopbackHttp(host) {
293
- const url = new URL(host);
294
- return url.protocol === "http:" && ["127.0.0.1", "localhost"].includes(url.hostname);
295
- }
296
- function cliEnvironment(profile, configFile) {
297
- return {
298
- DATABRICKS_CONFIG_FILE: configFile,
299
- DATABRICKS_CONFIG_PROFILE: profile.name,
300
- DATABRICKS_HOST: profile.host,
301
- ...(profile.accountId ? { DATABRICKS_ACCOUNT_ID: profile.accountId } : {}),
302
- ...(profile.workspaceId ? { DATABRICKS_WORKSPACE_ID: profile.workspaceId } : {}),
303
- ...(profile.authKind === AuthKind.PersonalAccessToken
304
- ? {
305
- DATABRICKS_AUTH_TYPE: "pat",
306
- DATABRICKS_TOKEN: profile.accessToken,
307
- }
308
- : {}),
309
- };
310
- }
311
- function stringValue(value) {
312
- return typeof value === "string" && value.trim() ? value : undefined;
313
- }
314
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWJyaWNrcy1hdXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RhdGFicmlja3MtYXV0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFakMsT0FBTyxLQUFLLGdCQUFnQixNQUFNLDBDQUEwQyxDQUFDO0FBRTdFLE9BQU8sRUFBRSxVQUFVLEVBQUUsYUFBYSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDeEMsT0FBTyxFQUFFLHFCQUFxQixFQUFFLG9CQUFvQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbEYsT0FBTyxFQUFFLFdBQVcsRUFBRSxjQUFjLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUscUNBQXFDLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNuRixPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLGFBQWEsRUFDYixpQkFBaUIsRUFDakIsd0JBQXdCLEdBQ3pCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxrQ0FBa0MsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzVFLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNyRCxPQUFPLEVBQ0wsUUFBUSxFQUVSLFdBQVcsRUFLWCwyQkFBMkIsRUFDM0IsT0FBTyxFQUNQLFVBQVUsRUFHVixtQkFBbUIsR0FDcEIsTUFBTSxZQUFZLENBQUM7QUFFcEIsTUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBU3hDLDZFQUE2RTtBQUM3RSxNQUFNLGNBQWM7SUFFQztJQUNBO0lBQ0E7SUFDQTtJQUNB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dkMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxJQUFJO1FBQzdCLEdBQUcsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLHFCQUFxQixFQUFFLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFLHVCQUF1QixFQUFFLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ2hGLEdBQUcsQ0FBQyxPQUFPLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQyxtQkFBbUI7WUFDbkQsQ0FBQyxDQUFDO2dCQUNFLG9CQUFvQixFQUFFLEtBQUs7Z0JBQzNCLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxXQUFZO2FBQ3ZDO1lBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUNSLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxXQUFXLENBQUMsS0FBYztJQUNqQyxPQUFPLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3ZFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBob21lZGlyIH0gZnJvbSBcIm5vZGU6b3NcIjtcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5cbmltcG9ydCAqIGFzIGVudmlyb25tZW50VXRpbHMgZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmUvZW52aXJvbm1lbnQtdXRpbHNcIjtcblxuaW1wb3J0IHsgYXV0aExvZ2dlciwgdG9rZW5NZXRhZGF0YSB9IGZyb20gXCIuL19sb2dnaW5nLnRzXCI7XG5pbXBvcnQgeyBBdXRoRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnMudHNcIjtcbmltcG9ydCB7IERhdGFicmlja3NDbGlQcm92aWRlciwgcmVzb2x2ZURhdGFicmlja3NDbGkgfSBmcm9tIFwiLi9kYXRhYnJpY2tzLWNsaS50c1wiO1xuaW1wb3J0IHsgcHVibGljVG9rZW4sIFRva2VuTGlmZWN5Y2xlIH0gZnJvbSBcIi4vbGlmZWN5Y2xlLnRzXCI7XG5pbXBvcnQgeyBGaWxlQ3JlZGVudGlhbFN0b3JlIH0gZnJvbSBcIi4vbm9kZS1zdG9yYWdlLnRzXCI7XG5pbXBvcnQgeyBEYXRhYnJpY2tzUGVyc29uYWxBY2Nlc3NUb2tlblByb3ZpZGVyIH0gZnJvbSBcIi4vcGVyc29uYWwtYWNjZXNzLXRva2VuLnRzXCI7XG5pbXBvcnQge1xuICBsaXN0RGF0YWJyaWNrc1Byb2ZpbGVzLFxuICBtYWNoaW5lU2NvcGVzLFxuICByZXNvbHZlQ29uZmlnRmlsZSxcbiAgcmVzb2x2ZURhdGFicmlja3NQcm9maWxlLFxufSBmcm9tIFwiLi9fcHJvZmlsZS50c1wiO1xuaW1wb3J0IHsgRGF0YWJyaWNrc1NlcnZpY2VQcmluY2lwYWxQcm92aWRlciB9IGZyb20gXCIuL3NlcnZpY2UtcHJpbmNpcGFsLnRzXCI7XG5pbXBvcnQgeyBNZW1vcnlDcmVkZW50aWFsU3RvcmUgfSBmcm9tIFwiLi9zdG9yYWdlLnRzXCI7XG5pbXBvcnQge1xuICBBdXRoS2luZCxcbiAgdHlwZSBBdXRoQ2xpZW50LFxuICBBdXRoT3B0aW9ucyxcbiAgdHlwZSBDcmVkZW50aWFsU3RvcmUsXG4gIHR5cGUgRGF0YWJyaWNrc0F1dGhPcHRpb25zLFxuICB0eXBlIERhdGFicmlja3NBdXRoU3RhdHVzLFxuICB0eXBlIERhdGFicmlja3NQcm9maWxlLFxuICBERUZBVUxUX0FDQ0VTU19UT0tFTl9IRUFERVIsXG4gIFN0b3JhZ2UsXG4gIFRhcmdldEtpbmQsXG4gIHR5cGUgVG9rZW4sXG4gIHR5cGUgVG9rZW5Qcm92aWRlcixcbiAgV09SS1NQQUNFX0lEX0hFQURFUixcbn0gZnJvbSBcIi4vdHlwZXMudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gYXV0aExvZ2dlcihcImRhdGFicmlja3NcIik7XG5cbi8qKiBJbmplY3RhYmxlIGhvc3QgY2FwYWJpbGl0aWVzIGZvciBEYXRhYnJpY2tzIGF1dGhlbnRpY2F0aW9uLiAqL1xuZXhwb3J0IGludGVyZmFjZSBEYXRhYnJpY2tzQXV0aERlcGVuZGVuY2llcyB7XG4gIGVudmlyb25tZW50PzogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPj47XG4gIGZldGNoPzogdHlwZW9mIGdsb2JhbFRoaXMuZmV0Y2g7XG4gIHJlc29sdmVDbGk/OiAob3B0aW9uczogeyBpbnN0YWxsOiBib29sZWFuIH0pID0+IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPjtcbn1cblxuLyoqIFBlcnNpc3RlbnQgRGF0YWJyaWNrcyBhdXRoIGZhY2FkZSBvdmVyIHRoZSBwcm92aWRlci1uZXV0cmFsIGxpZmVjeWNsZS4gKi9cbmNsYXNzIFBlcnNpc3RlbnRBdXRoIGltcGxlbWVudHMgQXV0aENsaWVudCB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcHJvZmlsZVZhbHVlOiBEYXRhYnJpY2tzUHJvZmlsZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHN0b3JhZ2VWYWx1ZTogU3RvcmFnZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IERhdGFicmlja3NBdXRoT3B0aW9ucyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGVudmlyb25tZW50OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+PixcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNsaWVudD86IFRva2VuTGlmZWN5Y2xlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcmVxdWVzdFRva2VuPzogVG9rZW4sXG4gICkge31cblxuICBhc3luYyBjaGFsbGVuZ2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLmNsaWVudClcbiAgICAgIHRocm93IG5ldyBBdXRoRXJyb3IoXCJvYXV0aFwiLCBcImFwcF9vYm8gdXNlcyB0aGUgY3VycmVudCByZXF1ZXN0IHRva2VuIGFuZCBjYW5ub3Qgc3RhcnQgbG9naW5cIik7XG4gICAgbG9nZ2VyLmRlYnVnKFwiYXV0aGVudGljYXRpb24gY2hhbGxlbmdlIHJlcXVlc3RlZFwiLCB0aGlzLmNvbnRleHQoKSk7XG4gICAgYXdhaXQgdGhpcy5jbGllbnQubG9naW4oKTtcbiAgICBsb2dnZXIuZGVidWcoXCJhdXRoZW50aWNhdGlvbiBjaGFsbGVuZ2UgY29tcGxldGVkXCIsIHRoaXMuY29udGV4dCgpKTtcbiAgfVxuXG4gIHRva2VuKGxvZ2luPzogYm9vbGVhbikge1xuICAgIGxvZ2dlci5kZWJ1ZyhcIkRhdGFicmlja3MgdG9rZW4gcmVxdWVzdGVkXCIsIHtcbiAgICAgIC4uLnRoaXMuY29udGV4dCgpLFxuICAgICAgbG9naW46IGxvZ2luID8/IFwiYXV0b1wiLFxuICAgICAgc291cmNlOiB0aGlzLnJlcXVlc3RUb2tlbiA/IFwicmVxdWVzdFwiIDogXCJsaWZlY3ljbGVcIixcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0VG9rZW5cbiAgICAgID8gUHJvbWlzZS5yZXNvbHZlKHB1YmxpY1Rva2VuKHRoaXMucmVxdWVzdFRva2VuKSlcbiAgICAgIDogdGhpcy5yZXF1aXJlZENsaWVudCgpLnRva2VuV2l0aExvZ2luKGxvZ2luKTtcbiAgfVxuXG4gIGFzeW5jIGF1dGhlbnRpY2F0ZShsb2dpbj86IGJvb2xlYW4pOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+IHtcbiAgICBjb25zdCB0b2tlbiA9IGF3YWl0IHRoaXMudG9rZW4obG9naW4pO1xuICAgIGNvbnN0IGhlYWRlcnMgPSB7XG4gICAgICBbREVGQVVMVF9BQ0NFU1NfVE9LRU5fSEVBREVSXTogYCR7dG9rZW4udG9rZW5UeXBlfSAke3Rva2VuLmFjY2Vzc1Rva2VufWAsXG4gICAgICAuLi4odGhpcy5wcm9maWxlVmFsdWUud29ya3NwYWNlSWRcbiAgICAgICAgPyB7IFtXT1JLU1BBQ0VfSURfSEVBREVSXTogdGhpcy5wcm9maWxlVmFsdWUud29ya3NwYWNlSWQgfVxuICAgICAgICA6IHt9KSxcbiAgICB9O1xuICAgIGxvZ2dlci5kZWJ1ZyhcImdlbmVyYXRlZCBEYXRhYnJpY2tzIGF1dGhlbnRpY2F0aW9uIGhlYWRlcnNcIiwge1xuICAgICAgLi4udGhpcy5jb250ZXh0KCksXG4gICAgICBoZWFkZXJOYW1lczogT2JqZWN0LmtleXMoaGVhZGVycyksXG4gICAgICB0b2tlbjogdG9rZW5NZXRhZGF0YSh0b2tlbiksXG4gICAgfSk7XG4gICAgcmV0dXJuIGhlYWRlcnM7XG4gIH1cblxuICBhc3luYyBhdXRob3JpemF0aW9uSGVhZGVyRm9yVXJsKFxuICAgIHJlcXVlc3RVcmw6IHN0cmluZyxcbiAgICBsb2dpbj86IGJvb2xlYW4sXG4gICk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLnJlcXVlc3RIZWFkZXJzRm9yVXJsKHJlcXVlc3RVcmwsIGxvZ2luKSlbREVGQVVMVF9BQ0NFU1NfVE9LRU5fSEVBREVSXTtcbiAgfVxuXG4gIGFzeW5jIHJlcXVlc3RIZWFkZXJzRm9yVXJsKHJlcXVlc3RVcmw6IHN0cmluZywgbG9naW4/OiBib29sZWFuKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PiB7XG4gICAgY29uc3QgcmVxdWVzdCA9IG5ldyBVUkwocmVxdWVzdFVybCk7XG4gICAgY29uc3QgY3JlZGVudGlhbE9yaWdpbiA9IG5ldyBVUkwodGhpcy5wcm9maWxlVmFsdWUuaG9zdCkub3JpZ2luO1xuICAgIGlmIChyZXF1ZXN0Lm9yaWdpbiAhPT0gY3JlZGVudGlhbE9yaWdpbikge1xuICAgICAgbG9nZ2VyLmRlYnVnKFwic2tpcHBlZCBhdXRoZW50aWNhdGlvbiBmb3IgZGlmZmVyZW50IG9yaWdpblwiLCB7XG4gICAgICAgIC4uLnRoaXMuY29udGV4dCgpLFxuICAgICAgICByZXF1ZXN0T3JpZ2luOiByZXF1ZXN0Lm9yaWdpbixcbiAgICAgICAgY3JlZGVudGlhbE9yaWdpbixcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgICBsb2dnZXIuZGVidWcoXCJhcHBseWluZyBhdXRoZW50aWNhdGlvbiB0byBtYXRjaGluZyBvcmlnaW5cIiwge1xuICAgICAgLi4udGhpcy5jb250ZXh0KCksXG4gICAgICByZXF1ZXN0T3JpZ2luOiByZXF1ZXN0Lm9yaWdpbixcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5hdXRoZW50aWNhdGUobG9naW4pO1xuICB9XG5cbiAgZm9yY2VSZWZyZXNoVG9rZW4obG9naW4gPSB0cnVlKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwiRGF0YWJyaWNrcyB0b2tlbiBmb3JjZSByZWZyZXNoIHJlcXVlc3RlZFwiLCB7IC4uLnRoaXMuY29udGV4dCgpLCBsb2dpbiB9KTtcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0VG9rZW5cbiAgICAgID8gUHJvbWlzZS5yZXNvbHZlKHB1YmxpY1Rva2VuKHRoaXMucmVxdWVzdFRva2VuKSlcbiAgICAgIDogdGhpcy5yZXF1aXJlZENsaWVudCgpLmZvcmNlUmVmcmVzaChsb2dpbik7XG4gIH1cblxuICByZWZyZXNoUmVqZWN0ZWRUb2tlbihzdGFsZUFjY2Vzc1Rva2VuOiBzdHJpbmcsIGxvZ2luID0gdHJ1ZSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcIkRhdGFicmlja3MgcmVqZWN0ZWQgdG9rZW4gcmVmcmVzaCByZXF1ZXN0ZWRcIiwge1xuICAgICAgLi4udGhpcy5jb250ZXh0KCksXG4gICAgICBsb2dpbixcbiAgICAgIHJlcXVlc3RUb2tlbjogQm9vbGVhbih0aGlzLnJlcXVlc3RUb2tlbiksXG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdFRva2VuXG4gICAgICA/IFByb21pc2UucmVzb2x2ZShwdWJsaWNUb2tlbih0aGlzLnJlcXVlc3RUb2tlbikpXG4gICAgICA6IHRoaXMucmVxdWlyZWRDbGllbnQoKS5yZWZyZXNoUmVqZWN0ZWRUb2tlbihzdGFsZUFjY2Vzc1Rva2VuLCBsb2dpbik7XG4gIH1cblxuICBsb2dvdXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbG9nZ2VyLmRlYnVnKFwiRGF0YWJyaWNrcyBsb2dvdXQgcmVxdWVzdGVkXCIsIHRoaXMuY29udGV4dCgpKTtcbiAgICByZXR1cm4gdGhpcy5jbGllbnQ/LmxvZ291dCgpID8/IFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgc3RhdHVzKCk6IERhdGFicmlja3NBdXRoU3RhdHVzIHtcbiAgICByZXR1cm4ge1xuICAgICAgcHJvZmlsZTogdGhpcy5wcm9maWxlVmFsdWUubmFtZSxcbiAgICAgIGhvc3Q6IHRoaXMucHJvZmlsZVZhbHVlLmhvc3QsXG4gICAgICBzdG9yYWdlOiB0aGlzLnN0b3JhZ2VWYWx1ZSxcbiAgICB9O1xuICB9XG5cbiAgcHJpbmNpcGFsKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMucHJvZmlsZVZhbHVlLnByaW5jaXBhbDtcbiAgfVxuXG4gIHdvcmtzcGFjZUlkKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMucHJvZmlsZVZhbHVlLndvcmtzcGFjZUlkO1xuICB9XG5cbiAgYXV0aEtpbmQoKTogQXV0aEtpbmQge1xuICAgIHJldHVybiB0aGlzLnByb2ZpbGVWYWx1ZS5hdXRoS2luZDtcbiAgfVxuXG4gIHByb2ZpbGUobmFtZT86IHN0cmluZykge1xuICAgIGNvbnN0IHByb2ZpbGUgPVxuICAgICAgIW5hbWUgfHwgbmFtZSA9PT0gdGhpcy5wcm9maWxlVmFsdWUubmFtZVxuICAgICAgICA/IHRoaXMucHJvZmlsZVZhbHVlXG4gICAgICAgIDogcmVzb2x2ZURhdGFicmlja3NQcm9maWxlKHsgLi4udGhpcy5vcHRpb25zLCBwcm9maWxlOiBuYW1lIH0sIHRoaXMuZW52aXJvbm1lbnQpO1xuICAgIHJldHVybiBwcm9maWxlU3VtbWFyeShwcm9maWxlKTtcbiAgfVxuXG4gIGxpc3RQcm9maWxlcyhyZWZyZXNoID0gZmFsc2UpIHtcbiAgICByZXR1cm4gbGlzdERhdGFicmlja3NQcm9maWxlcyh0aGlzLm9wdGlvbnMuY29uZmlnRmlsZSwgcmVmcmVzaCwgdGhpcy5lbnZpcm9ubWVudCk7XG4gIH1cblxuICBwcml2YXRlIHJlcXVpcmVkQ2xpZW50KCk6IFRva2VuTGlmZWN5Y2xlIHtcbiAgICBpZiAoIXRoaXMuY2xpZW50KSB0aHJvdyBuZXcgQXV0aEVycm9yKFwib2F1dGhcIiwgXCJBdXRoZW50aWNhdGlvbiBsaWZlY3ljbGUgaXMgbm90IGF2YWlsYWJsZVwiKTtcbiAgICByZXR1cm4gdGhpcy5jbGllbnQ7XG4gIH1cblxuICBwcml2YXRlIGNvbnRleHQoKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICAgIHJldHVybiB7XG4gICAgICBwcm9maWxlOiB0aGlzLnByb2ZpbGVWYWx1ZS5uYW1lLFxuICAgICAgaG9zdDogdGhpcy5wcm9maWxlVmFsdWUuaG9zdCxcbiAgICAgIGF1dGhLaW5kOiB0aGlzLnByb2ZpbGVWYWx1ZS5hdXRoS2luZCxcbiAgICAgIHN0b3JhZ2U6IHRoaXMuc3RvcmFnZVZhbHVlLFxuICAgICAgaGFzV29ya3NwYWNlSWQ6IEJvb2xlYW4odGhpcy5wcm9maWxlVmFsdWUud29ya3NwYWNlSWQpLFxuICAgIH07XG4gIH1cbn1cblxuLyoqIENyZWF0ZSBhIERhdGFicmlja3MgYXV0aGVudGljYXRpb24gY2xpZW50LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUF1dGhDbGllbnQoXG4gIG9wdGlvbnM6IERhdGFicmlja3NBdXRoT3B0aW9ucyA9IHsgcHJlZmVyVXNlclRvTWFjaGluZTogdHJ1ZSB9LFxuICBzdG9yYWdlID0gU3RvcmFnZS5BdXRvLFxuICBkZXBlbmRlbmNpZXM6IERhdGFicmlja3NBdXRoRGVwZW5kZW5jaWVzID0ge30sXG4pOiBQcm9taXNlPEF1dGhDbGllbnQ+IHtcbiAgcmV0dXJuIGNyZWF0ZVBlcnNpc3RlbnRBdXRoKG9wdGlvbnMsIHN0b3JhZ2UsIGRlcGVuZGVuY2llcyk7XG59XG5cbi8qKiBSZXNvbHZlIGEgRGF0YWJyaWNrcyBwcm9maWxlIGFuZCBvcGVuIGJ1aWx0LWluIGNyZWRlbnRpYWwgc3RvcmFnZS4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVBlcnNpc3RlbnRBdXRoKFxuICBvcHRpb25zOiBEYXRhYnJpY2tzQXV0aE9wdGlvbnMsXG4gIHN0b3JhZ2U6IFN0b3JhZ2UsXG4gIGRlcGVuZGVuY2llczogRGF0YWJyaWNrc0F1dGhEZXBlbmRlbmNpZXMsXG4pOiBQcm9taXNlPFBlcnNpc3RlbnRBdXRoPiB7XG4gIGNvbnN0IGVudmlyb25tZW50ID0gZGVwZW5kZW5jaWVzLmVudmlyb25tZW50ID8/IHByb2Nlc3MuZW52O1xuICBjb25zdCBwcm9maWxlID0gcmVzb2x2ZURhdGFicmlja3NQcm9maWxlKG9wdGlvbnMsIGVudmlyb25tZW50KTtcbiAgY29uc3QgaW5BcHAgPVxuICAgIHByb2ZpbGUuYXV0aEtpbmQgPT09IEF1dGhLaW5kLkFwcE9uQmVoYWxmT2YgfHxcbiAgICBwcm9maWxlLmF1dGhLaW5kID09PSBBdXRoS2luZC5BcHBTZXJ2aWNlUHJpbmNpcGFsO1xuICBjb25zdCBiYWNrZW5kID0gc3RvcmFnZSA9PT0gU3RvcmFnZS5BdXRvID8gU3RvcmFnZS5NZW1vcnkgOiBzdG9yYWdlO1xuICBsb2dnZXIuZGVidWcoXCJjcmVhdGluZyBwZXJzaXN0ZW50IERhdGFicmlja3MgYXV0aFwiLCB7XG4gICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgIGhvc3Q6IHByb2ZpbGUuaG9zdCxcbiAgICBhdXRoS2luZDogcHJvZmlsZS5hdXRoS2luZCxcbiAgICByZXF1ZXN0ZWRTdG9yYWdlOiBzdG9yYWdlLFxuICAgIHJlc29sdmVkU3RvcmFnZTogYmFja2VuZCxcbiAgICBpbkFwcCxcbiAgfSk7XG4gIGNvbnN0IHN0b3JlID1cbiAgICBiYWNrZW5kID09PSBTdG9yYWdlLk1lbW9yeVxuICAgICAgPyBuZXcgTWVtb3J5Q3JlZGVudGlhbFN0b3JlKClcbiAgICAgIDogbmV3IEZpbGVDcmVkZW50aWFsU3RvcmUob3B0aW9ucy5jYWNoZURpciA/PyBqb2luKGhvbWVkaXIoKSwgXCIuZGF0YWJyaWNrc1wiKSk7XG4gIHJldHVybiBjcmVhdGVQZXJzaXN0ZW50QXV0aFdpdGhTdG9yYWdlKG9wdGlvbnMsIHN0b3JlLCBzdG9yYWdlLCBkZXBlbmRlbmNpZXMsIHByb2ZpbGUpO1xufVxuXG4vKiogUmVzb2x2ZSBhIERhdGFicmlja3MgcHJvZmlsZSB1c2luZyBjYWxsZXItb3duZWQgZ2VuZXJpYyBzdG9yYWdlLiAqL1xuYXN5bmMgZnVuY3Rpb24gY3JlYXRlUGVyc2lzdGVudEF1dGhXaXRoU3RvcmFnZShcbiAgb3B0aW9uczogRGF0YWJyaWNrc0F1dGhPcHRpb25zLFxuICBzdG9yZTogQ3JlZGVudGlhbFN0b3JlLFxuICBzdG9yYWdlID0gc3RvcmUubmFtZSgpID09PSBcIm1lbW9yeVwiID8gU3RvcmFnZS5NZW1vcnkgOiBTdG9yYWdlLkZpbGUsXG4gIGRlcGVuZGVuY2llczogRGF0YWJyaWNrc0F1dGhEZXBlbmRlbmNpZXMgPSB7fSxcbiAgcmVzb2x2ZWRQcm9maWxlPzogRGF0YWJyaWNrc1Byb2ZpbGUsXG4pOiBQcm9taXNlPFBlcnNpc3RlbnRBdXRoPiB7XG4gIGNvbnN0IHByb2ZpbGUgPVxuICAgIHJlc29sdmVkUHJvZmlsZSA/PyByZXNvbHZlRGF0YWJyaWNrc1Byb2ZpbGUob3B0aW9ucywgZGVwZW5kZW5jaWVzLmVudmlyb25tZW50ID8/IHByb2Nlc3MuZW52KTtcbiAgaWYgKHByb2ZpbGUuYXV0aEtpbmQgPT09IEF1dGhLaW5kLkFwcE9uQmVoYWxmT2YpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJjcmVhdGVkIHJlcXVlc3Qtc2NvcGVkIEFwcCBPQk8gYXV0aGVudGljYXRpb25cIiwge1xuICAgICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgICAgaG9zdDogcHJvZmlsZS5ob3N0LFxuICAgICAgaGFzV29ya3NwYWNlSWQ6IEJvb2xlYW4ocHJvZmlsZS53b3Jrc3BhY2VJZCksXG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBQZXJzaXN0ZW50QXV0aChcbiAgICAgIHByb2ZpbGUsXG4gICAgICBTdG9yYWdlLk1lbW9yeSxcbiAgICAgIG9wdGlvbnMsXG4gICAgICBkZXBlbmRlbmNpZXMuZW52aXJvbm1lbnQgPz8gcHJvY2Vzcy5lbnYsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICB7XG4gICAgICAgIGFjY2Vzc1Rva2VuOiBwcm9maWxlLmFjY2Vzc1Rva2VuISxcbiAgICAgICAgdG9rZW5UeXBlOiBcIkJlYXJlclwiLFxuICAgICAgICBzY29wZXM6IFsuLi5wcm9maWxlLnNjb3Blc10sXG4gICAgICB9LFxuICAgICk7XG4gIH1cbiAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCBwcm92aWRlckZvcihwcm9maWxlLCBvcHRpb25zLCBkZXBlbmRlbmNpZXMpO1xuICBjb25zdCBjbGllbnQgPSBuZXcgVG9rZW5MaWZlY3ljbGUoXG4gICAgcHJvZmlsZS5jYWNoZUtleSxcbiAgICBwcm92aWRlcixcbiAgICBzdG9yZSxcbiAgICBBdXRoT3B0aW9ucy5jcmVhdGUob3B0aW9ucy5hdXRoKSxcbiAgKTtcbiAgY29uc3QgcGVyc2lzdGVudCA9IG5ldyBQZXJzaXN0ZW50QXV0aChcbiAgICBwcm9maWxlLFxuICAgIHN0b3JhZ2UgPT09IFN0b3JhZ2UuQXV0byA/IHN0b3JhZ2VGcm9tTmFtZShzdG9yZS5uYW1lKCkpIDogc3RvcmFnZSxcbiAgICBvcHRpb25zLFxuICAgIGRlcGVuZGVuY2llcy5lbnZpcm9ubWVudCA/PyBwcm9jZXNzLmVudixcbiAgICBjbGllbnQsXG4gICk7XG4gIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZWQgcGVyc2lzdGVudCBhdXRoZW50aWNhdGlvbiBsaWZlY3ljbGVcIiwge1xuICAgIHByb2ZpbGU6IHByb2ZpbGUubmFtZSxcbiAgICBob3N0OiBwcm9maWxlLmhvc3QsXG4gICAgYXV0aEtpbmQ6IHByb2ZpbGUuYXV0aEtpbmQsXG4gICAgc3RvcmFnZTogcGVyc2lzdGVudC5zdGF0dXMoKS5zdG9yYWdlLFxuICB9KTtcbiAgcmV0dXJuIHBlcnNpc3RlbnQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHByb3ZpZGVyRm9yKFxuICBwcm9maWxlOiBEYXRhYnJpY2tzUHJvZmlsZSxcbiAgb3B0aW9uczogRGF0YWJyaWNrc0F1dGhPcHRpb25zLFxuICBkZXBlbmRlbmNpZXM6IERhdGFicmlja3NBdXRoRGVwZW5kZW5jaWVzLFxuKTogUHJvbWlzZTxUb2tlblByb3ZpZGVyPiB7XG4gIGNvbnN0IGVudmlyb25tZW50ID0gZGVwZW5kZW5jaWVzLmVudmlyb25tZW50ID8/IHByb2Nlc3MuZW52O1xuICBjb25zdCBpbkFwcCA9IGVudmlyb25tZW50VXRpbHMuaXNEYXRhYnJpY2tzQXBwRW52KHsgLi4uZW52aXJvbm1lbnQgfSk7XG4gIHN3aXRjaCAocHJvZmlsZS5hdXRoS2luZCkge1xuICAgIGNhc2UgQXV0aEtpbmQuVXNlclRvTWFjaGluZToge1xuICAgICAgY29uc3QgaW5zdGFsbCA9ICFpbkFwcCB8fCBvcHRpb25zLmluc3RhbGxDbGlJbkFwcCA9PT0gdHJ1ZTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcInNlbGVjdGVkIERhdGFicmlja3MgQ0xJIHByb3ZpZGVyXCIsIHtcbiAgICAgICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgICAgICBpbkFwcCxcbiAgICAgICAgaW5zdGFsbCxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5ldyBEYXRhYnJpY2tzQ2xpUHJvdmlkZXIoXG4gICAgICAgIHByb2ZpbGUubmFtZSxcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICBkZXBlbmRlbmNpZXMucmVzb2x2ZUNsaVxuICAgICAgICAgICAgPyBkZXBlbmRlbmNpZXMucmVzb2x2ZUNsaSh7IGluc3RhbGwgfSlcbiAgICAgICAgICAgIDogcmVzb2x2ZURhdGFicmlja3NDbGkoZW52aXJvbm1lbnQsIHsgaW5zdGFsbCB9KSxcbiAgICAgICAgY2xpRW52aXJvbm1lbnQocHJvZmlsZSwgcmVzb2x2ZUNvbmZpZ0ZpbGUob3B0aW9ucy5jb25maWdGaWxlLCBlbnZpcm9ubWVudCkpLFxuICAgICAgKTtcbiAgICB9XG4gICAgY2FzZSBBdXRoS2luZC5QZXJzb25hbEFjY2Vzc1Rva2VuOlxuICAgICAgbG9nZ2VyLmRlYnVnKFwic2VsZWN0ZWQgcGVyc29uYWwgYWNjZXNzIHRva2VuIHByb3ZpZGVyXCIsIHsgcHJvZmlsZTogcHJvZmlsZS5uYW1lIH0pO1xuICAgICAgcmV0dXJuIG5ldyBEYXRhYnJpY2tzUGVyc29uYWxBY2Nlc3NUb2tlblByb3ZpZGVyKHByb2ZpbGUuYWNjZXNzVG9rZW4hKTtcbiAgICBjYXNlIEF1dGhLaW5kLk1hY2hpbmVUb01hY2hpbmU6XG4gICAgY2FzZSBBdXRoS2luZC5BcHBTZXJ2aWNlUHJpbmNpcGFsOiB7XG4gICAgICBsb2dnZXIuZGVidWcoXCJzZWxlY3RlZCBzZXJ2aWNlLXByaW5jaXBhbCBwcm92aWRlclwiLCB7XG4gICAgICAgIHByb2ZpbGU6IHByb2ZpbGUubmFtZSxcbiAgICAgICAgYXV0aEtpbmQ6IHByb2ZpbGUuYXV0aEtpbmQsXG4gICAgICAgIHRhcmdldDogcHJvZmlsZS50YXJnZXQsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGVuZHBvaW50cyA9IGF3YWl0IHJlc29sdmVPQXV0aEVuZHBvaW50cyhwcm9maWxlLCBkZXBlbmRlbmNpZXMuZmV0Y2gpO1xuICAgICAgcmV0dXJuIG5ldyBEYXRhYnJpY2tzU2VydmljZVByaW5jaXBhbFByb3ZpZGVyKHtcbiAgICAgICAgdG9rZW5FbmRwb2ludDogZW5kcG9pbnRzLnRva2VuRW5kcG9pbnQsXG4gICAgICAgIGNsaWVudElkOiBwcm9maWxlLmNsaWVudElkLFxuICAgICAgICBjbGllbnRTZWNyZXQ6IHByb2ZpbGUuY2xpZW50U2VjcmV0ISxcbiAgICAgICAgc2NvcGVzOiBtYWNoaW5lU2NvcGVzKHByb2ZpbGUuc2NvcGVzKSxcbiAgICAgICAgLi4uKHByb2ZpbGUuZ3JvdXBJZCA/IHsgZ3JvdXBJZDogcHJvZmlsZS5ncm91cElkIH0gOiB7fSksXG4gICAgICAgIGFsbG93SW5zZWN1cmVSZXF1ZXN0czogaXNMb29wYmFja0h0dHAocHJvZmlsZS5ob3N0KSxcbiAgICAgICAgZmV0Y2g6IGRlcGVuZGVuY2llcy5mZXRjaCxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBjYXNlIEF1dGhLaW5kLkFwcE9uQmVoYWxmT2Y6XG4gICAgICB0aHJvdyBuZXcgQXV0aEVycm9yKFwiY29uZmlnXCIsIFwiQXBwIE9CTyB0b2tlbnMgZG8gbm90IHVzZSBhIHBlcnNpc3RlbnQgcHJvdmlkZXJcIik7XG4gIH1cbn1cblxuaW50ZXJmYWNlIEF1dGhvcml6YXRpb25TZXJ2ZXIge1xuICB0b2tlbkVuZHBvaW50OiBzdHJpbmc7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVPQXV0aEVuZHBvaW50cyhcbiAgcHJvZmlsZTogRGF0YWJyaWNrc1Byb2ZpbGUsXG4gIGZldGNoZXI6IHR5cGVvZiBnbG9iYWxUaGlzLmZldGNoID0gZ2xvYmFsVGhpcy5mZXRjaCxcbik6IFByb21pc2U8QXV0aG9yaXphdGlvblNlcnZlcj4ge1xuICBjb25zdCBob3N0ID0gcHJvZmlsZS5ob3N0LnJlcGxhY2UoL1xcLyQvLCBcIlwiKTtcbiAgaWYgKHByb2ZpbGUudGFyZ2V0ID09PSBUYXJnZXRLaW5kLkFjY291bnQpIHtcbiAgICBpZiAoIXByb2ZpbGUuYWNjb3VudElkKSB0aHJvdyBuZXcgQXV0aEVycm9yKFwiY29uZmlnXCIsIFwiQWNjb3VudCB0YXJnZXQgcmVxdWlyZXMgYWNjb3VudF9pZFwiKTtcbiAgICBjb25zdCBlbmRwb2ludHMgPSB7XG4gICAgICB0b2tlbkVuZHBvaW50OiBgJHtob3N0fS9vaWRjL2FjY291bnRzLyR7cHJvZmlsZS5hY2NvdW50SWR9L3YxL3Rva2VuYCxcbiAgICB9O1xuICAgIGxvZ2dlci5kZWJ1ZyhcInJlc29sdmVkIGFjY291bnQgT0F1dGggZW5kcG9pbnRcIiwge1xuICAgICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgICAgdG9rZW5PcmlnaW46IG5ldyBVUkwoZW5kcG9pbnRzLnRva2VuRW5kcG9pbnQpLm9yaWdpbixcbiAgICB9KTtcbiAgICByZXR1cm4gZW5kcG9pbnRzO1xuICB9XG4gIGNvbnN0IGRpc2NvdmVyeSA9XG4gICAgcHJvZmlsZS50YXJnZXQgPT09IFRhcmdldEtpbmQuVW5pZmllZFxuICAgICAgPyBgJHtob3N0fS9vaWRjL2FjY291bnRzLyR7cmVxdWlyZWRBY2NvdW50SWQocHJvZmlsZSl9Ly53ZWxsLWtub3duL29hdXRoLWF1dGhvcml6YXRpb24tc2VydmVyYFxuICAgICAgOiBgJHtob3N0fS9vaWRjLy53ZWxsLWtub3duL29hdXRoLWF1dGhvcml6YXRpb24tc2VydmVyYDtcbiAgbG9nZ2VyLmRlYnVnKFwicmVxdWVzdGluZyBPQXV0aCBkaXNjb3ZlcnlcIiwge1xuICAgIHByb2ZpbGU6IHByb2ZpbGUubmFtZSxcbiAgICB0YXJnZXQ6IHByb2ZpbGUudGFyZ2V0LFxuICAgIGRpc2NvdmVyeSxcbiAgfSk7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2hlcihkaXNjb3ZlcnksIHsgcmVkaXJlY3Q6IFwibWFudWFsXCIgfSk7XG4gIGxvZ2dlci5kZWJ1ZyhcInJlY2VpdmVkIE9BdXRoIGRpc2NvdmVyeSByZXNwb25zZVwiLCB7XG4gICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgIHN0YXR1czogcmVzcG9uc2Uuc3RhdHVzLFxuICB9KTtcbiAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gNDA0KVxuICAgIHRocm93IG5ldyBBdXRoRXJyb3IoXCJvYXV0aFwiLCBgT0F1dGggaXMgbm90IHN1cHBvcnRlZCBhdCAke2Rpc2NvdmVyeX1gKTtcbiAgaWYgKCFyZXNwb25zZS5vaylcbiAgICB0aHJvdyBuZXcgQXV0aEVycm9yKFwib2F1dGhcIiwgYE9BdXRoIGRpc2NvdmVyeSByZXR1cm5lZCBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfWApO1xuICBjb25zdCB2YWx1ZSA9IChhd2FpdCByZXNwb25zZS5qc29uKCkpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCB0b2tlbkVuZHBvaW50ID0gc3RyaW5nVmFsdWUodmFsdWUudG9rZW5fZW5kcG9pbnQpO1xuICBpZiAoIXRva2VuRW5kcG9pbnQpIHRocm93IG5ldyBBdXRoRXJyb3IoXCJvYXV0aFwiLCBcIk9BdXRoIGRpc2NvdmVyeSByZXNwb25zZSBpcyBpbmNvbXBsZXRlXCIpO1xuICBsb2dnZXIuZGVidWcoXCJyZXNvbHZlZCBPQXV0aCB0b2tlbiBlbmRwb2ludFwiLCB7XG4gICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgIHRva2VuT3JpZ2luOiBuZXcgVVJMKHRva2VuRW5kcG9pbnQpLm9yaWdpbixcbiAgfSk7XG4gIHJldHVybiB7IHRva2VuRW5kcG9pbnQgfTtcbn1cblxuZnVuY3Rpb24gcmVxdWlyZWRBY2NvdW50SWQocHJvZmlsZTogRGF0YWJyaWNrc1Byb2ZpbGUpOiBzdHJpbmcge1xuICBpZiAoIXByb2ZpbGUuYWNjb3VudElkKSB0aHJvdyBuZXcgQXV0aEVycm9yKFwiY29uZmlnXCIsIFwiVW5pZmllZCB0YXJnZXQgcmVxdWlyZXMgYWNjb3VudF9pZFwiKTtcbiAgcmV0dXJuIHByb2ZpbGUuYWNjb3VudElkO1xufVxuXG5mdW5jdGlvbiBzdG9yYWdlRnJvbU5hbWUobmFtZTogc3RyaW5nKTogU3RvcmFnZSB7XG4gIHJldHVybiBuYW1lID09PSBcIm1lbW9yeVwiID8gU3RvcmFnZS5NZW1vcnkgOiBTdG9yYWdlLkZpbGU7XG59XG5cbmZ1bmN0aW9uIHByb2ZpbGVTdW1tYXJ5KHByb2ZpbGU6IERhdGFicmlja3NQcm9maWxlKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogcHJvZmlsZS5uYW1lLFxuICAgIGhvc3Q6IHByb2ZpbGUuaG9zdCxcbiAgICAuLi4ocHJvZmlsZS5hY2NvdW50SWQgPyB7IGFjY291bnRJZDogcHJvZmlsZS5hY2NvdW50SWQgfSA6IHt9KSxcbiAgICAuLi4ocHJvZmlsZS53b3Jrc3BhY2VJZCA/IHsgd29ya3NwYWNlSWQ6IHByb2ZpbGUud29ya3NwYWNlSWQgfSA6IHt9KSxcbiAgICB0YXJnZXQ6IHByb2ZpbGUudGFyZ2V0LFxuICAgIGF1dGhLaW5kOiBwcm9maWxlLmF1dGhLaW5kLFxuICB9O1xufVxuXG5mdW5jdGlvbiBpc0xvb3BiYWNrSHR0cChob3N0OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgdXJsID0gbmV3IFVSTChob3N0KTtcbiAgcmV0dXJuIHVybC5wcm90b2NvbCA9PT0gXCJodHRwOlwiICYmIFtcIjEyNy4wLjAuMVwiLCBcImxvY2FsaG9zdFwiXS5pbmNsdWRlcyh1cmwuaG9zdG5hbWUpO1xufVxuXG5mdW5jdGlvbiBjbGlFbnZpcm9ubWVudChwcm9maWxlOiBEYXRhYnJpY2tzUHJvZmlsZSwgY29uZmlnRmlsZTogc3RyaW5nKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIHJldHVybiB7XG4gICAgREFUQUJSSUNLU19DT05GSUdfRklMRTogY29uZmlnRmlsZSxcbiAgICBEQVRBQlJJQ0tTX0NPTkZJR19QUk9GSUxFOiBwcm9maWxlLm5hbWUsXG4gICAgREFUQUJSSUNLU19IT1NUOiBwcm9maWxlLmhvc3QsXG4gICAgLi4uKHByb2ZpbGUuYWNjb3VudElkID8geyBEQVRBQlJJQ0tTX0FDQ09VTlRfSUQ6IHByb2ZpbGUuYWNjb3VudElkIH0gOiB7fSksXG4gICAgLi4uKHByb2ZpbGUud29ya3NwYWNlSWQgPyB7IERBVEFCUklDS1NfV09SS1NQQUNFX0lEOiBwcm9maWxlLndvcmtzcGFjZUlkIH0gOiB7fSksXG4gICAgLi4uKHByb2ZpbGUuYXV0aEtpbmQgPT09IEF1dGhLaW5kLlBlcnNvbmFsQWNjZXNzVG9rZW5cbiAgICAgID8ge1xuICAgICAgICAgIERBVEFCUklDS1NfQVVUSF9UWVBFOiBcInBhdFwiLFxuICAgICAgICAgIERBVEFCUklDS1NfVE9LRU46IHByb2ZpbGUuYWNjZXNzVG9rZW4hLFxuICAgICAgICB9XG4gICAgICA6IHt9KSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc3RyaW5nVmFsdWUodmFsdWU6IHVua25vd24pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmIHZhbHVlLnRyaW0oKSA/IHZhbHVlIDogdW5kZWZpbmVkO1xufVxuIl19