@dbx-tools/appkit 0.3.44 → 0.4.1
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/index.d.ts +23 -0
- package/lib/index.js +20 -0
- package/lib/src/appkit.d.ts +51 -0
- package/lib/src/appkit.js +57 -0
- package/lib/src/config.d.ts +89 -0
- package/lib/src/config.js +403 -0
- package/lib/src/create-app.d.ts +72 -0
- package/lib/src/create-app.js +120 -0
- package/lib/src/databricks.d.ts +60 -0
- package/lib/src/databricks.js +107 -0
- package/lib/src/lakebase-resolver.d.ts +122 -0
- package/lib/src/lakebase-resolver.js +679 -0
- package/lib/src/pgaddress.d.ts +104 -0
- package/lib/src/pgaddress.js +171 -0
- package/lib/src/plugin.d.ts +90 -0
- package/lib/src/plugin.js +97 -0
- package/lib/src/provision.d.ts +51 -0
- package/lib/src/provision.js +133 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +11 -7
|
@@ -0,0 +1,403 @@
|
|
|
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7O0dBWUc7QUFFSCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDL0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDbkYsT0FBTyxFQUFFLEtBQUssSUFBSSxhQUFhLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDOUMsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUV4QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXhDLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7QUFjcEMsTUFBTSxvQkFBb0IsR0FBbUIsQ0FBQyxVQUFVLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBRTNFLE1BQU0sY0FBYyxHQUFHLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBVSxDQUFDO0FBRXhELE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxHQUFHLEVBQTBDLENBQUM7QUFFOUUsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDO0tBQ3ZCLE1BQU0sRUFBRTtLQUNSLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO0tB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QUEwQixvQkFBb0I7SUFDM0UsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxLQUFLLEtBQUssSUFBSSxNQUFNLEtBQUssVUFBVSxDQUFDLENBQUM7SUFDbkYsT0FBTyxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztBQUN0QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBMYXllcmVkIGNvbmZpZ3VyYXRpb24gcmVzb2x1dGlvbiBmb3IgbG9jYWwgZGV2ZWxvcG1lbnQgYWdhaW5zdCBhIERhdGFicmlja3NcbiAqIEFwcCAvIEFzc2V0IEJ1bmRsZS5cbiAqXG4gKiBEZWZhdWx0IHNvdXJjZXM6IGBleHBsaWNpdGAsIHRoZW4gYGVudmAsIHRoZW4gRGF0YWJyaWNrcyBBcHAgYGNvbmZpZy5lbnZgXG4gKiAoZnJvbSB7QGxpbmsgYnVuZGxlfSkgYW5kIGhhcmQtY29kZWQgYGFwcC55YW1sYCBlbnYgZW50cmllcyAoZnJvbVxuICoge0BsaW5rIGFwcFlhbWx9KS4gT3B0IGluIHRvIGBjbGlgIHdoZW4gYSBkZXYgY29tbWFuZCB3YW50cyBmbGFnIG92ZXJyaWRlcy5cbiAqXG4gKiBTZXJ2ZXItb25seSAoYG5vZGU6Y2hpbGRfcHJvY2Vzc2AsIGJ1bmRsZSByb290IGRpc2NvdmVyeSkuIERhdGFicmlja3MtYXBwXG4gKiBzcGVjaWZpYywgc28gaXQgbGl2ZXMgaW4gbm9kZS1hcHBraXQgcmF0aGVyIHRoYW4gc2hhcmVkLWNvcmUuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IHNwYXduU3luYyB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IHJlYWRGaWxlIH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IGRpcm5hbWUsIHJlc29sdmUgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBmaWxlLCBwcm9qZWN0IH0gZnJvbSBcIkBkYngtdG9vbHMvY29yZVwiO1xuaW1wb3J0IHsgZnVuY3Rpb25Nb2R1bGUsIGpzb24sIG9iamVjdCwgbG9nLCBzdHJpbmcgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgcGFyc2UgYXMgcGFyc2VZYW1sVGV4dCB9IGZyb20gXCJ5YW1sXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuXG5pbXBvcnQgeyBpc0FwcEVudiB9IGZyb20gXCIuL2RhdGFicmlja3NcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImNvbmZpZ1wiKTtcblxuLyoqIFBhcnNlZCBwYXlsb2FkIGZyb20gYGRhdGFicmlja3MgYnVuZGxlIHZhbGlkYXRlIC0tb3V0cHV0IGpzb25gLiAqL1xuZXhwb3J0IHR5cGUgQnVuZGxlVmFsaWRhdGVKc29uID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG5cbi8qKiBBIGNvbmZpZyBmaWxlIGRpc2NvdmVyZWQgb24gZGlzayB3aXRoIGl0cyBwYXJzZWQgY29udGVudHMuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbmZpZ0ZpbGUge1xuICBwYXRoOiBzdHJpbmc7XG4gIGRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xufVxuXG4vKiogU3VwcG9ydGVkIGNvbmZpZ3VyYXRpb24gc291cmNlcywgY29uc3VsdGVkIGluIGFycmF5IG9yZGVyLiAqL1xuZXhwb3J0IHR5cGUgQ29uZmlnU291cmNlID0gXCJleHBsaWNpdFwiIHwgXCJjbGlcIiB8IFwiZW52XCIgfCBcImJ1bmRsZVwiO1xuXG5jb25zdCBkZWZhdWx0Q29uZmlnU291cmNlczogQ29uZmlnU291cmNlW10gPSBbXCJleHBsaWNpdFwiLCBcImVudlwiLCBcImJ1bmRsZVwiXTtcblxuY29uc3QgQVBQX1lBTUxfTkFNRVMgPSBbXCJhcHAueWFtbFwiLCBcImFwcC55bWxcIl0gYXMgY29uc3Q7XG5cbmNvbnN0IGJ1bmRsZVZhbGlkYXRlQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgQnVuZGxlVmFsaWRhdGVKc29uIHwgdW5kZWZpbmVkPigpO1xuXG5jb25zdCBub3JtYWxpemVkU3RyaW5nID0gelxuICAuc3RyaW5nKClcbiAgLnRyYW5zZm9ybSgodmFsdWUpID0+IHZhbHVlLnRyaW0oKSlcbiAgLnBpcGUoei5zdHJpbmcoKS5taW4oMSkpO1xuXG5jb25zdCBidW5kbGVBcHBFbnZFbnRyeVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgbmFtZTogbm9ybWFsaXplZFN0cmluZy5vcHRpb25hbCgpLFxuICB2YWx1ZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICB2YWx1ZV9mcm9tOiBub3JtYWxpemVkU3RyaW5nLm9wdGlvbmFsKCksXG59KTtcblxuY29uc3QgYnVuZGxlQXBwUmVzb3VyY2VTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIG5hbWU6IG5vcm1hbGl6ZWRTdHJpbmcub3B0aW9uYWwoKSxcbiAgc3FsX3dhcmVob3VzZTogei5vYmplY3QoeyBpZDogbm9ybWFsaXplZFN0cmluZy5vcHRpb25hbCgpIH0pLm9wdGlvbmFsKCksXG4gIGdlbmllX3NwYWNlOiB6Lm9iamVjdCh7IHNwYWNlX2lkOiBub3JtYWxpemVkU3RyaW5nLm9wdGlvbmFsKCkgfSkub3B0aW9uYWwoKSxcbiAgcG9zdGdyZXM6IHpcbiAgICAub2JqZWN0KHtcbiAgICAgIGRhdGFiYXNlOiBub3JtYWxpemVkU3RyaW5nLm9wdGlvbmFsKCksXG4gICAgICBicmFuY2g6IG5vcm1hbGl6ZWRTdHJpbmcub3B0aW9uYWwoKSxcbiAgICAgIGVuZHBvaW50OiBub3JtYWxpemVkU3RyaW5nLm9wdGlvbmFsKCksXG4gICAgfSlcbiAgICAub3B0aW9uYWwoKSxcbn0pO1xuXG5jb25zdCBidW5kbGVBcHBTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIG5hbWU6IG5vcm1hbGl6ZWRTdHJpbmcub3B0aW9uYWwoKSxcbiAgc291cmNlX2NvZGVfcGF0aDogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICBjb25maWc6IHoub2JqZWN0KHsgZW52OiB6LmFycmF5KGJ1bmRsZUFwcEVudkVudHJ5U2NoZW1hKS5vcHRpb25hbCgpIH0pLm9wdGlvbmFsKCksXG4gIHJlc291cmNlczogei5hcnJheShidW5kbGVBcHBSZXNvdXJjZVNjaGVtYSkub3B0aW9uYWwoKSxcbn0pO1xuXG5jb25zdCBidW5kbGVWYWxpZGF0ZUFwcHNTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIHJlc291cmNlczogei5vYmplY3QoeyBhcHBzOiB6LnJlY29yZCh6LnN0cmluZygpLCBidW5kbGVBcHBTY2hlbWEpLm9wdGlvbmFsKCkgfSkub3B0aW9uYWwoKSxcbn0pO1xuXG5jb25zdCBhcHBZYW1sRW52RW50cnlTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIG5hbWU6IG5vcm1hbGl6ZWRTdHJpbmcsXG4gIHZhbHVlOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIHZhbHVlRnJvbTogbm9ybWFsaXplZFN0cmluZy5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IGFwcFlhbWxSZXNvdXJjZVNjaGVtYSA9IHpcbiAgLm9iamVjdCh7XG4gICAgbmFtZTogbm9ybWFsaXplZFN0cmluZyxcbiAgICBzcWxfd2FyZWhvdXNlOiB6Lm9iamVjdCh7IGlkOiBub3JtYWxpemVkU3RyaW5nLm9wdGlvbmFsKCkgfSkub3B0aW9uYWwoKSxcbiAgICBnZW5pZV9zcGFjZTogei5vYmplY3QoeyBzcGFjZV9pZDogbm9ybWFsaXplZFN0cmluZy5vcHRpb25hbCgpIH0pLm9wdGlvbmFsKCksXG4gICAgcG9zdGdyZXM6IHpcbiAgICAgIC5vYmplY3Qoe1xuICAgICAgICBkYXRhYmFzZTogbm9ybWFsaXplZFN0cmluZy5vcHRpb25hbCgpLFxuICAgICAgICBicmFuY2g6IG5vcm1hbGl6ZWRTdHJpbmcub3B0aW9uYWwoKSxcbiAgICAgICAgZW5kcG9pbnQ6IG5vcm1hbGl6ZWRTdHJpbmcub3B0aW9uYWwoKSxcbiAgICAgIH0pXG4gICAgICAub3B0aW9uYWwoKSxcbiAgfSlcbiAgLnBhc3N0aHJvdWdoKCk7XG5cbmNvbnN0IGFwcFlhbWxTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGVudjogei5hcnJheShhcHBZYW1sRW52RW50cnlTY2hlbWEpLm9wdGlvbmFsKCksXG4gIHJlc291cmNlczogei5hcnJheShhcHBZYW1sUmVzb3VyY2VTY2hlbWEpLm9wdGlvbmFsKCksXG59KTtcblxudHlwZSBCdW5kbGVBcHAgPSB6LmluZmVyPHR5cGVvZiBidW5kbGVBcHBTY2hlbWE+O1xuXG4vKiogU2luZ2xlIGNvbmZpZyBtYXAgZW50cnkgKHN0cmluZyBvciByZXBlYXRlZCB2YWx1ZXMsIGxpa2UgaGVhZGVycykuICovXG5leHBvcnQgdHlwZSBDb25maWdNYXBWYWx1ZSA9IHN0cmluZyB8IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJlc29sdmVDb25maWdWYWx1ZU9wdGlvbnMge1xuICAvKiogQnVuZGxlIHZhbGlkYXRlIEpTT04uIERlZmF1bHRzIHRvIHtAbGluayBidW5kbGV9IChza2lwcGVkIGluc2lkZSBhIERhdGFicmlja3MgQXBwKS4gKi9cbiAgYnVuZGxlRGF0YT86IENvbmZpZ0ZpbGU7XG4gIC8qKiBQYXJzZWQgYGFwcC55YW1sYCBjb250ZW50cy4gRGVmYXVsdHMgdG8ge0BsaW5rIGFwcFlhbWx9IChza2lwcGVkIGluc2lkZSBhIERhdGFicmlja3MgQXBwKS4gKi9cbiAgYXBwRGF0YT86IENvbmZpZ0ZpbGU7XG4gIC8qKlxuICAgKiBTb3VyY2VzIHRvIGNvbnN1bHQsIGZpcnN0IHRydXRoeSBzdHJpbmcgd2lucy4gRGVmYXVsdHMgdG8gYGV4cGxpY2l0YCwgdGhlblxuICAgKiBgZW52YCwgdGhlbiBgYnVuZGxlYC5cbiAgICovXG4gIHNvdXJjZXM/OiBDb25maWdTb3VyY2VbXTtcbiAgLyoqIFByb2dyYW1tYXRpYyBvdmVycmlkZXMuIFdoZW4gc2V0LCBgZXhwbGljaXRgIGlzIHByZXBlbmRlZCB0byBgc291cmNlc2AgdW5sZXNzIGFscmVhZHkgbGlzdGVkLiAqL1xuICBleHBsaWNpdD86IFJlY29yZDxzdHJpbmcsIENvbmZpZ01hcFZhbHVlPjtcbiAgLyoqIENMSSBmbGFnIHZhbHVlcyAod2hlbiBgY2xpYCBpcyBsaXN0ZWQgaW4gYHNvdXJjZXNgKS4gKi9cbiAgY2xpPzogUmVjb3JkPHN0cmluZywgQ29uZmlnTWFwVmFsdWU+O1xufVxuXG5jb25zdCBidW5kbGVEZWZhdWx0ID0gZnVuY3Rpb25Nb2R1bGUubWVtb2l6ZSgoKSA9PiBsb2FkQnVuZGxlKHByb2Nlc3MuY3dkKCkpKTtcbmNvbnN0IGFwcFlhbWxEZWZhdWx0ID0gZnVuY3Rpb25Nb2R1bGUubWVtb2l6ZSgoKSA9PiBsb2FkQXBwWWFtbChwcm9jZXNzLmN3ZCgpKSk7XG5cbmZ1bmN0aW9uIGVudktleXNGb3JOYW1lKG5hbWU6IHN0cmluZyk6IG9iamVjdC5TZXF1ZW5jZTxzdHJpbmc+IHtcbiAgY29uc3QgdHJpbW1lZCA9IG5hbWUudHJpbSgpO1xuICBpZiAoIXRyaW1tZWQpIHtcbiAgICByZXR1cm4gb2JqZWN0LnNlcXVlbmNlKCk7XG4gIH1cbiAgY29uc3Qga2V5cyA9IChmdW5jdGlvbiogKCkge1xuICAgIGNvbnN0IG1vZGlmaWVyczogKCgodmFsdWU6IHN0cmluZykgPT4gc3RyaW5nKSB8IG51bGwpW10gPSBbXG4gICAgICBudWxsLFxuICAgICAgKCkgPT4gdHJpbW1lZC50b1VwcGVyQ2FzZSgpLFxuICAgICAgKCkgPT4gQXJyYXkuZnJvbShzdHJpbmcudG9rZW5pemUodHJpbW1lZCkpLmpvaW4oXCJfXCIpLnRvVXBwZXJDYXNlKCksXG4gICAgXTtcbiAgICBmb3IgKGNvbnN0IG1vZGlmaWVyIG9mIG1vZGlmaWVycykge1xuICAgICAgeWllbGQgbW9kaWZpZXIgPyBtb2RpZmllcih0cmltbWVkKSA6IHRyaW1tZWQ7XG4gICAgfVxuICB9KSgpO1xuICByZXR1cm4gb2JqZWN0LnNlcXVlbmNlKGtleXMpLmNhY2hlKCkuZmlsdGVyKEJvb2xlYW4pLmRpc3RpbmN0KCk7XG59XG5cbmZ1bmN0aW9uIHJlYWRFbnYoa2V5czogSXRlcmFibGU8c3RyaW5nPik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcbiAgICBjb25zdCB2YWx1ZSA9IHByb2Nlc3MuZW52W2tleV0/LnRyaW0oKTtcbiAgICBpZiAodmFsdWUpIHJldHVybiB2YWx1ZTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiByZWFkQ29uZmlnTWFwVmFsdWUodmFsdWU6IENvbmZpZ01hcFZhbHVlKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKHZhbHVlID09IG51bGwpIHJldHVybiB1bmRlZmluZWQ7XG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiB2YWx1ZSkge1xuICAgICAgY29uc3QgdHJpbW1lZCA9IGl0ZW0/LnRyaW0oKTtcbiAgICAgIGlmICh0cmltbWVkKSByZXR1cm4gdHJpbW1lZDtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICBjb25zdCB0cmltbWVkID0gdmFsdWUudHJpbSgpO1xuICByZXR1cm4gdHJpbW1lZCB8fCB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHJlYWRNYXAoXG4gIGtleXM6IEl0ZXJhYmxlPHN0cmluZz4sXG4gIG1hcDogUmVjb3JkPHN0cmluZywgQ29uZmlnTWFwVmFsdWU+IHwgdW5kZWZpbmVkLFxuKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFtYXApIHJldHVybiB1bmRlZmluZWQ7XG4gIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcbiAgICBjb25zdCB2YWx1ZSA9IHJlYWRDb25maWdNYXBWYWx1ZShtYXBba2V5XSk7XG4gICAgaWYgKHZhbHVlKSByZXR1cm4gdmFsdWU7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gcmVhZEFwcEVudihrZXlzOiBJdGVyYWJsZTxzdHJpbmc+LCBlbnZNYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgY29uc3QgdmFsdWUgPSBlbnZNYXBba2V5XT8udHJpbSgpO1xuICAgIGlmICh2YWx1ZSkgcmV0dXJuIHZhbHVlO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHBhcnNlWWFtbCh0ZXh0OiBzdHJpbmcpOiB1bmtub3duIHtcbiAgcmV0dXJuIHBhcnNlWWFtbFRleHQodGV4dCk7XG59XG5cbmZ1bmN0aW9uIHBpY2tBcHBSZXNvdXJjZUlkKGFwcHM6IFJlY29yZDxzdHJpbmcsIEJ1bmRsZUFwcD4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoYXBwcyk7XG4gIHJldHVybiBrZXlzLmxlbmd0aCA9PT0gMSA/IGtleXNbMF0gOiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgZWZmZWN0aXZlIHZhbHVlIGEgYHZhbHVlX2Zyb21gL2B2YWx1ZUZyb21gIGVudHJ5IHBvaW50cyBhdDpcbiAqIHRoZSBmaXJzdCBwcmVzZW50IG9mIHRoZSB3YXJlaG91c2UgaWQsIEdlbmllIHNwYWNlIGlkLCBvciBQb3N0Z3Jlc1xuICogZW5kcG9pbnQvZGF0YWJhc2UvYnJhbmNoIG9uIHRoZSBuYW1lZCByZXNvdXJjZS4gU2hhcmVkIGJ5IGJvdGggdGhlXG4gKiBgYXBwLnlhbWxgIGFuZCBgYnVuZGxlIHZhbGlkYXRlYCBmbGF0dGVuZXJzLCB3aG9zZSByZXNvdXJjZSBzaGFwZXMgbWF0Y2guXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVSZXNvdXJjZVZhbHVlKFxuICByZXNvdXJjZTogei5pbmZlcjx0eXBlb2YgYnVuZGxlQXBwUmVzb3VyY2VTY2hlbWE+IHwgdW5kZWZpbmVkLFxuKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIChcbiAgICByZXNvdXJjZT8uc3FsX3dhcmVob3VzZT8uaWQgPz9cbiAgICByZXNvdXJjZT8uZ2VuaWVfc3BhY2U/LnNwYWNlX2lkID8/XG4gICAgcmVzb3VyY2U/LnBvc3RncmVzPy5lbmRwb2ludCA/P1xuICAgIHJlc291cmNlPy5wb3N0Z3Jlcz8uZGF0YWJhc2UgPz9cbiAgICByZXNvdXJjZT8ucG9zdGdyZXM/LmJyYW5jaFxuICApO1xufVxuXG4vKipcbiAqIEZsYXR0ZW4gYGVudmAgZW50cmllcyBmcm9tIHBhcnNlZCBgYXBwLnlhbWxgIGNvbnRlbnQuIExpdGVyYWwgYHZhbHVlYCBlbnRyaWVzXG4gKiBhcmUgcmV0dXJuZWQgYXMtaXM7IGB2YWx1ZUZyb21gIGVudHJpZXMgcmVzb2x2ZSBhZ2FpbnN0IHRoZSBzaWJsaW5nXG4gKiBgcmVzb3VyY2VzYCBhcnJheSB3aGVuIHBvc3NpYmxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmxhdHRlbkFwcFlhbWxFbnYoZGF0YTogdW5rbm93bik6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCBwYXJzZWQgPSBhcHBZYW1sU2NoZW1hLnNhZmVQYXJzZShkYXRhKTtcbiAgaWYgKCFwYXJzZWQuc3VjY2VzcyB8fCAhcGFyc2VkLmRhdGEuZW52Py5sZW5ndGgpIHtcbiAgICByZXR1cm4ge307XG4gIH1cblxuICBjb25zdCByZXNvdXJjZUJ5TmFtZSA9IG5ldyBNYXAoXG4gICAgKHBhcnNlZC5kYXRhLnJlc291cmNlcyA/PyBbXSkubWFwKChyZXNvdXJjZSkgPT4gW3Jlc291cmNlLm5hbWUsIHJlc291cmNlXSksXG4gICk7XG5cbiAgY29uc3Qgb3V0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gIGZvciAoY29uc3QgZW50cnkgb2YgcGFyc2VkLmRhdGEuZW52KSB7XG4gICAgaWYgKGVudHJ5LnZhbHVlPy50cmltKCkpIHtcbiAgICAgIG91dFtlbnRyeS5uYW1lXSA9IGVudHJ5LnZhbHVlLnRyaW0oKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAoIWVudHJ5LnZhbHVlRnJvbSkgY29udGludWU7XG4gICAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlUmVzb3VyY2VWYWx1ZShyZXNvdXJjZUJ5TmFtZS5nZXQoZW50cnkudmFsdWVGcm9tKSk7XG4gICAgaWYgKHJlc29sdmVkKSBvdXRbZW50cnkubmFtZV0gPSByZXNvbHZlZDtcbiAgfVxuICByZXR1cm4gb3V0O1xufVxuXG4vKipcbiAqIEZsYXR0ZW4gYHJlc291cmNlcy5hcHBzLjxrZXk+LmNvbmZpZy5lbnZgIGludG8gYSBgbmFtZSAtPiB2YWx1ZWAgbWFwLlxuICogQXV0by1waWNrcyB0aGUgYXBwIG9ubHkgd2hlbiB0aGUgYnVuZGxlIGRlZmluZXMgZXhhY3RseSBvbmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0dGVuQXBwRW52KGRhdGE6IHVua25vd24pOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgY29uc3QgcGFyc2VkID0gYnVuZGxlVmFsaWRhdGVBcHBzU2NoZW1hLnNhZmVQYXJzZShkYXRhKTtcbiAgaWYgKCFwYXJzZWQuc3VjY2VzcykgcmV0dXJuIHt9O1xuXG4gIGNvbnN0IGFwcHMgPSBwYXJzZWQuZGF0YS5yZXNvdXJjZXM/LmFwcHM7XG4gIGlmICghYXBwcyB8fCBPYmplY3Qua2V5cyhhcHBzKS5sZW5ndGggPT09IDApIHJldHVybiB7fTtcblxuICBjb25zdCBrZXkgPSBwaWNrQXBwUmVzb3VyY2VJZChhcHBzKTtcbiAgaWYgKCFrZXkpIHJldHVybiB7fTtcblxuICBjb25zdCBhcHAgPSBhcHBzW2tleV07XG4gIGlmICghYXBwPy5jb25maWc/LmVudj8ubGVuZ3RoKSByZXR1cm4ge307XG5cbiAgY29uc3QgcmVzb3VyY2VCeU5hbWUgPSBuZXcgTWFwKFxuICAgIChhcHAucmVzb3VyY2VzID8/IFtdKVxuICAgICAgLmZpbHRlcigocmVzb3VyY2UpID0+IHJlc291cmNlLm5hbWUpXG4gICAgICAubWFwKChyZXNvdXJjZSkgPT4gW3Jlc291cmNlLm5hbWUhLCByZXNvdXJjZV0pLFxuICApO1xuXG4gIGNvbnN0IG91dDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGFwcC5jb25maWcuZW52KSB7XG4gICAgaWYgKCFlbnRyeS5uYW1lKSBjb250aW51ZTtcbiAgICBpZiAoZW50cnkudmFsdWUpIHtcbiAgICAgIG91dFtlbnRyeS5uYW1lXSA9IGVudHJ5LnZhbHVlO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmICghZW50cnkudmFsdWVfZnJvbSkgY29udGludWU7XG4gICAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlUmVzb3VyY2VWYWx1ZShyZXNvdXJjZUJ5TmFtZS5nZXQoZW50cnkudmFsdWVfZnJvbSkpO1xuICAgIGlmIChyZXNvbHZlZCkgb3V0W2VudHJ5Lm5hbWVdID0gcmVzb2x2ZWQ7XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVCdW5kbGUocm9vdDogc3RyaW5nKTogQnVuZGxlVmFsaWRhdGVKc29uIHwgdW5kZWZpbmVkIHtcbiAgY29uc3Qga2V5ID0gcm9vdDtcbiAgaWYgKGJ1bmRsZVZhbGlkYXRlQ2FjaGUuaGFzKGtleSkpIHtcbiAgICByZXR1cm4gYnVuZGxlVmFsaWRhdGVDYWNoZS5nZXQoa2V5KTtcbiAgfVxuXG4gIGNvbnN0IGFyZ3MgPSBbXCJidW5kbGVcIiwgXCJ2YWxpZGF0ZVwiLCBcIi0tb3V0cHV0XCIsIFwianNvblwiXTtcbiAgdHJ5IHtcbiAgICBjb25zdCBwcm9jID0gc3Bhd25TeW5jKFwiZGF0YWJyaWNrc1wiLCBhcmdzLCB7XG4gICAgICBjd2Q6IHJvb3QsXG4gICAgICBlbmNvZGluZzogXCJ1dGY4XCIsXG4gICAgICBzdGRpbzogW1wiaWdub3JlXCIsIFwicGlwZVwiLCBcInBpcGVcIl0sXG4gICAgfSk7XG4gICAgY29uc3QgdGV4dCA9IHByb2Muc3Rkb3V0Py50cmltKCk7XG4gICAgaWYgKCF0ZXh0KSB7XG4gICAgICBidW5kbGVWYWxpZGF0ZUNhY2hlLnNldChrZXksIHVuZGVmaW5lZCk7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjb25zdCBkYXRhID0ganNvbi5wYXJzZTxCdW5kbGVWYWxpZGF0ZUpzb24+KHRleHQpO1xuICAgIGJ1bmRsZVZhbGlkYXRlQ2FjaGUuc2V0KGtleSwgZGF0YSk7XG4gICAgcmV0dXJuIGRhdGE7XG4gIH0gY2F0Y2gge1xuICAgIGJ1bmRsZVZhbGlkYXRlQ2FjaGUuc2V0KGtleSwgdW5kZWZpbmVkKTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGxvYWRCdW5kbGUoY3dkOiBzdHJpbmcpOiBQcm9taXNlPENvbmZpZ0ZpbGUgfCB1bmRlZmluZWQ+IHtcbiAgY29uc3QgY29uZmlnRmlsZSA9IHJlc29sdmVDb25maWdGaWxlKGN3ZCwgXCJkYXRhYnJpY2tzLnltbFwiKTtcbiAgaWYgKGNvbmZpZ0ZpbGUpIHtcbiAgICBjb25zdCBkYXRhID0gdmFsaWRhdGVCdW5kbGUoZGlybmFtZShjb25maWdGaWxlKSk7XG4gICAgaWYgKGRhdGEpIHJldHVybiB7IHBhdGg6IGNvbmZpZ0ZpbGUsIGRhdGEgfTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5hc3luYyBmdW5jdGlvbiBsb2FkQXBwWWFtbChjd2Q6IHN0cmluZyk6IFByb21pc2U8Q29uZmlnRmlsZSB8IHVuZGVmaW5lZD4ge1xuICBmb3IgKGNvbnN0IGZpbGVOYW1lIG9mIEFQUF9ZQU1MX05BTUVTKSB7XG4gICAgY29uc3QgY29uZmlnRmlsZSA9IHJlc29sdmVDb25maWdGaWxlKGN3ZCwgZmlsZU5hbWUpO1xuICAgIGlmICghY29uZmlnRmlsZSkgY29udGludWU7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRleHQgPSBhd2FpdCByZWFkRmlsZShjb25maWdGaWxlLCBcInV0ZjhcIik7XG4gICAgICBjb25zdCBkYXRhID0gcGFyc2VZYW1sKHRleHQpO1xuICAgICAgaWYgKCFvYmplY3QuaXNSZWNvcmQoZGF0YSkpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7IHBhdGg6IGNvbmZpZ0ZpbGUsIGRhdGEgfTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIGxvZ2dlci53YXJuKFwiZmFpbGVkIHRvIHBhcnNlIGFwcCB5YW1sXCIsIHsgcGF0aDogY29uZmlnRmlsZSB9KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNvbmZpZ0ZpbGUoY3dkOiBzdHJpbmcsIGNvbmZpZ0ZpbGU6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmIChpc0FwcEVudigpKSByZXR1cm4gdW5kZWZpbmVkO1xuICBmb3IgKGNvbnN0IHJvb3REaXIgb2YgcHJvamVjdC5yZXNvbHZlUHJvamVjdFJvb3RzKGN3ZCkpIHtcbiAgICBjb25zdCBidW5kbGVQYXRoID0gcmVzb2x2ZShyb290RGlyLCBjb25maWdGaWxlKTtcbiAgICBpZiAoZmlsZS5zdGF0U3luYyhidW5kbGVQYXRoKT8uaXNGaWxlKCkpIHJldHVybiBidW5kbGVQYXRoO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogTG9jYXRlIHRoZSBidW5kbGUgcm9vdCBhbmQgcnVuIGBkYXRhYnJpY2tzIGJ1bmRsZSB2YWxpZGF0ZSAtLW91dHB1dCBqc29uYC5cbiAqIFdoZW4gYGN3ZGAgaXMgb21pdHRlZCBvciBlcXVhbHMgYHByb2Nlc3MuY3dkKClgLCB0aGUgcmVzdWx0IGlzIG1lbW9pemVkIGZvclxuICogdGhlIHByb2Nlc3MgbGlmZXRpbWUuIFJldHVybnMgYHVuZGVmaW5lZGAgaW5zaWRlIGEgRGF0YWJyaWNrcyBBcHAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidW5kbGUoY3dkPzogc3RyaW5nKTogUHJvbWlzZTxDb25maWdGaWxlIHwgdW5kZWZpbmVkPiB7XG4gIGlmIChpc0FwcEVudigpKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHVuZGVmaW5lZCk7XG4gIHJldHVybiBjd2QgJiYgcmVzb2x2ZShjd2QpICE9PSBwcm9jZXNzLmN3ZCgpID8gbG9hZEJ1bmRsZShjd2QpIDogYnVuZGxlRGVmYXVsdCgpO1xufVxuXG4vKipcbiAqIExvY2F0ZSBhbmQgcGFyc2UgYGFwcC55YW1sYCAvIGBhcHAueW1sYCBmcm9tIHRoZSBidW5kbGUgb3IgcHJvamVjdCByb290LiBXaGVuXG4gKiBgY3dkYCBpcyBvbWl0dGVkIG9yIGVxdWFscyBgcHJvY2Vzcy5jd2QoKWAsIHRoZSByZXN1bHQgaXMgbWVtb2l6ZWQgZm9yIHRoZVxuICogcHJvY2VzcyBsaWZldGltZS4gUmV0dXJucyBgdW5kZWZpbmVkYCBpbnNpZGUgYSBEYXRhYnJpY2tzIEFwcC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcFlhbWwoY3dkPzogc3RyaW5nKTogUHJvbWlzZTxDb25maWdGaWxlIHwgdW5kZWZpbmVkPiB7XG4gIGlmIChpc0FwcEVudigpKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHVuZGVmaW5lZCk7XG4gIHJldHVybiBjd2QgJiYgcmVzb2x2ZShjd2QpICE9PSBwcm9jZXNzLmN3ZCgpID8gbG9hZEFwcFlhbWwoY3dkKSA6IGFwcFlhbWxEZWZhdWx0KCk7XG59XG5cbi8qKlxuICogV2FsayBhIGRvdC1zZXBhcmF0ZWQgcGF0aCB0aHJvdWdoIGJ1bmRsZSB2YWxpZGF0ZSBKU09OLiBXaGVuIHRoZSB0ZXJtaW5hbFxuICogbm9kZSBpcyBhIGJ1bmRsZSB2YXJpYWJsZSBvYmplY3QgKGB7IHZhbHVlOiBcIi4uLlwiIH1gKSwgdGhlIGB2YWx1ZWAgZmllbGQgaXNcbiAqIHJldHVybmVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QnVuZGxlUGF0aChkYXRhOiBCdW5kbGVWYWxpZGF0ZUpzb24sIHBhdGg6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHBhcnRzID0gcGF0aC5zcGxpdChcIi5cIikuZmlsdGVyKEJvb2xlYW4pO1xuICBpZiAocGFydHMubGVuZ3RoID09PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIGxldCBjdXJyZW50OiB1bmtub3duID0gZGF0YTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgIGlmICghb2JqZWN0LmlzUmVjb3JkKGN1cnJlbnQpKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHBhcnQgPSBwYXJ0c1tpXSE7XG4gICAgY29uc3QgbmV4dCA9IGN1cnJlbnRbcGFydF07XG4gICAgaWYgKGkgPT09IHBhcnRzLmxlbmd0aCAtIDEpIHtcbiAgICAgIGlmICh0eXBlb2YgbmV4dCA9PT0gXCJzdHJpbmdcIiAmJiBuZXh0KSByZXR1cm4gbmV4dDtcbiAgICAgIGlmIChvYmplY3QuaXNSZWNvcmQobmV4dCkpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBuZXh0LnZhbHVlO1xuICAgICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmIHZhbHVlID8gdmFsdWUgOiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjdXJyZW50ID0gbmV4dDtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlQXBwRW52TWFwKFxuICBvcHRpb25zOiBSZXNvbHZlQ29uZmlnVmFsdWVPcHRpb25zLFxuKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PiB7XG4gIGNvbnN0IGFwcERhdGEgPSBvcHRpb25zLmFwcERhdGEgPz8gKGF3YWl0IGFwcFlhbWwoKSk7XG4gIGNvbnN0IGJ1bmRsZURhdGEgPSBvcHRpb25zLmJ1bmRsZURhdGEgPz8gKGF3YWl0IGJ1bmRsZSgpKTtcbiAgY29uc3QgZnJvbVlhbWwgPSBhcHBEYXRhID8gZmxhdHRlbkFwcFlhbWxFbnYoYXBwRGF0YS5kYXRhKSA6IHt9O1xuICBjb25zdCBmcm9tQnVuZGxlID0gYnVuZGxlRGF0YSA/IGZsYXR0ZW5BcHBFbnYoYnVuZGxlRGF0YS5kYXRhKSA6IHt9O1xuICByZXR1cm4geyAuLi5mcm9tWWFtbCwgLi4uZnJvbUJ1bmRsZSB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU291cmNlcyhvcHRpb25zOiBSZXNvbHZlQ29uZmlnVmFsdWVPcHRpb25zKTogQ29uZmlnU291cmNlW10ge1xuICBjb25zdCBzb3VyY2VzID0gWy4uLihvcHRpb25zLnNvdXJjZXMgPz8gZGVmYXVsdENvbmZpZ1NvdXJjZXMpXTtcbiAgaWYgKG9wdGlvbnMuZXhwbGljaXQgIT09IHVuZGVmaW5lZCAmJiAhc291cmNlcy5pbmNsdWRlcyhcImV4cGxpY2l0XCIpKSB7XG4gICAgc291cmNlcy51bnNoaWZ0KFwiZXhwbGljaXRcIik7XG4gIH1cbiAgcmV0dXJuIHNvdXJjZXM7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBhIGNvbmZpZ3VyYXRpb24gc3RyaW5nIGZyb20gdGhlIGNvbmZpZ3VyZWQgc291cmNlcy4gUmV0dXJucyB0aGUgZmlyc3RcbiAqIG5vbi1lbXB0eSB2YWx1ZSwgb3IgYHVuZGVmaW5lZGAgd2hlbiBub3RoaW5nIG1hdGNoZXMuXG4gKlxuICogUHJlY2VkZW5jZSBmb2xsb3dzIEFwcEtpdCdzOiBleHBsaWNpdCBjb25maWcsIHRoZW4gZW52aXJvbm1lbnQgdmFyaWFibGUsIHRoZW5cbiAqIHdoYXRldmVyIHRoZSBEYXRhYnJpY2tzIEFwcCAvIGJ1bmRsZSBkZWZpbml0aW9uIHN1cHBsaWVzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgeyBjb25maWcgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbiAqXG4gKiBjb25zdCB3YXJlaG91c2VJZCA9IGF3YWl0IGNvbmZpZy5yZXNvbHZlQ29uZmlnVmFsdWUoXCJEQVRBQlJJQ0tTX1dBUkVIT1VTRV9JRFwiLCB7XG4gKiAgIGNsaTogeyBEQVRBQlJJQ0tTX1dBUkVIT1VTRV9JRDogZmxhZ3Mud2FyZWhvdXNlIH0sXG4gKiAgIHNvdXJjZXM6IGNvbmZpZy53aXRoQ2xpU291cmNlcygpLFxuICogfSk7XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlQ29uZmlnVmFsdWUoXG4gIG5hbWU6IHN0cmluZyxcbiAgb3B0aW9uczogUmVzb2x2ZUNvbmZpZ1ZhbHVlT3B0aW9ucyA9IHt9LFxuKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgY29uc3Qga2V5cyA9IGVudktleXNGb3JOYW1lKG5hbWUpLnRvQXJyYXkoKTtcbiAgaWYgKGtleXMubGVuZ3RoID09PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCBzb3VyY2VzID0gcmVzb2x2ZVNvdXJjZXMob3B0aW9ucyk7XG4gIGxldCBhcHBFbnZNYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCB1bmRlZmluZWQ7XG4gIGNvbnN0IHZhbHVlcyA9IChhc3luYyBmdW5jdGlvbiogKCkge1xuICAgIGZvciAoY29uc3Qgc291cmNlIG9mIHNvdXJjZXMpIHtcbiAgICAgIHN3aXRjaCAoc291cmNlKSB7XG4gICAgICAgIGNhc2UgXCJleHBsaWNpdFwiOlxuICAgICAgICAgIHlpZWxkIHJlYWRNYXAoa2V5cywgb3B0aW9ucy5leHBsaWNpdCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJjbGlcIjpcbiAgICAgICAgICB5aWVsZCByZWFkTWFwKGtleXMsIG9wdGlvbnMuY2xpKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcImVudlwiOlxuICAgICAgICAgIHlpZWxkIHJlYWRFbnYoa2V5cyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJidW5kbGVcIjpcbiAgICAgICAgICBpZiAoYXBwRW52TWFwID09PSB1bmRlZmluZWQpIGFwcEVudk1hcCA9IGF3YWl0IHJlc29sdmVBcHBFbnZNYXAob3B0aW9ucyk7XG4gICAgICAgICAgeWllbGQgcmVhZEFwcEVudihrZXlzLCBhcHBFbnZNYXApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IFZhbGlkYXRpb25FcnJvci5pbnZhbGlkVmFsdWUoXG4gICAgICAgICAgICBcInNvdXJjZXNcIixcbiAgICAgICAgICAgIHNvdXJjZSxcbiAgICAgICAgICAgIFwib25lIG9mOiBleHBsaWNpdCwgY2xpLCBlbnYsIGJ1bmRsZVwiLFxuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9KSgpO1xuICBmb3IgYXdhaXQgKGNvbnN0IHZhbHVlIG9mIHZhbHVlcykge1xuICAgIGlmICh2YWx1ZSkgcmV0dXJuIHZhbHVlO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogU291cmNlcyB3aXRoIGBjbGlgIGluY2x1ZGVkLCBpbiBDTEktZmlyc3Qgb3JkZXIuIFVzZSBmb3IgZGV2IGNvbW1hbmRzIHRoYXRcbiAqIGFjY2VwdCBmbGFnIG92ZXJyaWRlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdpdGhDbGlTb3VyY2VzKHNvdXJjZXM6IENvbmZpZ1NvdXJjZVtdID0gZGVmYXVsdENvbmZpZ1NvdXJjZXMpOiBDb25maWdTb3VyY2VbXSB7XG4gIGNvbnN0IHJlc3QgPSBzb3VyY2VzLmZpbHRlcigoc291cmNlKSA9PiBzb3VyY2UgIT09IFwiY2xpXCIgJiYgc291cmNlICE9PSBcImV4cGxpY2l0XCIpO1xuICByZXR1cm4gW1wiY2xpXCIsIFwiZXhwbGljaXRcIiwgLi4ucmVzdF07XG59XG4iXX0=
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createApp` wrapper: runs dbx-tools auto-configuration, then delegates to
|
|
3
|
+
* AppKit's own `createApp` with the exact same arguments.
|
|
4
|
+
*
|
|
5
|
+
* Drop it in as a one-for-one replacement for `@databricks/appkit`'s
|
|
6
|
+
* `createApp` - same parameters, same return type, full plugin-export inference
|
|
7
|
+
* preserved:
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { createApp } from "@dbx-tools/appkit";
|
|
11
|
+
* import { lakebase, server } from "@databricks/appkit";
|
|
12
|
+
*
|
|
13
|
+
* await createApp.createApp({ plugins: [server(), lakebase()] });
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Auto-configuration runs BEFORE delegating so plugins see a fully populated
|
|
17
|
+
* `process.env` during their synchronous `setup()`. Lakebase Postgres runs when
|
|
18
|
+
* a `lakebase` plugin is present, or when {@link AutoConfigureMode} is set
|
|
19
|
+
* explicitly on the config object.
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
import { createApp as appkitCreateApp } from "@databricks/appkit";
|
|
24
|
+
import type { PluginMap } from "@databricks/appkit/dist/shared/src/plugin";
|
|
25
|
+
type AppKitCreateAppConfig = NonNullable<Parameters<typeof appkitCreateApp>[0]>;
|
|
26
|
+
type AppKitPlugins = NonNullable<AppKitCreateAppConfig["plugins"]>;
|
|
27
|
+
/**
|
|
28
|
+
* What auto-configuration does before AppKit boots.
|
|
29
|
+
*
|
|
30
|
+
* - `"provision"`: resolve the Lakebase connection into `process.env`, then
|
|
31
|
+
* grant the AppKit cache schema to the connecting role.
|
|
32
|
+
* - `"env"`: resolve the Lakebase connection into `process.env` only.
|
|
33
|
+
*
|
|
34
|
+
* Omit it to get `"provision"` gated on a `lakebase` plugin being registered;
|
|
35
|
+
* set it explicitly to run regardless of the plugin list, or pass `false` to
|
|
36
|
+
* skip auto-configuration entirely.
|
|
37
|
+
*/
|
|
38
|
+
export type AutoConfigureMode = "env" | "provision";
|
|
39
|
+
/** AppKit's `createApp` config plus the dbx-tools auto-configuration switch. */
|
|
40
|
+
export type CreateAppConfig<T extends AppKitPlugins = AppKitPlugins> = Omit<AppKitCreateAppConfig, "plugins" | "onPluginsReady"> & {
|
|
41
|
+
plugins?: T;
|
|
42
|
+
onPluginsReady?: (appkit: PluginMap<T>) => void | Promise<void>;
|
|
43
|
+
/** Auto-configuration to run before AppKit boots. Defaults to `"provision"`. */
|
|
44
|
+
autoConfigure?: AutoConfigureMode | false;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Run enabled auto-configuration steps without calling AppKit's `createApp`.
|
|
48
|
+
*
|
|
49
|
+
* Lakebase Postgres resolves when {@link CreateAppConfig.autoConfigure} is set
|
|
50
|
+
* explicitly or a `lakebase` plugin is listed in `config.plugins`. `signal`
|
|
51
|
+
* cancels the resolution; it is combined with an internal boot timeout either
|
|
52
|
+
* way.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* import { createApp } from "@dbx-tools/appkit";
|
|
56
|
+
*
|
|
57
|
+
* // Populate PGHOST / PGDATABASE / LAKEBASE_ENDPOINT without booting AppKit.
|
|
58
|
+
* await createApp.autoConfigure({ autoConfigure: "env" });
|
|
59
|
+
*/
|
|
60
|
+
export declare function autoConfigure<T extends AppKitPlugins>(config?: CreateAppConfig<T>, signal?: AbortSignal): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Auto-configuring drop-in for AppKit's `createApp`: same config, same typed
|
|
63
|
+
* plugin-export map, with {@link autoConfigure} run first.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* import { createApp } from "@dbx-tools/appkit";
|
|
67
|
+
* import { lakebase, server } from "@databricks/appkit";
|
|
68
|
+
*
|
|
69
|
+
* const app = await createApp.createApp({ plugins: [server(), lakebase()] });
|
|
70
|
+
*/
|
|
71
|
+
export declare function createApp<T extends AppKitPlugins>(config?: CreateAppConfig<T>): Promise<PluginMap<T>>;
|
|
72
|
+
export {};
|