@dbx-tools/appkit 0.6.82 → 0.6.86
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 +6 -9
- package/index.ts +3 -3
- package/lib/index.d.ts +3 -3
- package/lib/index.js +3 -3
- package/lib/src/{config.d.ts → bundle.d.ts} +40 -17
- package/lib/src/bundle.js +359 -0
- package/lib/src/databricks.d.ts +1 -16
- package/lib/src/databricks.js +3 -20
- package/lib/src/identity.d.ts +1 -2
- package/lib/src/identity.js +5 -4
- package/lib/src/lakebase-resolver.d.ts +1 -1
- package/lib/src/lakebase-resolver.js +7 -7
- package/lib/src/provision.js +3 -3
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/{config.ts → bundle.ts} +55 -107
- package/src/databricks.ts +2 -21
- package/src/identity.ts +5 -4
- package/src/lakebase-resolver.ts +10 -6
- package/src/provision.ts +2 -3
- package/lib/src/config.js +0 -403
package/lib/src/config.js
DELETED
|
@@ -1,403 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Layered configuration resolution for local development against a Databricks
|
|
3
|
-
* App / Asset Bundle.
|
|
4
|
-
*
|
|
5
|
-
* Default sources: `explicit`, then `env`, then Databricks App `config.env`
|
|
6
|
-
* (from {@link bundle}) and hard-coded `app.yaml` env entries (from
|
|
7
|
-
* {@link appYaml}). Opt in to `cli` when a dev command wants flag overrides.
|
|
8
|
-
*
|
|
9
|
-
* Server-only (`node:child_process`, bundle root discovery). Databricks-app
|
|
10
|
-
* specific, so it lives in node-appkit rather than shared-core.
|
|
11
|
-
*
|
|
12
|
-
* @module
|
|
13
|
-
*/
|
|
14
|
-
import { spawnSync } from "node:child_process";
|
|
15
|
-
import { readFile } from "node:fs/promises";
|
|
16
|
-
import { dirname, resolve } from "node:path";
|
|
17
|
-
import { ValidationError } from "@databricks/appkit";
|
|
18
|
-
import { file, project } from "@dbx-tools/core";
|
|
19
|
-
import { functionModule, json, object, log, string } from "@dbx-tools/shared-core";
|
|
20
|
-
import { parse as parseYamlText } from "yaml";
|
|
21
|
-
import { z } from "zod";
|
|
22
|
-
import { isAppEnv } from "./databricks.js";
|
|
23
|
-
const logger = log.logger("config");
|
|
24
|
-
const defaultConfigSources = ["explicit", "env", "bundle"];
|
|
25
|
-
const APP_YAML_NAMES = ["app.yaml", "app.yml"];
|
|
26
|
-
const bundleValidateCache = new Map();
|
|
27
|
-
const normalizedString = z
|
|
28
|
-
.string()
|
|
29
|
-
.transform((value) => value.trim())
|
|
30
|
-
.pipe(z.string().min(1));
|
|
31
|
-
const bundleAppEnvEntrySchema = z.object({
|
|
32
|
-
name: normalizedString.optional(),
|
|
33
|
-
value: z.string().optional(),
|
|
34
|
-
value_from: normalizedString.optional(),
|
|
35
|
-
});
|
|
36
|
-
const bundleAppResourceSchema = z.object({
|
|
37
|
-
name: normalizedString.optional(),
|
|
38
|
-
sql_warehouse: z.object({ id: normalizedString.optional() }).optional(),
|
|
39
|
-
genie_space: z.object({ space_id: normalizedString.optional() }).optional(),
|
|
40
|
-
postgres: z
|
|
41
|
-
.object({
|
|
42
|
-
database: normalizedString.optional(),
|
|
43
|
-
branch: normalizedString.optional(),
|
|
44
|
-
endpoint: normalizedString.optional(),
|
|
45
|
-
})
|
|
46
|
-
.optional(),
|
|
47
|
-
});
|
|
48
|
-
const bundleAppSchema = z.object({
|
|
49
|
-
name: normalizedString.optional(),
|
|
50
|
-
source_code_path: z.string().optional(),
|
|
51
|
-
config: z.object({ env: z.array(bundleAppEnvEntrySchema).optional() }).optional(),
|
|
52
|
-
resources: z.array(bundleAppResourceSchema).optional(),
|
|
53
|
-
});
|
|
54
|
-
const bundleValidateAppsSchema = z.object({
|
|
55
|
-
resources: z.object({ apps: z.record(z.string(), bundleAppSchema).optional() }).optional(),
|
|
56
|
-
});
|
|
57
|
-
const appYamlEnvEntrySchema = z.object({
|
|
58
|
-
name: normalizedString,
|
|
59
|
-
value: z.string().optional(),
|
|
60
|
-
valueFrom: normalizedString.optional(),
|
|
61
|
-
});
|
|
62
|
-
const appYamlResourceSchema = z
|
|
63
|
-
.object({
|
|
64
|
-
name: normalizedString,
|
|
65
|
-
sql_warehouse: z.object({ id: normalizedString.optional() }).optional(),
|
|
66
|
-
genie_space: z.object({ space_id: normalizedString.optional() }).optional(),
|
|
67
|
-
postgres: z
|
|
68
|
-
.object({
|
|
69
|
-
database: normalizedString.optional(),
|
|
70
|
-
branch: normalizedString.optional(),
|
|
71
|
-
endpoint: normalizedString.optional(),
|
|
72
|
-
})
|
|
73
|
-
.optional(),
|
|
74
|
-
})
|
|
75
|
-
.passthrough();
|
|
76
|
-
const appYamlSchema = z.object({
|
|
77
|
-
env: z.array(appYamlEnvEntrySchema).optional(),
|
|
78
|
-
resources: z.array(appYamlResourceSchema).optional(),
|
|
79
|
-
});
|
|
80
|
-
const bundleDefault = functionModule.memoize(() => loadBundle(process.cwd()));
|
|
81
|
-
const appYamlDefault = functionModule.memoize(() => loadAppYaml(process.cwd()));
|
|
82
|
-
function envKeysForName(name) {
|
|
83
|
-
const trimmed = name.trim();
|
|
84
|
-
if (!trimmed) {
|
|
85
|
-
return object.sequence();
|
|
86
|
-
}
|
|
87
|
-
const keys = (function* () {
|
|
88
|
-
const modifiers = [
|
|
89
|
-
null,
|
|
90
|
-
() => trimmed.toUpperCase(),
|
|
91
|
-
() => Array.from(string.tokenize(trimmed)).join("_").toUpperCase(),
|
|
92
|
-
];
|
|
93
|
-
for (const modifier of modifiers) {
|
|
94
|
-
yield modifier ? modifier(trimmed) : trimmed;
|
|
95
|
-
}
|
|
96
|
-
})();
|
|
97
|
-
return object.sequence(keys).cache().filter(Boolean).distinct();
|
|
98
|
-
}
|
|
99
|
-
function readEnv(keys) {
|
|
100
|
-
for (const key of keys) {
|
|
101
|
-
const value = process.env[key]?.trim();
|
|
102
|
-
if (value)
|
|
103
|
-
return value;
|
|
104
|
-
}
|
|
105
|
-
return undefined;
|
|
106
|
-
}
|
|
107
|
-
function readConfigMapValue(value) {
|
|
108
|
-
if (value == null)
|
|
109
|
-
return undefined;
|
|
110
|
-
if (Array.isArray(value)) {
|
|
111
|
-
for (const item of value) {
|
|
112
|
-
const trimmed = item?.trim();
|
|
113
|
-
if (trimmed)
|
|
114
|
-
return trimmed;
|
|
115
|
-
}
|
|
116
|
-
return undefined;
|
|
117
|
-
}
|
|
118
|
-
const trimmed = value.trim();
|
|
119
|
-
return trimmed || undefined;
|
|
120
|
-
}
|
|
121
|
-
function readMap(keys, map) {
|
|
122
|
-
if (!map)
|
|
123
|
-
return undefined;
|
|
124
|
-
for (const key of keys) {
|
|
125
|
-
const value = readConfigMapValue(map[key]);
|
|
126
|
-
if (value)
|
|
127
|
-
return value;
|
|
128
|
-
}
|
|
129
|
-
return undefined;
|
|
130
|
-
}
|
|
131
|
-
function readAppEnv(keys, envMap) {
|
|
132
|
-
for (const key of keys) {
|
|
133
|
-
const value = envMap[key]?.trim();
|
|
134
|
-
if (value)
|
|
135
|
-
return value;
|
|
136
|
-
}
|
|
137
|
-
return undefined;
|
|
138
|
-
}
|
|
139
|
-
function parseYaml(text) {
|
|
140
|
-
return parseYamlText(text);
|
|
141
|
-
}
|
|
142
|
-
function pickAppResourceId(apps) {
|
|
143
|
-
const keys = Object.keys(apps);
|
|
144
|
-
return keys.length === 1 ? keys[0] : undefined;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Resolve the effective value a `value_from`/`valueFrom` entry points at:
|
|
148
|
-
* the first present of the warehouse id, Genie space id, or Postgres
|
|
149
|
-
* endpoint/database/branch on the named resource. Shared by both the
|
|
150
|
-
* `app.yaml` and `bundle validate` flatteners, whose resource shapes match.
|
|
151
|
-
*/
|
|
152
|
-
function resolveResourceValue(resource) {
|
|
153
|
-
return (resource?.sql_warehouse?.id ??
|
|
154
|
-
resource?.genie_space?.space_id ??
|
|
155
|
-
resource?.postgres?.endpoint ??
|
|
156
|
-
resource?.postgres?.database ??
|
|
157
|
-
resource?.postgres?.branch);
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Flatten `env` entries from parsed `app.yaml` content. Literal `value` entries
|
|
161
|
-
* are returned as-is; `valueFrom` entries resolve against the sibling
|
|
162
|
-
* `resources` array when possible.
|
|
163
|
-
*/
|
|
164
|
-
export function flattenAppYamlEnv(data) {
|
|
165
|
-
const parsed = appYamlSchema.safeParse(data);
|
|
166
|
-
if (!parsed.success || !parsed.data.env?.length) {
|
|
167
|
-
return {};
|
|
168
|
-
}
|
|
169
|
-
const resourceByName = new Map((parsed.data.resources ?? []).map((resource) => [resource.name, resource]));
|
|
170
|
-
const out = {};
|
|
171
|
-
for (const entry of parsed.data.env) {
|
|
172
|
-
if (entry.value?.trim()) {
|
|
173
|
-
out[entry.name] = entry.value.trim();
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
if (!entry.valueFrom)
|
|
177
|
-
continue;
|
|
178
|
-
const resolved = resolveResourceValue(resourceByName.get(entry.valueFrom));
|
|
179
|
-
if (resolved)
|
|
180
|
-
out[entry.name] = resolved;
|
|
181
|
-
}
|
|
182
|
-
return out;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Flatten `resources.apps.<key>.config.env` into a `name -> value` map.
|
|
186
|
-
* Auto-picks the app only when the bundle defines exactly one.
|
|
187
|
-
*/
|
|
188
|
-
export function flattenAppEnv(data) {
|
|
189
|
-
const parsed = bundleValidateAppsSchema.safeParse(data);
|
|
190
|
-
if (!parsed.success)
|
|
191
|
-
return {};
|
|
192
|
-
const apps = parsed.data.resources?.apps;
|
|
193
|
-
if (!apps || Object.keys(apps).length === 0)
|
|
194
|
-
return {};
|
|
195
|
-
const key = pickAppResourceId(apps);
|
|
196
|
-
if (!key)
|
|
197
|
-
return {};
|
|
198
|
-
const app = apps[key];
|
|
199
|
-
if (!app?.config?.env?.length)
|
|
200
|
-
return {};
|
|
201
|
-
const resourceByName = new Map((app.resources ?? [])
|
|
202
|
-
.filter((resource) => resource.name)
|
|
203
|
-
.map((resource) => [resource.name, resource]));
|
|
204
|
-
const out = {};
|
|
205
|
-
for (const entry of app.config.env) {
|
|
206
|
-
if (!entry.name)
|
|
207
|
-
continue;
|
|
208
|
-
if (entry.value) {
|
|
209
|
-
out[entry.name] = entry.value;
|
|
210
|
-
continue;
|
|
211
|
-
}
|
|
212
|
-
if (!entry.value_from)
|
|
213
|
-
continue;
|
|
214
|
-
const resolved = resolveResourceValue(resourceByName.get(entry.value_from));
|
|
215
|
-
if (resolved)
|
|
216
|
-
out[entry.name] = resolved;
|
|
217
|
-
}
|
|
218
|
-
return out;
|
|
219
|
-
}
|
|
220
|
-
function validateBundle(root) {
|
|
221
|
-
const key = root;
|
|
222
|
-
if (bundleValidateCache.has(key)) {
|
|
223
|
-
return bundleValidateCache.get(key);
|
|
224
|
-
}
|
|
225
|
-
const args = ["bundle", "validate", "--output", "json"];
|
|
226
|
-
try {
|
|
227
|
-
const proc = spawnSync("databricks", args, {
|
|
228
|
-
cwd: root,
|
|
229
|
-
encoding: "utf8",
|
|
230
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
231
|
-
});
|
|
232
|
-
const text = proc.stdout?.trim();
|
|
233
|
-
if (!text) {
|
|
234
|
-
bundleValidateCache.set(key, undefined);
|
|
235
|
-
return undefined;
|
|
236
|
-
}
|
|
237
|
-
const data = json.parse(text);
|
|
238
|
-
bundleValidateCache.set(key, data);
|
|
239
|
-
return data;
|
|
240
|
-
}
|
|
241
|
-
catch {
|
|
242
|
-
bundleValidateCache.set(key, undefined);
|
|
243
|
-
return undefined;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
async function loadBundle(cwd) {
|
|
247
|
-
const configFile = resolveConfigFile(cwd, "databricks.yml");
|
|
248
|
-
if (configFile) {
|
|
249
|
-
const data = validateBundle(dirname(configFile));
|
|
250
|
-
if (data)
|
|
251
|
-
return { path: configFile, data };
|
|
252
|
-
}
|
|
253
|
-
return undefined;
|
|
254
|
-
}
|
|
255
|
-
async function loadAppYaml(cwd) {
|
|
256
|
-
for (const fileName of APP_YAML_NAMES) {
|
|
257
|
-
const configFile = resolveConfigFile(cwd, fileName);
|
|
258
|
-
if (!configFile)
|
|
259
|
-
continue;
|
|
260
|
-
try {
|
|
261
|
-
const text = await readFile(configFile, "utf8");
|
|
262
|
-
const data = parseYaml(text);
|
|
263
|
-
if (!object.isRecord(data)) {
|
|
264
|
-
return undefined;
|
|
265
|
-
}
|
|
266
|
-
return { path: configFile, data };
|
|
267
|
-
}
|
|
268
|
-
catch {
|
|
269
|
-
logger.warn("failed to parse app yaml", { path: configFile });
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return undefined;
|
|
273
|
-
}
|
|
274
|
-
function resolveConfigFile(cwd, configFile) {
|
|
275
|
-
if (isAppEnv())
|
|
276
|
-
return undefined;
|
|
277
|
-
for (const rootDir of project.resolveProjectRoots(cwd)) {
|
|
278
|
-
const bundlePath = resolve(rootDir, configFile);
|
|
279
|
-
if (file.statSync(bundlePath)?.isFile())
|
|
280
|
-
return bundlePath;
|
|
281
|
-
}
|
|
282
|
-
return undefined;
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Locate the bundle root and run `databricks bundle validate --output json`.
|
|
286
|
-
* When `cwd` is omitted or equals `process.cwd()`, the result is memoized for
|
|
287
|
-
* the process lifetime. Returns `undefined` inside a Databricks App.
|
|
288
|
-
*/
|
|
289
|
-
export function bundle(cwd) {
|
|
290
|
-
if (isAppEnv())
|
|
291
|
-
return Promise.resolve(undefined);
|
|
292
|
-
return cwd && resolve(cwd) !== process.cwd() ? loadBundle(cwd) : bundleDefault();
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Locate and parse `app.yaml` / `app.yml` from the bundle or project root. When
|
|
296
|
-
* `cwd` is omitted or equals `process.cwd()`, the result is memoized for the
|
|
297
|
-
* process lifetime. Returns `undefined` inside a Databricks App.
|
|
298
|
-
*/
|
|
299
|
-
export function appYaml(cwd) {
|
|
300
|
-
if (isAppEnv())
|
|
301
|
-
return Promise.resolve(undefined);
|
|
302
|
-
return cwd && resolve(cwd) !== process.cwd() ? loadAppYaml(cwd) : appYamlDefault();
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Walk a dot-separated path through bundle validate JSON. When the terminal
|
|
306
|
-
* node is a bundle variable object (`{ value: "..." }`), the `value` field is
|
|
307
|
-
* returned.
|
|
308
|
-
*/
|
|
309
|
-
export function getBundlePath(data, path) {
|
|
310
|
-
const parts = path.split(".").filter(Boolean);
|
|
311
|
-
if (parts.length === 0)
|
|
312
|
-
return undefined;
|
|
313
|
-
let current = data;
|
|
314
|
-
for (let i = 0; i < parts.length; i++) {
|
|
315
|
-
if (!object.isRecord(current))
|
|
316
|
-
return undefined;
|
|
317
|
-
const part = parts[i];
|
|
318
|
-
const next = current[part];
|
|
319
|
-
if (i === parts.length - 1) {
|
|
320
|
-
if (typeof next === "string" && next)
|
|
321
|
-
return next;
|
|
322
|
-
if (object.isRecord(next)) {
|
|
323
|
-
const value = next.value;
|
|
324
|
-
return typeof value === "string" && value ? value : undefined;
|
|
325
|
-
}
|
|
326
|
-
return undefined;
|
|
327
|
-
}
|
|
328
|
-
current = next;
|
|
329
|
-
}
|
|
330
|
-
return undefined;
|
|
331
|
-
}
|
|
332
|
-
async function resolveAppEnvMap(options) {
|
|
333
|
-
const appData = options.appData ?? (await appYaml());
|
|
334
|
-
const bundleData = options.bundleData ?? (await bundle());
|
|
335
|
-
const fromYaml = appData ? flattenAppYamlEnv(appData.data) : {};
|
|
336
|
-
const fromBundle = bundleData ? flattenAppEnv(bundleData.data) : {};
|
|
337
|
-
return { ...fromYaml, ...fromBundle };
|
|
338
|
-
}
|
|
339
|
-
function resolveSources(options) {
|
|
340
|
-
const sources = [...(options.sources ?? defaultConfigSources)];
|
|
341
|
-
if (options.explicit !== undefined && !sources.includes("explicit")) {
|
|
342
|
-
sources.unshift("explicit");
|
|
343
|
-
}
|
|
344
|
-
return sources;
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* Resolve a configuration string from the configured sources. Returns the first
|
|
348
|
-
* non-empty value, or `undefined` when nothing matches.
|
|
349
|
-
*
|
|
350
|
-
* Precedence follows AppKit's: explicit config, then environment variable, then
|
|
351
|
-
* whatever the Databricks App / bundle definition supplies.
|
|
352
|
-
*
|
|
353
|
-
* @example
|
|
354
|
-
* import { config } from "@dbx-tools/appkit";
|
|
355
|
-
*
|
|
356
|
-
* const warehouseId = await config.resolveConfigValue("DATABRICKS_WAREHOUSE_ID", {
|
|
357
|
-
* cli: { DATABRICKS_WAREHOUSE_ID: flags.warehouse },
|
|
358
|
-
* sources: config.withCliSources(),
|
|
359
|
-
* });
|
|
360
|
-
*/
|
|
361
|
-
export async function resolveConfigValue(name, options = {}) {
|
|
362
|
-
const keys = envKeysForName(name).toArray();
|
|
363
|
-
if (keys.length === 0)
|
|
364
|
-
return undefined;
|
|
365
|
-
const sources = resolveSources(options);
|
|
366
|
-
let appEnvMap;
|
|
367
|
-
const values = (async function* () {
|
|
368
|
-
for (const source of sources) {
|
|
369
|
-
switch (source) {
|
|
370
|
-
case "explicit":
|
|
371
|
-
yield readMap(keys, options.explicit);
|
|
372
|
-
break;
|
|
373
|
-
case "cli":
|
|
374
|
-
yield readMap(keys, options.cli);
|
|
375
|
-
break;
|
|
376
|
-
case "env":
|
|
377
|
-
yield readEnv(keys);
|
|
378
|
-
break;
|
|
379
|
-
case "bundle":
|
|
380
|
-
if (appEnvMap === undefined)
|
|
381
|
-
appEnvMap = await resolveAppEnvMap(options);
|
|
382
|
-
yield readAppEnv(keys, appEnvMap);
|
|
383
|
-
break;
|
|
384
|
-
default:
|
|
385
|
-
throw ValidationError.invalidValue("sources", source, "one of: explicit, cli, env, bundle");
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
})();
|
|
389
|
-
for await (const value of values) {
|
|
390
|
-
if (value)
|
|
391
|
-
return value;
|
|
392
|
-
}
|
|
393
|
-
return undefined;
|
|
394
|
-
}
|
|
395
|
-
/**
|
|
396
|
-
* Sources with `cli` included, in CLI-first order. Use for dev commands that
|
|
397
|
-
* accept flag overrides.
|
|
398
|
-
*/
|
|
399
|
-
export function withCliSources(sources = defaultConfigSources) {
|
|
400
|
-
const rest = sources.filter((source) => source !== "cli" && source !== "explicit");
|
|
401
|
-
return ["cli", "explicit", ...rest];
|
|
402
|
-
}
|
|
403
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7O0dBWUc7QUFFSCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDL0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDbkYsT0FBTyxFQUFFLEtBQUssSUFBSSxhQUFhLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDOUMsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUV4QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFM0MsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQWNwQyxNQUFNLG9CQUFvQixHQUFtQixDQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFFM0UsTUFBTSxjQUFjLEdBQUcsQ0FBQyxVQUFVLEVBQUUsU0FBUyxDQUFVLENBQUM7QUFFeEQsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsRUFBMEMsQ0FBQztBQUU5RSxNQUFNLGdCQUFnQixHQUFHLENBQUM7S0FDdkIsTUFBTSxFQUFFO0tBQ1IsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7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LFVBQTBCLG9CQUFvQjtJQUMzRSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLEtBQUssS0FBSyxJQUFJLE1BQU0sS0FBSyxVQUFVLENBQUMsQ0FBQztJQUNuRixPQUFPLENBQUMsS0FBSyxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQ3RDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIExheWVyZWQgY29uZmlndXJhdGlvbiByZXNvbHV0aW9uIGZvciBsb2NhbCBkZXZlbG9wbWVudCBhZ2FpbnN0IGEgRGF0YWJyaWNrc1xuICogQXBwIC8gQXNzZXQgQnVuZGxlLlxuICpcbiAqIERlZmF1bHQgc291cmNlczogYGV4cGxpY2l0YCwgdGhlbiBgZW52YCwgdGhlbiBEYXRhYnJpY2tzIEFwcCBgY29uZmlnLmVudmBcbiAqIChmcm9tIHtAbGluayBidW5kbGV9KSBhbmQgaGFyZC1jb2RlZCBgYXBwLnlhbWxgIGVudiBlbnRyaWVzIChmcm9tXG4gKiB7QGxpbmsgYXBwWWFtbH0pLiBPcHQgaW4gdG8gYGNsaWAgd2hlbiBhIGRldiBjb21tYW5kIHdhbnRzIGZsYWcgb3ZlcnJpZGVzLlxuICpcbiAqIFNlcnZlci1vbmx5IChgbm9kZTpjaGlsZF9wcm9jZXNzYCwgYnVuZGxlIHJvb3QgZGlzY292ZXJ5KS4gRGF0YWJyaWNrcy1hcHBcbiAqIHNwZWNpZmljLCBzbyBpdCBsaXZlcyBpbiBub2RlLWFwcGtpdCByYXRoZXIgdGhhbiBzaGFyZWQtY29yZS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgc3Bhd25TeW5jIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgcmVhZEZpbGUgfSBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHsgZGlybmFtZSwgcmVzb2x2ZSB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IFZhbGlkYXRpb25FcnJvciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGZpbGUsIHByb2plY3QgfSBmcm9tIFwiQGRieC10b29scy9jb3JlXCI7XG5pbXBvcnQgeyBmdW5jdGlvbk1vZHVsZSwganNvbiwgb2JqZWN0LCBsb2csIHN0cmluZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBwYXJzZSBhcyBwYXJzZVlhbWxUZXh0IH0gZnJvbSBcInlhbWxcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbmltcG9ydCB7IGlzQXBwRW52IH0gZnJvbSBcIi4vZGF0YWJyaWNrcy50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiY29uZmlnXCIpO1xuXG4vKiogUGFyc2VkIHBheWxvYWQgZnJvbSBgZGF0YWJyaWNrcyBidW5kbGUgdmFsaWRhdGUgLS1vdXRwdXQganNvbmAuICovXG5leHBvcnQgdHlwZSBCdW5kbGVWYWxpZGF0ZUpzb24gPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuLyoqIEEgY29uZmlnIGZpbGUgZGlzY292ZXJlZCBvbiBkaXNrIHdpdGggaXRzIHBhcnNlZCBjb250ZW50cy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29uZmlnRmlsZSB7XG4gIHBhdGg6IHN0cmluZztcbiAgZGF0YTogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8qKiBTdXBwb3J0ZWQgY29uZmlndXJhdGlvbiBzb3VyY2VzLCBjb25zdWx0ZWQgaW4gYXJyYXkgb3JkZXIuICovXG5leHBvcnQgdHlwZSBDb25maWdTb3VyY2UgPSBcImV4cGxpY2l0XCIgfCBcImNsaVwiIHwgXCJlbnZcIiB8IFwiYnVuZGxlXCI7XG5cbmNvbnN0IGRlZmF1bHRDb25maWdTb3VyY2VzOiBDb25maWdTb3VyY2VbXSA9IFtcImV4cGxpY2l0XCIsIFwiZW52XCIsIFwiYnVuZGxlXCJdO1xuXG5jb25zdCBBUFBfWUFNTF9OQU1FUyA9IFtcImFwcC55YW1sXCIsIFwiYXBwLnltbFwiXSBhcyBjb25zdDtcblxuY29uc3QgYnVuZGxlVmFsaWRhdGVDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBCdW5kbGVWYWxpZGF0ZUpzb24gfCB1bmRlZmluZWQ+KCk7XG5cbmNvbnN0IG5vcm1hbGl6ZWRTdHJpbmcgPSB6XG4gIC5zdHJpbmcoKVxuICAudHJhbnNmb3JtKCh2YWx1ZSkgPT4gdmFsdWUudHJpbSgpKVxuICAucGlwZSh6LnN0cmluZygpLm1pbigxKSk7XG5cbmNvbnN0IGJ1bmRsZUFwcEVudkVudHJ5U2NoZW1hID0gei5vYmplY3Qoe1xuICBuYW1lOiBub3JtYWxpemVkU3RyaW5nLm9wdGlvbmFsKCksXG4gIHZhbHVlOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIHZhbHVlX2Zyb206IG5vcm1hbGl6ZWRTdHJpbmcub3B0aW9uYWwoKSxcbn0pO1xuXG5jb25zdCBidW5kbGVBcHBSZXNvdXJjZVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgbmFtZTogbm9ybWFsaXplZFN0cmluZy5vcHRpb25hbCgpLFxuICBzcWxfd2FyZWhvdXNlOiB6Lm9iamVjdCh7IGlkOiBub3JtYWxpemVkU3RyaW5nLm9wdGlvbmFsKCkgfSkub3B0aW9uYWwoKSxcbiAgZ2VuaWVfc3BhY2U6IHoub2JqZWN0KHsgc3BhY2VfaWQ6IG5vcm1hbGl6ZWRTdHJpbmcub3B0aW9uYWwoKSB9KS5vcHRpb25hbCgpLFxuICBwb3N0Z3JlczogelxuICAgIC5vYmplY3Qoe1xuICAgICAgZGF0YWJhc2U6IG5vcm1hbGl6ZWRTdHJpbmcub3B0aW9uYWwoKSxcbiAgICAgIGJyYW5jaDogbm9ybWFsaXplZFN0cmluZy5vcHRpb25hbCgpLFxuICAgICAgZW5kcG9pbnQ6IG5vcm1hbGl6ZWRTdHJpbmcub3B0aW9uYWwoKSxcbiAgICB9KVxuICAgIC5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IGJ1bmRsZUFwcFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgbmFtZTogbm9ybWFsaXplZFN0cmluZy5vcHRpb25hbCgpLFxuICBzb3VyY2VfY29kZV9wYXRoOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIGNvbmZpZzogei5vYmplY3QoeyBlbnY6IHouYXJyYXkoYnVuZGxlQXBwRW52RW50cnlTY2hlbWEpLm9wdGlvbmFsKCkgfSkub3B0aW9uYWwoKSxcbiAgcmVzb3VyY2VzOiB6LmFycmF5KGJ1bmRsZUFwcFJlc291cmNlU2NoZW1hKS5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IGJ1bmRsZVZhbGlkYXRlQXBwc1NjaGVtYSA9IHoub2JqZWN0KHtcbiAgcmVzb3VyY2VzOiB6Lm9iamVjdCh7IGFwcHM6IHoucmVjb3JkKHouc3RyaW5nKCksIGJ1bmRsZUFwcFNjaGVtYSkub3B0aW9uYWwoKSB9KS5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IGFwcFlhbWxFbnZFbnRyeVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgbmFtZTogbm9ybWFsaXplZFN0cmluZyxcbiAgdmFsdWU6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgdmFsdWVGcm9tOiBub3JtYWxpemVkU3RyaW5nLm9wdGlvbmFsKCksXG59KTtcblxuY29uc3QgYXBwWWFtbFJlc291cmNlU2NoZW1hID0gelxuICAub2JqZWN0KHtcbiAgICBuYW1lOiBub3JtYWxpemVkU3RyaW5nLFxuICAgIHNxbF93YXJlaG91c2U6IHoub2JqZWN0KHsgaWQ6IG5vcm1hbGl6ZWRTdHJpbmcub3B0aW9uYWwoKSB9KS5vcHRpb25hbCgpLFxuICAgIGdlbmllX3NwYWNlOiB6Lm9iamVjdCh7IHNwYWNlX2lkOiBub3JtYWxpemVkU3RyaW5nLm9wdGlvbmFsKCkgfSkub3B0aW9uYWwoKSxcbiAgICBwb3N0Z3JlczogelxuICAgICAgLm9iamVjdCh7XG4gICAgICAgIGRhdGFiYXNlOiBub3JtYWxpemVkU3RyaW5nLm9wdGlvbmFsKCksXG4gICAgICAgIGJyYW5jaDogbm9ybWFsaXplZFN0cmluZy5vcHRpb25hbCgpLFxuICAgICAgICBlbmRwb2ludDogbm9ybWFsaXplZFN0cmluZy5vcHRpb25hbCgpLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb25hbCgpLFxuICB9KVxuICAucGFzc3Rocm91Z2goKTtcblxuY29uc3QgYXBwWWFtbFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgZW52OiB6LmFycmF5KGFwcFlhbWxFbnZFbnRyeVNjaGVtYSkub3B0aW9uYWwoKSxcbiAgcmVzb3VyY2VzOiB6LmFycmF5KGFwcFlhbWxSZXNvdXJjZVNjaGVtYSkub3B0aW9uYWwoKSxcbn0pO1xuXG50eXBlIEJ1bmRsZUFwcCA9IHouaW5mZXI8dHlwZW9mIGJ1bmRsZUFwcFNjaGVtYT47XG5cbi8qKiBTaW5nbGUgY29uZmlnIG1hcCBlbnRyeSAoc3RyaW5nIG9yIHJlcGVhdGVkIHZhbHVlcywgbGlrZSBoZWFkZXJzKS4gKi9cbmV4cG9ydCB0eXBlIENvbmZpZ01hcFZhbHVlID0gc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb2x2ZUNvbmZpZ1ZhbHVlT3B0aW9ucyB7XG4gIC8qKiBCdW5kbGUgdmFsaWRhdGUgSlNPTi4gRGVmYXVsdHMgdG8ge0BsaW5rIGJ1bmRsZX0gKHNraXBwZWQgaW5zaWRlIGEgRGF0YWJyaWNrcyBBcHApLiAqL1xuICBidW5kbGVEYXRhPzogQ29uZmlnRmlsZTtcbiAgLyoqIFBhcnNlZCBgYXBwLnlhbWxgIGNvbnRlbnRzLiBEZWZhdWx0cyB0byB7QGxpbmsgYXBwWWFtbH0gKHNraXBwZWQgaW5zaWRlIGEgRGF0YWJyaWNrcyBBcHApLiAqL1xuICBhcHBEYXRhPzogQ29uZmlnRmlsZTtcbiAgLyoqXG4gICAqIFNvdXJjZXMgdG8gY29uc3VsdCwgZmlyc3QgdHJ1dGh5IHN0cmluZyB3aW5zLiBEZWZhdWx0cyB0byBgZXhwbGljaXRgLCB0aGVuXG4gICAqIGBlbnZgLCB0aGVuIGBidW5kbGVgLlxuICAgKi9cbiAgc291cmNlcz86IENvbmZpZ1NvdXJjZVtdO1xuICAvKiogUHJvZ3JhbW1hdGljIG92ZXJyaWRlcy4gV2hlbiBzZXQsIGBleHBsaWNpdGAgaXMgcHJlcGVuZGVkIHRvIGBzb3VyY2VzYCB1bmxlc3MgYWxyZWFkeSBsaXN0ZWQuICovXG4gIGV4cGxpY2l0PzogUmVjb3JkPHN0cmluZywgQ29uZmlnTWFwVmFsdWU+O1xuICAvKiogQ0xJIGZsYWcgdmFsdWVzICh3aGVuIGBjbGlgIGlzIGxpc3RlZCBpbiBgc291cmNlc2ApLiAqL1xuICBjbGk/OiBSZWNvcmQ8c3RyaW5nLCBDb25maWdNYXBWYWx1ZT47XG59XG5cbmNvbnN0IGJ1bmRsZURlZmF1bHQgPSBmdW5jdGlvbk1vZHVsZS5tZW1vaXplKCgpID0+IGxvYWRCdW5kbGUocHJvY2Vzcy5jd2QoKSkpO1xuY29uc3QgYXBwWWFtbERlZmF1bHQgPSBmdW5jdGlvbk1vZHVsZS5tZW1vaXplKCgpID0+IGxvYWRBcHBZYW1sKHByb2Nlc3MuY3dkKCkpKTtcblxuZnVuY3Rpb24gZW52S2V5c0Zvck5hbWUobmFtZTogc3RyaW5nKTogb2JqZWN0LlNlcXVlbmNlPHN0cmluZz4ge1xuICBjb25zdCB0cmltbWVkID0gbmFtZS50cmltKCk7XG4gIGlmICghdHJpbW1lZCkge1xuICAgIHJldHVybiBvYmplY3Quc2VxdWVuY2UoKTtcbiAgfVxuICBjb25zdCBrZXlzID0gKGZ1bmN0aW9uKiAoKSB7XG4gICAgY29uc3QgbW9kaWZpZXJzOiAoKCh2YWx1ZTogc3RyaW5nKSA9PiBzdHJpbmcpIHwgbnVsbClbXSA9IFtcbiAgICAgIG51bGwsXG4gICAgICAoKSA9PiB0cmltbWVkLnRvVXBwZXJDYXNlKCksXG4gICAgICAoKSA9PiBBcnJheS5mcm9tKHN0cmluZy50b2tlbml6ZSh0cmltbWVkKSkuam9pbihcIl9cIikudG9VcHBlckNhc2UoKSxcbiAgICBdO1xuICAgIGZvciAoY29uc3QgbW9kaWZpZXIgb2YgbW9kaWZpZXJzKSB7XG4gICAgICB5aWVsZCBtb2RpZmllciA/IG1vZGlmaWVyKHRyaW1tZWQpIDogdHJpbW1lZDtcbiAgICB9XG4gIH0pKCk7XG4gIHJldHVybiBvYmplY3Quc2VxdWVuY2Uoa2V5cykuY2FjaGUoKS5maWx0ZXIoQm9vbGVhbikuZGlzdGluY3QoKTtcbn1cblxuZnVuY3Rpb24gcmVhZEVudihrZXlzOiBJdGVyYWJsZTxzdHJpbmc+KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgIGNvbnN0IHZhbHVlID0gcHJvY2Vzcy5lbnZba2V5XT8udHJpbSgpO1xuICAgIGlmICh2YWx1ZSkgcmV0dXJuIHZhbHVlO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHJlYWRDb25maWdNYXBWYWx1ZSh2YWx1ZTogQ29uZmlnTWFwVmFsdWUpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAodmFsdWUgPT0gbnVsbCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgZm9yIChjb25zdCBpdGVtIG9mIHZhbHVlKSB7XG4gICAgICBjb25zdCB0cmltbWVkID0gaXRlbT8udHJpbSgpO1xuICAgICAgaWYgKHRyaW1tZWQpIHJldHVybiB0cmltbWVkO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIGNvbnN0IHRyaW1tZWQgPSB2YWx1ZS50cmltKCk7XG4gIHJldHVybiB0cmltbWVkIHx8IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gcmVhZE1hcChcbiAga2V5czogSXRlcmFibGU8c3RyaW5nPixcbiAgbWFwOiBSZWNvcmQ8c3RyaW5nLCBDb25maWdNYXBWYWx1ZT4gfCB1bmRlZmluZWQsXG4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoIW1hcCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgIGNvbnN0IHZhbHVlID0gcmVhZENvbmZpZ01hcFZhbHVlKG1hcFtrZXldKTtcbiAgICBpZiAodmFsdWUpIHJldHVybiB2YWx1ZTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiByZWFkQXBwRW52KGtleXM6IEl0ZXJhYmxlPHN0cmluZz4sIGVudk1hcDogUmVjb3JkPHN0cmluZywgc3RyaW5nPik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcbiAgICBjb25zdCB2YWx1ZSA9IGVudk1hcFtrZXldPy50cmltKCk7XG4gICAgaWYgKHZhbHVlKSByZXR1cm4gdmFsdWU7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gcGFyc2VZYW1sKHRleHQ6IHN0cmluZyk6IHVua25vd24ge1xuICByZXR1cm4gcGFyc2VZYW1sVGV4dCh0ZXh0KTtcbn1cblxuZnVuY3Rpb24gcGlja0FwcFJlc291cmNlSWQoYXBwczogUmVjb3JkPHN0cmluZywgQnVuZGxlQXBwPik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhhcHBzKTtcbiAgcmV0dXJuIGtleXMubGVuZ3RoID09PSAxID8ga2V5c1swXSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBlZmZlY3RpdmUgdmFsdWUgYSBgdmFsdWVfZnJvbWAvYHZhbHVlRnJvbWAgZW50cnkgcG9pbnRzIGF0OlxuICogdGhlIGZpcnN0IHByZXNlbnQgb2YgdGhlIHdhcmVob3VzZSBpZCwgR2VuaWUgc3BhY2UgaWQsIG9yIFBvc3RncmVzXG4gKiBlbmRwb2ludC9kYXRhYmFzZS9icmFuY2ggb24gdGhlIG5hbWVkIHJlc291cmNlLiBTaGFyZWQgYnkgYm90aCB0aGVcbiAqIGBhcHAueWFtbGAgYW5kIGBidW5kbGUgdmFsaWRhdGVgIGZsYXR0ZW5lcnMsIHdob3NlIHJlc291cmNlIHNoYXBlcyBtYXRjaC5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVJlc291cmNlVmFsdWUoXG4gIHJlc291cmNlOiB6LmluZmVyPHR5cGVvZiBidW5kbGVBcHBSZXNvdXJjZVNjaGVtYT4gfCB1bmRlZmluZWQsXG4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gKFxuICAgIHJlc291cmNlPy5zcWxfd2FyZWhvdXNlPy5pZCA/P1xuICAgIHJlc291cmNlPy5nZW5pZV9zcGFjZT8uc3BhY2VfaWQgPz9cbiAgICByZXNvdXJjZT8ucG9zdGdyZXM/LmVuZHBvaW50ID8/XG4gICAgcmVzb3VyY2U/LnBvc3RncmVzPy5kYXRhYmFzZSA/P1xuICAgIHJlc291cmNlPy5wb3N0Z3Jlcz8uYnJhbmNoXG4gICk7XG59XG5cbi8qKlxuICogRmxhdHRlbiBgZW52YCBlbnRyaWVzIGZyb20gcGFyc2VkIGBhcHAueWFtbGAgY29udGVudC4gTGl0ZXJhbCBgdmFsdWVgIGVudHJpZXNcbiAqIGFyZSByZXR1cm5lZCBhcy1pczsgYHZhbHVlRnJvbWAgZW50cmllcyByZXNvbHZlIGFnYWluc3QgdGhlIHNpYmxpbmdcbiAqIGByZXNvdXJjZXNgIGFycmF5IHdoZW4gcG9zc2libGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0dGVuQXBwWWFtbEVudihkYXRhOiB1bmtub3duKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IHBhcnNlZCA9IGFwcFlhbWxTY2hlbWEuc2FmZVBhcnNlKGRhdGEpO1xuICBpZiAoIXBhcnNlZC5zdWNjZXNzIHx8ICFwYXJzZWQuZGF0YS5lbnY/Lmxlbmd0aCkge1xuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIGNvbnN0IHJlc291cmNlQnlOYW1lID0gbmV3IE1hcChcbiAgICAocGFyc2VkLmRhdGEucmVzb3VyY2VzID8/IFtdKS5tYXAoKHJlc291cmNlKSA9PiBbcmVzb3VyY2UubmFtZSwgcmVzb3VyY2VdKSxcbiAgKTtcblxuICBjb25zdCBvdXQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgZm9yIChjb25zdCBlbnRyeSBvZiBwYXJzZWQuZGF0YS5lbnYpIHtcbiAgICBpZiAoZW50cnkudmFsdWU/LnRyaW0oKSkge1xuICAgICAgb3V0W2VudHJ5Lm5hbWVdID0gZW50cnkudmFsdWUudHJpbSgpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmICghZW50cnkudmFsdWVGcm9tKSBjb250aW51ZTtcbiAgICBjb25zdCByZXNvbHZlZCA9IHJlc29sdmVSZXNvdXJjZVZhbHVlKHJlc291cmNlQnlOYW1lLmdldChlbnRyeS52YWx1ZUZyb20pKTtcbiAgICBpZiAocmVzb2x2ZWQpIG91dFtlbnRyeS5uYW1lXSA9IHJlc29sdmVkO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKlxuICogRmxhdHRlbiBgcmVzb3VyY2VzLmFwcHMuPGtleT4uY29uZmlnLmVudmAgaW50byBhIGBuYW1lIC0+IHZhbHVlYCBtYXAuXG4gKiBBdXRvLXBpY2tzIHRoZSBhcHAgb25seSB3aGVuIHRoZSBidW5kbGUgZGVmaW5lcyBleGFjdGx5IG9uZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsYXR0ZW5BcHBFbnYoZGF0YTogdW5rbm93bik6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCBwYXJzZWQgPSBidW5kbGVWYWxpZGF0ZUFwcHNTY2hlbWEuc2FmZVBhcnNlKGRhdGEpO1xuICBpZiAoIXBhcnNlZC5zdWNjZXNzKSByZXR1cm4ge307XG5cbiAgY29uc3QgYXBwcyA9IHBhcnNlZC5kYXRhLnJlc291cmNlcz8uYXBwcztcbiAgaWYgKCFhcHBzIHx8IE9iamVjdC5rZXlzKGFwcHMpLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHt9O1xuXG4gIGNvbnN0IGtleSA9IHBpY2tBcHBSZXNvdXJjZUlkKGFwcHMpO1xuICBpZiAoIWtleSkgcmV0dXJuIHt9O1xuXG4gIGNvbnN0IGFwcCA9IGFwcHNba2V5XTtcbiAgaWYgKCFhcHA/LmNvbmZpZz8uZW52Py5sZW5ndGgpIHJldHVybiB7fTtcblxuICBjb25zdCByZXNvdXJjZUJ5TmFtZSA9IG5ldyBNYXAoXG4gICAgKGFwcC5yZXNvdXJjZXMgPz8gW10pXG4gICAgICAuZmlsdGVyKChyZXNvdXJjZSkgPT4gcmVzb3VyY2UubmFtZSlcbiAgICAgIC5tYXAoKHJlc291cmNlKSA9PiBbcmVzb3VyY2UubmFtZSEsIHJlc291cmNlXSksXG4gICk7XG5cbiAgY29uc3Qgb3V0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gIGZvciAoY29uc3QgZW50cnkgb2YgYXBwLmNvbmZpZy5lbnYpIHtcbiAgICBpZiAoIWVudHJ5Lm5hbWUpIGNvbnRpbnVlO1xuICAgIGlmIChlbnRyeS52YWx1ZSkge1xuICAgICAgb3V0W2VudHJ5Lm5hbWVdID0gZW50cnkudmFsdWU7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKCFlbnRyeS52YWx1ZV9mcm9tKSBjb250aW51ZTtcbiAgICBjb25zdCByZXNvbHZlZCA9IHJlc29sdmVSZXNvdXJjZVZhbHVlKHJlc291cmNlQnlOYW1lLmdldChlbnRyeS52YWx1ZV9mcm9tKSk7XG4gICAgaWYgKHJlc29sdmVkKSBvdXRbZW50cnkubmFtZV0gPSByZXNvbHZlZDtcbiAgfVxuICByZXR1cm4gb3V0O1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUJ1bmRsZShyb290OiBzdHJpbmcpOiBCdW5kbGVWYWxpZGF0ZUpzb24gfCB1bmRlZmluZWQge1xuICBjb25zdCBrZXkgPSByb290O1xuICBpZiAoYnVuZGxlVmFsaWRhdGVDYWNoZS5oYXMoa2V5KSkge1xuICAgIHJldHVybiBidW5kbGVWYWxpZGF0ZUNhY2hlLmdldChrZXkpO1xuICB9XG5cbiAgY29uc3QgYXJncyA9IFtcImJ1bmRsZVwiLCBcInZhbGlkYXRlXCIsIFwiLS1vdXRwdXRcIiwgXCJqc29uXCJdO1xuICB0cnkge1xuICAgIGNvbnN0IHByb2MgPSBzcGF3blN5bmMoXCJkYXRhYnJpY2tzXCIsIGFyZ3MsIHtcbiAgICAgIGN3ZDogcm9vdCxcbiAgICAgIGVuY29kaW5nOiBcInV0ZjhcIixcbiAgICAgIHN0ZGlvOiBbXCJpZ25vcmVcIiwgXCJwaXBlXCIsIFwicGlwZVwiXSxcbiAgICB9KTtcbiAgICBjb25zdCB0ZXh0ID0gcHJvYy5zdGRvdXQ/LnRyaW0oKTtcbiAgICBpZiAoIXRleHQpIHtcbiAgICAgIGJ1bmRsZVZhbGlkYXRlQ2FjaGUuc2V0KGtleSwgdW5kZWZpbmVkKTtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGNvbnN0IGRhdGEgPSBqc29uLnBhcnNlPEJ1bmRsZVZhbGlkYXRlSnNvbj4odGV4dCk7XG4gICAgYnVuZGxlVmFsaWRhdGVDYWNoZS5zZXQoa2V5LCBkYXRhKTtcbiAgICByZXR1cm4gZGF0YTtcbiAgfSBjYXRjaCB7XG4gICAgYnVuZGxlVmFsaWRhdGVDYWNoZS5zZXQoa2V5LCB1bmRlZmluZWQpO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9hZEJ1bmRsZShjd2Q6IHN0cmluZyk6IFByb21pc2U8Q29uZmlnRmlsZSB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCBjb25maWdGaWxlID0gcmVzb2x2ZUNvbmZpZ0ZpbGUoY3dkLCBcImRhdGFicmlja3MueW1sXCIpO1xuICBpZiAoY29uZmlnRmlsZSkge1xuICAgIGNvbnN0IGRhdGEgPSB2YWxpZGF0ZUJ1bmRsZShkaXJuYW1lKGNvbmZpZ0ZpbGUpKTtcbiAgICBpZiAoZGF0YSkgcmV0dXJuIHsgcGF0aDogY29uZmlnRmlsZSwgZGF0YSB9O1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGxvYWRBcHBZYW1sKGN3ZDogc3RyaW5nKTogUHJvbWlzZTxDb25maWdGaWxlIHwgdW5kZWZpbmVkPiB7XG4gIGZvciAoY29uc3QgZmlsZU5hbWUgb2YgQVBQX1lBTUxfTkFNRVMpIHtcbiAgICBjb25zdCBjb25maWdGaWxlID0gcmVzb2x2ZUNvbmZpZ0ZpbGUoY3dkLCBmaWxlTmFtZSk7XG4gICAgaWYgKCFjb25maWdGaWxlKSBjb250aW51ZTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdGV4dCA9IGF3YWl0IHJlYWRGaWxlKGNvbmZpZ0ZpbGUsIFwidXRmOFwiKTtcbiAgICAgIGNvbnN0IGRhdGEgPSBwYXJzZVlhbWwodGV4dCk7XG4gICAgICBpZiAoIW9iamVjdC5pc1JlY29yZChkYXRhKSkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHsgcGF0aDogY29uZmlnRmlsZSwgZGF0YSB9O1xuICAgIH0gY2F0Y2gge1xuICAgICAgbG9nZ2VyLndhcm4oXCJmYWlsZWQgdG8gcGFyc2UgYXBwIHlhbWxcIiwgeyBwYXRoOiBjb25maWdGaWxlIH0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ29uZmlnRmlsZShjd2Q6IHN0cmluZywgY29uZmlnRmlsZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKGlzQXBwRW52KCkpIHJldHVybiB1bmRlZmluZWQ7XG4gIGZvciAoY29uc3Qgcm9vdERpciBvZiBwcm9qZWN0LnJlc29sdmVQcm9qZWN0Um9vdHMoY3dkKSkge1xuICAgIGNvbnN0IGJ1bmRsZVBhdGggPSByZXNvbHZlKHJvb3REaXIsIGNvbmZpZ0ZpbGUpO1xuICAgIGlmIChmaWxlLnN0YXRTeW5jKGJ1bmRsZVBhdGgpPy5pc0ZpbGUoKSkgcmV0dXJuIGJ1bmRsZVBhdGg7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBMb2NhdGUgdGhlIGJ1bmRsZSByb290IGFuZCBydW4gYGRhdGFicmlja3MgYnVuZGxlIHZhbGlkYXRlIC0tb3V0cHV0IGpzb25gLlxuICogV2hlbiBgY3dkYCBpcyBvbWl0dGVkIG9yIGVxdWFscyBgcHJvY2Vzcy5jd2QoKWAsIHRoZSByZXN1bHQgaXMgbWVtb2l6ZWQgZm9yXG4gKiB0aGUgcHJvY2VzcyBsaWZldGltZS4gUmV0dXJucyBgdW5kZWZpbmVkYCBpbnNpZGUgYSBEYXRhYnJpY2tzIEFwcC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1bmRsZShjd2Q/OiBzdHJpbmcpOiBQcm9taXNlPENvbmZpZ0ZpbGUgfCB1bmRlZmluZWQ+IHtcbiAgaWYgKGlzQXBwRW52KCkpIHJldHVybiBQcm9taXNlLnJlc29sdmUodW5kZWZpbmVkKTtcbiAgcmV0dXJuIGN3ZCAmJiByZXNvbHZlKGN3ZCkgIT09IHByb2Nlc3MuY3dkKCkgPyBsb2FkQnVuZGxlKGN3ZCkgOiBidW5kbGVEZWZhdWx0KCk7XG59XG5cbi8qKlxuICogTG9jYXRlIGFuZCBwYXJzZSBgYXBwLnlhbWxgIC8gYGFwcC55bWxgIGZyb20gdGhlIGJ1bmRsZSBvciBwcm9qZWN0IHJvb3QuIFdoZW5cbiAqIGBjd2RgIGlzIG9taXR0ZWQgb3IgZXF1YWxzIGBwcm9jZXNzLmN3ZCgpYCwgdGhlIHJlc3VsdCBpcyBtZW1vaXplZCBmb3IgdGhlXG4gKiBwcm9jZXNzIGxpZmV0aW1lLiBSZXR1cm5zIGB1bmRlZmluZWRgIGluc2lkZSBhIERhdGFicmlja3MgQXBwLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwWWFtbChjd2Q/OiBzdHJpbmcpOiBQcm9taXNlPENvbmZpZ0ZpbGUgfCB1bmRlZmluZWQ+IHtcbiAgaWYgKGlzQXBwRW52KCkpIHJldHVybiBQcm9taXNlLnJlc29sdmUodW5kZWZpbmVkKTtcbiAgcmV0dXJuIGN3ZCAmJiByZXNvbHZlKGN3ZCkgIT09IHByb2Nlc3MuY3dkKCkgPyBsb2FkQXBwWWFtbChjd2QpIDogYXBwWWFtbERlZmF1bHQoKTtcbn1cblxuLyoqXG4gKiBXYWxrIGEgZG90LXNlcGFyYXRlZCBwYXRoIHRocm91Z2ggYnVuZGxlIHZhbGlkYXRlIEpTT04uIFdoZW4gdGhlIHRlcm1pbmFsXG4gKiBub2RlIGlzIGEgYnVuZGxlIHZhcmlhYmxlIG9iamVjdCAoYHsgdmFsdWU6IFwiLi4uXCIgfWApLCB0aGUgYHZhbHVlYCBmaWVsZCBpc1xuICogcmV0dXJuZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRCdW5kbGVQYXRoKGRhdGE6IEJ1bmRsZVZhbGlkYXRlSnNvbiwgcGF0aDogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcGFydHMgPSBwYXRoLnNwbGl0KFwiLlwiKS5maWx0ZXIoQm9vbGVhbik7XG4gIGlmIChwYXJ0cy5sZW5ndGggPT09IDApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgbGV0IGN1cnJlbnQ6IHVua25vd24gPSBkYXRhO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFvYmplY3QuaXNSZWNvcmQoY3VycmVudCkpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgY29uc3QgcGFydCA9IHBhcnRzW2ldITtcbiAgICBjb25zdCBuZXh0ID0gY3VycmVudFtwYXJ0XTtcbiAgICBpZiAoaSA9PT0gcGFydHMubGVuZ3RoIC0gMSkge1xuICAgICAgaWYgKHR5cGVvZiBuZXh0ID09PSBcInN0cmluZ1wiICYmIG5leHQpIHJldHVybiBuZXh0O1xuICAgICAgaWYgKG9iamVjdC5pc1JlY29yZChuZXh0KSkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IG5leHQudmFsdWU7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiYgdmFsdWUgPyB2YWx1ZSA6IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGN1cnJlbnQgPSBuZXh0O1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVBcHBFbnZNYXAoXG4gIG9wdGlvbnM6IFJlc29sdmVDb25maWdWYWx1ZU9wdGlvbnMsXG4pOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+IHtcbiAgY29uc3QgYXBwRGF0YSA9IG9wdGlvbnMuYXBwRGF0YSA/PyAoYXdhaXQgYXBwWWFtbCgpKTtcbiAgY29uc3QgYnVuZGxlRGF0YSA9IG9wdGlvbnMuYnVuZGxlRGF0YSA/PyAoYXdhaXQgYnVuZGxlKCkpO1xuICBjb25zdCBmcm9tWWFtbCA9IGFwcERhdGEgPyBmbGF0dGVuQXBwWWFtbEVudihhcHBEYXRhLmRhdGEpIDoge307XG4gIGNvbnN0IGZyb21CdW5kbGUgPSBidW5kbGVEYXRhID8gZmxhdHRlbkFwcEVudihidW5kbGVEYXRhLmRhdGEpIDoge307XG4gIHJldHVybiB7IC4uLmZyb21ZYW1sLCAuLi5mcm9tQnVuZGxlIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTb3VyY2VzKG9wdGlvbnM6IFJlc29sdmVDb25maWdWYWx1ZU9wdGlvbnMpOiBDb25maWdTb3VyY2VbXSB7XG4gIGNvbnN0IHNvdXJjZXMgPSBbLi4uKG9wdGlvbnMuc291cmNlcyA/PyBkZWZhdWx0Q29uZmlnU291cmNlcyldO1xuICBpZiAob3B0aW9ucy5leHBsaWNpdCAhPT0gdW5kZWZpbmVkICYmICFzb3VyY2VzLmluY2x1ZGVzKFwiZXhwbGljaXRcIikpIHtcbiAgICBzb3VyY2VzLnVuc2hpZnQoXCJleHBsaWNpdFwiKTtcbiAgfVxuICByZXR1cm4gc291cmNlcztcbn1cblxuLyoqXG4gKiBSZXNvbHZlIGEgY29uZmlndXJhdGlvbiBzdHJpbmcgZnJvbSB0aGUgY29uZmlndXJlZCBzb3VyY2VzLiBSZXR1cm5zIHRoZSBmaXJzdFxuICogbm9uLWVtcHR5IHZhbHVlLCBvciBgdW5kZWZpbmVkYCB3aGVuIG5vdGhpbmcgbWF0Y2hlcy5cbiAqXG4gKiBQcmVjZWRlbmNlIGZvbGxvd3MgQXBwS2l0J3M6IGV4cGxpY2l0IGNvbmZpZywgdGhlbiBlbnZpcm9ubWVudCB2YXJpYWJsZSwgdGhlblxuICogd2hhdGV2ZXIgdGhlIERhdGFicmlja3MgQXBwIC8gYnVuZGxlIGRlZmluaXRpb24gc3VwcGxpZXMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCB7IGNvbmZpZyB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuICpcbiAqIGNvbnN0IHdhcmVob3VzZUlkID0gYXdhaXQgY29uZmlnLnJlc29sdmVDb25maWdWYWx1ZShcIkRBVEFCUklDS1NfV0FSRUhPVVNFX0lEXCIsIHtcbiAqICAgY2xpOiB7IERBVEFCUklDS1NfV0FSRUhPVVNFX0lEOiBmbGFncy53YXJlaG91c2UgfSxcbiAqICAgc291cmNlczogY29uZmlnLndpdGhDbGlTb3VyY2VzKCksXG4gKiB9KTtcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc29sdmVDb25maWdWYWx1ZShcbiAgbmFtZTogc3RyaW5nLFxuICBvcHRpb25zOiBSZXNvbHZlQ29uZmlnVmFsdWVPcHRpb25zID0ge30sXG4pOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCBrZXlzID0gZW52S2V5c0Zvck5hbWUobmFtZSkudG9BcnJheSgpO1xuICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IHNvdXJjZXMgPSByZXNvbHZlU291cmNlcyhvcHRpb25zKTtcbiAgbGV0IGFwcEVudk1hcDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IHVuZGVmaW5lZDtcbiAgY29uc3QgdmFsdWVzID0gKGFzeW5jIGZ1bmN0aW9uKiAoKSB7XG4gICAgZm9yIChjb25zdCBzb3VyY2Ugb2Ygc291cmNlcykge1xuICAgICAgc3dpdGNoIChzb3VyY2UpIHtcbiAgICAgICAgY2FzZSBcImV4cGxpY2l0XCI6XG4gICAgICAgICAgeWllbGQgcmVhZE1hcChrZXlzLCBvcHRpb25zLmV4cGxpY2l0KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcImNsaVwiOlxuICAgICAgICAgIHlpZWxkIHJlYWRNYXAoa2V5cywgb3B0aW9ucy5jbGkpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiZW52XCI6XG4gICAgICAgICAgeWllbGQgcmVhZEVudihrZXlzKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcImJ1bmRsZVwiOlxuICAgICAgICAgIGlmIChhcHBFbnZNYXAgPT09IHVuZGVmaW5lZCkgYXBwRW52TWFwID0gYXdhaXQgcmVzb2x2ZUFwcEVudk1hcChvcHRpb25zKTtcbiAgICAgICAgICB5aWVsZCByZWFkQXBwRW52KGtleXMsIGFwcEVudk1hcCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgVmFsaWRhdGlvbkVycm9yLmludmFsaWRWYWx1ZShcbiAgICAgICAgICAgIFwic291cmNlc1wiLFxuICAgICAgICAgICAgc291cmNlLFxuICAgICAgICAgICAgXCJvbmUgb2Y6IGV4cGxpY2l0LCBjbGksIGVudiwgYnVuZGxlXCIsXG4gICAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pKCk7XG4gIGZvciBhd2FpdCAoY29uc3QgdmFsdWUgb2YgdmFsdWVzKSB7XG4gICAgaWYgKHZhbHVlKSByZXR1cm4gdmFsdWU7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBTb3VyY2VzIHdpdGggYGNsaWAgaW5jbHVkZWQsIGluIENMSS1maXJzdCBvcmRlci4gVXNlIGZvciBkZXYgY29tbWFuZHMgdGhhdFxuICogYWNjZXB0IGZsYWcgb3ZlcnJpZGVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gd2l0aENsaVNvdXJjZXMoc291cmNlczogQ29uZmlnU291cmNlW10gPSBkZWZhdWx0Q29uZmlnU291cmNlcyk6IENvbmZpZ1NvdXJjZVtdIHtcbiAgY29uc3QgcmVzdCA9IHNvdXJjZXMuZmlsdGVyKChzb3VyY2UpID0+IHNvdXJjZSAhPT0gXCJjbGlcIiAmJiBzb3VyY2UgIT09IFwiZXhwbGljaXRcIik7XG4gIHJldHVybiBbXCJjbGlcIiwgXCJleHBsaWNpdFwiLCAuLi5yZXN0XTtcbn1cbiJdfQ==
|