@dbx-tools/appkit 0.3.43 → 0.4.0

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.
@@ -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 {};