@dbx-tools/appkit 0.6.89 → 0.6.90
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 +15 -16
- package/index.ts +0 -3
- package/lib/index.d.ts +0 -3
- package/lib/index.js +1 -3
- package/lib/src/lakebase-resolver.d.ts +2 -2
- package/lib/src/lakebase-resolver.js +8 -9
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -5
- package/src/lakebase-resolver.ts +7 -8
- package/lib/src/bundle.d.ts +0 -114
- package/lib/src/bundle.js +0 -359
- package/src/bundle.ts +0 -422
package/lib/src/bundle.d.ts
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DATABRICKS-APP configuration resolution: the bundle and `app.yaml` vocabulary.
|
|
3
|
-
*
|
|
4
|
-
* node-core's `config` module owns the generic lookup - environment, `.env`,
|
|
5
|
-
* `databricks bundle validate` - and knows nothing about what a bundle resource
|
|
6
|
-
* IS. That last part is this module: `sql_warehouse`, `genie_space`, and
|
|
7
|
-
* `postgres` are Databricks-App concepts, and an `app.yaml` / bundle
|
|
8
|
-
* `value_from` entry is a REFERENCE to one of them whose real value is the
|
|
9
|
-
* warehouse id or Genie space id sitting on the named resource. So this module
|
|
10
|
-
* extends node-core's resource schema, adds `app.yaml` (which the bundle CLI
|
|
11
|
-
* never sees), and resolves those references.
|
|
12
|
-
*
|
|
13
|
-
* Default sources: `explicit`, then `env`, then Databricks App `config.env`
|
|
14
|
-
* (from {@link bundle}) and hard-coded `app.yaml` env entries (from
|
|
15
|
-
* {@link appYaml}). Opt in to `cli` when a dev command wants flag overrides.
|
|
16
|
-
*
|
|
17
|
-
* Server-only, and Databricks-app specific, so it lives in node-appkit rather
|
|
18
|
-
* than node-core.
|
|
19
|
-
*
|
|
20
|
-
* @module
|
|
21
|
-
*/
|
|
22
|
-
import { z } from "zod";
|
|
23
|
-
/** Parsed payload from `databricks bundle validate --output json`. */
|
|
24
|
-
export type BundleValidateJson = Record<string, unknown>;
|
|
25
|
-
/** A config file discovered on disk with its parsed contents. */
|
|
26
|
-
export interface ConfigFile {
|
|
27
|
-
path: string;
|
|
28
|
-
data: Record<string, unknown>;
|
|
29
|
-
}
|
|
30
|
-
/** Supported configuration sources, consulted in array order. */
|
|
31
|
-
export type ConfigSource = "explicit" | "cli" | "env" | "bundle";
|
|
32
|
-
export declare const bundleAppResourceSchema: z.ZodObject<{
|
|
33
|
-
name: z.ZodOptional<z.ZodString>;
|
|
34
|
-
sql_warehouse: z.ZodOptional<z.ZodObject<{
|
|
35
|
-
id: z.ZodOptional<z.ZodString>;
|
|
36
|
-
}, z.core.$strip>>;
|
|
37
|
-
genie_space: z.ZodOptional<z.ZodObject<{
|
|
38
|
-
space_id: z.ZodOptional<z.ZodString>;
|
|
39
|
-
}, z.core.$strip>>;
|
|
40
|
-
postgres: z.ZodOptional<z.ZodObject<{
|
|
41
|
-
database: z.ZodOptional<z.ZodString>;
|
|
42
|
-
branch: z.ZodOptional<z.ZodString>;
|
|
43
|
-
endpoint: z.ZodOptional<z.ZodString>;
|
|
44
|
-
}, z.core.$strip>>;
|
|
45
|
-
}, z.core.$loose>;
|
|
46
|
-
/** Single config map entry (string or repeated values, like headers). */
|
|
47
|
-
export type ConfigMapValue = string | string[] | undefined;
|
|
48
|
-
export interface ResolveConfigValueOptions {
|
|
49
|
-
/** Bundle validate JSON. Defaults to {@link bundle} (skipped inside a Databricks App). */
|
|
50
|
-
bundleData?: ConfigFile;
|
|
51
|
-
/** Parsed `app.yaml` contents. Defaults to {@link appYaml} (skipped inside a Databricks App). */
|
|
52
|
-
appData?: ConfigFile;
|
|
53
|
-
/**
|
|
54
|
-
* Sources to consult, first truthy string wins. Defaults to `explicit`, then
|
|
55
|
-
* `env`, then `bundle`.
|
|
56
|
-
*/
|
|
57
|
-
sources?: ConfigSource[];
|
|
58
|
-
/** Programmatic overrides. When set, `explicit` is prepended to `sources` unless already listed. */
|
|
59
|
-
explicit?: Record<string, ConfigMapValue>;
|
|
60
|
-
/** CLI flag values (when `cli` is listed in `sources`). */
|
|
61
|
-
cli?: Record<string, ConfigMapValue>;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Flatten `env` entries from parsed `app.yaml` content. Literal `value` entries
|
|
65
|
-
* are returned as-is; `valueFrom` entries resolve against the sibling
|
|
66
|
-
* `resources` array when possible.
|
|
67
|
-
*/
|
|
68
|
-
export declare function flattenAppYamlEnv(data: unknown): Record<string, string>;
|
|
69
|
-
/**
|
|
70
|
-
* Flatten `resources.apps.<key>.config.env` into a `name -> value` map.
|
|
71
|
-
* Auto-picks the app only when the bundle defines exactly one.
|
|
72
|
-
*/
|
|
73
|
-
export declare function flattenAppEnv(data: unknown): Record<string, string>;
|
|
74
|
-
/**
|
|
75
|
-
* The validated bundle for `cwd` - {@link coreConfig.bundleFile}, which caches it
|
|
76
|
-
* per working directory. Returns `undefined` inside a Databricks App, where the
|
|
77
|
-
* platform has already turned `config.env` into real environment variables and
|
|
78
|
-
* there is no bundle to validate.
|
|
79
|
-
*/
|
|
80
|
-
export declare function bundle(cwd?: string): Promise<ConfigFile | undefined>;
|
|
81
|
-
/**
|
|
82
|
-
* Locate and parse `app.yaml` / `app.yml` from the bundle or project root.
|
|
83
|
-
* Cached per working directory through {@link context.cached}, so a `cwd` change
|
|
84
|
-
* re-reads instead of returning another project's file. Returns `undefined`
|
|
85
|
-
* inside a Databricks App.
|
|
86
|
-
*/
|
|
87
|
-
export declare function appYaml(cwd?: string): Promise<ConfigFile | undefined>;
|
|
88
|
-
/**
|
|
89
|
-
* Walk a dot-separated path through bundle validate JSON. When the terminal
|
|
90
|
-
* node is a bundle variable object (`{ value: "..." }`), the `value` field is
|
|
91
|
-
* returned.
|
|
92
|
-
*/
|
|
93
|
-
export declare function getBundlePath(data: BundleValidateJson, path: string): string | undefined;
|
|
94
|
-
/**
|
|
95
|
-
* Resolve a configuration string from the configured sources. Returns the first
|
|
96
|
-
* non-empty value, or `undefined` when nothing matches.
|
|
97
|
-
*
|
|
98
|
-
* Precedence follows AppKit's: explicit config, then environment variable, then
|
|
99
|
-
* whatever the Databricks App / bundle definition supplies.
|
|
100
|
-
*
|
|
101
|
-
* @example
|
|
102
|
-
* import { bundle } from "@dbx-tools/appkit";
|
|
103
|
-
*
|
|
104
|
-
* const warehouseId = await bundle.resolveConfigValue("DATABRICKS_WAREHOUSE_ID", {
|
|
105
|
-
* cli: { DATABRICKS_WAREHOUSE_ID: flags.warehouse },
|
|
106
|
-
* sources: bundle.withCliSources(),
|
|
107
|
-
* });
|
|
108
|
-
*/
|
|
109
|
-
export declare function resolveConfigValue(name: string, options?: ResolveConfigValueOptions): Promise<string | undefined>;
|
|
110
|
-
/**
|
|
111
|
-
* Sources with `cli` included, in CLI-first order. Use for dev commands that
|
|
112
|
-
* accept flag overrides.
|
|
113
|
-
*/
|
|
114
|
-
export declare function withCliSources(sources?: ConfigSource[]): ConfigSource[];
|
package/lib/src/bundle.js
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DATABRICKS-APP configuration resolution: the bundle and `app.yaml` vocabulary.
|
|
3
|
-
*
|
|
4
|
-
* node-core's `config` module owns the generic lookup - environment, `.env`,
|
|
5
|
-
* `databricks bundle validate` - and knows nothing about what a bundle resource
|
|
6
|
-
* IS. That last part is this module: `sql_warehouse`, `genie_space`, and
|
|
7
|
-
* `postgres` are Databricks-App concepts, and an `app.yaml` / bundle
|
|
8
|
-
* `value_from` entry is a REFERENCE to one of them whose real value is the
|
|
9
|
-
* warehouse id or Genie space id sitting on the named resource. So this module
|
|
10
|
-
* extends node-core's resource schema, adds `app.yaml` (which the bundle CLI
|
|
11
|
-
* never sees), and resolves those references.
|
|
12
|
-
*
|
|
13
|
-
* Default sources: `explicit`, then `env`, then Databricks App `config.env`
|
|
14
|
-
* (from {@link bundle}) and hard-coded `app.yaml` env entries (from
|
|
15
|
-
* {@link appYaml}). Opt in to `cli` when a dev command wants flag overrides.
|
|
16
|
-
*
|
|
17
|
-
* Server-only, and Databricks-app specific, so it lives in node-appkit rather
|
|
18
|
-
* than node-core.
|
|
19
|
-
*
|
|
20
|
-
* @module
|
|
21
|
-
*/
|
|
22
|
-
import { readFile } from "node:fs/promises";
|
|
23
|
-
import { resolve } from "node:path";
|
|
24
|
-
import { ValidationError } from "@databricks/appkit";
|
|
25
|
-
import { config as coreConfig, file, project } from "@dbx-tools/core";
|
|
26
|
-
import { context, object, log, string } from "@dbx-tools/shared-core";
|
|
27
|
-
import { parse as yamlParse } from "yaml";
|
|
28
|
-
import { z } from "zod";
|
|
29
|
-
const logger = log.logger("config");
|
|
30
|
-
const defaultConfigSources = ["explicit", "env", "bundle"];
|
|
31
|
-
const APP_YAML_NAMES = ["app.yaml", "app.yml"];
|
|
32
|
-
export const bundleAppResourceSchema = coreConfig.bundleResourceSchema.extend({
|
|
33
|
-
sql_warehouse: z.object({ id: coreConfig.valueSchema.optional() }).optional(),
|
|
34
|
-
genie_space: z.object({ space_id: coreConfig.valueSchema.optional() }).optional(),
|
|
35
|
-
postgres: z
|
|
36
|
-
.object({
|
|
37
|
-
database: coreConfig.valueSchema.optional(),
|
|
38
|
-
branch: coreConfig.valueSchema.optional(),
|
|
39
|
-
endpoint: coreConfig.valueSchema.optional(),
|
|
40
|
-
})
|
|
41
|
-
.optional(),
|
|
42
|
-
});
|
|
43
|
-
const bundleAppSchema = coreConfig.bundleAppSchema.extend({
|
|
44
|
-
resources: z.array(bundleAppResourceSchema).optional(),
|
|
45
|
-
});
|
|
46
|
-
const bundleValidateAppsSchema = z.object({
|
|
47
|
-
resources: z.object({ apps: z.record(z.string(), bundleAppSchema).optional() }).optional(),
|
|
48
|
-
});
|
|
49
|
-
const appYamlEnvEntrySchema = coreConfig.bundleEnvEntrySchema.omit({ value_from: true }).extend({
|
|
50
|
-
name: coreConfig.valueSchema,
|
|
51
|
-
valueFrom: coreConfig.valueSchema.optional(),
|
|
52
|
-
});
|
|
53
|
-
const appYamlResourceSchema = coreConfig.bundleResourceSchema
|
|
54
|
-
.extend({
|
|
55
|
-
name: coreConfig.valueSchema,
|
|
56
|
-
sql_warehouse: z.object({ id: coreConfig.valueSchema.optional() }).optional(),
|
|
57
|
-
genie_space: z.object({ space_id: coreConfig.valueSchema.optional() }).optional(),
|
|
58
|
-
postgres: z
|
|
59
|
-
.object({
|
|
60
|
-
database: coreConfig.valueSchema.optional(),
|
|
61
|
-
branch: coreConfig.valueSchema.optional(),
|
|
62
|
-
endpoint: coreConfig.valueSchema.optional(),
|
|
63
|
-
})
|
|
64
|
-
.optional(),
|
|
65
|
-
})
|
|
66
|
-
.passthrough();
|
|
67
|
-
const appYamlSchema = z.object({
|
|
68
|
-
env: z.array(appYamlEnvEntrySchema).optional(),
|
|
69
|
-
resources: z.array(appYamlResourceSchema).optional(),
|
|
70
|
-
});
|
|
71
|
-
function envKeysForName(name) {
|
|
72
|
-
const trimmed = name.trim();
|
|
73
|
-
if (!trimmed) {
|
|
74
|
-
return object.sequence();
|
|
75
|
-
}
|
|
76
|
-
const keys = (function* () {
|
|
77
|
-
const modifiers = [
|
|
78
|
-
null,
|
|
79
|
-
() => trimmed.toUpperCase(),
|
|
80
|
-
() => Array.from(string.tokenize(trimmed)).join("_").toUpperCase(),
|
|
81
|
-
];
|
|
82
|
-
for (const modifier of modifiers) {
|
|
83
|
-
yield modifier ? modifier(trimmed) : trimmed;
|
|
84
|
-
}
|
|
85
|
-
})();
|
|
86
|
-
return object.sequence(keys).cache().filter(Boolean).distinct();
|
|
87
|
-
}
|
|
88
|
-
function readEnv(keys) {
|
|
89
|
-
for (const key of keys) {
|
|
90
|
-
const value = process.env[key]?.trim();
|
|
91
|
-
if (value)
|
|
92
|
-
return value;
|
|
93
|
-
}
|
|
94
|
-
return undefined;
|
|
95
|
-
}
|
|
96
|
-
function readConfigMapValue(value) {
|
|
97
|
-
if (value == null)
|
|
98
|
-
return undefined;
|
|
99
|
-
if (Array.isArray(value)) {
|
|
100
|
-
for (const item of value) {
|
|
101
|
-
const trimmed = item?.trim();
|
|
102
|
-
if (trimmed)
|
|
103
|
-
return trimmed;
|
|
104
|
-
}
|
|
105
|
-
return undefined;
|
|
106
|
-
}
|
|
107
|
-
const trimmed = value.trim();
|
|
108
|
-
return trimmed || undefined;
|
|
109
|
-
}
|
|
110
|
-
function readMap(keys, map) {
|
|
111
|
-
if (!map)
|
|
112
|
-
return undefined;
|
|
113
|
-
for (const key of keys) {
|
|
114
|
-
const value = readConfigMapValue(map[key]);
|
|
115
|
-
if (value)
|
|
116
|
-
return value;
|
|
117
|
-
}
|
|
118
|
-
return undefined;
|
|
119
|
-
}
|
|
120
|
-
function readAppEnv(keys, envMap) {
|
|
121
|
-
for (const key of keys) {
|
|
122
|
-
const value = envMap[key]?.trim();
|
|
123
|
-
if (value)
|
|
124
|
-
return value;
|
|
125
|
-
}
|
|
126
|
-
return undefined;
|
|
127
|
-
}
|
|
128
|
-
function parseYaml(text) {
|
|
129
|
-
return yamlParse(text);
|
|
130
|
-
}
|
|
131
|
-
function pickAppResourceId(apps) {
|
|
132
|
-
const keys = Object.keys(apps);
|
|
133
|
-
return keys.length === 1 ? keys[0] : undefined;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Resolve the effective value a `value_from`/`valueFrom` entry points at:
|
|
137
|
-
* the first present of the warehouse id, Genie space id, or Postgres
|
|
138
|
-
* endpoint/database/branch on the named resource. Shared by both the
|
|
139
|
-
* `app.yaml` and `bundle validate` flatteners, whose resource shapes match.
|
|
140
|
-
*/
|
|
141
|
-
function resolveResourceValue(resource) {
|
|
142
|
-
return (resource?.sql_warehouse?.id ??
|
|
143
|
-
resource?.genie_space?.space_id ??
|
|
144
|
-
resource?.postgres?.endpoint ??
|
|
145
|
-
resource?.postgres?.database ??
|
|
146
|
-
resource?.postgres?.branch);
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Flatten `env` entries from parsed `app.yaml` content. Literal `value` entries
|
|
150
|
-
* are returned as-is; `valueFrom` entries resolve against the sibling
|
|
151
|
-
* `resources` array when possible.
|
|
152
|
-
*/
|
|
153
|
-
export function flattenAppYamlEnv(data) {
|
|
154
|
-
const parsed = appYamlSchema.safeParse(data);
|
|
155
|
-
if (!parsed.success || !parsed.data.env?.length) {
|
|
156
|
-
return {};
|
|
157
|
-
}
|
|
158
|
-
const resourceByName = new Map((parsed.data.resources ?? []).map((resource) => [resource.name, resource]));
|
|
159
|
-
const out = {};
|
|
160
|
-
for (const entry of parsed.data.env) {
|
|
161
|
-
const value = coreConfig.valueSchema.safeParse(entry.value);
|
|
162
|
-
if (value.success) {
|
|
163
|
-
out[entry.name] = value.data;
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
if (!entry.valueFrom)
|
|
167
|
-
continue;
|
|
168
|
-
const resolved = resolveResourceValue(resourceByName.get(entry.valueFrom));
|
|
169
|
-
if (resolved)
|
|
170
|
-
out[entry.name] = resolved;
|
|
171
|
-
}
|
|
172
|
-
return out;
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Flatten `resources.apps.<key>.config.env` into a `name -> value` map.
|
|
176
|
-
* Auto-picks the app only when the bundle defines exactly one.
|
|
177
|
-
*/
|
|
178
|
-
export function flattenAppEnv(data) {
|
|
179
|
-
const parsed = bundleValidateAppsSchema.safeParse(data);
|
|
180
|
-
if (!parsed.success)
|
|
181
|
-
return {};
|
|
182
|
-
const apps = parsed.data.resources?.apps;
|
|
183
|
-
if (!apps || Object.keys(apps).length === 0)
|
|
184
|
-
return {};
|
|
185
|
-
const key = pickAppResourceId(apps);
|
|
186
|
-
if (!key)
|
|
187
|
-
return {};
|
|
188
|
-
const app = apps[key];
|
|
189
|
-
if (!app?.config?.env?.length)
|
|
190
|
-
return {};
|
|
191
|
-
const resourceByName = new Map((app.resources ?? [])
|
|
192
|
-
.filter((resource) => resource.name)
|
|
193
|
-
.map((resource) => [resource.name, resource]));
|
|
194
|
-
const out = {};
|
|
195
|
-
for (const entry of app.config.env) {
|
|
196
|
-
if (!entry.name)
|
|
197
|
-
continue;
|
|
198
|
-
const value = coreConfig.valueSchema.safeParse(entry.value);
|
|
199
|
-
if (value.success) {
|
|
200
|
-
out[entry.name] = value.data;
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
if (!entry.value_from)
|
|
204
|
-
continue;
|
|
205
|
-
const resolved = resolveResourceValue(resourceByName.get(entry.value_from));
|
|
206
|
-
if (resolved)
|
|
207
|
-
out[entry.name] = resolved;
|
|
208
|
-
}
|
|
209
|
-
return out;
|
|
210
|
-
}
|
|
211
|
-
async function loadAppYaml(cwd) {
|
|
212
|
-
for (const fileName of APP_YAML_NAMES) {
|
|
213
|
-
const configFile = resolveConfigFile(cwd, fileName);
|
|
214
|
-
if (!configFile)
|
|
215
|
-
continue;
|
|
216
|
-
try {
|
|
217
|
-
const text = await readFile(configFile, "utf8");
|
|
218
|
-
const data = parseYaml(text);
|
|
219
|
-
if (!object.isRecord(data)) {
|
|
220
|
-
return undefined;
|
|
221
|
-
}
|
|
222
|
-
return { path: configFile, data };
|
|
223
|
-
}
|
|
224
|
-
catch {
|
|
225
|
-
logger.warn("failed to parse app yaml", { path: configFile });
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return undefined;
|
|
229
|
-
}
|
|
230
|
-
function resolveConfigFile(cwd, configFile) {
|
|
231
|
-
if (coreConfig.isDatabricksAppEnv())
|
|
232
|
-
return undefined;
|
|
233
|
-
for (const rootDir of project.resolveProjectRoots(cwd)) {
|
|
234
|
-
const bundlePath = resolve(rootDir, configFile);
|
|
235
|
-
if (file.statSync(bundlePath)?.isFile())
|
|
236
|
-
return bundlePath;
|
|
237
|
-
}
|
|
238
|
-
return undefined;
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* The validated bundle for `cwd` - {@link coreConfig.bundleFile}, which caches it
|
|
242
|
-
* per working directory. Returns `undefined` inside a Databricks App, where the
|
|
243
|
-
* platform has already turned `config.env` into real environment variables and
|
|
244
|
-
* there is no bundle to validate.
|
|
245
|
-
*/
|
|
246
|
-
export function bundle(cwd) {
|
|
247
|
-
return Promise.resolve(coreConfig.isDatabricksAppEnv() ? undefined : coreConfig.bundleFile(cwd));
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Locate and parse `app.yaml` / `app.yml` from the bundle or project root.
|
|
251
|
-
* Cached per working directory through {@link context.cached}, so a `cwd` change
|
|
252
|
-
* re-reads instead of returning another project's file. Returns `undefined`
|
|
253
|
-
* inside a Databricks App.
|
|
254
|
-
*/
|
|
255
|
-
export function appYaml(cwd) {
|
|
256
|
-
if (coreConfig.isDatabricksAppEnv())
|
|
257
|
-
return Promise.resolve(undefined);
|
|
258
|
-
return context.cached(["appkit", "appYaml"], (resolved) => loadAppYaml(resolved ?? "."), cwd);
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Walk a dot-separated path through bundle validate JSON. When the terminal
|
|
262
|
-
* node is a bundle variable object (`{ value: "..." }`), the `value` field is
|
|
263
|
-
* returned.
|
|
264
|
-
*/
|
|
265
|
-
export function getBundlePath(data, path) {
|
|
266
|
-
const parts = path.split(".").filter(Boolean);
|
|
267
|
-
if (parts.length === 0)
|
|
268
|
-
return undefined;
|
|
269
|
-
let current = data;
|
|
270
|
-
for (let i = 0; i < parts.length; i++) {
|
|
271
|
-
if (!object.isRecord(current))
|
|
272
|
-
return undefined;
|
|
273
|
-
const part = parts[i];
|
|
274
|
-
const next = current[part];
|
|
275
|
-
if (i === parts.length - 1) {
|
|
276
|
-
if (typeof next === "string" && next)
|
|
277
|
-
return next;
|
|
278
|
-
if (object.isRecord(next)) {
|
|
279
|
-
const value = next.value;
|
|
280
|
-
return typeof value === "string" && value ? value : undefined;
|
|
281
|
-
}
|
|
282
|
-
return undefined;
|
|
283
|
-
}
|
|
284
|
-
current = next;
|
|
285
|
-
}
|
|
286
|
-
return undefined;
|
|
287
|
-
}
|
|
288
|
-
async function resolveAppEnvMap(options) {
|
|
289
|
-
const appData = options.appData ?? (await appYaml());
|
|
290
|
-
const bundleData = options.bundleData ?? (await bundle());
|
|
291
|
-
const fromYaml = appData ? flattenAppYamlEnv(appData.data) : {};
|
|
292
|
-
const fromBundle = bundleData ? flattenAppEnv(bundleData.data) : {};
|
|
293
|
-
return { ...fromYaml, ...fromBundle };
|
|
294
|
-
}
|
|
295
|
-
function resolveSources(options) {
|
|
296
|
-
const sources = [...(options.sources ?? defaultConfigSources)];
|
|
297
|
-
if (options.explicit !== undefined && !sources.includes("explicit")) {
|
|
298
|
-
sources.unshift("explicit");
|
|
299
|
-
}
|
|
300
|
-
return sources;
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Resolve a configuration string from the configured sources. Returns the first
|
|
304
|
-
* non-empty value, or `undefined` when nothing matches.
|
|
305
|
-
*
|
|
306
|
-
* Precedence follows AppKit's: explicit config, then environment variable, then
|
|
307
|
-
* whatever the Databricks App / bundle definition supplies.
|
|
308
|
-
*
|
|
309
|
-
* @example
|
|
310
|
-
* import { bundle } from "@dbx-tools/appkit";
|
|
311
|
-
*
|
|
312
|
-
* const warehouseId = await bundle.resolveConfigValue("DATABRICKS_WAREHOUSE_ID", {
|
|
313
|
-
* cli: { DATABRICKS_WAREHOUSE_ID: flags.warehouse },
|
|
314
|
-
* sources: bundle.withCliSources(),
|
|
315
|
-
* });
|
|
316
|
-
*/
|
|
317
|
-
export async function resolveConfigValue(name, options = {}) {
|
|
318
|
-
const keys = envKeysForName(name).toArray();
|
|
319
|
-
if (keys.length === 0)
|
|
320
|
-
return undefined;
|
|
321
|
-
const sources = resolveSources(options);
|
|
322
|
-
let appEnvMap;
|
|
323
|
-
const values = (async function* () {
|
|
324
|
-
for (const source of sources) {
|
|
325
|
-
switch (source) {
|
|
326
|
-
case "explicit":
|
|
327
|
-
yield readMap(keys, options.explicit);
|
|
328
|
-
break;
|
|
329
|
-
case "cli":
|
|
330
|
-
yield readMap(keys, options.cli);
|
|
331
|
-
break;
|
|
332
|
-
case "env":
|
|
333
|
-
yield readEnv(keys);
|
|
334
|
-
break;
|
|
335
|
-
case "bundle":
|
|
336
|
-
if (appEnvMap === undefined)
|
|
337
|
-
appEnvMap = await resolveAppEnvMap(options);
|
|
338
|
-
yield readAppEnv(keys, appEnvMap);
|
|
339
|
-
break;
|
|
340
|
-
default:
|
|
341
|
-
throw ValidationError.invalidValue("sources", source, "one of: explicit, cli, env, bundle");
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
})();
|
|
345
|
-
for await (const value of values) {
|
|
346
|
-
if (value)
|
|
347
|
-
return value;
|
|
348
|
-
}
|
|
349
|
-
return undefined;
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Sources with `cli` included, in CLI-first order. Use for dev commands that
|
|
353
|
-
* accept flag overrides.
|
|
354
|
-
*/
|
|
355
|
-
export function withCliSources(sources = defaultConfigSources) {
|
|
356
|
-
const rest = sources.filter((source) => source !== "cli" && source !== "explicit");
|
|
357
|
-
return ["cli", "explicit", ...rest];
|
|
358
|
-
}
|
|
359
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVuZGxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2J1bmRsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFFSCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUFFLE1BQU0sSUFBSSxVQUFVLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN0RSxPQUFPLEVBQUUsS0FBSyxJQUFJLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMxQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBRXhCLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7QUFjcEMsTUFBTSxvQkFBb0IsR0FBbUIsQ0FBQyxVQUFVLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBRTNFLE1BQU0sY0FBYyxHQUFHLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBVSxDQUFDO0FBRXhELE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLFVBQVUsQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUM7SUFDNUUsYUFBYSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsVUFBVSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFO0lBQzdFLFdBQVcsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsUUFBUSxFQUFFLFVBQVUsQ0FB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M0UsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxLQUFLLEtBQUssSUFBSSxNQUFNLEtBQUssVUFBVSxDQUFDLENBQUM7SUFDbkYsT0FBTyxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztBQUN0QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBEQVRBQlJJQ0tTLUFQUCBjb25maWd1cmF0aW9uIHJlc29sdXRpb246IHRoZSBidW5kbGUgYW5kIGBhcHAueWFtbGAgdm9jYWJ1bGFyeS5cbiAqXG4gKiBub2RlLWNvcmUncyBgY29uZmlnYCBtb2R1bGUgb3ducyB0aGUgZ2VuZXJpYyBsb29rdXAgLSBlbnZpcm9ubWVudCwgYC5lbnZgLFxuICogYGRhdGFicmlja3MgYnVuZGxlIHZhbGlkYXRlYCAtIGFuZCBrbm93cyBub3RoaW5nIGFib3V0IHdoYXQgYSBidW5kbGUgcmVzb3VyY2VcbiAqIElTLiBUaGF0IGxhc3QgcGFydCBpcyB0aGlzIG1vZHVsZTogYHNxbF93YXJlaG91c2VgLCBgZ2VuaWVfc3BhY2VgLCBhbmRcbiAqIGBwb3N0Z3Jlc2AgYXJlIERhdGFicmlja3MtQXBwIGNvbmNlcHRzLCBhbmQgYW4gYGFwcC55YW1sYCAvIGJ1bmRsZVxuICogYHZhbHVlX2Zyb21gIGVudHJ5IGlzIGEgUkVGRVJFTkNFIHRvIG9uZSBvZiB0aGVtIHdob3NlIHJlYWwgdmFsdWUgaXMgdGhlXG4gKiB3YXJlaG91c2UgaWQgb3IgR2VuaWUgc3BhY2UgaWQgc2l0dGluZyBvbiB0aGUgbmFtZWQgcmVzb3VyY2UuIFNvIHRoaXMgbW9kdWxlXG4gKiBleHRlbmRzIG5vZGUtY29yZSdzIHJlc291cmNlIHNjaGVtYSwgYWRkcyBgYXBwLnlhbWxgICh3aGljaCB0aGUgYnVuZGxlIENMSVxuICogbmV2ZXIgc2VlcyksIGFuZCByZXNvbHZlcyB0aG9zZSByZWZlcmVuY2VzLlxuICpcbiAqIERlZmF1bHQgc291cmNlczogYGV4cGxpY2l0YCwgdGhlbiBgZW52YCwgdGhlbiBEYXRhYnJpY2tzIEFwcCBgY29uZmlnLmVudmBcbiAqIChmcm9tIHtAbGluayBidW5kbGV9KSBhbmQgaGFyZC1jb2RlZCBgYXBwLnlhbWxgIGVudiBlbnRyaWVzIChmcm9tXG4gKiB7QGxpbmsgYXBwWWFtbH0pLiBPcHQgaW4gdG8gYGNsaWAgd2hlbiBhIGRldiBjb21tYW5kIHdhbnRzIGZsYWcgb3ZlcnJpZGVzLlxuICpcbiAqIFNlcnZlci1vbmx5LCBhbmQgRGF0YWJyaWNrcy1hcHAgc3BlY2lmaWMsIHNvIGl0IGxpdmVzIGluIG5vZGUtYXBwa2l0IHJhdGhlclxuICogdGhhbiBub2RlLWNvcmUuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IHJlYWRGaWxlIH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBjb25maWcgYXMgY29yZUNvbmZpZywgZmlsZSwgcHJvamVjdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2NvcmVcIjtcbmltcG9ydCB7IGNvbnRleHQsIG9iamVjdCwgbG9nLCBzdHJpbmcgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgcGFyc2UgYXMgeWFtbFBhcnNlIH0gZnJvbSBcInlhbWxcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJjb25maWdcIik7XG5cbi8qKiBQYXJzZWQgcGF5bG9hZCBmcm9tIGBkYXRhYnJpY2tzIGJ1bmRsZSB2YWxpZGF0ZSAtLW91dHB1dCBqc29uYC4gKi9cbmV4cG9ydCB0eXBlIEJ1bmRsZVZhbGlkYXRlSnNvbiA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4vKiogQSBjb25maWcgZmlsZSBkaXNjb3ZlcmVkIG9uIGRpc2sgd2l0aCBpdHMgcGFyc2VkIGNvbnRlbnRzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb25maWdGaWxlIHtcbiAgcGF0aDogc3RyaW5nO1xuICBkYXRhOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuLyoqIFN1cHBvcnRlZCBjb25maWd1cmF0aW9uIHNvdXJjZXMsIGNvbnN1bHRlZCBpbiBhcnJheSBvcmRlci4gKi9cbmV4cG9ydCB0eXBlIENvbmZpZ1NvdXJjZSA9IFwiZXhwbGljaXRcIiB8IFwiY2xpXCIgfCBcImVudlwiIHwgXCJidW5kbGVcIjtcblxuY29uc3QgZGVmYXVsdENvbmZpZ1NvdXJjZXM6IENvbmZpZ1NvdXJjZVtdID0gW1wiZXhwbGljaXRcIiwgXCJlbnZcIiwgXCJidW5kbGVcIl07XG5cbmNvbnN0IEFQUF9ZQU1MX05BTUVTID0gW1wiYXBwLnlhbWxcIiwgXCJhcHAueW1sXCJdIGFzIGNvbnN0O1xuXG5leHBvcnQgY29uc3QgYnVuZGxlQXBwUmVzb3VyY2VTY2hlbWEgPSBjb3JlQ29uZmlnLmJ1bmRsZVJlc291cmNlU2NoZW1hLmV4dGVuZCh7XG4gIHNxbF93YXJlaG91c2U6IHoub2JqZWN0KHsgaWQ6IGNvcmVDb25maWcudmFsdWVTY2hlbWEub3B0aW9uYWwoKSB9KS5vcHRpb25hbCgpLFxuICBnZW5pZV9zcGFjZTogei5vYmplY3QoeyBzcGFjZV9pZDogY29yZUNvbmZpZy52YWx1ZVNjaGVtYS5vcHRpb25hbCgpIH0pLm9wdGlvbmFsKCksXG4gIHBvc3RncmVzOiB6XG4gICAgLm9iamVjdCh7XG4gICAgICBkYXRhYmFzZTogY29yZUNvbmZpZy52YWx1ZVNjaGVtYS5vcHRpb25hbCgpLFxuICAgICAgYnJhbmNoOiBjb3JlQ29uZmlnLnZhbHVlU2NoZW1hLm9wdGlvbmFsKCksXG4gICAgICBlbmRwb2ludDogY29yZUNvbmZpZy52YWx1ZVNjaGVtYS5vcHRpb25hbCgpLFxuICAgIH0pXG4gICAgLm9wdGlvbmFsKCksXG59KTtcblxuY29uc3QgYnVuZGxlQXBwU2NoZW1hID0gY29yZUNvbmZpZy5idW5kbGVBcHBTY2hlbWEuZXh0ZW5kKHtcbiAgcmVzb3VyY2VzOiB6LmFycmF5KGJ1bmRsZUFwcFJlc291cmNlU2NoZW1hKS5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IGJ1bmRsZVZhbGlkYXRlQXBwc1NjaGVtYSA9IHoub2JqZWN0KHtcbiAgcmVzb3VyY2VzOiB6Lm9iamVjdCh7IGFwcHM6IHoucmVjb3JkKHouc3RyaW5nKCksIGJ1bmRsZUFwcFNjaGVtYSkub3B0aW9uYWwoKSB9KS5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IGFwcFlhbWxFbnZFbnRyeVNjaGVtYSA9IGNvcmVDb25maWcuYnVuZGxlRW52RW50cnlTY2hlbWEub21pdCh7IHZhbHVlX2Zyb206IHRydWUgfSkuZXh0ZW5kKHtcbiAgbmFtZTogY29yZUNvbmZpZy52YWx1ZVNjaGVtYSxcbiAgdmFsdWVGcm9tOiBjb3JlQ29uZmlnLnZhbHVlU2NoZW1hLm9wdGlvbmFsKCksXG59KTtcblxuY29uc3QgYXBwWWFtbFJlc291cmNlU2NoZW1hID0gY29yZUNvbmZpZy5idW5kbGVSZXNvdXJjZVNjaGVtYVxuICAuZXh0ZW5kKHtcbiAgICBuYW1lOiBjb3JlQ29uZmlnLnZhbHVlU2NoZW1hLFxuICAgIHNxbF93YXJlaG91c2U6IHoub2JqZWN0KHsgaWQ6IGNvcmVDb25maWcudmFsdWVTY2hlbWEub3B0aW9uYWwoKSB9KS5vcHRpb25hbCgpLFxuICAgIGdlbmllX3NwYWNlOiB6Lm9iamVjdCh7IHNwYWNlX2lkOiBjb3JlQ29uZmlnLnZhbHVlU2NoZW1hLm9wdGlvbmFsKCkgfSkub3B0aW9uYWwoKSxcbiAgICBwb3N0Z3JlczogelxuICAgICAgLm9iamVjdCh7XG4gICAgICAgIGRhdGFiYXNlOiBjb3JlQ29uZmlnLnZhbHVlU2NoZW1hLm9wdGlvbmFsKCksXG4gICAgICAgIGJyYW5jaDogY29yZUNvbmZpZy52YWx1ZVNjaGVtYS5vcHRpb25hbCgpLFxuICAgICAgICBlbmRwb2ludDogY29yZUNvbmZpZy52YWx1ZVNjaGVtYS5vcHRpb25hbCgpLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb25hbCgpLFxuICB9KVxuICAucGFzc3Rocm91Z2goKTtcblxuY29uc3QgYXBwWWFtbFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgZW52OiB6LmFycmF5KGFwcFlhbWxFbnZFbnRyeVNjaGVtYSkub3B0aW9uYWwoKSxcbiAgcmVzb3VyY2VzOiB6LmFycmF5KGFwcFlhbWxSZXNvdXJjZVNjaGVtYSkub3B0aW9uYWwoKSxcbn0pO1xuXG50eXBlIEJ1bmRsZUFwcCA9IHouaW5mZXI8dHlwZW9mIGJ1bmRsZUFwcFNjaGVtYT47XG5cbi8qKiBTaW5nbGUgY29uZmlnIG1hcCBlbnRyeSAoc3RyaW5nIG9yIHJlcGVhdGVkIHZhbHVlcywgbGlrZSBoZWFkZXJzKS4gKi9cbmV4cG9ydCB0eXBlIENvbmZpZ01hcFZhbHVlID0gc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb2x2ZUNvbmZpZ1ZhbHVlT3B0aW9ucyB7XG4gIC8qKiBCdW5kbGUgdmFsaWRhdGUgSlNPTi4gRGVmYXVsdHMgdG8ge0BsaW5rIGJ1bmRsZX0gKHNraXBwZWQgaW5zaWRlIGEgRGF0YWJyaWNrcyBBcHApLiAqL1xuICBidW5kbGVEYXRhPzogQ29uZmlnRmlsZTtcbiAgLyoqIFBhcnNlZCBgYXBwLnlhbWxgIGNvbnRlbnRzLiBEZWZhdWx0cyB0byB7QGxpbmsgYXBwWWFtbH0gKHNraXBwZWQgaW5zaWRlIGEgRGF0YWJyaWNrcyBBcHApLiAqL1xuICBhcHBEYXRhPzogQ29uZmlnRmlsZTtcbiAgLyoqXG4gICAqIFNvdXJjZXMgdG8gY29uc3VsdCwgZmlyc3QgdHJ1dGh5IHN0cmluZyB3aW5zLiBEZWZhdWx0cyB0byBgZXhwbGljaXRgLCB0aGVuXG4gICAqIGBlbnZgLCB0aGVuIGBidW5kbGVgLlxuICAgKi9cbiAgc291cmNlcz86IENvbmZpZ1NvdXJjZVtdO1xuICAvKiogUHJvZ3JhbW1hdGljIG92ZXJyaWRlcy4gV2hlbiBzZXQsIGBleHBsaWNpdGAgaXMgcHJlcGVuZGVkIHRvIGBzb3VyY2VzYCB1bmxlc3MgYWxyZWFkeSBsaXN0ZWQuICovXG4gIGV4cGxpY2l0PzogUmVjb3JkPHN0cmluZywgQ29uZmlnTWFwVmFsdWU+O1xuICAvKiogQ0xJIGZsYWcgdmFsdWVzICh3aGVuIGBjbGlgIGlzIGxpc3RlZCBpbiBgc291cmNlc2ApLiAqL1xuICBjbGk/OiBSZWNvcmQ8c3RyaW5nLCBDb25maWdNYXBWYWx1ZT47XG59XG5cbmZ1bmN0aW9uIGVudktleXNGb3JOYW1lKG5hbWU6IHN0cmluZyk6IG9iamVjdC5TZXF1ZW5jZTxzdHJpbmc+IHtcbiAgY29uc3QgdHJpbW1lZCA9IG5hbWUudHJpbSgpO1xuICBpZiAoIXRyaW1tZWQpIHtcbiAgICByZXR1cm4gb2JqZWN0LnNlcXVlbmNlKCk7XG4gIH1cbiAgY29uc3Qga2V5cyA9IChmdW5jdGlvbiogKCkge1xuICAgIGNvbnN0IG1vZGlmaWVyczogKCgodmFsdWU6IHN0cmluZykgPT4gc3RyaW5nKSB8IG51bGwpW10gPSBbXG4gICAgICBudWxsLFxuICAgICAgKCkgPT4gdHJpbW1lZC50b1VwcGVyQ2FzZSgpLFxuICAgICAgKCkgPT4gQXJyYXkuZnJvbShzdHJpbmcudG9rZW5pemUodHJpbW1lZCkpLmpvaW4oXCJfXCIpLnRvVXBwZXJDYXNlKCksXG4gICAgXTtcbiAgICBmb3IgKGNvbnN0IG1vZGlmaWVyIG9mIG1vZGlmaWVycykge1xuICAgICAgeWllbGQgbW9kaWZpZXIgPyBtb2RpZmllcih0cmltbWVkKSA6IHRyaW1tZWQ7XG4gICAgfVxuICB9KSgpO1xuICByZXR1cm4gb2JqZWN0LnNlcXVlbmNlKGtleXMpLmNhY2hlKCkuZmlsdGVyKEJvb2xlYW4pLmRpc3RpbmN0KCk7XG59XG5cbmZ1bmN0aW9uIHJlYWRFbnYoa2V5czogSXRlcmFibGU8c3RyaW5nPik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcbiAgICBjb25zdCB2YWx1ZSA9IHByb2Nlc3MuZW52W2tleV0/LnRyaW0oKTtcbiAgICBpZiAodmFsdWUpIHJldHVybiB2YWx1ZTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiByZWFkQ29uZmlnTWFwVmFsdWUodmFsdWU6IENvbmZpZ01hcFZhbHVlKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKHZhbHVlID09IG51bGwpIHJldHVybiB1bmRlZmluZWQ7XG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiB2YWx1ZSkge1xuICAgICAgY29uc3QgdHJpbW1lZCA9IGl0ZW0/LnRyaW0oKTtcbiAgICAgIGlmICh0cmltbWVkKSByZXR1cm4gdHJpbW1lZDtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICBjb25zdCB0cmltbWVkID0gdmFsdWUudHJpbSgpO1xuICByZXR1cm4gdHJpbW1lZCB8fCB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHJlYWRNYXAoXG4gIGtleXM6IEl0ZXJhYmxlPHN0cmluZz4sXG4gIG1hcDogUmVjb3JkPHN0cmluZywgQ29uZmlnTWFwVmFsdWU+IHwgdW5kZWZpbmVkLFxuKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFtYXApIHJldHVybiB1bmRlZmluZWQ7XG4gIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcbiAgICBjb25zdCB2YWx1ZSA9IHJlYWRDb25maWdNYXBWYWx1ZShtYXBba2V5XSk7XG4gICAgaWYgKHZhbHVlKSByZXR1cm4gdmFsdWU7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gcmVhZEFwcEVudihrZXlzOiBJdGVyYWJsZTxzdHJpbmc+LCBlbnZNYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgY29uc3QgdmFsdWUgPSBlbnZNYXBba2V5XT8udHJpbSgpO1xuICAgIGlmICh2YWx1ZSkgcmV0dXJuIHZhbHVlO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHBhcnNlWWFtbCh0ZXh0OiBzdHJpbmcpOiB1bmtub3duIHtcbiAgcmV0dXJuIHlhbWxQYXJzZSh0ZXh0KTtcbn1cblxuZnVuY3Rpb24gcGlja0FwcFJlc291cmNlSWQoYXBwczogUmVjb3JkPHN0cmluZywgQnVuZGxlQXBwPik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhhcHBzKTtcbiAgcmV0dXJuIGtleXMubGVuZ3RoID09PSAxID8ga2V5c1swXSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBlZmZlY3RpdmUgdmFsdWUgYSBgdmFsdWVfZnJvbWAvYHZhbHVlRnJvbWAgZW50cnkgcG9pbnRzIGF0OlxuICogdGhlIGZpcnN0IHByZXNlbnQgb2YgdGhlIHdhcmVob3VzZSBpZCwgR2VuaWUgc3BhY2UgaWQsIG9yIFBvc3RncmVzXG4gKiBlbmRwb2ludC9kYXRhYmFzZS9icmFuY2ggb24gdGhlIG5hbWVkIHJlc291cmNlLiBTaGFyZWQgYnkgYm90aCB0aGVcbiAqIGBhcHAueWFtbGAgYW5kIGBidW5kbGUgdmFsaWRhdGVgIGZsYXR0ZW5lcnMsIHdob3NlIHJlc291cmNlIHNoYXBlcyBtYXRjaC5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVJlc291cmNlVmFsdWUoXG4gIHJlc291cmNlOiB6LmluZmVyPHR5cGVvZiBidW5kbGVBcHBSZXNvdXJjZVNjaGVtYT4gfCB1bmRlZmluZWQsXG4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gKFxuICAgIHJlc291cmNlPy5zcWxfd2FyZWhvdXNlPy5pZCA/P1xuICAgIHJlc291cmNlPy5nZW5pZV9zcGFjZT8uc3BhY2VfaWQgPz9cbiAgICByZXNvdXJjZT8ucG9zdGdyZXM/LmVuZHBvaW50ID8/XG4gICAgcmVzb3VyY2U/LnBvc3RncmVzPy5kYXRhYmFzZSA/P1xuICAgIHJlc291cmNlPy5wb3N0Z3Jlcz8uYnJhbmNoXG4gICk7XG59XG5cbi8qKlxuICogRmxhdHRlbiBgZW52YCBlbnRyaWVzIGZyb20gcGFyc2VkIGBhcHAueWFtbGAgY29udGVudC4gTGl0ZXJhbCBgdmFsdWVgIGVudHJpZXNcbiAqIGFyZSByZXR1cm5lZCBhcy1pczsgYHZhbHVlRnJvbWAgZW50cmllcyByZXNvbHZlIGFnYWluc3QgdGhlIHNpYmxpbmdcbiAqIGByZXNvdXJjZXNgIGFycmF5IHdoZW4gcG9zc2libGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0dGVuQXBwWWFtbEVudihkYXRhOiB1bmtub3duKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IHBhcnNlZCA9IGFwcFlhbWxTY2hlbWEuc2FmZVBhcnNlKGRhdGEpO1xuICBpZiAoIXBhcnNlZC5zdWNjZXNzIHx8ICFwYXJzZWQuZGF0YS5lbnY/Lmxlbmd0aCkge1xuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIGNvbnN0IHJlc291cmNlQnlOYW1lID0gbmV3IE1hcChcbiAgICAocGFyc2VkLmRhdGEucmVzb3VyY2VzID8/IFtdKS5tYXAoKHJlc291cmNlKSA9PiBbcmVzb3VyY2UubmFtZSwgcmVzb3VyY2VdKSxcbiAgKTtcblxuICBjb25zdCBvdXQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgZm9yIChjb25zdCBlbnRyeSBvZiBwYXJzZWQuZGF0YS5lbnYpIHtcbiAgICBjb25zdCB2YWx1ZSA9IGNvcmVDb25maWcudmFsdWVTY2hlbWEuc2FmZVBhcnNlKGVudHJ5LnZhbHVlKTtcbiAgICBpZiAodmFsdWUuc3VjY2Vzcykge1xuICAgICAgb3V0W2VudHJ5Lm5hbWVdID0gdmFsdWUuZGF0YTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAoIWVudHJ5LnZhbHVlRnJvbSkgY29udGludWU7XG4gICAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlUmVzb3VyY2VWYWx1ZShyZXNvdXJjZUJ5TmFtZS5nZXQoZW50cnkudmFsdWVGcm9tKSk7XG4gICAgaWYgKHJlc29sdmVkKSBvdXRbZW50cnkubmFtZV0gPSByZXNvbHZlZDtcbiAgfVxuICByZXR1cm4gb3V0O1xufVxuXG4vKipcbiAqIEZsYXR0ZW4gYHJlc291cmNlcy5hcHBzLjxrZXk+LmNvbmZpZy5lbnZgIGludG8gYSBgbmFtZSAtPiB2YWx1ZWAgbWFwLlxuICogQXV0by1waWNrcyB0aGUgYXBwIG9ubHkgd2hlbiB0aGUgYnVuZGxlIGRlZmluZXMgZXhhY3RseSBvbmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0dGVuQXBwRW52KGRhdGE6IHVua25vd24pOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgY29uc3QgcGFyc2VkID0gYnVuZGxlVmFsaWRhdGVBcHBzU2NoZW1hLnNhZmVQYXJzZShkYXRhKTtcbiAgaWYgKCFwYXJzZWQuc3VjY2VzcykgcmV0dXJuIHt9O1xuXG4gIGNvbnN0IGFwcHMgPSBwYXJzZWQuZGF0YS5yZXNvdXJjZXM/LmFwcHM7XG4gIGlmICghYXBwcyB8fCBPYmplY3Qua2V5cyhhcHBzKS5sZW5ndGggPT09IDApIHJldHVybiB7fTtcblxuICBjb25zdCBrZXkgPSBwaWNrQXBwUmVzb3VyY2VJZChhcHBzKTtcbiAgaWYgKCFrZXkpIHJldHVybiB7fTtcblxuICBjb25zdCBhcHAgPSBhcHBzW2tleV07XG4gIGlmICghYXBwPy5jb25maWc/LmVudj8ubGVuZ3RoKSByZXR1cm4ge307XG5cbiAgY29uc3QgcmVzb3VyY2VCeU5hbWUgPSBuZXcgTWFwKFxuICAgIChhcHAucmVzb3VyY2VzID8/IFtdKVxuICAgICAgLmZpbHRlcigocmVzb3VyY2UpID0+IHJlc291cmNlLm5hbWUpXG4gICAgICAubWFwKChyZXNvdXJjZSkgPT4gW3Jlc291cmNlLm5hbWUhLCByZXNvdXJjZV0pLFxuICApO1xuXG4gIGNvbnN0IG91dDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGFwcC5jb25maWcuZW52KSB7XG4gICAgaWYgKCFlbnRyeS5uYW1lKSBjb250aW51ZTtcbiAgICBjb25zdCB2YWx1ZSA9IGNvcmVDb25maWcudmFsdWVTY2hlbWEuc2FmZVBhcnNlKGVudHJ5LnZhbHVlKTtcbiAgICBpZiAodmFsdWUuc3VjY2Vzcykge1xuICAgICAgb3V0W2VudHJ5Lm5hbWVdID0gdmFsdWUuZGF0YTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAoIWVudHJ5LnZhbHVlX2Zyb20pIGNvbnRpbnVlO1xuICAgIGNvbnN0IHJlc29sdmVkID0gcmVzb2x2ZVJlc291cmNlVmFsdWUocmVzb3VyY2VCeU5hbWUuZ2V0KGVudHJ5LnZhbHVlX2Zyb20pKTtcbiAgICBpZiAocmVzb2x2ZWQpIG91dFtlbnRyeS5uYW1lXSA9IHJlc29sdmVkO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGxvYWRBcHBZYW1sKGN3ZDogc3RyaW5nKTogUHJvbWlzZTxDb25maWdGaWxlIHwgdW5kZWZpbmVkPiB7XG4gIGZvciAoY29uc3QgZmlsZU5hbWUgb2YgQVBQX1lBTUxfTkFNRVMpIHtcbiAgICBjb25zdCBjb25maWdGaWxlID0gcmVzb2x2ZUNvbmZpZ0ZpbGUoY3dkLCBmaWxlTmFtZSk7XG4gICAgaWYgKCFjb25maWdGaWxlKSBjb250aW51ZTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdGV4dCA9IGF3YWl0IHJlYWRGaWxlKGNvbmZpZ0ZpbGUsIFwidXRmOFwiKTtcbiAgICAgIGNvbnN0IGRhdGEgPSBwYXJzZVlhbWwodGV4dCk7XG4gICAgICBpZiAoIW9iamVjdC5pc1JlY29yZChkYXRhKSkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHsgcGF0aDogY29uZmlnRmlsZSwgZGF0YSB9O1xuICAgIH0gY2F0Y2gge1xuICAgICAgbG9nZ2VyLndhcm4oXCJmYWlsZWQgdG8gcGFyc2UgYXBwIHlhbWxcIiwgeyBwYXRoOiBjb25maWdGaWxlIH0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ29uZmlnRmlsZShjd2Q6IHN0cmluZywgY29uZmlnRmlsZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKGNvcmVDb25maWcuaXNEYXRhYnJpY2tzQXBwRW52KCkpIHJldHVybiB1bmRlZmluZWQ7XG4gIGZvciAoY29uc3Qgcm9vdERpciBvZiBwcm9qZWN0LnJlc29sdmVQcm9qZWN0Um9vdHMoY3dkKSkge1xuICAgIGNvbnN0IGJ1bmRsZVBhdGggPSByZXNvbHZlKHJvb3REaXIsIGNvbmZpZ0ZpbGUpO1xuICAgIGlmIChmaWxlLnN0YXRTeW5jKGJ1bmRsZVBhdGgpPy5pc0ZpbGUoKSkgcmV0dXJuIGJ1bmRsZVBhdGg7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBUaGUgdmFsaWRhdGVkIGJ1bmRsZSBmb3IgYGN3ZGAgLSB7QGxpbmsgY29yZUNvbmZpZy5idW5kbGVGaWxlfSwgd2hpY2ggY2FjaGVzIGl0XG4gKiBwZXIgd29ya2luZyBkaXJlY3RvcnkuIFJldHVybnMgYHVuZGVmaW5lZGAgaW5zaWRlIGEgRGF0YWJyaWNrcyBBcHAsIHdoZXJlIHRoZVxuICogcGxhdGZvcm0gaGFzIGFscmVhZHkgdHVybmVkIGBjb25maWcuZW52YCBpbnRvIHJlYWwgZW52aXJvbm1lbnQgdmFyaWFibGVzIGFuZFxuICogdGhlcmUgaXMgbm8gYnVuZGxlIHRvIHZhbGlkYXRlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVuZGxlKGN3ZD86IHN0cmluZyk6IFByb21pc2U8Q29uZmlnRmlsZSB8IHVuZGVmaW5lZD4ge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGNvcmVDb25maWcuaXNEYXRhYnJpY2tzQXBwRW52KCkgPyB1bmRlZmluZWQgOiBjb3JlQ29uZmlnLmJ1bmRsZUZpbGUoY3dkKSk7XG59XG5cbi8qKlxuICogTG9jYXRlIGFuZCBwYXJzZSBgYXBwLnlhbWxgIC8gYGFwcC55bWxgIGZyb20gdGhlIGJ1bmRsZSBvciBwcm9qZWN0IHJvb3QuXG4gKiBDYWNoZWQgcGVyIHdvcmtpbmcgZGlyZWN0b3J5IHRocm91Z2gge0BsaW5rIGNvbnRleHQuY2FjaGVkfSwgc28gYSBgY3dkYCBjaGFuZ2VcbiAqIHJlLXJlYWRzIGluc3RlYWQgb2YgcmV0dXJuaW5nIGFub3RoZXIgcHJvamVjdCdzIGZpbGUuIFJldHVybnMgYHVuZGVmaW5lZGBcbiAqIGluc2lkZSBhIERhdGFicmlja3MgQXBwLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwWWFtbChjd2Q/OiBzdHJpbmcpOiBQcm9taXNlPENvbmZpZ0ZpbGUgfCB1bmRlZmluZWQ+IHtcbiAgaWYgKGNvcmVDb25maWcuaXNEYXRhYnJpY2tzQXBwRW52KCkpIHJldHVybiBQcm9taXNlLnJlc29sdmUodW5kZWZpbmVkKTtcbiAgcmV0dXJuIGNvbnRleHQuY2FjaGVkKFtcImFwcGtpdFwiLCBcImFwcFlhbWxcIl0sIChyZXNvbHZlZCkgPT4gbG9hZEFwcFlhbWwocmVzb2x2ZWQgPz8gXCIuXCIpLCBjd2QpO1xufVxuXG4vKipcbiAqIFdhbGsgYSBkb3Qtc2VwYXJhdGVkIHBhdGggdGhyb3VnaCBidW5kbGUgdmFsaWRhdGUgSlNPTi4gV2hlbiB0aGUgdGVybWluYWxcbiAqIG5vZGUgaXMgYSBidW5kbGUgdmFyaWFibGUgb2JqZWN0IChgeyB2YWx1ZTogXCIuLi5cIiB9YCksIHRoZSBgdmFsdWVgIGZpZWxkIGlzXG4gKiByZXR1cm5lZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEJ1bmRsZVBhdGgoZGF0YTogQnVuZGxlVmFsaWRhdGVKc29uLCBwYXRoOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBwYXJ0cyA9IHBhdGguc3BsaXQoXCIuXCIpLmZpbHRlcihCb29sZWFuKTtcbiAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICBsZXQgY3VycmVudDogdW5rbm93biA9IGRhdGE7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIW9iamVjdC5pc1JlY29yZChjdXJyZW50KSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBjb25zdCBwYXJ0ID0gcGFydHNbaV0hO1xuICAgIGNvbnN0IG5leHQgPSBjdXJyZW50W3BhcnRdO1xuICAgIGlmIChpID09PSBwYXJ0cy5sZW5ndGggLSAxKSB7XG4gICAgICBpZiAodHlwZW9mIG5leHQgPT09IFwic3RyaW5nXCIgJiYgbmV4dCkgcmV0dXJuIG5leHQ7XG4gICAgICBpZiAob2JqZWN0LmlzUmVjb3JkKG5leHQpKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gbmV4dC52YWx1ZTtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiB2YWx1ZSA/IHZhbHVlIDogdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgY3VycmVudCA9IG5leHQ7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUFwcEVudk1hcChcbiAgb3B0aW9uczogUmVzb2x2ZUNvbmZpZ1ZhbHVlT3B0aW9ucyxcbik6IFByb21pc2U8UmVjb3JkPHN0cmluZywgc3RyaW5nPj4ge1xuICBjb25zdCBhcHBEYXRhID0gb3B0aW9ucy5hcHBEYXRhID8/IChhd2FpdCBhcHBZYW1sKCkpO1xuICBjb25zdCBidW5kbGVEYXRhID0gb3B0aW9ucy5idW5kbGVEYXRhID8/IChhd2FpdCBidW5kbGUoKSk7XG4gIGNvbnN0IGZyb21ZYW1sID0gYXBwRGF0YSA/IGZsYXR0ZW5BcHBZYW1sRW52KGFwcERhdGEuZGF0YSkgOiB7fTtcbiAgY29uc3QgZnJvbUJ1bmRsZSA9IGJ1bmRsZURhdGEgPyBmbGF0dGVuQXBwRW52KGJ1bmRsZURhdGEuZGF0YSkgOiB7fTtcbiAgcmV0dXJuIHsgLi4uZnJvbVlhbWwsIC4uLmZyb21CdW5kbGUgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVNvdXJjZXMob3B0aW9uczogUmVzb2x2ZUNvbmZpZ1ZhbHVlT3B0aW9ucyk6IENvbmZpZ1NvdXJjZVtdIHtcbiAgY29uc3Qgc291cmNlcyA9IFsuLi4ob3B0aW9ucy5zb3VyY2VzID8/IGRlZmF1bHRDb25maWdTb3VyY2VzKV07XG4gIGlmIChvcHRpb25zLmV4cGxpY2l0ICE9PSB1bmRlZmluZWQgJiYgIXNvdXJjZXMuaW5jbHVkZXMoXCJleHBsaWNpdFwiKSkge1xuICAgIHNvdXJjZXMudW5zaGlmdChcImV4cGxpY2l0XCIpO1xuICB9XG4gIHJldHVybiBzb3VyY2VzO1xufVxuXG4vKipcbiAqIFJlc29sdmUgYSBjb25maWd1cmF0aW9uIHN0cmluZyBmcm9tIHRoZSBjb25maWd1cmVkIHNvdXJjZXMuIFJldHVybnMgdGhlIGZpcnN0XG4gKiBub24tZW1wdHkgdmFsdWUsIG9yIGB1bmRlZmluZWRgIHdoZW4gbm90aGluZyBtYXRjaGVzLlxuICpcbiAqIFByZWNlZGVuY2UgZm9sbG93cyBBcHBLaXQnczogZXhwbGljaXQgY29uZmlnLCB0aGVuIGVudmlyb25tZW50IHZhcmlhYmxlLCB0aGVuXG4gKiB3aGF0ZXZlciB0aGUgRGF0YWJyaWNrcyBBcHAgLyBidW5kbGUgZGVmaW5pdGlvbiBzdXBwbGllcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IHsgYnVuZGxlIH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG4gKlxuICogY29uc3Qgd2FyZWhvdXNlSWQgPSBhd2FpdCBidW5kbGUucmVzb2x2ZUNvbmZpZ1ZhbHVlKFwiREFUQUJSSUNLU19XQVJFSE9VU0VfSURcIiwge1xuICogICBjbGk6IHsgREFUQUJSSUNLU19XQVJFSE9VU0VfSUQ6IGZsYWdzLndhcmVob3VzZSB9LFxuICogICBzb3VyY2VzOiBidW5kbGUud2l0aENsaVNvdXJjZXMoKSxcbiAqIH0pO1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUNvbmZpZ1ZhbHVlKFxuICBuYW1lOiBzdHJpbmcsXG4gIG9wdGlvbnM6IFJlc29sdmVDb25maWdWYWx1ZU9wdGlvbnMgPSB7fSxcbik6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IGtleXMgPSBlbnZLZXlzRm9yTmFtZShuYW1lKS50b0FycmF5KCk7XG4gIGlmIChrZXlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3Qgc291cmNlcyA9IHJlc29sdmVTb3VyY2VzKG9wdGlvbnMpO1xuICBsZXQgYXBwRW52TWFwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgdW5kZWZpbmVkO1xuICBjb25zdCB2YWx1ZXMgPSAoYXN5bmMgZnVuY3Rpb24qICgpIHtcbiAgICBmb3IgKGNvbnN0IHNvdXJjZSBvZiBzb3VyY2VzKSB7XG4gICAgICBzd2l0Y2ggKHNvdXJjZSkge1xuICAgICAgICBjYXNlIFwiZXhwbGljaXRcIjpcbiAgICAgICAgICB5aWVsZCByZWFkTWFwKGtleXMsIG9wdGlvbnMuZXhwbGljaXQpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiY2xpXCI6XG4gICAgICAgICAgeWllbGQgcmVhZE1hcChrZXlzLCBvcHRpb25zLmNsaSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJlbnZcIjpcbiAgICAgICAgICB5aWVsZCByZWFkRW52KGtleXMpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiYnVuZGxlXCI6XG4gICAgICAgICAgaWYgKGFwcEVudk1hcCA9PT0gdW5kZWZpbmVkKSBhcHBFbnZNYXAgPSBhd2FpdCByZXNvbHZlQXBwRW52TWFwKG9wdGlvbnMpO1xuICAgICAgICAgIHlpZWxkIHJlYWRBcHBFbnYoa2V5cywgYXBwRW52TWFwKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBWYWxpZGF0aW9uRXJyb3IuaW52YWxpZFZhbHVlKFxuICAgICAgICAgICAgXCJzb3VyY2VzXCIsXG4gICAgICAgICAgICBzb3VyY2UsXG4gICAgICAgICAgICBcIm9uZSBvZjogZXhwbGljaXQsIGNsaSwgZW52LCBidW5kbGVcIixcbiAgICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfSkoKTtcbiAgZm9yIGF3YWl0IChjb25zdCB2YWx1ZSBvZiB2YWx1ZXMpIHtcbiAgICBpZiAodmFsdWUpIHJldHVybiB2YWx1ZTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFNvdXJjZXMgd2l0aCBgY2xpYCBpbmNsdWRlZCwgaW4gQ0xJLWZpcnN0IG9yZGVyLiBVc2UgZm9yIGRldiBjb21tYW5kcyB0aGF0XG4gKiBhY2NlcHQgZmxhZyBvdmVycmlkZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3aXRoQ2xpU291cmNlcyhzb3VyY2VzOiBDb25maWdTb3VyY2VbXSA9IGRlZmF1bHRDb25maWdTb3VyY2VzKTogQ29uZmlnU291cmNlW10ge1xuICBjb25zdCByZXN0ID0gc291cmNlcy5maWx0ZXIoKHNvdXJjZSkgPT4gc291cmNlICE9PSBcImNsaVwiICYmIHNvdXJjZSAhPT0gXCJleHBsaWNpdFwiKTtcbiAgcmV0dXJuIFtcImNsaVwiLCBcImV4cGxpY2l0XCIsIC4uLnJlc3RdO1xufVxuIl19
|