@dbx-tools/appkit 0.6.81 → 0.6.85

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/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==