@dbx-tools/appkit 0.6.82 → 0.6.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,7 +42,7 @@ Use this package when the friction is around bootstrapping and reuse:
42
42
  - AppKit plugin instances are generic; the lookup helpers keep sibling-plugin
43
43
  access typed and errors actionable.
44
44
  - AppKit does not own your local CLI flags, bundle validation output, or
45
- `app.yaml`; `config.resolveConfigValue()` gives setup scripts one resolution
45
+ `app.yaml`; `bundle.resolveConfigValue()` gives setup scripts one resolution
46
46
  path across those sources.
47
47
  - AppKit's `asUser(req)` throws outside `NODE_ENV=development` when a request
48
48
  carries no OBO token; `identity` makes falling back to the service principal a
@@ -158,22 +158,22 @@ await; `lakebaseResolver.applyLakebaseEnv()` resolves and applies the full set.
158
158
 
159
159
  ## Resolve Local And Bundle Config
160
160
 
161
- `config.resolveConfigValue()` checks explicit options, CLI overrides, env vars,
161
+ `bundle.resolveConfigValue()` checks explicit options, CLI overrides, env vars,
162
162
  Databricks Asset Bundle validation output, and `app.yaml` env entries, in AppKit's
163
163
  precedence order: explicit config, then environment variable, then the app or
164
164
  bundle definition.
165
165
 
166
166
  ```ts
167
- import { config } from "@dbx-tools/appkit";
167
+ import { bundle } from "@dbx-tools/appkit";
168
168
 
169
- const warehouseId = await config.resolveConfigValue("DATABRICKS_WAREHOUSE_ID", {
169
+ const warehouseId = await bundle.resolveConfigValue("DATABRICKS_WAREHOUSE_ID", {
170
170
  cli: { DATABRICKS_WAREHOUSE_ID: flags.warehouse },
171
- sources: config.withCliSources(),
171
+ sources: bundle.withCliSources(),
172
172
  });
173
173
  ```
174
174
 
175
175
  Use this in CLIs and setup scripts that should behave the same locally and in a
176
- Databricks App deployment. `config.bundle()` and `config.appYaml()` expose the
176
+ Databricks App deployment. `bundle.bundle()` and `bundle.appYaml()` expose the
177
177
  parsed files when you need to diagnose which source won.
178
178
 
179
179
  ## Parse Lakebase Addresses
@@ -228,9 +228,6 @@ await client.apiClient.request(
228
228
  );
229
229
  ```
230
230
 
231
- `databricks.isAppEnv()` checks the Databricks App environment shape for setup
232
- code that should skip local-only filesystem or bundle discovery.
233
-
234
231
  ## Look Up Sibling Plugins
235
232
 
236
233
  AppKit's plugin map is intentionally generic. `plugin.data()`,
package/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
 
5
5
  export * as appkit from "./src/appkit.ts";
6
- export * as config from "./src/config.ts";
6
+ export * as bundle from "./src/bundle.ts";
7
7
  export * as databricks from "./src/databricks.ts";
8
8
  export * as identity from "./src/identity.ts";
9
9
  export * as interceptor from "./src/interceptor.ts";
@@ -12,8 +12,8 @@ export * as pgaddress from "./src/pgaddress.ts";
12
12
  export * as plugin from "./src/plugin.ts";
13
13
  export * as provision from "./src/provision.ts";
14
14
  export type { AutoConfigureMode, CreateAppConfig, ExecutionContextLike, WorkspaceClientLike } from "./src/appkit.ts";
15
- export type { BundleValidateJson, ConfigFile, ConfigSource, ConfigMapValue, ResolveConfigValueOptions } from "./src/config.ts";
16
- export { MAX_TCP_PORT } from "./src/databricks.ts";
15
+ export { bundleAppResourceSchema } from "./src/bundle.ts";
16
+ export type { BundleValidateJson, ConfigFile, ConfigSource, ConfigMapValue, ResolveConfigValueOptions } from "./src/bundle.ts";
17
17
  export type { ContextLike } from "./src/databricks.ts";
18
18
  export { ACCESS_TOKEN_HEADER, USER_ID_HEADER, USER_EMAIL_HEADER, IDENTITY_MODES, DEFAULT_IDENTITY_MODE } from "./src/identity.ts";
19
19
  export type { IdentityMode, HeaderBearing } from "./src/identity.ts";
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export * as appkit from "./src/appkit.ts";
2
- export * as config from "./src/config.ts";
2
+ export * as bundle from "./src/bundle.ts";
3
3
  export * as databricks from "./src/databricks.ts";
4
4
  export * as identity from "./src/identity.ts";
5
5
  export * as interceptor from "./src/interceptor.ts";
@@ -8,8 +8,8 @@ export * as pgaddress from "./src/pgaddress.ts";
8
8
  export * as plugin from "./src/plugin.ts";
9
9
  export * as provision from "./src/provision.ts";
10
10
  export type { AutoConfigureMode, CreateAppConfig, ExecutionContextLike, WorkspaceClientLike } from "./src/appkit.ts";
11
- export type { BundleValidateJson, ConfigFile, ConfigSource, ConfigMapValue, ResolveConfigValueOptions } from "./src/config.ts";
12
- export { MAX_TCP_PORT } from "./src/databricks.ts";
11
+ export { bundleAppResourceSchema } from "./src/bundle.ts";
12
+ export type { BundleValidateJson, ConfigFile, ConfigSource, ConfigMapValue, ResolveConfigValueOptions } from "./src/bundle.ts";
13
13
  export type { ContextLike } from "./src/databricks.ts";
14
14
  export { ACCESS_TOKEN_HEADER, USER_ID_HEADER, USER_EMAIL_HEADER, IDENTITY_MODES, DEFAULT_IDENTITY_MODE } from "./src/identity.ts";
15
15
  export type { IdentityMode, HeaderBearing } from "./src/identity.ts";
package/lib/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // Regenerated from the exporting modules in ./src.
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
  export * as appkit from "./src/appkit.js";
5
- export * as config from "./src/config.js";
5
+ export * as bundle from "./src/bundle.js";
6
6
  export * as databricks from "./src/databricks.js";
7
7
  export * as identity from "./src/identity.js";
8
8
  export * as interceptor from "./src/interceptor.js";
@@ -10,8 +10,8 @@ export * as lakebaseResolver from "./src/lakebase-resolver.js";
10
10
  export * as pgaddress from "./src/pgaddress.js";
11
11
  export * as plugin from "./src/plugin.js";
12
12
  export * as provision from "./src/provision.js";
13
- export { MAX_TCP_PORT } from "./src/databricks.js";
13
+ export { bundleAppResourceSchema } from "./src/bundle.js";
14
14
  export { ACCESS_TOKEN_HEADER, USER_ID_HEADER, USER_EMAIL_HEADER, IDENTITY_MODES, DEFAULT_IDENTITY_MODE } from "./src/identity.js";
15
15
  export { LifecycleBridgePlugin, lifecycleBridge } from "./src/interceptor.js";
16
16
  export { SSL_MODES } from "./src/pgaddress.js";
17
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssTUFBTSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFVBQVUsTUFBTSxxQkFBcUIsQ0FBQztBQUNsRCxPQUFPLEtBQUssUUFBUSxNQUFNLG1CQUFtQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxXQUFXLE1BQU0sc0JBQXNCLENBQUM7QUFDcEQsT0FBTyxLQUFLLGdCQUFnQixNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBR2hELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUVuRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsY0FBYyxFQUFFLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRWxJLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUc5RSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sb0JBQW9CLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBHRU5FUkFURUQgYnkgcHJvamVuIHdhdGNoIC0gRE8gTk9UIEVESVQuXG4vLyBSZWdlbmVyYXRlZCBmcm9tIHRoZSBleHBvcnRpbmcgbW9kdWxlcyBpbiAuL3NyYy5cbi8vIEhhbmQgZWRpdHMgYXJlIG92ZXJ3cml0dGVuIG9uIHRoZSBuZXh0IHdhdGNoOyB0aGlzIGZpbGUgaXMgcmVhZC1vbmx5LlxuXG5leHBvcnQgKiBhcyBhcHBraXQgZnJvbSBcIi4vc3JjL2FwcGtpdC50c1wiO1xuZXhwb3J0ICogYXMgY29uZmlnIGZyb20gXCIuL3NyYy9jb25maWcudHNcIjtcbmV4cG9ydCAqIGFzIGRhdGFicmlja3MgZnJvbSBcIi4vc3JjL2RhdGFicmlja3MudHNcIjtcbmV4cG9ydCAqIGFzIGlkZW50aXR5IGZyb20gXCIuL3NyYy9pZGVudGl0eS50c1wiO1xuZXhwb3J0ICogYXMgaW50ZXJjZXB0b3IgZnJvbSBcIi4vc3JjL2ludGVyY2VwdG9yLnRzXCI7XG5leHBvcnQgKiBhcyBsYWtlYmFzZVJlc29sdmVyIGZyb20gXCIuL3NyYy9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuZXhwb3J0ICogYXMgcGdhZGRyZXNzIGZyb20gXCIuL3NyYy9wZ2FkZHJlc3MudHNcIjtcbmV4cG9ydCAqIGFzIHBsdWdpbiBmcm9tIFwiLi9zcmMvcGx1Z2luLnRzXCI7XG5leHBvcnQgKiBhcyBwcm92aXNpb24gZnJvbSBcIi4vc3JjL3Byb3Zpc2lvbi50c1wiO1xuZXhwb3J0IHR5cGUgeyBBdXRvQ29uZmlndXJlTW9kZSwgQ3JlYXRlQXBwQ29uZmlnLCBFeGVjdXRpb25Db250ZXh0TGlrZSwgV29ya3NwYWNlQ2xpZW50TGlrZSB9IGZyb20gXCIuL3NyYy9hcHBraXQudHNcIjtcbmV4cG9ydCB0eXBlIHsgQnVuZGxlVmFsaWRhdGVKc29uLCBDb25maWdGaWxlLCBDb25maWdTb3VyY2UsIENvbmZpZ01hcFZhbHVlLCBSZXNvbHZlQ29uZmlnVmFsdWVPcHRpb25zIH0gZnJvbSBcIi4vc3JjL2NvbmZpZy50c1wiO1xuZXhwb3J0IHsgTUFYX1RDUF9QT1JUIH0gZnJvbSBcIi4vc3JjL2RhdGFicmlja3MudHNcIjtcbmV4cG9ydCB0eXBlIHsgQ29udGV4dExpa2UgfSBmcm9tIFwiLi9zcmMvZGF0YWJyaWNrcy50c1wiO1xuZXhwb3J0IHsgQUNDRVNTX1RPS0VOX0hFQURFUiwgVVNFUl9JRF9IRUFERVIsIFVTRVJfRU1BSUxfSEVBREVSLCBJREVOVElUWV9NT0RFUywgREVGQVVMVF9JREVOVElUWV9NT0RFIH0gZnJvbSBcIi4vc3JjL2lkZW50aXR5LnRzXCI7XG5leHBvcnQgdHlwZSB7IElkZW50aXR5TW9kZSwgSGVhZGVyQmVhcmluZyB9IGZyb20gXCIuL3NyYy9pZGVudGl0eS50c1wiO1xuZXhwb3J0IHsgTGlmZWN5Y2xlQnJpZGdlUGx1Z2luLCBsaWZlY3ljbGVCcmlkZ2UgfSBmcm9tIFwiLi9zcmMvaW50ZXJjZXB0b3IudHNcIjtcbmV4cG9ydCB0eXBlIHsgTGlmZWN5Y2xlRXZlbnQsIExpZmVjeWNsZUhhbmRsZXIsIFJlc29sdmVkQXBwRW52LCBCaW5kYWJsZVByb2Nlc3MsIEludGVyY2VwdG9yQ29udGV4dCwgSW50ZXJjZXB0b3IsIEludGVyY2VwdG9yUnVudGltZSB9IGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0IHR5cGUgeyBMYWtlYmFzZVJlc29sdmVySW5wdXRzLCBMYWtlYmFzZUNvbm5lY3Rpb24gfSBmcm9tIFwiLi9zcmMvbGFrZWJhc2UtcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCB7IFNTTF9NT0RFUyB9IGZyb20gXCIuL3NyYy9wZ2FkZHJlc3MudHNcIjtcbmV4cG9ydCB0eXBlIHsgU3NsTW9kZSwgTGFrZWJhc2VDb25uZWN0aW9uSW5wdXRzLCBQYXJzZWRBZGRyZXNzIH0gZnJvbSBcIi4vc3JjL3BnYWRkcmVzcy50c1wiO1xuZXhwb3J0IHR5cGUgeyBQbHVnaW5Db250ZXh0TGlrZSB9IGZyb20gXCIuL3NyYy9wbHVnaW4udHNcIjtcbiJdfQ==
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssTUFBTSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFVBQVUsTUFBTSxxQkFBcUIsQ0FBQztBQUNsRCxPQUFPLEtBQUssUUFBUSxNQUFNLG1CQUFtQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxXQUFXLE1BQU0sc0JBQXNCLENBQUM7QUFDcEQsT0FBTyxLQUFLLGdCQUFnQixNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBRWhELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRzFELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxjQUFjLEVBQUUsaUJBQWlCLEVBQUUsY0FBYyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFbEksT0FBTyxFQUFFLHFCQUFxQixFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRzlFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCAqIGFzIGFwcGtpdCBmcm9tIFwiLi9zcmMvYXBwa2l0LnRzXCI7XG5leHBvcnQgKiBhcyBidW5kbGUgZnJvbSBcIi4vc3JjL2J1bmRsZS50c1wiO1xuZXhwb3J0ICogYXMgZGF0YWJyaWNrcyBmcm9tIFwiLi9zcmMvZGF0YWJyaWNrcy50c1wiO1xuZXhwb3J0ICogYXMgaWRlbnRpdHkgZnJvbSBcIi4vc3JjL2lkZW50aXR5LnRzXCI7XG5leHBvcnQgKiBhcyBpbnRlcmNlcHRvciBmcm9tIFwiLi9zcmMvaW50ZXJjZXB0b3IudHNcIjtcbmV4cG9ydCAqIGFzIGxha2ViYXNlUmVzb2x2ZXIgZnJvbSBcIi4vc3JjL2xha2ViYXNlLXJlc29sdmVyLnRzXCI7XG5leHBvcnQgKiBhcyBwZ2FkZHJlc3MgZnJvbSBcIi4vc3JjL3BnYWRkcmVzcy50c1wiO1xuZXhwb3J0ICogYXMgcGx1Z2luIGZyb20gXCIuL3NyYy9wbHVnaW4udHNcIjtcbmV4cG9ydCAqIGFzIHByb3Zpc2lvbiBmcm9tIFwiLi9zcmMvcHJvdmlzaW9uLnRzXCI7XG5leHBvcnQgdHlwZSB7IEF1dG9Db25maWd1cmVNb2RlLCBDcmVhdGVBcHBDb25maWcsIEV4ZWN1dGlvbkNvbnRleHRMaWtlLCBXb3Jrc3BhY2VDbGllbnRMaWtlIH0gZnJvbSBcIi4vc3JjL2FwcGtpdC50c1wiO1xuZXhwb3J0IHsgYnVuZGxlQXBwUmVzb3VyY2VTY2hlbWEgfSBmcm9tIFwiLi9zcmMvYnVuZGxlLnRzXCI7XG5leHBvcnQgdHlwZSB7IEJ1bmRsZVZhbGlkYXRlSnNvbiwgQ29uZmlnRmlsZSwgQ29uZmlnU291cmNlLCBDb25maWdNYXBWYWx1ZSwgUmVzb2x2ZUNvbmZpZ1ZhbHVlT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9idW5kbGUudHNcIjtcbmV4cG9ydCB0eXBlIHsgQ29udGV4dExpa2UgfSBmcm9tIFwiLi9zcmMvZGF0YWJyaWNrcy50c1wiO1xuZXhwb3J0IHsgQUNDRVNTX1RPS0VOX0hFQURFUiwgVVNFUl9JRF9IRUFERVIsIFVTRVJfRU1BSUxfSEVBREVSLCBJREVOVElUWV9NT0RFUywgREVGQVVMVF9JREVOVElUWV9NT0RFIH0gZnJvbSBcIi4vc3JjL2lkZW50aXR5LnRzXCI7XG5leHBvcnQgdHlwZSB7IElkZW50aXR5TW9kZSwgSGVhZGVyQmVhcmluZyB9IGZyb20gXCIuL3NyYy9pZGVudGl0eS50c1wiO1xuZXhwb3J0IHsgTGlmZWN5Y2xlQnJpZGdlUGx1Z2luLCBsaWZlY3ljbGVCcmlkZ2UgfSBmcm9tIFwiLi9zcmMvaW50ZXJjZXB0b3IudHNcIjtcbmV4cG9ydCB0eXBlIHsgTGlmZWN5Y2xlRXZlbnQsIExpZmVjeWNsZUhhbmRsZXIsIFJlc29sdmVkQXBwRW52LCBCaW5kYWJsZVByb2Nlc3MsIEludGVyY2VwdG9yQ29udGV4dCwgSW50ZXJjZXB0b3IsIEludGVyY2VwdG9yUnVudGltZSB9IGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0IHR5cGUgeyBMYWtlYmFzZVJlc29sdmVySW5wdXRzLCBMYWtlYmFzZUNvbm5lY3Rpb24gfSBmcm9tIFwiLi9zcmMvbGFrZWJhc2UtcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCB7IFNTTF9NT0RFUyB9IGZyb20gXCIuL3NyYy9wZ2FkZHJlc3MudHNcIjtcbmV4cG9ydCB0eXBlIHsgU3NsTW9kZSwgTGFrZWJhc2VDb25uZWN0aW9uSW5wdXRzLCBQYXJzZWRBZGRyZXNzIH0gZnJvbSBcIi4vc3JjL3BnYWRkcmVzcy50c1wiO1xuZXhwb3J0IHR5cGUgeyBQbHVnaW5Db250ZXh0TGlrZSB9IGZyb20gXCIuL3NyYy9wbHVnaW4udHNcIjtcbiJdfQ==
@@ -1,25 +1,46 @@
1
1
  /**
2
- * Layered configuration resolution for local development against a Databricks
3
- * App / Asset Bundle.
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.
4
12
  *
5
13
  * Default sources: `explicit`, then `env`, then Databricks App `config.env`
6
14
  * (from {@link bundle}) and hard-coded `app.yaml` env entries (from
7
15
  * {@link appYaml}). Opt in to `cli` when a dev command wants flag overrides.
8
16
  *
9
- * Server-only (`node:child_process`, bundle root discovery). Databricks-app
10
- * specific, so it lives in node-appkit rather than shared-core.
17
+ * Server-only, and Databricks-app specific, so it lives in node-appkit rather
18
+ * than node-core.
11
19
  *
12
20
  * @module
13
21
  */
22
+ import { config as coreConfig } from "@dbx-tools/core";
23
+ import { z } from "zod";
14
24
  /** Parsed payload from `databricks bundle validate --output json`. */
15
25
  export type BundleValidateJson = Record<string, unknown>;
16
26
  /** A config file discovered on disk with its parsed contents. */
17
- export interface ConfigFile {
18
- path: string;
19
- data: Record<string, unknown>;
20
- }
27
+ export type ConfigFile = coreConfig.ConfigFile;
21
28
  /** Supported configuration sources, consulted in array order. */
22
29
  export type ConfigSource = "explicit" | "cli" | "env" | "bundle";
30
+ export declare const bundleAppResourceSchema: z.ZodObject<{
31
+ name: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
32
+ sql_warehouse: z.ZodOptional<z.ZodObject<{
33
+ id: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
34
+ }, z.core.$strip>>;
35
+ genie_space: z.ZodOptional<z.ZodObject<{
36
+ space_id: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
37
+ }, z.core.$strip>>;
38
+ postgres: z.ZodOptional<z.ZodObject<{
39
+ database: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
40
+ branch: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
41
+ endpoint: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
42
+ }, z.core.$strip>>;
43
+ }, z.core.$loose>;
23
44
  /** Single config map entry (string or repeated values, like headers). */
24
45
  export type ConfigMapValue = string | string[] | undefined;
25
46
  export interface ResolveConfigValueOptions {
@@ -49,15 +70,17 @@ export declare function flattenAppYamlEnv(data: unknown): Record<string, string>
49
70
  */
50
71
  export declare function flattenAppEnv(data: unknown): Record<string, string>;
51
72
  /**
52
- * Locate the bundle root and run `databricks bundle validate --output json`.
53
- * When `cwd` is omitted or equals `process.cwd()`, the result is memoized for
54
- * the process lifetime. Returns `undefined` inside a Databricks App.
73
+ * The validated bundle for `cwd` - {@link coreConfig.bundleFile}, which caches it
74
+ * per working directory. Returns `undefined` inside a Databricks App, where the
75
+ * platform has already turned `config.env` into real environment variables and
76
+ * there is no bundle to validate.
55
77
  */
56
78
  export declare function bundle(cwd?: string): Promise<ConfigFile | undefined>;
57
79
  /**
58
- * Locate and parse `app.yaml` / `app.yml` from the bundle or project root. When
59
- * `cwd` is omitted or equals `process.cwd()`, the result is memoized for the
60
- * process lifetime. Returns `undefined` inside a Databricks App.
80
+ * Locate and parse `app.yaml` / `app.yml` from the bundle or project root.
81
+ * Cached per working directory through {@link context.cached}, so a `cwd` change
82
+ * re-reads instead of returning another project's file. Returns `undefined`
83
+ * inside a Databricks App.
61
84
  */
62
85
  export declare function appYaml(cwd?: string): Promise<ConfigFile | undefined>;
63
86
  /**
@@ -74,11 +97,11 @@ export declare function getBundlePath(data: BundleValidateJson, path: string): s
74
97
  * whatever the Databricks App / bundle definition supplies.
75
98
  *
76
99
  * @example
77
- * import { config } from "@dbx-tools/appkit";
100
+ * import { bundle } from "@dbx-tools/appkit";
78
101
  *
79
- * const warehouseId = await config.resolveConfigValue("DATABRICKS_WAREHOUSE_ID", {
102
+ * const warehouseId = await bundle.resolveConfigValue("DATABRICKS_WAREHOUSE_ID", {
80
103
  * cli: { DATABRICKS_WAREHOUSE_ID: flags.warehouse },
81
- * sources: config.withCliSources(),
104
+ * sources: bundle.withCliSources(),
82
105
  * });
83
106
  */
84
107
  export declare function resolveConfigValue(name: string, options?: ResolveConfigValueOptions): Promise<string | undefined>;
@@ -0,0 +1,359 @@
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 parseYamlText } 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.bundleValue.optional() }).optional(),
34
+ genie_space: z.object({ space_id: coreConfig.bundleValue.optional() }).optional(),
35
+ postgres: z
36
+ .object({
37
+ database: coreConfig.bundleValue.optional(),
38
+ branch: coreConfig.bundleValue.optional(),
39
+ endpoint: coreConfig.bundleValue.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.bundleValue,
51
+ valueFrom: coreConfig.bundleValue.optional(),
52
+ });
53
+ const appYamlResourceSchema = coreConfig.bundleResourceSchema
54
+ .extend({
55
+ name: coreConfig.bundleValue,
56
+ sql_warehouse: z.object({ id: coreConfig.bundleValue.optional() }).optional(),
57
+ genie_space: z.object({ space_id: coreConfig.bundleValue.optional() }).optional(),
58
+ postgres: z
59
+ .object({
60
+ database: coreConfig.bundleValue.optional(),
61
+ branch: coreConfig.bundleValue.optional(),
62
+ endpoint: coreConfig.bundleValue.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 parseYamlText(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.bundleValue.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.bundleValue.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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVuZGxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2J1bmRsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFFSCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUFFLE1BQU0sSUFBSSxVQUFVLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN0RSxPQUFPLEVBQUUsS0FBSyxJQUFJLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM5QyxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBRXhCLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7QUFXcEMsTUFBTSxvQkFBb0IsR0FBbUIsQ0FBQyxVQUFVLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBRTNFLE1BQU0sY0FBYyxHQUFHLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBVSxDQUFDO0FBRXhELE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLFVBQVUsQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUM7SUFDNUUsYUFBYSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsVUFBVSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFO0lBQzdFLFdBQVcsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsUUFBUSxFQUFFLFVBQVUsQ0FB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M0UsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxLQUFLLEtBQUssSUFBSSxNQUFNLEtBQUssVUFBVSxDQUFDLENBQUM7SUFDbkYsT0FBTyxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztBQUN0QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBEQVRBQlJJQ0tTLUFQUCBjb25maWd1cmF0aW9uIHJlc29sdXRpb246IHRoZSBidW5kbGUgYW5kIGBhcHAueWFtbGAgdm9jYWJ1bGFyeS5cbiAqXG4gKiBub2RlLWNvcmUncyBgY29uZmlnYCBtb2R1bGUgb3ducyB0aGUgZ2VuZXJpYyBsb29rdXAgLSBlbnZpcm9ubWVudCwgYC5lbnZgLFxuICogYGRhdGFicmlja3MgYnVuZGxlIHZhbGlkYXRlYCAtIGFuZCBrbm93cyBub3RoaW5nIGFib3V0IHdoYXQgYSBidW5kbGUgcmVzb3VyY2VcbiAqIElTLiBUaGF0IGxhc3QgcGFydCBpcyB0aGlzIG1vZHVsZTogYHNxbF93YXJlaG91c2VgLCBgZ2VuaWVfc3BhY2VgLCBhbmRcbiAqIGBwb3N0Z3Jlc2AgYXJlIERhdGFicmlja3MtQXBwIGNvbmNlcHRzLCBhbmQgYW4gYGFwcC55YW1sYCAvIGJ1bmRsZVxuICogYHZhbHVlX2Zyb21gIGVudHJ5IGlzIGEgUkVGRVJFTkNFIHRvIG9uZSBvZiB0aGVtIHdob3NlIHJlYWwgdmFsdWUgaXMgdGhlXG4gKiB3YXJlaG91c2UgaWQgb3IgR2VuaWUgc3BhY2UgaWQgc2l0dGluZyBvbiB0aGUgbmFtZWQgcmVzb3VyY2UuIFNvIHRoaXMgbW9kdWxlXG4gKiBleHRlbmRzIG5vZGUtY29yZSdzIHJlc291cmNlIHNjaGVtYSwgYWRkcyBgYXBwLnlhbWxgICh3aGljaCB0aGUgYnVuZGxlIENMSVxuICogbmV2ZXIgc2VlcyksIGFuZCByZXNvbHZlcyB0aG9zZSByZWZlcmVuY2VzLlxuICpcbiAqIERlZmF1bHQgc291cmNlczogYGV4cGxpY2l0YCwgdGhlbiBgZW52YCwgdGhlbiBEYXRhYnJpY2tzIEFwcCBgY29uZmlnLmVudmBcbiAqIChmcm9tIHtAbGluayBidW5kbGV9KSBhbmQgaGFyZC1jb2RlZCBgYXBwLnlhbWxgIGVudiBlbnRyaWVzIChmcm9tXG4gKiB7QGxpbmsgYXBwWWFtbH0pLiBPcHQgaW4gdG8gYGNsaWAgd2hlbiBhIGRldiBjb21tYW5kIHdhbnRzIGZsYWcgb3ZlcnJpZGVzLlxuICpcbiAqIFNlcnZlci1vbmx5LCBhbmQgRGF0YWJyaWNrcy1hcHAgc3BlY2lmaWMsIHNvIGl0IGxpdmVzIGluIG5vZGUtYXBwa2l0IHJhdGhlclxuICogdGhhbiBub2RlLWNvcmUuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IHJlYWRGaWxlIH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBjb25maWcgYXMgY29yZUNvbmZpZywgZmlsZSwgcHJvamVjdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2NvcmVcIjtcbmltcG9ydCB7IGNvbnRleHQsIG9iamVjdCwgbG9nLCBzdHJpbmcgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgcGFyc2UgYXMgcGFyc2VZYW1sVGV4dCB9IGZyb20gXCJ5YW1sXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiY29uZmlnXCIpO1xuXG4vKiogUGFyc2VkIHBheWxvYWQgZnJvbSBgZGF0YWJyaWNrcyBidW5kbGUgdmFsaWRhdGUgLS1vdXRwdXQganNvbmAuICovXG5leHBvcnQgdHlwZSBCdW5kbGVWYWxpZGF0ZUpzb24gPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuLyoqIEEgY29uZmlnIGZpbGUgZGlzY292ZXJlZCBvbiBkaXNrIHdpdGggaXRzIHBhcnNlZCBjb250ZW50cy4gKi9cbmV4cG9ydCB0eXBlIENvbmZpZ0ZpbGUgPSBjb3JlQ29uZmlnLkNvbmZpZ0ZpbGU7XG5cbi8qKiBTdXBwb3J0ZWQgY29uZmlndXJhdGlvbiBzb3VyY2VzLCBjb25zdWx0ZWQgaW4gYXJyYXkgb3JkZXIuICovXG5leHBvcnQgdHlwZSBDb25maWdTb3VyY2UgPSBcImV4cGxpY2l0XCIgfCBcImNsaVwiIHwgXCJlbnZcIiB8IFwiYnVuZGxlXCI7XG5cbmNvbnN0IGRlZmF1bHRDb25maWdTb3VyY2VzOiBDb25maWdTb3VyY2VbXSA9IFtcImV4cGxpY2l0XCIsIFwiZW52XCIsIFwiYnVuZGxlXCJdO1xuXG5jb25zdCBBUFBfWUFNTF9OQU1FUyA9IFtcImFwcC55YW1sXCIsIFwiYXBwLnltbFwiXSBhcyBjb25zdDtcblxuZXhwb3J0IGNvbnN0IGJ1bmRsZUFwcFJlc291cmNlU2NoZW1hID0gY29yZUNvbmZpZy5idW5kbGVSZXNvdXJjZVNjaGVtYS5leHRlbmQoe1xuICBzcWxfd2FyZWhvdXNlOiB6Lm9iamVjdCh7IGlkOiBjb3JlQ29uZmlnLmJ1bmRsZVZhbHVlLm9wdGlvbmFsKCkgfSkub3B0aW9uYWwoKSxcbiAgZ2VuaWVfc3BhY2U6IHoub2JqZWN0KHsgc3BhY2VfaWQ6IGNvcmVDb25maWcuYnVuZGxlVmFsdWUub3B0aW9uYWwoKSB9KS5vcHRpb25hbCgpLFxuICBwb3N0Z3JlczogelxuICAgIC5vYmplY3Qoe1xuICAgICAgZGF0YWJhc2U6IGNvcmVDb25maWcuYnVuZGxlVmFsdWUub3B0aW9uYWwoKSxcbiAgICAgIGJyYW5jaDogY29yZUNvbmZpZy5idW5kbGVWYWx1ZS5vcHRpb25hbCgpLFxuICAgICAgZW5kcG9pbnQ6IGNvcmVDb25maWcuYnVuZGxlVmFsdWUub3B0aW9uYWwoKSxcbiAgICB9KVxuICAgIC5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IGJ1bmRsZUFwcFNjaGVtYSA9IGNvcmVDb25maWcuYnVuZGxlQXBwU2NoZW1hLmV4dGVuZCh7XG4gIHJlc291cmNlczogei5hcnJheShidW5kbGVBcHBSZXNvdXJjZVNjaGVtYSkub3B0aW9uYWwoKSxcbn0pO1xuXG5jb25zdCBidW5kbGVWYWxpZGF0ZUFwcHNTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIHJlc291cmNlczogei5vYmplY3QoeyBhcHBzOiB6LnJlY29yZCh6LnN0cmluZygpLCBidW5kbGVBcHBTY2hlbWEpLm9wdGlvbmFsKCkgfSkub3B0aW9uYWwoKSxcbn0pO1xuXG5jb25zdCBhcHBZYW1sRW52RW50cnlTY2hlbWEgPSBjb3JlQ29uZmlnLmJ1bmRsZUVudkVudHJ5U2NoZW1hLm9taXQoeyB2YWx1ZV9mcm9tOiB0cnVlIH0pLmV4dGVuZCh7XG4gIG5hbWU6IGNvcmVDb25maWcuYnVuZGxlVmFsdWUsXG4gIHZhbHVlRnJvbTogY29yZUNvbmZpZy5idW5kbGVWYWx1ZS5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IGFwcFlhbWxSZXNvdXJjZVNjaGVtYSA9IGNvcmVDb25maWcuYnVuZGxlUmVzb3VyY2VTY2hlbWFcbiAgLmV4dGVuZCh7XG4gICAgbmFtZTogY29yZUNvbmZpZy5idW5kbGVWYWx1ZSxcbiAgICBzcWxfd2FyZWhvdXNlOiB6Lm9iamVjdCh7IGlkOiBjb3JlQ29uZmlnLmJ1bmRsZVZhbHVlLm9wdGlvbmFsKCkgfSkub3B0aW9uYWwoKSxcbiAgICBnZW5pZV9zcGFjZTogei5vYmplY3QoeyBzcGFjZV9pZDogY29yZUNvbmZpZy5idW5kbGVWYWx1ZS5vcHRpb25hbCgpIH0pLm9wdGlvbmFsKCksXG4gICAgcG9zdGdyZXM6IHpcbiAgICAgIC5vYmplY3Qoe1xuICAgICAgICBkYXRhYmFzZTogY29yZUNvbmZpZy5idW5kbGVWYWx1ZS5vcHRpb25hbCgpLFxuICAgICAgICBicmFuY2g6IGNvcmVDb25maWcuYnVuZGxlVmFsdWUub3B0aW9uYWwoKSxcbiAgICAgICAgZW5kcG9pbnQ6IGNvcmVDb25maWcuYnVuZGxlVmFsdWUub3B0aW9uYWwoKSxcbiAgICAgIH0pXG4gICAgICAub3B0aW9uYWwoKSxcbiAgfSlcbiAgLnBhc3N0aHJvdWdoKCk7XG5cbmNvbnN0IGFwcFlhbWxTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGVudjogei5hcnJheShhcHBZYW1sRW52RW50cnlTY2hlbWEpLm9wdGlvbmFsKCksXG4gIHJlc291cmNlczogei5hcnJheShhcHBZYW1sUmVzb3VyY2VTY2hlbWEpLm9wdGlvbmFsKCksXG59KTtcblxudHlwZSBCdW5kbGVBcHAgPSB6LmluZmVyPHR5cGVvZiBidW5kbGVBcHBTY2hlbWE+O1xuXG4vKiogU2luZ2xlIGNvbmZpZyBtYXAgZW50cnkgKHN0cmluZyBvciByZXBlYXRlZCB2YWx1ZXMsIGxpa2UgaGVhZGVycykuICovXG5leHBvcnQgdHlwZSBDb25maWdNYXBWYWx1ZSA9IHN0cmluZyB8IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJlc29sdmVDb25maWdWYWx1ZU9wdGlvbnMge1xuICAvKiogQnVuZGxlIHZhbGlkYXRlIEpTT04uIERlZmF1bHRzIHRvIHtAbGluayBidW5kbGV9IChza2lwcGVkIGluc2lkZSBhIERhdGFicmlja3MgQXBwKS4gKi9cbiAgYnVuZGxlRGF0YT86IENvbmZpZ0ZpbGU7XG4gIC8qKiBQYXJzZWQgYGFwcC55YW1sYCBjb250ZW50cy4gRGVmYXVsdHMgdG8ge0BsaW5rIGFwcFlhbWx9IChza2lwcGVkIGluc2lkZSBhIERhdGFicmlja3MgQXBwKS4gKi9cbiAgYXBwRGF0YT86IENvbmZpZ0ZpbGU7XG4gIC8qKlxuICAgKiBTb3VyY2VzIHRvIGNvbnN1bHQsIGZpcnN0IHRydXRoeSBzdHJpbmcgd2lucy4gRGVmYXVsdHMgdG8gYGV4cGxpY2l0YCwgdGhlblxuICAgKiBgZW52YCwgdGhlbiBgYnVuZGxlYC5cbiAgICovXG4gIHNvdXJjZXM/OiBDb25maWdTb3VyY2VbXTtcbiAgLyoqIFByb2dyYW1tYXRpYyBvdmVycmlkZXMuIFdoZW4gc2V0LCBgZXhwbGljaXRgIGlzIHByZXBlbmRlZCB0byBgc291cmNlc2AgdW5sZXNzIGFscmVhZHkgbGlzdGVkLiAqL1xuICBleHBsaWNpdD86IFJlY29yZDxzdHJpbmcsIENvbmZpZ01hcFZhbHVlPjtcbiAgLyoqIENMSSBmbGFnIHZhbHVlcyAod2hlbiBgY2xpYCBpcyBsaXN0ZWQgaW4gYHNvdXJjZXNgKS4gKi9cbiAgY2xpPzogUmVjb3JkPHN0cmluZywgQ29uZmlnTWFwVmFsdWU+O1xufVxuXG5mdW5jdGlvbiBlbnZLZXlzRm9yTmFtZShuYW1lOiBzdHJpbmcpOiBvYmplY3QuU2VxdWVuY2U8c3RyaW5nPiB7XG4gIGNvbnN0IHRyaW1tZWQgPSBuYW1lLnRyaW0oKTtcbiAgaWYgKCF0cmltbWVkKSB7XG4gICAgcmV0dXJuIG9iamVjdC5zZXF1ZW5jZSgpO1xuICB9XG4gIGNvbnN0IGtleXMgPSAoZnVuY3Rpb24qICgpIHtcbiAgICBjb25zdCBtb2RpZmllcnM6ICgoKHZhbHVlOiBzdHJpbmcpID0+IHN0cmluZykgfCBudWxsKVtdID0gW1xuICAgICAgbnVsbCxcbiAgICAgICgpID0+IHRyaW1tZWQudG9VcHBlckNhc2UoKSxcbiAgICAgICgpID0+IEFycmF5LmZyb20oc3RyaW5nLnRva2VuaXplKHRyaW1tZWQpKS5qb2luKFwiX1wiKS50b1VwcGVyQ2FzZSgpLFxuICAgIF07XG4gICAgZm9yIChjb25zdCBtb2RpZmllciBvZiBtb2RpZmllcnMpIHtcbiAgICAgIHlpZWxkIG1vZGlmaWVyID8gbW9kaWZpZXIodHJpbW1lZCkgOiB0cmltbWVkO1xuICAgIH1cbiAgfSkoKTtcbiAgcmV0dXJuIG9iamVjdC5zZXF1ZW5jZShrZXlzKS5jYWNoZSgpLmZpbHRlcihCb29sZWFuKS5kaXN0aW5jdCgpO1xufVxuXG5mdW5jdGlvbiByZWFkRW52KGtleXM6IEl0ZXJhYmxlPHN0cmluZz4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgY29uc3QgdmFsdWUgPSBwcm9jZXNzLmVudltrZXldPy50cmltKCk7XG4gICAgaWYgKHZhbHVlKSByZXR1cm4gdmFsdWU7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gcmVhZENvbmZpZ01hcFZhbHVlKHZhbHVlOiBDb25maWdNYXBWYWx1ZSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICh2YWx1ZSA9PSBudWxsKSByZXR1cm4gdW5kZWZpbmVkO1xuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgdmFsdWUpIHtcbiAgICAgIGNvbnN0IHRyaW1tZWQgPSBpdGVtPy50cmltKCk7XG4gICAgICBpZiAodHJpbW1lZCkgcmV0dXJuIHRyaW1tZWQ7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgY29uc3QgdHJpbW1lZCA9IHZhbHVlLnRyaW0oKTtcbiAgcmV0dXJuIHRyaW1tZWQgfHwgdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiByZWFkTWFwKFxuICBrZXlzOiBJdGVyYWJsZTxzdHJpbmc+LFxuICBtYXA6IFJlY29yZDxzdHJpbmcsIENvbmZpZ01hcFZhbHVlPiB8IHVuZGVmaW5lZCxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICghbWFwKSByZXR1cm4gdW5kZWZpbmVkO1xuICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgY29uc3QgdmFsdWUgPSByZWFkQ29uZmlnTWFwVmFsdWUobWFwW2tleV0pO1xuICAgIGlmICh2YWx1ZSkgcmV0dXJuIHZhbHVlO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHJlYWRBcHBFbnYoa2V5czogSXRlcmFibGU8c3RyaW5nPiwgZW52TWFwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgIGNvbnN0IHZhbHVlID0gZW52TWFwW2tleV0/LnRyaW0oKTtcbiAgICBpZiAodmFsdWUpIHJldHVybiB2YWx1ZTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBwYXJzZVlhbWwodGV4dDogc3RyaW5nKTogdW5rbm93biB7XG4gIHJldHVybiBwYXJzZVlhbWxUZXh0KHRleHQpO1xufVxuXG5mdW5jdGlvbiBwaWNrQXBwUmVzb3VyY2VJZChhcHBzOiBSZWNvcmQ8c3RyaW5nLCBCdW5kbGVBcHA+KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGFwcHMpO1xuICByZXR1cm4ga2V5cy5sZW5ndGggPT09IDEgPyBrZXlzWzBdIDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJlc29sdmUgdGhlIGVmZmVjdGl2ZSB2YWx1ZSBhIGB2YWx1ZV9mcm9tYC9gdmFsdWVGcm9tYCBlbnRyeSBwb2ludHMgYXQ6XG4gKiB0aGUgZmlyc3QgcHJlc2VudCBvZiB0aGUgd2FyZWhvdXNlIGlkLCBHZW5pZSBzcGFjZSBpZCwgb3IgUG9zdGdyZXNcbiAqIGVuZHBvaW50L2RhdGFiYXNlL2JyYW5jaCBvbiB0aGUgbmFtZWQgcmVzb3VyY2UuIFNoYXJlZCBieSBib3RoIHRoZVxuICogYGFwcC55YW1sYCBhbmQgYGJ1bmRsZSB2YWxpZGF0ZWAgZmxhdHRlbmVycywgd2hvc2UgcmVzb3VyY2Ugc2hhcGVzIG1hdGNoLlxuICovXG5mdW5jdGlvbiByZXNvbHZlUmVzb3VyY2VWYWx1ZShcbiAgcmVzb3VyY2U6IHouaW5mZXI8dHlwZW9mIGJ1bmRsZUFwcFJlc291cmNlU2NoZW1hPiB8IHVuZGVmaW5lZCxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiAoXG4gICAgcmVzb3VyY2U/LnNxbF93YXJlaG91c2U/LmlkID8/XG4gICAgcmVzb3VyY2U/LmdlbmllX3NwYWNlPy5zcGFjZV9pZCA/P1xuICAgIHJlc291cmNlPy5wb3N0Z3Jlcz8uZW5kcG9pbnQgPz9cbiAgICByZXNvdXJjZT8ucG9zdGdyZXM/LmRhdGFiYXNlID8/XG4gICAgcmVzb3VyY2U/LnBvc3RncmVzPy5icmFuY2hcbiAgKTtcbn1cblxuLyoqXG4gKiBGbGF0dGVuIGBlbnZgIGVudHJpZXMgZnJvbSBwYXJzZWQgYGFwcC55YW1sYCBjb250ZW50LiBMaXRlcmFsIGB2YWx1ZWAgZW50cmllc1xuICogYXJlIHJldHVybmVkIGFzLWlzOyBgdmFsdWVGcm9tYCBlbnRyaWVzIHJlc29sdmUgYWdhaW5zdCB0aGUgc2libGluZ1xuICogYHJlc291cmNlc2AgYXJyYXkgd2hlbiBwb3NzaWJsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsYXR0ZW5BcHBZYW1sRW52KGRhdGE6IHVua25vd24pOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgY29uc3QgcGFyc2VkID0gYXBwWWFtbFNjaGVtYS5zYWZlUGFyc2UoZGF0YSk7XG4gIGlmICghcGFyc2VkLnN1Y2Nlc3MgfHwgIXBhcnNlZC5kYXRhLmVudj8ubGVuZ3RoKSB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgY29uc3QgcmVzb3VyY2VCeU5hbWUgPSBuZXcgTWFwKFxuICAgIChwYXJzZWQuZGF0YS5yZXNvdXJjZXMgPz8gW10pLm1hcCgocmVzb3VyY2UpID0+IFtyZXNvdXJjZS5uYW1lLCByZXNvdXJjZV0pLFxuICApO1xuXG4gIGNvbnN0IG91dDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBmb3IgKGNvbnN0IGVudHJ5IG9mIHBhcnNlZC5kYXRhLmVudikge1xuICAgIGNvbnN0IHZhbHVlID0gY29yZUNvbmZpZy5idW5kbGVWYWx1ZS5zYWZlUGFyc2UoZW50cnkudmFsdWUpO1xuICAgIGlmICh2YWx1ZS5zdWNjZXNzKSB7XG4gICAgICBvdXRbZW50cnkubmFtZV0gPSB2YWx1ZS5kYXRhO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmICghZW50cnkudmFsdWVGcm9tKSBjb250aW51ZTtcbiAgICBjb25zdCByZXNvbHZlZCA9IHJlc29sdmVSZXNvdXJjZVZhbHVlKHJlc291cmNlQnlOYW1lLmdldChlbnRyeS52YWx1ZUZyb20pKTtcbiAgICBpZiAocmVzb2x2ZWQpIG91dFtlbnRyeS5uYW1lXSA9IHJlc29sdmVkO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKlxuICogRmxhdHRlbiBgcmVzb3VyY2VzLmFwcHMuPGtleT4uY29uZmlnLmVudmAgaW50byBhIGBuYW1lIC0+IHZhbHVlYCBtYXAuXG4gKiBBdXRvLXBpY2tzIHRoZSBhcHAgb25seSB3aGVuIHRoZSBidW5kbGUgZGVmaW5lcyBleGFjdGx5IG9uZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsYXR0ZW5BcHBFbnYoZGF0YTogdW5rbm93bik6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCBwYXJzZWQgPSBidW5kbGVWYWxpZGF0ZUFwcHNTY2hlbWEuc2FmZVBhcnNlKGRhdGEpO1xuICBpZiAoIXBhcnNlZC5zdWNjZXNzKSByZXR1cm4ge307XG5cbiAgY29uc3QgYXBwcyA9IHBhcnNlZC5kYXRhLnJlc291cmNlcz8uYXBwcztcbiAgaWYgKCFhcHBzIHx8IE9iamVjdC5rZXlzKGFwcHMpLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHt9O1xuXG4gIGNvbnN0IGtleSA9IHBpY2tBcHBSZXNvdXJjZUlkKGFwcHMpO1xuICBpZiAoIWtleSkgcmV0dXJuIHt9O1xuXG4gIGNvbnN0IGFwcCA9IGFwcHNba2V5XTtcbiAgaWYgKCFhcHA/LmNvbmZpZz8uZW52Py5sZW5ndGgpIHJldHVybiB7fTtcblxuICBjb25zdCByZXNvdXJjZUJ5TmFtZSA9IG5ldyBNYXAoXG4gICAgKGFwcC5yZXNvdXJjZXMgPz8gW10pXG4gICAgICAuZmlsdGVyKChyZXNvdXJjZSkgPT4gcmVzb3VyY2UubmFtZSlcbiAgICAgIC5tYXAoKHJlc291cmNlKSA9PiBbcmVzb3VyY2UubmFtZSEsIHJlc291cmNlXSksXG4gICk7XG5cbiAgY29uc3Qgb3V0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gIGZvciAoY29uc3QgZW50cnkgb2YgYXBwLmNvbmZpZy5lbnYpIHtcbiAgICBpZiAoIWVudHJ5Lm5hbWUpIGNvbnRpbnVlO1xuICAgIGNvbnN0IHZhbHVlID0gY29yZUNvbmZpZy5idW5kbGVWYWx1ZS5zYWZlUGFyc2UoZW50cnkudmFsdWUpO1xuICAgIGlmICh2YWx1ZS5zdWNjZXNzKSB7XG4gICAgICBvdXRbZW50cnkubmFtZV0gPSB2YWx1ZS5kYXRhO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmICghZW50cnkudmFsdWVfZnJvbSkgY29udGludWU7XG4gICAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlUmVzb3VyY2VWYWx1ZShyZXNvdXJjZUJ5TmFtZS5nZXQoZW50cnkudmFsdWVfZnJvbSkpO1xuICAgIGlmIChyZXNvbHZlZCkgb3V0W2VudHJ5Lm5hbWVdID0gcmVzb2x2ZWQ7XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9hZEFwcFlhbWwoY3dkOiBzdHJpbmcpOiBQcm9taXNlPENvbmZpZ0ZpbGUgfCB1bmRlZmluZWQ+IHtcbiAgZm9yIChjb25zdCBmaWxlTmFtZSBvZiBBUFBfWUFNTF9OQU1FUykge1xuICAgIGNvbnN0IGNvbmZpZ0ZpbGUgPSByZXNvbHZlQ29uZmlnRmlsZShjd2QsIGZpbGVOYW1lKTtcbiAgICBpZiAoIWNvbmZpZ0ZpbGUpIGNvbnRpbnVlO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVhZEZpbGUoY29uZmlnRmlsZSwgXCJ1dGY4XCIpO1xuICAgICAgY29uc3QgZGF0YSA9IHBhcnNlWWFtbCh0ZXh0KTtcbiAgICAgIGlmICghb2JqZWN0LmlzUmVjb3JkKGRhdGEpKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4geyBwYXRoOiBjb25maWdGaWxlLCBkYXRhIH07XG4gICAgfSBjYXRjaCB7XG4gICAgICBsb2dnZXIud2FybihcImZhaWxlZCB0byBwYXJzZSBhcHAgeWFtbFwiLCB7IHBhdGg6IGNvbmZpZ0ZpbGUgfSk7XG4gICAgfVxuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDb25maWdGaWxlKGN3ZDogc3RyaW5nLCBjb25maWdGaWxlOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoY29yZUNvbmZpZy5pc0RhdGFicmlja3NBcHBFbnYoKSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgZm9yIChjb25zdCByb290RGlyIG9mIHByb2plY3QucmVzb2x2ZVByb2plY3RSb290cyhjd2QpKSB7XG4gICAgY29uc3QgYnVuZGxlUGF0aCA9IHJlc29sdmUocm9vdERpciwgY29uZmlnRmlsZSk7XG4gICAgaWYgKGZpbGUuc3RhdFN5bmMoYnVuZGxlUGF0aCk/LmlzRmlsZSgpKSByZXR1cm4gYnVuZGxlUGF0aDtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFRoZSB2YWxpZGF0ZWQgYnVuZGxlIGZvciBgY3dkYCAtIHtAbGluayBjb3JlQ29uZmlnLmJ1bmRsZUZpbGV9LCB3aGljaCBjYWNoZXMgaXRcbiAqIHBlciB3b3JraW5nIGRpcmVjdG9yeS4gUmV0dXJucyBgdW5kZWZpbmVkYCBpbnNpZGUgYSBEYXRhYnJpY2tzIEFwcCwgd2hlcmUgdGhlXG4gKiBwbGF0Zm9ybSBoYXMgYWxyZWFkeSB0dXJuZWQgYGNvbmZpZy5lbnZgIGludG8gcmVhbCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgYW5kXG4gKiB0aGVyZSBpcyBubyBidW5kbGUgdG8gdmFsaWRhdGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidW5kbGUoY3dkPzogc3RyaW5nKTogUHJvbWlzZTxDb25maWdGaWxlIHwgdW5kZWZpbmVkPiB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoY29yZUNvbmZpZy5pc0RhdGFicmlja3NBcHBFbnYoKSA/IHVuZGVmaW5lZCA6IGNvcmVDb25maWcuYnVuZGxlRmlsZShjd2QpKTtcbn1cblxuLyoqXG4gKiBMb2NhdGUgYW5kIHBhcnNlIGBhcHAueWFtbGAgLyBgYXBwLnltbGAgZnJvbSB0aGUgYnVuZGxlIG9yIHByb2plY3Qgcm9vdC5cbiAqIENhY2hlZCBwZXIgd29ya2luZyBkaXJlY3RvcnkgdGhyb3VnaCB7QGxpbmsgY29udGV4dC5jYWNoZWR9LCBzbyBhIGBjd2RgIGNoYW5nZVxuICogcmUtcmVhZHMgaW5zdGVhZCBvZiByZXR1cm5pbmcgYW5vdGhlciBwcm9qZWN0J3MgZmlsZS4gUmV0dXJucyBgdW5kZWZpbmVkYFxuICogaW5zaWRlIGEgRGF0YWJyaWNrcyBBcHAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBZYW1sKGN3ZD86IHN0cmluZyk6IFByb21pc2U8Q29uZmlnRmlsZSB8IHVuZGVmaW5lZD4ge1xuICBpZiAoY29yZUNvbmZpZy5pc0RhdGFicmlja3NBcHBFbnYoKSkgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh1bmRlZmluZWQpO1xuICByZXR1cm4gY29udGV4dC5jYWNoZWQoW1wiYXBwa2l0XCIsIFwiYXBwWWFtbFwiXSwgKHJlc29sdmVkKSA9PiBsb2FkQXBwWWFtbChyZXNvbHZlZCA/PyBcIi5cIiksIGN3ZCk7XG59XG5cbi8qKlxuICogV2FsayBhIGRvdC1zZXBhcmF0ZWQgcGF0aCB0aHJvdWdoIGJ1bmRsZSB2YWxpZGF0ZSBKU09OLiBXaGVuIHRoZSB0ZXJtaW5hbFxuICogbm9kZSBpcyBhIGJ1bmRsZSB2YXJpYWJsZSBvYmplY3QgKGB7IHZhbHVlOiBcIi4uLlwiIH1gKSwgdGhlIGB2YWx1ZWAgZmllbGQgaXNcbiAqIHJldHVybmVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QnVuZGxlUGF0aChkYXRhOiBCdW5kbGVWYWxpZGF0ZUpzb24sIHBhdGg6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHBhcnRzID0gcGF0aC5zcGxpdChcIi5cIikuZmlsdGVyKEJvb2xlYW4pO1xuICBpZiAocGFydHMubGVuZ3RoID09PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIGxldCBjdXJyZW50OiB1bmtub3duID0gZGF0YTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgIGlmICghb2JqZWN0LmlzUmVjb3JkKGN1cnJlbnQpKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHBhcnQgPSBwYXJ0c1tpXSE7XG4gICAgY29uc3QgbmV4dCA9IGN1cnJlbnRbcGFydF07XG4gICAgaWYgKGkgPT09IHBhcnRzLmxlbmd0aCAtIDEpIHtcbiAgICAgIGlmICh0eXBlb2YgbmV4dCA9PT0gXCJzdHJpbmdcIiAmJiBuZXh0KSByZXR1cm4gbmV4dDtcbiAgICAgIGlmIChvYmplY3QuaXNSZWNvcmQobmV4dCkpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBuZXh0LnZhbHVlO1xuICAgICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmIHZhbHVlID8gdmFsdWUgOiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjdXJyZW50ID0gbmV4dDtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlQXBwRW52TWFwKFxuICBvcHRpb25zOiBSZXNvbHZlQ29uZmlnVmFsdWVPcHRpb25zLFxuKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PiB7XG4gIGNvbnN0IGFwcERhdGEgPSBvcHRpb25zLmFwcERhdGEgPz8gKGF3YWl0IGFwcFlhbWwoKSk7XG4gIGNvbnN0IGJ1bmRsZURhdGEgPSBvcHRpb25zLmJ1bmRsZURhdGEgPz8gKGF3YWl0IGJ1bmRsZSgpKTtcbiAgY29uc3QgZnJvbVlhbWwgPSBhcHBEYXRhID8gZmxhdHRlbkFwcFlhbWxFbnYoYXBwRGF0YS5kYXRhKSA6IHt9O1xuICBjb25zdCBmcm9tQnVuZGxlID0gYnVuZGxlRGF0YSA/IGZsYXR0ZW5BcHBFbnYoYnVuZGxlRGF0YS5kYXRhKSA6IHt9O1xuICByZXR1cm4geyAuLi5mcm9tWWFtbCwgLi4uZnJvbUJ1bmRsZSB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU291cmNlcyhvcHRpb25zOiBSZXNvbHZlQ29uZmlnVmFsdWVPcHRpb25zKTogQ29uZmlnU291cmNlW10ge1xuICBjb25zdCBzb3VyY2VzID0gWy4uLihvcHRpb25zLnNvdXJjZXMgPz8gZGVmYXVsdENvbmZpZ1NvdXJjZXMpXTtcbiAgaWYgKG9wdGlvbnMuZXhwbGljaXQgIT09IHVuZGVmaW5lZCAmJiAhc291cmNlcy5pbmNsdWRlcyhcImV4cGxpY2l0XCIpKSB7XG4gICAgc291cmNlcy51bnNoaWZ0KFwiZXhwbGljaXRcIik7XG4gIH1cbiAgcmV0dXJuIHNvdXJjZXM7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBhIGNvbmZpZ3VyYXRpb24gc3RyaW5nIGZyb20gdGhlIGNvbmZpZ3VyZWQgc291cmNlcy4gUmV0dXJucyB0aGUgZmlyc3RcbiAqIG5vbi1lbXB0eSB2YWx1ZSwgb3IgYHVuZGVmaW5lZGAgd2hlbiBub3RoaW5nIG1hdGNoZXMuXG4gKlxuICogUHJlY2VkZW5jZSBmb2xsb3dzIEFwcEtpdCdzOiBleHBsaWNpdCBjb25maWcsIHRoZW4gZW52aXJvbm1lbnQgdmFyaWFibGUsIHRoZW5cbiAqIHdoYXRldmVyIHRoZSBEYXRhYnJpY2tzIEFwcCAvIGJ1bmRsZSBkZWZpbml0aW9uIHN1cHBsaWVzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgeyBidW5kbGUgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbiAqXG4gKiBjb25zdCB3YXJlaG91c2VJZCA9IGF3YWl0IGJ1bmRsZS5yZXNvbHZlQ29uZmlnVmFsdWUoXCJEQVRBQlJJQ0tTX1dBUkVIT1VTRV9JRFwiLCB7XG4gKiAgIGNsaTogeyBEQVRBQlJJQ0tTX1dBUkVIT1VTRV9JRDogZmxhZ3Mud2FyZWhvdXNlIH0sXG4gKiAgIHNvdXJjZXM6IGJ1bmRsZS53aXRoQ2xpU291cmNlcygpLFxuICogfSk7XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlQ29uZmlnVmFsdWUoXG4gIG5hbWU6IHN0cmluZyxcbiAgb3B0aW9uczogUmVzb2x2ZUNvbmZpZ1ZhbHVlT3B0aW9ucyA9IHt9LFxuKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgY29uc3Qga2V5cyA9IGVudktleXNGb3JOYW1lKG5hbWUpLnRvQXJyYXkoKTtcbiAgaWYgKGtleXMubGVuZ3RoID09PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCBzb3VyY2VzID0gcmVzb2x2ZVNvdXJjZXMob3B0aW9ucyk7XG4gIGxldCBhcHBFbnZNYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCB1bmRlZmluZWQ7XG4gIGNvbnN0IHZhbHVlcyA9IChhc3luYyBmdW5jdGlvbiogKCkge1xuICAgIGZvciAoY29uc3Qgc291cmNlIG9mIHNvdXJjZXMpIHtcbiAgICAgIHN3aXRjaCAoc291cmNlKSB7XG4gICAgICAgIGNhc2UgXCJleHBsaWNpdFwiOlxuICAgICAgICAgIHlpZWxkIHJlYWRNYXAoa2V5cywgb3B0aW9ucy5leHBsaWNpdCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJjbGlcIjpcbiAgICAgICAgICB5aWVsZCByZWFkTWFwKGtleXMsIG9wdGlvbnMuY2xpKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcImVudlwiOlxuICAgICAgICAgIHlpZWxkIHJlYWRFbnYoa2V5cyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJidW5kbGVcIjpcbiAgICAgICAgICBpZiAoYXBwRW52TWFwID09PSB1bmRlZmluZWQpIGFwcEVudk1hcCA9IGF3YWl0IHJlc29sdmVBcHBFbnZNYXAob3B0aW9ucyk7XG4gICAgICAgICAgeWllbGQgcmVhZEFwcEVudihrZXlzLCBhcHBFbnZNYXApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IFZhbGlkYXRpb25FcnJvci5pbnZhbGlkVmFsdWUoXG4gICAgICAgICAgICBcInNvdXJjZXNcIixcbiAgICAgICAgICAgIHNvdXJjZSxcbiAgICAgICAgICAgIFwib25lIG9mOiBleHBsaWNpdCwgY2xpLCBlbnYsIGJ1bmRsZVwiLFxuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9KSgpO1xuICBmb3IgYXdhaXQgKGNvbnN0IHZhbHVlIG9mIHZhbHVlcykge1xuICAgIGlmICh2YWx1ZSkgcmV0dXJuIHZhbHVlO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogU291cmNlcyB3aXRoIGBjbGlgIGluY2x1ZGVkLCBpbiBDTEktZmlyc3Qgb3JkZXIuIFVzZSBmb3IgZGV2IGNvbW1hbmRzIHRoYXRcbiAqIGFjY2VwdCBmbGFnIG92ZXJyaWRlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdpdGhDbGlTb3VyY2VzKHNvdXJjZXM6IENvbmZpZ1NvdXJjZVtdID0gZGVmYXVsdENvbmZpZ1NvdXJjZXMpOiBDb25maWdTb3VyY2VbXSB7XG4gIGNvbnN0IHJlc3QgPSBzb3VyY2VzLmZpbHRlcigoc291cmNlKSA9PiBzb3VyY2UgIT09IFwiY2xpXCIgJiYgc291cmNlICE9PSBcImV4cGxpY2l0XCIpO1xuICByZXR1cm4gW1wiY2xpXCIsIFwiZXhwbGljaXRcIiwgLi4ucmVzdF07XG59XG4iXX0=