@dbx-tools/appkit 0.6.59 → 0.6.61

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
@@ -20,6 +20,12 @@ Lakebase auto-configuration without taking on a heavier feature package.
20
20
  `Context` values.
21
21
  - Lakebase cache-schema provisioning for deployments where the app identity must
22
22
  be granted access before persistent cache initialization.
23
+ - An interceptor context on `createApp` (`interceptor?: Interceptor | Interceptor[]`)
24
+ that hands add-ons the computed env, AppKit lifecycle hooks (`onLifecycle`, using
25
+ AppKit's own `setup:complete` / `server:ready` / `shutdown` vocabulary), signal
26
+ broadcast, and `bindProcess` for concurrently-style child supervision - any
27
+ bound process's death tears the app down, signals pass through. `@dbx-tools/tunnel`
28
+ is the primary consumer.
23
29
 
24
30
  ## Why Use This Over Native AppKit
25
31
 
@@ -99,7 +105,7 @@ pool. AppKit's PERSISTENT cache is the common case: it builds its own pool from
99
105
  env, and `createLakebasePool()` throws unless `LAKEBASE_ENDPOINT`, `PGHOST`,
100
106
  `PGDATABASE`, and a username are all present — while a Databricks App `postgres`
101
107
  resource binding supplies only the first. Miss one and the cache degrades silently
102
- to in-memory. `@dbx-tools/cli-tunnel`'s OTP gate calls this for exactly that
108
+ to in-memory. `@dbx-tools/tunnel`'s OTP gate calls this for exactly that
103
109
  reason.
104
110
 
105
111
  ## Configuration
@@ -109,6 +115,7 @@ reason.
109
115
  | Option | Type | Default | Description |
110
116
  | --------------- | ------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
111
117
  | `autoConfigure` | `"provision" \| "env" \| false` | `"provision"` | What to run before AppKit boots. `"provision"` resolves the Lakebase connection into `process.env` and grants the AppKit cache schema; `"env"` resolves the connection only; `false` skips auto-configuration. Omit it to gate the default on a `lakebase` plugin being registered, or set it explicitly to run regardless. |
118
+ | `interceptor` | `Interceptor \| Interceptor[]` | none | One or many callbacks handed an `InterceptorContext` after auto-config computes the env and before AppKit boots. The context carries the resolved env, `onLifecycle` (AppKit's `setup:complete` / `server:ready` / `shutdown`), `broadcastSignal`, and `bindProcess` for concurrently-style child supervision. |
112
119
 
113
120
  Set `autoConfigure` explicitly on an app that registers no `lakebase()` plugin but
114
121
  still wants AppKit's PERSISTENT cache. AppKit only chooses Lakebase for
@@ -277,7 +284,7 @@ behaviour depends entirely on `NODE_ENV`:
277
284
  That throw is right for an app behind the front door, where a missing token means
278
285
  something is broken. It is fatal for an app whose traffic legitimately arrives
279
286
  without one - a public tunnel where callers authenticate by email code
280
- ([`@dbx-tools/cli-tunnel`](../../cli/tunnel)), or a bot channel that validates its
287
+ ([`@dbx-tools/tunnel`](../../node/tunnel)), or a bot channel that validates its
281
288
  own inbound JWT (`POST /api/teams/messages`). Those apps must not run with
282
289
  `NODE_ENV=development` just to get the fallback, since that flag also relaxes
283
290
  secure cookies and unlocks other dev-only escape hatches.
package/index.ts CHANGED
@@ -7,6 +7,7 @@ export * as config from "./src/config.ts";
7
7
  export * as createApp from "./src/create-app.ts";
8
8
  export * as databricks from "./src/databricks.ts";
9
9
  export * as identity from "./src/identity.ts";
10
+ export * as interceptor from "./src/interceptor.ts";
10
11
  export * as lakebaseResolver from "./src/lakebase-resolver.ts";
11
12
  export * as pgaddress from "./src/pgaddress.ts";
12
13
  export * as plugin from "./src/plugin.ts";
@@ -18,6 +19,8 @@ export { MAX_TCP_PORT } from "./src/databricks.ts";
18
19
  export type { ContextLike } from "./src/databricks.ts";
19
20
  export { ACCESS_TOKEN_HEADER, USER_ID_HEADER, USER_EMAIL_HEADER, IDENTITY_MODES, DEFAULT_IDENTITY_MODE } from "./src/identity.ts";
20
21
  export type { IdentityMode, HeaderBearing } from "./src/identity.ts";
22
+ export { LifecycleBridgePlugin, lifecycleBridge } from "./src/interceptor.ts";
23
+ export type { LifecycleEvent, LifecycleHandler, ResolvedAppEnv, BindableProcess, InterceptorContext, Interceptor, InterceptorRuntime } from "./src/interceptor.ts";
21
24
  export type { LakebaseResolverInputs, LakebaseConnection } from "./src/lakebase-resolver.ts";
22
25
  export { SSL_MODES } from "./src/pgaddress.ts";
23
26
  export type { SslMode, LakebaseConnectionInputs, ParsedAddress } from "./src/pgaddress.ts";
package/lib/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * as config from "./src/config.ts";
3
3
  export * as createApp from "./src/create-app.ts";
4
4
  export * as databricks from "./src/databricks.ts";
5
5
  export * as identity from "./src/identity.ts";
6
+ export * as interceptor from "./src/interceptor.ts";
6
7
  export * as lakebaseResolver from "./src/lakebase-resolver.ts";
7
8
  export * as pgaddress from "./src/pgaddress.ts";
8
9
  export * as plugin from "./src/plugin.ts";
@@ -14,6 +15,8 @@ export { MAX_TCP_PORT } from "./src/databricks.ts";
14
15
  export type { ContextLike } from "./src/databricks.ts";
15
16
  export { ACCESS_TOKEN_HEADER, USER_ID_HEADER, USER_EMAIL_HEADER, IDENTITY_MODES, DEFAULT_IDENTITY_MODE } from "./src/identity.ts";
16
17
  export type { IdentityMode, HeaderBearing } from "./src/identity.ts";
18
+ export { LifecycleBridgePlugin, lifecycleBridge } from "./src/interceptor.ts";
19
+ export type { LifecycleEvent, LifecycleHandler, ResolvedAppEnv, BindableProcess, InterceptorContext, Interceptor, InterceptorRuntime } from "./src/interceptor.ts";
17
20
  export type { LakebaseResolverInputs, LakebaseConnection } from "./src/lakebase-resolver.ts";
18
21
  export { SSL_MODES } from "./src/pgaddress.ts";
19
22
  export type { SslMode, LakebaseConnectionInputs, ParsedAddress } from "./src/pgaddress.ts";
package/lib/index.js CHANGED
@@ -6,11 +6,13 @@ export * as config from "./src/config.js";
6
6
  export * as createApp from "./src/create-app.js";
7
7
  export * as databricks from "./src/databricks.js";
8
8
  export * as identity from "./src/identity.js";
9
+ export * as interceptor from "./src/interceptor.js";
9
10
  export * as lakebaseResolver from "./src/lakebase-resolver.js";
10
11
  export * as pgaddress from "./src/pgaddress.js";
11
12
  export * as plugin from "./src/plugin.js";
12
13
  export * as provision from "./src/provision.js";
13
14
  export { MAX_TCP_PORT } from "./src/databricks.js";
14
15
  export { ACCESS_TOKEN_HEADER, USER_ID_HEADER, USER_EMAIL_HEADER, IDENTITY_MODES, DEFAULT_IDENTITY_MODE } from "./src/identity.js";
16
+ export { LifecycleBridgePlugin, lifecycleBridge } from "./src/interceptor.js";
15
17
  export { SSL_MODES } from "./src/pgaddress.js";
16
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssTUFBTSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFNBQVMsTUFBTSxxQkFBcUIsQ0FBQztBQUNqRCxPQUFPLEtBQUssVUFBVSxNQUFNLHFCQUFxQixDQUFDO0FBQ2xELE9BQU8sS0FBSyxRQUFRLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxLQUFLLGdCQUFnQixNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBSWhELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUVuRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsY0FBYyxFQUFFLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBR2xJLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCAqIGFzIGFwcGtpdCBmcm9tIFwiLi9zcmMvYXBwa2l0LnRzXCI7XG5leHBvcnQgKiBhcyBjb25maWcgZnJvbSBcIi4vc3JjL2NvbmZpZy50c1wiO1xuZXhwb3J0ICogYXMgY3JlYXRlQXBwIGZyb20gXCIuL3NyYy9jcmVhdGUtYXBwLnRzXCI7XG5leHBvcnQgKiBhcyBkYXRhYnJpY2tzIGZyb20gXCIuL3NyYy9kYXRhYnJpY2tzLnRzXCI7XG5leHBvcnQgKiBhcyBpZGVudGl0eSBmcm9tIFwiLi9zcmMvaWRlbnRpdHkudHNcIjtcbmV4cG9ydCAqIGFzIGxha2ViYXNlUmVzb2x2ZXIgZnJvbSBcIi4vc3JjL2xha2ViYXNlLXJlc29sdmVyLnRzXCI7XG5leHBvcnQgKiBhcyBwZ2FkZHJlc3MgZnJvbSBcIi4vc3JjL3BnYWRkcmVzcy50c1wiO1xuZXhwb3J0ICogYXMgcGx1Z2luIGZyb20gXCIuL3NyYy9wbHVnaW4udHNcIjtcbmV4cG9ydCAqIGFzIHByb3Zpc2lvbiBmcm9tIFwiLi9zcmMvcHJvdmlzaW9uLnRzXCI7XG5leHBvcnQgdHlwZSB7IEV4ZWN1dGlvbkNvbnRleHRMaWtlLCBXb3Jrc3BhY2VDbGllbnRMaWtlIH0gZnJvbSBcIi4vc3JjL2FwcGtpdC50c1wiO1xuZXhwb3J0IHR5cGUgeyBCdW5kbGVWYWxpZGF0ZUpzb24sIENvbmZpZ0ZpbGUsIENvbmZpZ1NvdXJjZSwgQ29uZmlnTWFwVmFsdWUsIFJlc29sdmVDb25maWdWYWx1ZU9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvY29uZmlnLnRzXCI7XG5leHBvcnQgdHlwZSB7IEF1dG9Db25maWd1cmVNb2RlLCBDcmVhdGVBcHBDb25maWcgfSBmcm9tIFwiLi9zcmMvY3JlYXRlLWFwcC50c1wiO1xuZXhwb3J0IHsgTUFYX1RDUF9QT1JUIH0gZnJvbSBcIi4vc3JjL2RhdGFicmlja3MudHNcIjtcbmV4cG9ydCB0eXBlIHsgQ29udGV4dExpa2UgfSBmcm9tIFwiLi9zcmMvZGF0YWJyaWNrcy50c1wiO1xuZXhwb3J0IHsgQUNDRVNTX1RPS0VOX0hFQURFUiwgVVNFUl9JRF9IRUFERVIsIFVTRVJfRU1BSUxfSEVBREVSLCBJREVOVElUWV9NT0RFUywgREVGQVVMVF9JREVOVElUWV9NT0RFIH0gZnJvbSBcIi4vc3JjL2lkZW50aXR5LnRzXCI7XG5leHBvcnQgdHlwZSB7IElkZW50aXR5TW9kZSwgSGVhZGVyQmVhcmluZyB9IGZyb20gXCIuL3NyYy9pZGVudGl0eS50c1wiO1xuZXhwb3J0IHR5cGUgeyBMYWtlYmFzZVJlc29sdmVySW5wdXRzLCBMYWtlYmFzZUNvbm5lY3Rpb24gfSBmcm9tIFwiLi9zcmMvbGFrZWJhc2UtcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCB7IFNTTF9NT0RFUyB9IGZyb20gXCIuL3NyYy9wZ2FkZHJlc3MudHNcIjtcbmV4cG9ydCB0eXBlIHsgU3NsTW9kZSwgTGFrZWJhc2VDb25uZWN0aW9uSW5wdXRzLCBQYXJzZWRBZGRyZXNzIH0gZnJvbSBcIi4vc3JjL3BnYWRkcmVzcy50c1wiO1xuZXhwb3J0IHR5cGUgeyBQbHVnaW5Db250ZXh0TGlrZSB9IGZyb20gXCIuL3NyYy9wbHVnaW4udHNcIjtcbiJdfQ==
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssTUFBTSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFNBQVMsTUFBTSxxQkFBcUIsQ0FBQztBQUNqRCxPQUFPLEtBQUssVUFBVSxNQUFNLHFCQUFxQixDQUFDO0FBQ2xELE9BQU8sS0FBSyxRQUFRLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxLQUFLLFdBQVcsTUFBTSxzQkFBc0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sNEJBQTRCLENBQUM7QUFDL0QsT0FBTyxLQUFLLFNBQVMsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLEtBQUssTUFBTSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFJaEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRW5ELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxjQUFjLEVBQUUsaUJBQWlCLEVBQUUsY0FBYyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFbEksT0FBTyxFQUFFLHFCQUFxQixFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRzlFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCAqIGFzIGFwcGtpdCBmcm9tIFwiLi9zcmMvYXBwa2l0LnRzXCI7XG5leHBvcnQgKiBhcyBjb25maWcgZnJvbSBcIi4vc3JjL2NvbmZpZy50c1wiO1xuZXhwb3J0ICogYXMgY3JlYXRlQXBwIGZyb20gXCIuL3NyYy9jcmVhdGUtYXBwLnRzXCI7XG5leHBvcnQgKiBhcyBkYXRhYnJpY2tzIGZyb20gXCIuL3NyYy9kYXRhYnJpY2tzLnRzXCI7XG5leHBvcnQgKiBhcyBpZGVudGl0eSBmcm9tIFwiLi9zcmMvaWRlbnRpdHkudHNcIjtcbmV4cG9ydCAqIGFzIGludGVyY2VwdG9yIGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0ICogYXMgbGFrZWJhc2VSZXNvbHZlciBmcm9tIFwiLi9zcmMvbGFrZWJhc2UtcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCAqIGFzIHBnYWRkcmVzcyBmcm9tIFwiLi9zcmMvcGdhZGRyZXNzLnRzXCI7XG5leHBvcnQgKiBhcyBwbHVnaW4gZnJvbSBcIi4vc3JjL3BsdWdpbi50c1wiO1xuZXhwb3J0ICogYXMgcHJvdmlzaW9uIGZyb20gXCIuL3NyYy9wcm92aXNpb24udHNcIjtcbmV4cG9ydCB0eXBlIHsgRXhlY3V0aW9uQ29udGV4dExpa2UsIFdvcmtzcGFjZUNsaWVudExpa2UgfSBmcm9tIFwiLi9zcmMvYXBwa2l0LnRzXCI7XG5leHBvcnQgdHlwZSB7IEJ1bmRsZVZhbGlkYXRlSnNvbiwgQ29uZmlnRmlsZSwgQ29uZmlnU291cmNlLCBDb25maWdNYXBWYWx1ZSwgUmVzb2x2ZUNvbmZpZ1ZhbHVlT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9jb25maWcudHNcIjtcbmV4cG9ydCB0eXBlIHsgQXV0b0NvbmZpZ3VyZU1vZGUsIENyZWF0ZUFwcENvbmZpZyB9IGZyb20gXCIuL3NyYy9jcmVhdGUtYXBwLnRzXCI7XG5leHBvcnQgeyBNQVhfVENQX1BPUlQgfSBmcm9tIFwiLi9zcmMvZGF0YWJyaWNrcy50c1wiO1xuZXhwb3J0IHR5cGUgeyBDb250ZXh0TGlrZSB9IGZyb20gXCIuL3NyYy9kYXRhYnJpY2tzLnRzXCI7XG5leHBvcnQgeyBBQ0NFU1NfVE9LRU5fSEVBREVSLCBVU0VSX0lEX0hFQURFUiwgVVNFUl9FTUFJTF9IRUFERVIsIElERU5USVRZX01PREVTLCBERUZBVUxUX0lERU5USVRZX01PREUgfSBmcm9tIFwiLi9zcmMvaWRlbnRpdHkudHNcIjtcbmV4cG9ydCB0eXBlIHsgSWRlbnRpdHlNb2RlLCBIZWFkZXJCZWFyaW5nIH0gZnJvbSBcIi4vc3JjL2lkZW50aXR5LnRzXCI7XG5leHBvcnQgeyBMaWZlY3ljbGVCcmlkZ2VQbHVnaW4sIGxpZmVjeWNsZUJyaWRnZSB9IGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0IHR5cGUgeyBMaWZlY3ljbGVFdmVudCwgTGlmZWN5Y2xlSGFuZGxlciwgUmVzb2x2ZWRBcHBFbnYsIEJpbmRhYmxlUHJvY2VzcywgSW50ZXJjZXB0b3JDb250ZXh0LCBJbnRlcmNlcHRvciwgSW50ZXJjZXB0b3JSdW50aW1lIH0gZnJvbSBcIi4vc3JjL2ludGVyY2VwdG9yLnRzXCI7XG5leHBvcnQgdHlwZSB7IExha2ViYXNlUmVzb2x2ZXJJbnB1dHMsIExha2ViYXNlQ29ubmVjdGlvbiB9IGZyb20gXCIuL3NyYy9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuZXhwb3J0IHsgU1NMX01PREVTIH0gZnJvbSBcIi4vc3JjL3BnYWRkcmVzcy50c1wiO1xuZXhwb3J0IHR5cGUgeyBTc2xNb2RlLCBMYWtlYmFzZUNvbm5lY3Rpb25JbnB1dHMsIFBhcnNlZEFkZHJlc3MgfSBmcm9tIFwiLi9zcmMvcGdhZGRyZXNzLnRzXCI7XG5leHBvcnQgdHlwZSB7IFBsdWdpbkNvbnRleHRMaWtlIH0gZnJvbSBcIi4vc3JjL3BsdWdpbi50c1wiO1xuIl19
@@ -22,6 +22,8 @@
22
22
  */
23
23
  import { createApp as appkitCreateApp } from "@databricks/appkit";
24
24
  import type { PluginMap } from "@databricks/appkit/dist/shared/src/plugin";
25
+ import { type Interceptor } from "./interceptor.ts";
26
+ import { type LakebaseConnection } from "./lakebase-resolver.ts";
25
27
  type AppKitCreateAppConfig = NonNullable<Parameters<typeof appkitCreateApp>[0]>;
26
28
  type AppKitPlugins = NonNullable<AppKitCreateAppConfig["plugins"]>;
27
29
  /**
@@ -50,6 +52,13 @@ export type CreateAppConfig<T extends AppKitPlugins = AppKitPlugins> = Omit<AppK
50
52
  onPluginsReady?: (appkit: PluginMap<T>) => void | Promise<void>;
51
53
  /** Auto-configuration to run before AppKit boots. Defaults to `"provision"`. */
52
54
  autoConfigure?: AutoConfigureMode | false;
55
+ /**
56
+ * One or many {@link Interceptor}s handed an {@link InterceptorContext} once
57
+ * auto-configuration has computed the env. Each receives the resolved env, an
58
+ * AppKit-lifecycle hook, and `bindProcess` for concurrently-style supervision -
59
+ * see `./interceptor`. The tunnel is the primary consumer.
60
+ */
61
+ interceptor?: Interceptor | Interceptor[];
53
62
  };
54
63
  /**
55
64
  * Run enabled auto-configuration steps without calling AppKit's `createApp`.
@@ -65,11 +74,18 @@ export type CreateAppConfig<T extends AppKitPlugins = AppKitPlugins> = Omit<AppK
65
74
  * // Populate PGHOST / PGDATABASE / LAKEBASE_ENDPOINT without booting AppKit.
66
75
  * await createApp.autoConfigure({ autoConfigure: "env" });
67
76
  */
68
- export declare function autoConfigure<T extends AppKitPlugins>(config?: CreateAppConfig<T>, signal?: AbortSignal): Promise<void>;
77
+ export declare function autoConfigure<T extends AppKitPlugins>(config?: CreateAppConfig<T>, signal?: AbortSignal): Promise<LakebaseConnection | undefined>;
69
78
  /**
70
79
  * Auto-configuring drop-in for AppKit's `createApp`: same config, same typed
71
80
  * plugin-export map, with {@link autoConfigure} run first.
72
81
  *
82
+ * When {@link CreateAppConfig.interceptor}s are given, each is invoked with an
83
+ * {@link InterceptorContext} AFTER auto-configuration computes the env and BEFORE
84
+ * AppKit boots - so an interceptor can read the resolved connection, register
85
+ * lifecycle handlers, and `bindProcess` a child. A hidden {@link lifecycleBridge}
86
+ * plugin is injected so those `onLifecycle` handlers fire on the genuine AppKit
87
+ * events; it has no exports, so the returned {@link PluginMap} is unchanged.
88
+ *
73
89
  * @example
74
90
  * import { createApp } from "@dbx-tools/appkit";
75
91
  * import { lakebase, server } from "@databricks/appkit";
@@ -22,6 +22,7 @@
22
22
  */
23
23
  import { createApp as appkitCreateApp } from "@databricks/appkit";
24
24
  import { async, log } from "@dbx-tools/shared-core";
25
+ import { createInterceptorContext, lifecycleBridge, } from "./interceptor.js";
25
26
  import { applyLakebaseEnv } from "./lakebase-resolver.js";
26
27
  import { provisionCacheSchema } from "./provision.js";
27
28
  const logger = log.logger("create-app");
@@ -63,14 +64,15 @@ export async function autoConfigure(config, signal) {
63
64
  provisioned: false,
64
65
  skippedReason: mode === false ? "disabled" : "no lakebase plugin",
65
66
  });
66
- return;
67
+ return undefined;
67
68
  }
68
69
  const controller = new AbortController();
69
70
  async.tieAbortSignal(controller, signal);
70
71
  async.tieAbortSignal(controller, AbortSignal.timeout(AUTO_CONFIGURE_TIMEOUT_MS));
71
72
  const provision = mode === "provision";
72
- await autoConfigureLakebase(provision, controller.signal);
73
+ const resolved = await autoConfigureLakebase(provision, controller.signal);
73
74
  logger.info("ready", { autoConfigure: mode, lakebasePluginPresent, provisioned: provision });
75
+ return resolved;
74
76
  }
75
77
  /**
76
78
  * Resolve Lakebase Postgres connection info, write the resolved values to
@@ -97,10 +99,30 @@ function redactLakebaseConnection(resolved) {
97
99
  sslMode: resolved.sslMode,
98
100
  };
99
101
  }
102
+ /** Build the {@link ResolvedAppEnv} interceptors read, from the auto-config result. */
103
+ function resolvedAppEnv(lakebase) {
104
+ return {
105
+ ...(lakebase ? { lakebase } : {}),
106
+ ...(process.env.DATABRICKS_HOST ? { databricksHost: process.env.DATABRICKS_HOST } : {}),
107
+ };
108
+ }
109
+ /** Normalize the `interceptor?: Interceptor | Interceptor[]` option to an array. */
110
+ function interceptorList(interceptor) {
111
+ if (!interceptor)
112
+ return [];
113
+ return Array.isArray(interceptor) ? interceptor : [interceptor];
114
+ }
100
115
  /**
101
116
  * Auto-configuring drop-in for AppKit's `createApp`: same config, same typed
102
117
  * plugin-export map, with {@link autoConfigure} run first.
103
118
  *
119
+ * When {@link CreateAppConfig.interceptor}s are given, each is invoked with an
120
+ * {@link InterceptorContext} AFTER auto-configuration computes the env and BEFORE
121
+ * AppKit boots - so an interceptor can read the resolved connection, register
122
+ * lifecycle handlers, and `bindProcess` a child. A hidden {@link lifecycleBridge}
123
+ * plugin is injected so those `onLifecycle` handlers fire on the genuine AppKit
124
+ * events; it has no exports, so the returned {@link PluginMap} is unchanged.
125
+ *
104
126
  * @example
105
127
  * import { createApp } from "@dbx-tools/appkit";
106
128
  * import { lakebase, server } from "@databricks/appkit";
@@ -108,9 +130,25 @@ function redactLakebaseConnection(resolved) {
108
130
  * const app = await createApp.createApp({ plugins: [server(), lakebase()] });
109
131
  */
110
132
  export async function createApp(config) {
111
- await autoConfigure(config);
133
+ const lakebase = await autoConfigure(config);
112
134
  const appConfig = { ...config };
113
135
  delete appConfig.autoConfigure;
136
+ delete appConfig.interceptor;
137
+ const interceptors = interceptorList(config?.interceptor);
138
+ if (interceptors.length === 0) {
139
+ return appkitCreateApp(appConfig);
140
+ }
141
+ // Build the context from the computed env, run each interceptor (they register
142
+ // lifecycle handlers + bind processes), then inject the bridge that relays the
143
+ // REAL AppKit lifecycle into `runtime.emitLifecycle` during its `setup()`.
144
+ const runtime = createInterceptorContext(resolvedAppEnv(lakebase));
145
+ for (const interceptor of interceptors) {
146
+ await interceptor(runtime.context);
147
+ }
148
+ // Append the bridge to the plugins tuple. It is hidden and exports nothing, so
149
+ // the returned map still matches `PluginMap<T>`; the cast (through `unknown`) is
150
+ // only because appending widens the tuple type beyond `T`.
151
+ appConfig.plugins = [...(appConfig.plugins ?? []), lifecycleBridge({ runtime })];
114
152
  return appkitCreateApp(appConfig);
115
153
  }
116
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLWFwcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jcmVhdGUtYXBwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFFSCxPQUFPLEVBQUUsU0FBUyxJQUFJLGVBQWUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBSWxFLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFcEQsT0FBTyxFQUFFLGdCQUFnQixFQUEyQixNQUFNLHdCQUF3QixDQUFDO0FBQ25GLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBcUN0RCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBRXhDLE1BQU0sZUFBZSxHQUFHLFVBQVUsQ0FBQztBQUNuQyxNQUFNLHNCQUFzQixHQUFzQixXQUFXLENBQUM7QUFFOUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSx5QkFBeUIsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFDO0FBRTlDLFNBQVMsVUFBVSxDQUNqQixNQUFzQyxFQUN0QyxJQUFZO0lBRVosT0FBTyxPQUFPLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQztBQUN4RSxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsYUFBYSxDQUNqQyxNQUEyQixFQUMzQixNQUFvQjtJQUVwQixNQUFNLElBQUksR0FBRyxNQUFNLEVBQUUsYUFBYSxJQUFJLHNCQUFzQixDQUFDO0lBQzdELE1BQU0sUUFBUSxHQUFHLE1BQU0sRUFBRSxhQUFhLEtBQUssU0FBUyxDQUFDO0lBQ3JELE1BQU0scUJBQXFCLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxlQUFlLENBQUMsQ0FBQztJQUNsRSxJQUFJLElBQUksS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDLFFBQVEsSUFBSSxxQkFBcUIsQ0FBQyxFQUFFLENBQUM7UUFDM0QsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDbkIsYUFBYSxFQUFFLElBQUk7WUFDbkIscUJBQXFCO1lBQ3JCLFdBQVcsRUFBRSxLQUFLO1lBQ2xCLGFBQWEsRUFBRSxJQUFJLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLG9CQUFvQjtTQUNsRSxDQUFDLENBQUM7UUFDSCxPQUFPO0lBQ1QsQ0FBQztJQUVELE1BQU0sVUFBVSxHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7SUFDekMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDekMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxVQUFVLEVBQUUsV0FBVyxDQUFDLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLENBQUM7SUFFakYsTUFBTSxTQUFTLEdBQUcsSUFBSSxLQUFLLFdBQVcsQ0FBQztJQUN2QyxNQUFNLHFCQUFxQixDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUQsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLHFCQUFxQixFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0FBQy9GLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILEtBQUssVUFBVSxxQkFBcUIsQ0FDbEMsU0FBa0IsRUFDbEIsTUFBbUI7SUFFbkIsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNyRSxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxFQUFFLEdBQUcsd0JBQXdCLENBQUMsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUM1RSxJQUFJLFNBQVMsRUFBRSxDQUFDO1FBQ2QsTUFBTSxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUNELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUM7QUFFRCxTQUFTLHdCQUF3QixDQUFDLFFBQTRCO0lBQzVELE9BQU87UUFDTCxPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87UUFDekIsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNO1FBQ3ZCLFFBQVEsRUFBRSxRQUFRLENBQUMsUUFBUTtRQUMzQixRQUFRLEVBQUUsUUFBUSxDQUFDLFFBQVE7UUFDM0IsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJO1FBQ25CLElBQUksRUFBRSxRQUFRLENBQUMsSUFBSTtRQUNuQixPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87S0FDMUIsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLFNBQVMsQ0FDN0IsTUFBMkI7SUFFM0IsTUFBTSxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDNUIsTUFBTSxTQUFTLEdBQUcsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO0lBQ2hDLE9BQU8sU0FBUyxDQUFDLGFBQWEsQ0FBQztJQUMvQixPQUFPLGVBQWUsQ0FBSSxTQUFTLENBQUMsQ0FBQztBQUN2QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBgY3JlYXRlQXBwYCB3cmFwcGVyOiBydW5zIGRieC10b29scyBhdXRvLWNvbmZpZ3VyYXRpb24sIHRoZW4gZGVsZWdhdGVzIHRvXG4gKiBBcHBLaXQncyBvd24gYGNyZWF0ZUFwcGAgd2l0aCB0aGUgZXhhY3Qgc2FtZSBhcmd1bWVudHMuXG4gKlxuICogRHJvcCBpdCBpbiBhcyBhIG9uZS1mb3Itb25lIHJlcGxhY2VtZW50IGZvciBgQGRhdGFicmlja3MvYXBwa2l0YCdzXG4gKiBgY3JlYXRlQXBwYCAtIHNhbWUgcGFyYW1ldGVycywgc2FtZSByZXR1cm4gdHlwZSwgZnVsbCBwbHVnaW4tZXhwb3J0IGluZmVyZW5jZVxuICogcHJlc2VydmVkOlxuICpcbiAqIGBgYHRzXG4gKiBpbXBvcnQgeyBjcmVhdGVBcHAgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbiAqIGltcG9ydCB7IGxha2ViYXNlLCBzZXJ2ZXIgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG4gKlxuICogYXdhaXQgY3JlYXRlQXBwLmNyZWF0ZUFwcCh7IHBsdWdpbnM6IFtzZXJ2ZXIoKSwgbGFrZWJhc2UoKV0gfSk7XG4gKiBgYGBcbiAqXG4gKiBBdXRvLWNvbmZpZ3VyYXRpb24gcnVucyBCRUZPUkUgZGVsZWdhdGluZyBzbyBwbHVnaW5zIHNlZSBhIGZ1bGx5IHBvcHVsYXRlZFxuICogYHByb2Nlc3MuZW52YCBkdXJpbmcgdGhlaXIgc3luY2hyb25vdXMgYHNldHVwKClgLiBMYWtlYmFzZSBQb3N0Z3JlcyBydW5zIHdoZW5cbiAqIGEgYGxha2ViYXNlYCBwbHVnaW4gaXMgcHJlc2VudCwgb3Igd2hlbiB7QGxpbmsgQXV0b0NvbmZpZ3VyZU1vZGV9IGlzIHNldFxuICogZXhwbGljaXRseSBvbiB0aGUgY29uZmlnIG9iamVjdC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgY3JlYXRlQXBwIGFzIGFwcGtpdENyZWF0ZUFwcCB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbi8vIEFwcEtpdCdzIHJvb3QgYmFycmVsIHJlLWV4cG9ydHMgYFBsdWdpbkRhdGFgIGJ1dCBub3QgYFBsdWdpbk1hcGA7IHRoZSBwYWNrYWdlXG4vLyBwdWJsaXNoZXMgdGhpcyBzdWJwYXRoIGZvciBleGFjdGx5IHRoYXQgdHlwZS5cbmltcG9ydCB0eXBlIHsgUGx1Z2luTWFwIH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdC9kaXN0L3NoYXJlZC9zcmMvcGx1Z2luXCI7XG5pbXBvcnQgeyBhc3luYywgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcblxuaW1wb3J0IHsgYXBwbHlMYWtlYmFzZUVudiwgdHlwZSBMYWtlYmFzZUNvbm5lY3Rpb24gfSBmcm9tIFwiLi9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuaW1wb3J0IHsgcHJvdmlzaW9uQ2FjaGVTY2hlbWEgfSBmcm9tIFwiLi9wcm92aXNpb24udHNcIjtcblxudHlwZSBBcHBLaXRDcmVhdGVBcHBDb25maWcgPSBOb25OdWxsYWJsZTxQYXJhbWV0ZXJzPHR5cGVvZiBhcHBraXRDcmVhdGVBcHA+WzBdPjtcbnR5cGUgQXBwS2l0UGx1Z2lucyA9IE5vbk51bGxhYmxlPEFwcEtpdENyZWF0ZUFwcENvbmZpZ1tcInBsdWdpbnNcIl0+O1xuXG4vKipcbiAqIFdoYXQgYXV0by1jb25maWd1cmF0aW9uIGRvZXMgYmVmb3JlIEFwcEtpdCBib290cy5cbiAqXG4gKiAtIGBcInByb3Zpc2lvblwiYDogcmVzb2x2ZSB0aGUgTGFrZWJhc2UgY29ubmVjdGlvbiBpbnRvIGBwcm9jZXNzLmVudmAsIHRoZW5cbiAqICAgZ3JhbnQgdGhlIEFwcEtpdCBjYWNoZSBzY2hlbWEgdG8gdGhlIGNvbm5lY3Rpbmcgcm9sZS5cbiAqIC0gYFwiZW52XCJgOiByZXNvbHZlIHRoZSBMYWtlYmFzZSBjb25uZWN0aW9uIGludG8gYHByb2Nlc3MuZW52YCBvbmx5LlxuICpcbiAqIE9taXQgaXQgdG8gZ2V0IGBcInByb3Zpc2lvblwiYCBnYXRlZCBvbiBhIGBsYWtlYmFzZWAgcGx1Z2luIGJlaW5nIHJlZ2lzdGVyZWQ7XG4gKiBzZXQgaXQgZXhwbGljaXRseSB0byBydW4gcmVnYXJkbGVzcyBvZiB0aGUgcGx1Z2luIGxpc3QsIG9yIHBhc3MgYGZhbHNlYCB0b1xuICogc2tpcCBhdXRvLWNvbmZpZ3VyYXRpb24gZW50aXJlbHkuXG4gKlxuICogU2V0IGl0IEVYUExJQ0lUTFkgb24gYW4gYXBwIHRoYXQgaGFzIG5vIGBsYWtlYmFzZSgpYCBwbHVnaW4gYnV0IHN0aWxsIHdhbnRzXG4gKiBBcHBLaXQncyBQRVJTSVNURU5UIGNhY2hlLiBBcHBLaXQgcGlja3MgTGFrZWJhc2UgZm9yIGBDYWNoZU1hbmFnZXJgIG9ubHkgd2hlblxuICogYGNyZWF0ZUxha2ViYXNlUG9vbCgpYCBjYW4gYnVpbGQgYSBwb29sLCBhbmQgdGhhdCByZWFkcyBgTEFLRUJBU0VfRU5EUE9JTlRgIC9cbiAqIGBQR0hPU1RgIC8gYFBHREFUQUJBU0VgIHN0cmFpZ2h0IGZyb20gYHByb2Nlc3MuZW52YCAtIHNvIHdpdGhvdXQgdGhpcyBzdGVwIHRoZVxuICogY2FjaGUgc2lsZW50bHkgZmFsbHMgYmFjayB0byBpbi1tZW1vcnksIGFuZCBhbnl0aGluZyBpdCBob2xkcyAoYSBzZXNzaW9uXG4gKiBzaWduaW5nIGtleSwgYSBvbmUtdGltZSBjb2RlKSBpcyBsb3N0IG9uIHJlc3RhcnQuIGBcImVudlwiYCBpcyB0aGUgcmlnaHQgbW9kZVxuICogdGhlcmU6IHRoZSBhcHAgU1AgY2Fubm90IGdyYW50IG9uIHRoZSBjYWNoZSBzY2hlbWEgYW55d2F5LlxuICovXG5leHBvcnQgdHlwZSBBdXRvQ29uZmlndXJlTW9kZSA9IFwiZW52XCIgfCBcInByb3Zpc2lvblwiO1xuXG4vKiogQXBwS2l0J3MgYGNyZWF0ZUFwcGAgY29uZmlnIHBsdXMgdGhlIGRieC10b29scyBhdXRvLWNvbmZpZ3VyYXRpb24gc3dpdGNoLiAqL1xuZXhwb3J0IHR5cGUgQ3JlYXRlQXBwQ29uZmlnPFQgZXh0ZW5kcyBBcHBLaXRQbHVnaW5zID0gQXBwS2l0UGx1Z2lucz4gPSBPbWl0PFxuICBBcHBLaXRDcmVhdGVBcHBDb25maWcsXG4gIFwicGx1Z2luc1wiIHwgXCJvblBsdWdpbnNSZWFkeVwiXG4+ICYge1xuICBwbHVnaW5zPzogVDtcbiAgb25QbHVnaW5zUmVhZHk/OiAoYXBwa2l0OiBQbHVnaW5NYXA8VD4pID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+O1xuICAvKiogQXV0by1jb25maWd1cmF0aW9uIHRvIHJ1biBiZWZvcmUgQXBwS2l0IGJvb3RzLiBEZWZhdWx0cyB0byBgXCJwcm92aXNpb25cImAuICovXG4gIGF1dG9Db25maWd1cmU/OiBBdXRvQ29uZmlndXJlTW9kZSB8IGZhbHNlO1xufTtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImNyZWF0ZS1hcHBcIik7XG5cbmNvbnN0IExBS0VCQVNFX1BMVUdJTiA9IFwibGFrZWJhc2VcIjtcbmNvbnN0IERFRkFVTFRfQVVUT19DT05GSUdVUkU6IEF1dG9Db25maWd1cmVNb2RlID0gXCJwcm92aXNpb25cIjtcblxuLyoqXG4gKiBVcHBlciBib3VuZCBvbiBib290LXRpbWUgYXV0by1jb25maWd1cmF0aW9uLiBJdCBydW5zIGFzIHRoZSBzZXJ2aWNlIHByaW5jaXBhbFxuICogYmVmb3JlIGFueSBwbHVnaW4gaXMgY29uc3RydWN0ZWQsIHNvIGl0IHNpdHMgb3V0c2lkZSBBcHBLaXQncyBpbnRlcmNlcHRvclxuICogY2hhaW4gYW5kIGluaGVyaXRzIG5vIHRpbWVvdXQsIHJldHJ5LCBvciB0ZWxlbWV0cnkgZnJvbSBpdC4gVGhlIGJ1ZGdldCBjb3ZlcnNcbiAqIHRoZSByZXNvbHZlcidzIG93biB3b3JzdCBjYXNlIChjcmVhdGUgYSBwcm9qZWN0LCB0aGVuIHdhaXQgZm9yIGl0cyBlbmRwb2ludClcbiAqIHBsdXMgdGhlIGNhY2hlLXNjaGVtYSBncmFudHMuXG4gKi9cbmNvbnN0IEFVVE9fQ09ORklHVVJFX1RJTUVPVVRfTVMgPSAxMSAqIDYwXzAwMDtcblxuZnVuY3Rpb24gdXNlc1BsdWdpbjxUIGV4dGVuZHMgQXBwS2l0UGx1Z2lucz4oXG4gIGNvbmZpZzogQ3JlYXRlQXBwQ29uZmlnPFQ+IHwgdW5kZWZpbmVkLFxuICBuYW1lOiBzdHJpbmcsXG4pOiBib29sZWFuIHtcbiAgcmV0dXJuIEJvb2xlYW4oY29uZmlnPy5wbHVnaW5zPy5zb21lKChlbnRyeSkgPT4gZW50cnkubmFtZSA9PT0gbmFtZSkpO1xufVxuXG4vKipcbiAqIFJ1biBlbmFibGVkIGF1dG8tY29uZmlndXJhdGlvbiBzdGVwcyB3aXRob3V0IGNhbGxpbmcgQXBwS2l0J3MgYGNyZWF0ZUFwcGAuXG4gKlxuICogTGFrZWJhc2UgUG9zdGdyZXMgcmVzb2x2ZXMgd2hlbiB7QGxpbmsgQ3JlYXRlQXBwQ29uZmlnLmF1dG9Db25maWd1cmV9IGlzIHNldFxuICogZXhwbGljaXRseSBvciBhIGBsYWtlYmFzZWAgcGx1Z2luIGlzIGxpc3RlZCBpbiBgY29uZmlnLnBsdWdpbnNgLiBgc2lnbmFsYFxuICogY2FuY2VscyB0aGUgcmVzb2x1dGlvbjsgaXQgaXMgY29tYmluZWQgd2l0aCBhbiBpbnRlcm5hbCBib290IHRpbWVvdXQgZWl0aGVyXG4gKiB3YXkuXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCB7IGNyZWF0ZUFwcCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuICpcbiAqIC8vIFBvcHVsYXRlIFBHSE9TVCAvIFBHREFUQUJBU0UgLyBMQUtFQkFTRV9FTkRQT0lOVCB3aXRob3V0IGJvb3RpbmcgQXBwS2l0LlxuICogYXdhaXQgY3JlYXRlQXBwLmF1dG9Db25maWd1cmUoeyBhdXRvQ29uZmlndXJlOiBcImVudlwiIH0pO1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXV0b0NvbmZpZ3VyZTxUIGV4dGVuZHMgQXBwS2l0UGx1Z2lucz4oXG4gIGNvbmZpZz86IENyZWF0ZUFwcENvbmZpZzxUPixcbiAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgbW9kZSA9IGNvbmZpZz8uYXV0b0NvbmZpZ3VyZSA/PyBERUZBVUxUX0FVVE9fQ09ORklHVVJFO1xuICBjb25zdCBleHBsaWNpdCA9IGNvbmZpZz8uYXV0b0NvbmZpZ3VyZSAhPT0gdW5kZWZpbmVkO1xuICBjb25zdCBsYWtlYmFzZVBsdWdpblByZXNlbnQgPSB1c2VzUGx1Z2luKGNvbmZpZywgTEFLRUJBU0VfUExVR0lOKTtcbiAgaWYgKG1vZGUgPT09IGZhbHNlIHx8ICEoZXhwbGljaXQgfHwgbGFrZWJhc2VQbHVnaW5QcmVzZW50KSkge1xuICAgIGxvZ2dlci5pbmZvKFwicmVhZHlcIiwge1xuICAgICAgYXV0b0NvbmZpZ3VyZTogbW9kZSxcbiAgICAgIGxha2ViYXNlUGx1Z2luUHJlc2VudCxcbiAgICAgIHByb3Zpc2lvbmVkOiBmYWxzZSxcbiAgICAgIHNraXBwZWRSZWFzb246IG1vZGUgPT09IGZhbHNlID8gXCJkaXNhYmxlZFwiIDogXCJubyBsYWtlYmFzZSBwbHVnaW5cIixcbiAgICB9KTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICBhc3luYy50aWVBYm9ydFNpZ25hbChjb250cm9sbGVyLCBzaWduYWwpO1xuICBhc3luYy50aWVBYm9ydFNpZ25hbChjb250cm9sbGVyLCBBYm9ydFNpZ25hbC50aW1lb3V0KEFVVE9fQ09ORklHVVJFX1RJTUVPVVRfTVMpKTtcblxuICBjb25zdCBwcm92aXNpb24gPSBtb2RlID09PSBcInByb3Zpc2lvblwiO1xuICBhd2FpdCBhdXRvQ29uZmlndXJlTGFrZWJhc2UocHJvdmlzaW9uLCBjb250cm9sbGVyLnNpZ25hbCk7XG4gIGxvZ2dlci5pbmZvKFwicmVhZHlcIiwgeyBhdXRvQ29uZmlndXJlOiBtb2RlLCBsYWtlYmFzZVBsdWdpblByZXNlbnQsIHByb3Zpc2lvbmVkOiBwcm92aXNpb24gfSk7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBMYWtlYmFzZSBQb3N0Z3JlcyBjb25uZWN0aW9uIGluZm8sIHdyaXRlIHRoZSByZXNvbHZlZCB2YWx1ZXMgdG9cbiAqIGBwcm9jZXNzLmVudmAsIGFuZCByZXR1cm4gdGhlIHJlY29yZC4gVXNlZCBieSB7QGxpbmsgYXV0b0NvbmZpZ3VyZX07IGNhbGxcbiAqIHtAbGluayBhcHBseUxha2ViYXNlRW52fSBkaXJlY3RseSB3aGVuIGZpbmVyIGNvbnRyb2wgaXMgbmVlZGVkIChhIGRpZmZlcmVudFxuICogYGF1dG9DcmVhdGVgIHBvbGljeSwgb3IgYSBjYWxsZXIgdGhhdCB3YW50cyB0aGUgZW52IHdpdGhvdXQgYm9vdGluZyBBcHBLaXQpLlxuICovXG5hc3luYyBmdW5jdGlvbiBhdXRvQ29uZmlndXJlTGFrZWJhc2UoXG4gIHByb3Zpc2lvbjogYm9vbGVhbixcbiAgc2lnbmFsOiBBYm9ydFNpZ25hbCxcbik6IFByb21pc2U8TGFrZWJhc2VDb25uZWN0aW9uPiB7XG4gIGNvbnN0IHsgcmVzb2x2ZWQsIHVzZXIgfSA9IGF3YWl0IGFwcGx5TGFrZWJhc2VFbnYodW5kZWZpbmVkLCBzaWduYWwpO1xuICBsb2dnZXIuaW5mbyhcImVudiB1cGRhdGVkXCIsIHsgLi4ucmVkYWN0TGFrZWJhc2VDb25uZWN0aW9uKHJlc29sdmVkKSwgdXNlciB9KTtcbiAgaWYgKHByb3Zpc2lvbikge1xuICAgIGF3YWl0IHByb3Zpc2lvbkNhY2hlU2NoZW1hKHVzZXIsIGxvZ2dlcik7XG4gIH1cbiAgcmV0dXJuIHJlc29sdmVkO1xufVxuXG5mdW5jdGlvbiByZWRhY3RMYWtlYmFzZUNvbm5lY3Rpb24ocmVzb2x2ZWQ6IExha2ViYXNlQ29ubmVjdGlvbik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgcmV0dXJuIHtcbiAgICBwcm9qZWN0OiByZXNvbHZlZC5wcm9qZWN0LFxuICAgIGJyYW5jaDogcmVzb2x2ZWQuYnJhbmNoLFxuICAgIGVuZHBvaW50OiByZXNvbHZlZC5lbmRwb2ludCxcbiAgICBkYXRhYmFzZTogcmVzb2x2ZWQuZGF0YWJhc2UsXG4gICAgaG9zdDogcmVzb2x2ZWQuaG9zdCxcbiAgICBwb3J0OiByZXNvbHZlZC5wb3J0LFxuICAgIHNzbE1vZGU6IHJlc29sdmVkLnNzbE1vZGUsXG4gIH07XG59XG5cbi8qKlxuICogQXV0by1jb25maWd1cmluZyBkcm9wLWluIGZvciBBcHBLaXQncyBgY3JlYXRlQXBwYDogc2FtZSBjb25maWcsIHNhbWUgdHlwZWRcbiAqIHBsdWdpbi1leHBvcnQgbWFwLCB3aXRoIHtAbGluayBhdXRvQ29uZmlndXJlfSBydW4gZmlyc3QuXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCB7IGNyZWF0ZUFwcCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuICogaW1wb3J0IHsgbGFrZWJhc2UsIHNlcnZlciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbiAqXG4gKiBjb25zdCBhcHAgPSBhd2FpdCBjcmVhdGVBcHAuY3JlYXRlQXBwKHsgcGx1Z2luczogW3NlcnZlcigpLCBsYWtlYmFzZSgpXSB9KTtcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUFwcDxUIGV4dGVuZHMgQXBwS2l0UGx1Z2lucz4oXG4gIGNvbmZpZz86IENyZWF0ZUFwcENvbmZpZzxUPixcbik6IFByb21pc2U8UGx1Z2luTWFwPFQ+PiB7XG4gIGF3YWl0IGF1dG9Db25maWd1cmUoY29uZmlnKTtcbiAgY29uc3QgYXBwQ29uZmlnID0geyAuLi5jb25maWcgfTtcbiAgZGVsZXRlIGFwcENvbmZpZy5hdXRvQ29uZmlndXJlO1xuICByZXR1cm4gYXBwa2l0Q3JlYXRlQXBwPFQ+KGFwcENvbmZpZyk7XG59XG4iXX0=
154
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLWFwcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jcmVhdGUtYXBwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFFSCxPQUFPLEVBQUUsU0FBUyxJQUFJLGVBQWUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBSWxFLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFcEQsT0FBTyxFQUNMLHdCQUF3QixFQUd4QixlQUFlLEdBRWhCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUFFLGdCQUFnQixFQUEyQixNQUFNLHdCQUF3QixDQUFDO0FBQ25GLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBNEN0RCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBRXhDLE1BQU0sZUFBZSxHQUFHLFVBQVUsQ0FBQztBQUNuQyxNQUFNLHNCQUFzQixHQUFzQixXQUFXLENBQUM7QUFFOUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSx5QkFBeUIsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFDO0FBRTlDLFNBQVMsVUFBVSxDQUNqQixNQUFzQyxFQUN0QyxJQUFZO0lBRVosT0FBTyxPQUFPLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQztBQUN4RSxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsYUFBYSxDQUNqQyxNQUEyQixFQUMzQixNQUFvQjtJQUVwQixNQUFNLElBQUksR0FBRyxNQUFNLEVBQUUsYUFBYSxJQUFJLHNCQUFzQixDQUFDO0lBQzdELE1BQU0sUUFBUSxHQUFHLE1BQU0sRUFB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ZGJ4LXRvb2xzIGF1dG8tY29uZmlndXJhdGlvbiwgdGhlbiBkZWxlZ2F0ZXMgdG9cbiAqIEFwcEtpdCdzIG93biBgY3JlYXRlQXBwYCB3aXRoIHRoZSBleGFjdCBzYW1lIGFyZ3VtZW50cy5cbiAqXG4gKiBEcm9wIGl0IGluIGFzIGEgb25lLWZvci1vbmUgcmVwbGFjZW1lbnQgZm9yIGBAZGF0YWJyaWNrcy9hcHBraXRgJ3NcbiAqIGBjcmVhdGVBcHBgIC0gc2FtZSBwYXJhbWV0ZXJzLCBzYW1lIHJldHVybiB0eXBlLCBmdWxsIHBsdWdpbi1leHBvcnQgaW5mZXJlbmNlXG4gKiBwcmVzZXJ2ZWQ6XG4gKlxuICogYGBgdHNcbiAqIGltcG9ydCB7IGNyZWF0ZUFwcCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuICogaW1wb3J0IHsgbGFrZWJhc2UsIHNlcnZlciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbiAqXG4gKiBhd2FpdCBjcmVhdGVBcHAuY3JlYXRlQXBwKHsgcGx1Z2luczogW3NlcnZlcigpLCBsYWtlYmFzZSgpXSB9KTtcbiAqIGBgYFxuICpcbiAqIEF1dG8tY29uZmlndXJhdGlvbiBydW5zIEJFRk9SRSBkZWxlZ2F0aW5nIHNvIHBsdWdpbnMgc2VlIGEgZnVsbHkgcG9wdWxhdGVkXG4gKiBgcHJvY2Vzcy5lbnZgIGR1cmluZyB0aGVpciBzeW5jaHJvbm91cyBgc2V0dXAoKWAuIExha2ViYXNlIFBvc3RncmVzIHJ1bnMgd2hlblxuICogYSBgbGFrZWJhc2VgIHBsdWdpbiBpcyBwcmVzZW50LCBvciB3aGVuIHtAbGluayBBdXRvQ29uZmlndXJlTW9kZX0gaXMgc2V0XG4gKiBleHBsaWNpdGx5IG9uIHRoZSBjb25maWcgb2JqZWN0LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBjcmVhdGVBcHAgYXMgYXBwa2l0Q3JlYXRlQXBwIH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuLy8gQXBwS2l0J3Mgcm9vdCBiYXJyZWwgcmUtZXhwb3J0cyBgUGx1Z2luRGF0YWAgYnV0IG5vdCBgUGx1Z2luTWFwYDsgdGhlIHBhY2thZ2Vcbi8vIHB1Ymxpc2hlcyB0aGlzIHN1YnBhdGggZm9yIGV4YWN0bHkgdGhhdCB0eXBlLlxuaW1wb3J0IHR5cGUgeyBQbHVnaW5NYXAgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0L2Rpc3Qvc2hhcmVkL3NyYy9wbHVnaW5cIjtcbmltcG9ydCB7IGFzeW5jLCBsb2cgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuXG5pbXBvcnQge1xuICBjcmVhdGVJbnRlcmNlcHRvckNvbnRleHQsXG4gIHR5cGUgSW50ZXJjZXB0b3IsXG4gIHR5cGUgSW50ZXJjZXB0b3JSdW50aW1lLFxuICBsaWZlY3ljbGVCcmlkZ2UsXG4gIHR5cGUgUmVzb2x2ZWRBcHBFbnYsXG59IGZyb20gXCIuL2ludGVyY2VwdG9yLnRzXCI7XG5pbXBvcnQgeyBhcHBseUxha2ViYXNlRW52LCB0eXBlIExha2ViYXNlQ29ubmVjdGlvbiB9IGZyb20gXCIuL2xha2ViYXNlLXJlc29sdmVyLnRzXCI7XG5pbXBvcnQgeyBwcm92aXNpb25DYWNoZVNjaGVtYSB9IGZyb20gXCIuL3Byb3Zpc2lvbi50c1wiO1xuXG50eXBlIEFwcEtpdENyZWF0ZUFwcENvbmZpZyA9IE5vbk51bGxhYmxlPFBhcmFtZXRlcnM8dHlwZW9mIGFwcGtpdENyZWF0ZUFwcD5bMF0+O1xudHlwZSBBcHBLaXRQbHVnaW5zID0gTm9uTnVsbGFibGU8QXBwS2l0Q3JlYXRlQXBwQ29uZmlnW1wicGx1Z2luc1wiXT47XG5cbi8qKlxuICogV2hhdCBhdXRvLWNvbmZpZ3VyYXRpb24gZG9lcyBiZWZvcmUgQXBwS2l0IGJvb3RzLlxuICpcbiAqIC0gYFwicHJvdmlzaW9uXCJgOiByZXNvbHZlIHRoZSBMYWtlYmFzZSBjb25uZWN0aW9uIGludG8gYHByb2Nlc3MuZW52YCwgdGhlblxuICogICBncmFudCB0aGUgQXBwS2l0IGNhY2hlIHNjaGVtYSB0byB0aGUgY29ubmVjdGluZyByb2xlLlxuICogLSBgXCJlbnZcImA6IHJlc29sdmUgdGhlIExha2ViYXNlIGNvbm5lY3Rpb24gaW50byBgcHJvY2Vzcy5lbnZgIG9ubHkuXG4gKlxuICogT21pdCBpdCB0byBnZXQgYFwicHJvdmlzaW9uXCJgIGdhdGVkIG9uIGEgYGxha2ViYXNlYCBwbHVnaW4gYmVpbmcgcmVnaXN0ZXJlZDtcbiAqIHNldCBpdCBleHBsaWNpdGx5IHRvIHJ1biByZWdhcmRsZXNzIG9mIHRoZSBwbHVnaW4gbGlzdCwgb3IgcGFzcyBgZmFsc2VgIHRvXG4gKiBza2lwIGF1dG8tY29uZmlndXJhdGlvbiBlbnRpcmVseS5cbiAqXG4gKiBTZXQgaXQgRVhQTElDSVRMWSBvbiBhbiBhcHAgdGhhdCBoYXMgbm8gYGxha2ViYXNlKClgIHBsdWdpbiBidXQgc3RpbGwgd2FudHNcbiAqIEFwcEtpdCdzIFBFUlNJU1RFTlQgY2FjaGUuIEFwcEtpdCBwaWNrcyBMYWtlYmFzZSBmb3IgYENhY2hlTWFuYWdlcmAgb25seSB3aGVuXG4gKiBgY3JlYXRlTGFrZWJhc2VQb29sKClgIGNhbiBidWlsZCBhIHBvb2wsIGFuZCB0aGF0IHJlYWRzIGBMQUtFQkFTRV9FTkRQT0lOVGAgL1xuICogYFBHSE9TVGAgLyBgUEdEQVRBQkFTRWAgc3RyYWlnaHQgZnJvbSBgcHJvY2Vzcy5lbnZgIC0gc28gd2l0aG91dCB0aGlzIHN0ZXAgdGhlXG4gKiBjYWNoZSBzaWxlbnRseSBmYWxscyBiYWNrIHRvIGluLW1lbW9yeSwgYW5kIGFueXRoaW5nIGl0IGhvbGRzIChhIHNlc3Npb25cbiAqIHNpZ25pbmcga2V5LCBhIG9uZS10aW1lIGNvZGUpIGlzIGxvc3Qgb24gcmVzdGFydC4gYFwiZW52XCJgIGlzIHRoZSByaWdodCBtb2RlXG4gKiB0aGVyZTogdGhlIGFwcCBTUCBjYW5ub3QgZ3JhbnQgb24gdGhlIGNhY2hlIHNjaGVtYSBhbnl3YXkuXG4gKi9cbmV4cG9ydCB0eXBlIEF1dG9Db25maWd1cmVNb2RlID0gXCJlbnZcIiB8IFwicHJvdmlzaW9uXCI7XG5cbi8qKiBBcHBLaXQncyBgY3JlYXRlQXBwYCBjb25maWcgcGx1cyB0aGUgZGJ4LXRvb2xzIGF1dG8tY29uZmlndXJhdGlvbiBzd2l0Y2guICovXG5leHBvcnQgdHlwZSBDcmVhdGVBcHBDb25maWc8VCBleHRlbmRzIEFwcEtpdFBsdWdpbnMgPSBBcHBLaXRQbHVnaW5zPiA9IE9taXQ8XG4gIEFwcEtpdENyZWF0ZUFwcENvbmZpZyxcbiAgXCJwbHVnaW5zXCIgfCBcIm9uUGx1Z2luc1JlYWR5XCJcbj4gJiB7XG4gIHBsdWdpbnM/OiBUO1xuICBvblBsdWdpbnNSZWFkeT86IChhcHBraXQ6IFBsdWdpbk1hcDxUPikgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG4gIC8qKiBBdXRvLWNvbmZpZ3VyYXRpb24gdG8gcnVuIGJlZm9yZSBBcHBLaXQgYm9vdHMuIERlZmF1bHRzIHRvIGBcInByb3Zpc2lvblwiYC4gKi9cbiAgYXV0b0NvbmZpZ3VyZT86IEF1dG9Db25maWd1cmVNb2RlIHwgZmFsc2U7XG4gIC8qKlxuICAgKiBPbmUgb3IgbWFueSB7QGxpbmsgSW50ZXJjZXB0b3J9cyBoYW5kZWQgYW4ge0BsaW5rIEludGVyY2VwdG9yQ29udGV4dH0gb25jZVxuICAgKiBhdXRvLWNvbmZpZ3VyYXRpb24gaGFzIGNvbXB1dGVkIHRoZSBlbnYuIEVhY2ggcmVjZWl2ZXMgdGhlIHJlc29sdmVkIGVudiwgYW5cbiAgICogQXBwS2l0LWxpZmVjeWNsZSBob29rLCBhbmQgYGJpbmRQcm9jZXNzYCBmb3IgY29uY3VycmVudGx5LXN0eWxlIHN1cGVydmlzaW9uIC1cbiAgICogc2VlIGAuL2ludGVyY2VwdG9yYC4gVGhlIHR1bm5lbCBpcyB0aGUgcHJpbWFyeSBjb25zdW1lci5cbiAgICovXG4gIGludGVyY2VwdG9yPzogSW50ZXJjZXB0b3IgfCBJbnRlcmNlcHRvcltdO1xufTtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImNyZWF0ZS1hcHBcIik7XG5cbmNvbnN0IExBS0VCQVNFX1BMVUdJTiA9IFwibGFrZWJhc2VcIjtcbmNvbnN0IERFRkFVTFRfQVVUT19DT05GSUdVUkU6IEF1dG9Db25maWd1cmVNb2RlID0gXCJwcm92aXNpb25cIjtcblxuLyoqXG4gKiBVcHBlciBib3VuZCBvbiBib290LXRpbWUgYXV0by1jb25maWd1cmF0aW9uLiBJdCBydW5zIGFzIHRoZSBzZXJ2aWNlIHByaW5jaXBhbFxuICogYmVmb3JlIGFueSBwbHVnaW4gaXMgY29uc3RydWN0ZWQsIHNvIGl0IHNpdHMgb3V0c2lkZSBBcHBLaXQncyBpbnRlcmNlcHRvclxuICogY2hhaW4gYW5kIGluaGVyaXRzIG5vIHRpbWVvdXQsIHJldHJ5LCBvciB0ZWxlbWV0cnkgZnJvbSBpdC4gVGhlIGJ1ZGdldCBjb3ZlcnNcbiAqIHRoZSByZXNvbHZlcidzIG93biB3b3JzdCBjYXNlIChjcmVhdGUgYSBwcm9qZWN0LCB0aGVuIHdhaXQgZm9yIGl0cyBlbmRwb2ludClcbiAqIHBsdXMgdGhlIGNhY2hlLXNjaGVtYSBncmFudHMuXG4gKi9cbmNvbnN0IEFVVE9fQ09ORklHVVJFX1RJTUVPVVRfTVMgPSAxMSAqIDYwXzAwMDtcblxuZnVuY3Rpb24gdXNlc1BsdWdpbjxUIGV4dGVuZHMgQXBwS2l0UGx1Z2lucz4oXG4gIGNvbmZpZzogQ3JlYXRlQXBwQ29uZmlnPFQ+IHwgdW5kZWZpbmVkLFxuICBuYW1lOiBzdHJpbmcsXG4pOiBib29sZWFuIHtcbiAgcmV0dXJuIEJvb2xlYW4oY29uZmlnPy5wbHVnaW5zPy5zb21lKChlbnRyeSkgPT4gZW50cnkubmFtZSA9PT0gbmFtZSkpO1xufVxuXG4vKipcbiAqIFJ1biBlbmFibGVkIGF1dG8tY29uZmlndXJhdGlvbiBzdGVwcyB3aXRob3V0IGNhbGxpbmcgQXBwS2l0J3MgYGNyZWF0ZUFwcGAuXG4gKlxuICogTGFrZWJhc2UgUG9zdGdyZXMgcmVzb2x2ZXMgd2hlbiB7QGxpbmsgQ3JlYXRlQXBwQ29uZmlnLmF1dG9Db25maWd1cmV9IGlzIHNldFxuICogZXhwbGljaXRseSBvciBhIGBsYWtlYmFzZWAgcGx1Z2luIGlzIGxpc3RlZCBpbiBgY29uZmlnLnBsdWdpbnNgLiBgc2lnbmFsYFxuICogY2FuY2VscyB0aGUgcmVzb2x1dGlvbjsgaXQgaXMgY29tYmluZWQgd2l0aCBhbiBpbnRlcm5hbCBib290IHRpbWVvdXQgZWl0aGVyXG4gKiB3YXkuXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCB7IGNyZWF0ZUFwcCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuICpcbiAqIC8vIFBvcHVsYXRlIFBHSE9TVCAvIFBHREFUQUJBU0UgLyBMQUtFQkFTRV9FTkRQT0lOVCB3aXRob3V0IGJvb3RpbmcgQXBwS2l0LlxuICogYXdhaXQgY3JlYXRlQXBwLmF1dG9Db25maWd1cmUoeyBhdXRvQ29uZmlndXJlOiBcImVudlwiIH0pO1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXV0b0NvbmZpZ3VyZTxUIGV4dGVuZHMgQXBwS2l0UGx1Z2lucz4oXG4gIGNvbmZpZz86IENyZWF0ZUFwcENvbmZpZzxUPixcbiAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4pOiBQcm9taXNlPExha2ViYXNlQ29ubmVjdGlvbiB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCBtb2RlID0gY29uZmlnPy5hdXRvQ29uZmlndXJlID8/IERFRkFVTFRfQVVUT19DT05GSUdVUkU7XG4gIGNvbnN0IGV4cGxpY2l0ID0gY29uZmlnPy5hdXRvQ29uZmlndXJlICE9PSB1bmRlZmluZWQ7XG4gIGNvbnN0IGxha2ViYXNlUGx1Z2luUHJlc2VudCA9IHVzZXNQbHVnaW4oY29uZmlnLCBMQUtFQkFTRV9QTFVHSU4pO1xuICBpZiAobW9kZSA9PT0gZmFsc2UgfHwgIShleHBsaWNpdCB8fCBsYWtlYmFzZVBsdWdpblByZXNlbnQpKSB7XG4gICAgbG9nZ2VyLmluZm8oXCJyZWFkeVwiLCB7XG4gICAgICBhdXRvQ29uZmlndXJlOiBtb2RlLFxuICAgICAgbGFrZWJhc2VQbHVnaW5QcmVzZW50LFxuICAgICAgcHJvdmlzaW9uZWQ6IGZhbHNlLFxuICAgICAgc2tpcHBlZFJlYXNvbjogbW9kZSA9PT0gZmFsc2UgPyBcImRpc2FibGVkXCIgOiBcIm5vIGxha2ViYXNlIHBsdWdpblwiLFxuICAgIH0pO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICBhc3luYy50aWVBYm9ydFNpZ25hbChjb250cm9sbGVyLCBzaWduYWwpO1xuICBhc3luYy50aWVBYm9ydFNpZ25hbChjb250cm9sbGVyLCBBYm9ydFNpZ25hbC50aW1lb3V0KEFVVE9fQ09ORklHVVJFX1RJTUVPVVRfTVMpKTtcblxuICBjb25zdCBwcm92aXNpb24gPSBtb2RlID09PSBcInByb3Zpc2lvblwiO1xuICBjb25zdCByZXNvbHZlZCA9IGF3YWl0IGF1dG9Db25maWd1cmVMYWtlYmFzZShwcm92aXNpb24sIGNvbnRyb2xsZXIuc2lnbmFsKTtcbiAgbG9nZ2VyLmluZm8oXCJyZWFkeVwiLCB7IGF1dG9Db25maWd1cmU6IG1vZGUsIGxha2ViYXNlUGx1Z2luUHJlc2VudCwgcHJvdmlzaW9uZWQ6IHByb3Zpc2lvbiB9KTtcbiAgcmV0dXJuIHJlc29sdmVkO1xufVxuXG4vKipcbiAqIFJlc29sdmUgTGFrZWJhc2UgUG9zdGdyZXMgY29ubmVjdGlvbiBpbmZvLCB3cml0ZSB0aGUgcmVzb2x2ZWQgdmFsdWVzIHRvXG4gKiBgcHJvY2Vzcy5lbnZgLCBhbmQgcmV0dXJuIHRoZSByZWNvcmQuIFVzZWQgYnkge0BsaW5rIGF1dG9Db25maWd1cmV9OyBjYWxsXG4gKiB7QGxpbmsgYXBwbHlMYWtlYmFzZUVudn0gZGlyZWN0bHkgd2hlbiBmaW5lciBjb250cm9sIGlzIG5lZWRlZCAoYSBkaWZmZXJlbnRcbiAqIGBhdXRvQ3JlYXRlYCBwb2xpY3ksIG9yIGEgY2FsbGVyIHRoYXQgd2FudHMgdGhlIGVudiB3aXRob3V0IGJvb3RpbmcgQXBwS2l0KS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gYXV0b0NvbmZpZ3VyZUxha2ViYXNlKFxuICBwcm92aXNpb246IGJvb2xlYW4sXG4gIHNpZ25hbDogQWJvcnRTaWduYWwsXG4pOiBQcm9taXNlPExha2ViYXNlQ29ubmVjdGlvbj4ge1xuICBjb25zdCB7IHJlc29sdmVkLCB1c2VyIH0gPSBhd2FpdCBhcHBseUxha2ViYXNlRW52KHVuZGVmaW5lZCwgc2lnbmFsKTtcbiAgbG9nZ2VyLmluZm8oXCJlbnYgdXBkYXRlZFwiLCB7IC4uLnJlZGFjdExha2ViYXNlQ29ubmVjdGlvbihyZXNvbHZlZCksIHVzZXIgfSk7XG4gIGlmIChwcm92aXNpb24pIHtcbiAgICBhd2FpdCBwcm92aXNpb25DYWNoZVNjaGVtYSh1c2VyLCBsb2dnZXIpO1xuICB9XG4gIHJldHVybiByZXNvbHZlZDtcbn1cblxuZnVuY3Rpb24gcmVkYWN0TGFrZWJhc2VDb25uZWN0aW9uKHJlc29sdmVkOiBMYWtlYmFzZUNvbm5lY3Rpb24pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIHJldHVybiB7XG4gICAgcHJvamVjdDogcmVzb2x2ZWQucHJvamVjdCxcbiAgICBicmFuY2g6IHJlc29sdmVkLmJyYW5jaCxcbiAgICBlbmRwb2ludDogcmVzb2x2ZWQuZW5kcG9pbnQsXG4gICAgZGF0YWJhc2U6IHJlc29sdmVkLmRhdGFiYXNlLFxuICAgIGhvc3Q6IHJlc29sdmVkLmhvc3QsXG4gICAgcG9ydDogcmVzb2x2ZWQucG9ydCxcbiAgICBzc2xNb2RlOiByZXNvbHZlZC5zc2xNb2RlLFxuICB9O1xufVxuXG4vKiogQnVpbGQgdGhlIHtAbGluayBSZXNvbHZlZEFwcEVudn0gaW50ZXJjZXB0b3JzIHJlYWQsIGZyb20gdGhlIGF1dG8tY29uZmlnIHJlc3VsdC4gKi9cbmZ1bmN0aW9uIHJlc29sdmVkQXBwRW52KGxha2ViYXNlOiBMYWtlYmFzZUNvbm5lY3Rpb24gfCB1bmRlZmluZWQpOiBSZXNvbHZlZEFwcEVudiB7XG4gIHJldHVybiB7XG4gICAgLi4uKGxha2ViYXNlID8geyBsYWtlYmFzZSB9IDoge30pLFxuICAgIC4uLihwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0hPU1QgPyB7IGRhdGFicmlja3NIb3N0OiBwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0hPU1QgfSA6IHt9KSxcbiAgfTtcbn1cblxuLyoqIE5vcm1hbGl6ZSB0aGUgYGludGVyY2VwdG9yPzogSW50ZXJjZXB0b3IgfCBJbnRlcmNlcHRvcltdYCBvcHRpb24gdG8gYW4gYXJyYXkuICovXG5mdW5jdGlvbiBpbnRlcmNlcHRvckxpc3QoaW50ZXJjZXB0b3I6IENyZWF0ZUFwcENvbmZpZ1tcImludGVyY2VwdG9yXCJdKTogSW50ZXJjZXB0b3JbXSB7XG4gIGlmICghaW50ZXJjZXB0b3IpIHJldHVybiBbXTtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoaW50ZXJjZXB0b3IpID8gaW50ZXJjZXB0b3IgOiBbaW50ZXJjZXB0b3JdO1xufVxuXG4vKipcbiAqIEF1dG8tY29uZmlndXJpbmcgZHJvcC1pbiBmb3IgQXBwS2l0J3MgYGNyZWF0ZUFwcGA6IHNhbWUgY29uZmlnLCBzYW1lIHR5cGVkXG4gKiBwbHVnaW4tZXhwb3J0IG1hcCwgd2l0aCB7QGxpbmsgYXV0b0NvbmZpZ3VyZX0gcnVuIGZpcnN0LlxuICpcbiAqIFdoZW4ge0BsaW5rIENyZWF0ZUFwcENvbmZpZy5pbnRlcmNlcHRvcn1zIGFyZSBnaXZlbiwgZWFjaCBpcyBpbnZva2VkIHdpdGggYW5cbiAqIHtAbGluayBJbnRlcmNlcHRvckNvbnRleHR9IEFGVEVSIGF1dG8tY29uZmlndXJhdGlvbiBjb21wdXRlcyB0aGUgZW52IGFuZCBCRUZPUkVcbiAqIEFwcEtpdCBib290cyAtIHNvIGFuIGludGVyY2VwdG9yIGNhbiByZWFkIHRoZSByZXNvbHZlZCBjb25uZWN0aW9uLCByZWdpc3RlclxuICogbGlmZWN5Y2xlIGhhbmRsZXJzLCBhbmQgYGJpbmRQcm9jZXNzYCBhIGNoaWxkLiBBIGhpZGRlbiB7QGxpbmsgbGlmZWN5Y2xlQnJpZGdlfVxuICogcGx1Z2luIGlzIGluamVjdGVkIHNvIHRob3NlIGBvbkxpZmVjeWNsZWAgaGFuZGxlcnMgZmlyZSBvbiB0aGUgZ2VudWluZSBBcHBLaXRcbiAqIGV2ZW50czsgaXQgaGFzIG5vIGV4cG9ydHMsIHNvIHRoZSByZXR1cm5lZCB7QGxpbmsgUGx1Z2luTWFwfSBpcyB1bmNoYW5nZWQuXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCB7IGNyZWF0ZUFwcCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuICogaW1wb3J0IHsgbGFrZWJhc2UsIHNlcnZlciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbiAqXG4gKiBjb25zdCBhcHAgPSBhd2FpdCBjcmVhdGVBcHAuY3JlYXRlQXBwKHsgcGx1Z2luczogW3NlcnZlcigpLCBsYWtlYmFzZSgpXSB9KTtcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUFwcDxUIGV4dGVuZHMgQXBwS2l0UGx1Z2lucz4oXG4gIGNvbmZpZz86IENyZWF0ZUFwcENvbmZpZzxUPixcbik6IFByb21pc2U8UGx1Z2luTWFwPFQ+PiB7XG4gIGNvbnN0IGxha2ViYXNlID0gYXdhaXQgYXV0b0NvbmZpZ3VyZShjb25maWcpO1xuICBjb25zdCBhcHBDb25maWcgPSB7IC4uLmNvbmZpZyB9O1xuICBkZWxldGUgYXBwQ29uZmlnLmF1dG9Db25maWd1cmU7XG4gIGRlbGV0ZSBhcHBDb25maWcuaW50ZXJjZXB0b3I7XG5cbiAgY29uc3QgaW50ZXJjZXB0b3JzID0gaW50ZXJjZXB0b3JMaXN0KGNvbmZpZz8uaW50ZXJjZXB0b3IpO1xuICBpZiAoaW50ZXJjZXB0b3JzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBhcHBraXRDcmVhdGVBcHA8VD4oYXBwQ29uZmlnKTtcbiAgfVxuXG4gIC8vIEJ1aWxkIHRoZSBjb250ZXh0IGZyb20gdGhlIGNvbXB1dGVkIGVudiwgcnVuIGVhY2ggaW50ZXJjZXB0b3IgKHRoZXkgcmVnaXN0ZXJcbiAgLy8gbGlmZWN5Y2xlIGhhbmRsZXJzICsgYmluZCBwcm9jZXNzZXMpLCB0aGVuIGluamVjdCB0aGUgYnJpZGdlIHRoYXQgcmVsYXlzIHRoZVxuICAvLyBSRUFMIEFwcEtpdCBsaWZlY3ljbGUgaW50byBgcnVudGltZS5lbWl0TGlmZWN5Y2xlYCBkdXJpbmcgaXRzIGBzZXR1cCgpYC5cbiAgY29uc3QgcnVudGltZTogSW50ZXJjZXB0b3JSdW50aW1lID0gY3JlYXRlSW50ZXJjZXB0b3JDb250ZXh0KHJlc29sdmVkQXBwRW52KGxha2ViYXNlKSk7XG4gIGZvciAoY29uc3QgaW50ZXJjZXB0b3Igb2YgaW50ZXJjZXB0b3JzKSB7XG4gICAgYXdhaXQgaW50ZXJjZXB0b3IocnVudGltZS5jb250ZXh0KTtcbiAgfVxuICAvLyBBcHBlbmQgdGhlIGJyaWRnZSB0byB0aGUgcGx1Z2lucyB0dXBsZS4gSXQgaXMgaGlkZGVuIGFuZCBleHBvcnRzIG5vdGhpbmcsIHNvXG4gIC8vIHRoZSByZXR1cm5lZCBtYXAgc3RpbGwgbWF0Y2hlcyBgUGx1Z2luTWFwPFQ+YDsgdGhlIGNhc3QgKHRocm91Z2ggYHVua25vd25gKSBpc1xuICAvLyBvbmx5IGJlY2F1c2UgYXBwZW5kaW5nIHdpZGVucyB0aGUgdHVwbGUgdHlwZSBiZXlvbmQgYFRgLlxuICBhcHBDb25maWcucGx1Z2lucyA9IFsuLi4oYXBwQ29uZmlnLnBsdWdpbnMgPz8gW10pLCBsaWZlY3ljbGVCcmlkZ2UoeyBydW50aW1lIH0pXSBhcyB1bmtub3duIGFzIFQ7XG4gIHJldHVybiBhcHBraXRDcmVhdGVBcHA8VD4oYXBwQ29uZmlnKTtcbn1cbiJdfQ==
@@ -20,7 +20,7 @@
20
20
  * where a missing token means something is wrong. It is fatal for an app whose
21
21
  * traffic legitimately arrives WITHOUT one:
22
22
  *
23
- * - a public tunnel (`@dbx-tools/cli-tunnel`), where callers authenticate by
23
+ * - a public tunnel (`@dbx-tools/tunnel`), where callers authenticate by
24
24
  * email OTP and no OBO token exists to forward - the gate can prove WHO the
25
25
  * caller is, but it cannot mint a Databricks credential for them;
26
26
  * - any reverse proxy, webhook, or bot channel (`POST /api/teams/messages`)
@@ -41,7 +41,7 @@
41
41
  *
42
42
  * `"auto"` decides per REQUEST, not per boot, because a single container serves
43
43
  * both doors at once - the tunnel gate and the platform front door share a port
44
- * (see `@dbx-tools/cli-tunnel`). A boot-time flag would have to be wrong for one
44
+ * (see `@dbx-tools/tunnel`). A boot-time flag would have to be wrong for one
45
45
  * of them.
46
46
  *
47
47
  * What the service principal does NOT change is WHO the request belongs to. The
@@ -20,7 +20,7 @@
20
20
  * where a missing token means something is wrong. It is fatal for an app whose
21
21
  * traffic legitimately arrives WITHOUT one:
22
22
  *
23
- * - a public tunnel (`@dbx-tools/cli-tunnel`), where callers authenticate by
23
+ * - a public tunnel (`@dbx-tools/tunnel`), where callers authenticate by
24
24
  * email OTP and no OBO token exists to forward - the gate can prove WHO the
25
25
  * caller is, but it cannot mint a Databricks credential for them;
26
26
  * - any reverse proxy, webhook, or bot channel (`POST /api/teams/messages`)
@@ -41,7 +41,7 @@
41
41
  *
42
42
  * `"auto"` decides per REQUEST, not per boot, because a single container serves
43
43
  * both doors at once - the tunnel gate and the platform front door share a port
44
- * (see `@dbx-tools/cli-tunnel`). A boot-time flag would have to be wrong for one
44
+ * (see `@dbx-tools/tunnel`). A boot-time flag would have to be wrong for one
45
45
  * of them.
46
46
  *
47
47
  * What the service principal does NOT change is WHO the request belongs to. The
@@ -134,4 +134,4 @@ export function useServicePrincipal(mode, req) {
134
134
  return false;
135
135
  return requestAccessToken(req) === undefined;
136
136
  }
137
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRlbnRpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaWRlbnRpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvREc7QUFFSCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQWUsTUFBTSx3QkFBd0IsQ0FBQztBQUV6RTs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQztBQUU3RCw4RUFBOEU7QUFDOUUsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUM7QUFFbkQsNEVBQTRFO0FBQzVFLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQztBQUt6RCxvRkFBb0Y7QUFDcEYsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUE0QixDQUFDLE1BQU0sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUU3Rjs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBaUIsTUFBTSxDQUFDO0FBTzFEOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUNqQyxVQUE4QixFQUM5QixPQUFlLEVBQ2YsS0FBSyxHQUFHLFVBQVU7SUFFbEIsTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDNUMsSUFBSSxHQUFHLEtBQUssSUFBSTtRQUFFLE9BQU8scUJBQXFCLENBQUM7SUFDL0MsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLFdBQVcsRUFBa0IsQ0FBQztJQUMvQyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ25DLE1BQU0sS0FBSyxHQUFHLE9BQU8sT0FBTyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzFFLE1BQU0sSUFBSSxrQkFBa0IsQ0FDMUIsR0FBRyxLQUFLLG1CQUFtQixjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEtBQUssR0FBRyxFQUN2RSxFQUFFLE9BQU8sRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUNyRCxDQUFDO0lBQ0osQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUFDLEdBQThCO0lBQy9ELE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUMsSUFBSSxTQUFTLENBQUM7QUFDMUUsQ0FBQztBQUVELHNEQUFzRDtBQUN0RCxNQUFNLFVBQVUsYUFBYSxDQUFDLEdBQThCO0lBQzFELE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLElBQUksU0FBUyxDQUFDO0FBQ3JFLENBQUM7QUFFRCx5REFBeUQ7QUFDekQsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEdBQThCO0lBQzdELE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsSUFBSSxTQUFTLENBQUM7QUFDeEUsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxJQUFrQixFQUFFLEdBQW1CO0lBQ3pFLElBQUksSUFBSSxLQUFLLG1CQUFtQjtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQzlDLElBQUksSUFBSSxLQUFLLE1BQU07UUFBRSxPQUFPLEtBQUssQ0FBQztJQUNsQyxPQUFPLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxLQUFLLFNBQVMsQ0FBQztBQUMvQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBXaGljaCBEYXRhYnJpY2tzIGlkZW50aXR5IGEgcmVxdWVzdCdzIHdvcmtzcGFjZSBjYWxscyBydW4gYXMuXG4gKlxuICogQXBwS2l0IGdpdmVzIGEgcGx1Z2luIHR3byBpZGVudGl0aWVzOiB0aGUgYW1iaWVudCBTRVJWSUNFIGNvbnRleHQgKHRoZSBhcHAnc1xuICogb3duIHNlcnZpY2UgcHJpbmNpcGFsKSBhbmQgYSBwZXItcmVxdWVzdCBVU0VSIGNvbnRleHQgZW50ZXJlZCB3aXRoXG4gKiBgYXNVc2VyKHJlcSlgLCB3aGljaCBhdXRoZW50aWNhdGVzIGFzIHRoZSBjYWxsZXIgb24tYmVoYWxmLW9mIChPQk8pLiBUaGVcbiAqIGNob2ljZSBpcyBvbmUgY2FsbCwgc28gdGhlIHdob2xlIGRlY2lzaW9uIGlzIFwiZG8gd2UgZW50ZXIgYGFzVXNlcmAgZm9yIHRoaXNcbiAqIHJlcXVlc3RcIi5cbiAqXG4gKiBgYXNVc2VyKHJlcSlgIG5lZWRzIHRoZSBPQk8gdG9rZW4gdGhlIHBsYXRmb3JtIGZyb250IGRvb3IgZm9yd2FyZHMgb25cbiAqIHtAbGluayBBQ0NFU1NfVE9LRU5fSEVBREVSfS4gTWVhc3VyZWQgYWdhaW5zdCB0aGUgaW5zdGFsbGVkIEFwcEtpdCwgaXRzXG4gKiBiZWhhdmlvciB3aGVuIHRoYXQgaGVhZGVyIGlzIGFic2VudCBkZXBlbmRzIEVOVElSRUxZIG9uIGBOT0RFX0VOVmA6XG4gKlxuICogfCBgTk9ERV9FTlZgICAgIHwgbm8gYHgtZm9yd2FyZGVkLWFjY2Vzcy10b2tlbmAgICAgICAgICAgICAgICAgICAgICAgICB8XG4gKiB8IC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHxcbiAqIHwgYGRldmVsb3BtZW50YCB8IGxvZ3MgYSB3YXJuaW5nLCBzaWxlbnRseSBydW5zIGFzIHRoZSBzZXJ2aWNlIHByaW5jaXBhbCB8XG4gKiB8IGFueXRoaW5nIGVsc2UgfCB0aHJvd3MgYEF1dGhlbnRpY2F0aW9uRXJyb3I6IE1pc3NpbmcgdXNlciB0b2tlbmAgICAgICB8XG4gKlxuICogVGhhdCBwcm9kdWN0aW9uIHRocm93IGlzIGNvcnJlY3QgZm9yIGFuIGFwcCBiZWhpbmQgdGhlIERhdGFicmlja3MgZnJvbnQgZG9vcixcbiAqIHdoZXJlIGEgbWlzc2luZyB0b2tlbiBtZWFucyBzb21ldGhpbmcgaXMgd3JvbmcuIEl0IGlzIGZhdGFsIGZvciBhbiBhcHAgd2hvc2VcbiAqIHRyYWZmaWMgbGVnaXRpbWF0ZWx5IGFycml2ZXMgV0lUSE9VVCBvbmU6XG4gKlxuICogICAtIGEgcHVibGljIHR1bm5lbCAoYEBkYngtdG9vbHMvY2xpLXR1bm5lbGApLCB3aGVyZSBjYWxsZXJzIGF1dGhlbnRpY2F0ZSBieVxuICogICAgIGVtYWlsIE9UUCBhbmQgbm8gT0JPIHRva2VuIGV4aXN0cyB0byBmb3J3YXJkIC0gdGhlIGdhdGUgY2FuIHByb3ZlIFdITyB0aGVcbiAqICAgICBjYWxsZXIgaXMsIGJ1dCBpdCBjYW5ub3QgbWludCBhIERhdGFicmlja3MgY3JlZGVudGlhbCBmb3IgdGhlbTtcbiAqICAgLSBhbnkgcmV2ZXJzZSBwcm94eSwgd2ViaG9vaywgb3IgYm90IGNoYW5uZWwgKGBQT1NUIC9hcGkvdGVhbXMvbWVzc2FnZXNgKVxuICogICAgIHRoYXQgYXV0aGVudGljYXRlcyBpdHMgb3duIHdheS5cbiAqXG4gKiBTdWNoIGFuIGFwcCBtdXN0IG5vdCBydW4gd2l0aCBgTk9ERV9FTlY9ZGV2ZWxvcG1lbnRgIGp1c3QgdG8gZ2V0IHRoZSBmYWxsYmFjazpcbiAqIHRoYXQgZmxhZyBhbHNvIHJlbGF4ZXMgc2VjdXJlIGNvb2tpZXMsIEFwcEtpdCdzIG93biBkZXYgYWZmb3JkYW5jZXMsIGFuZFxuICogYGFsbG93VW5hdXRoZW50aWNhdGVkYCBlc2NhcGUgaGF0Y2hlcy4gSGVuY2Uge0BsaW5rIElkZW50aXR5TW9kZX06XG4gKlxuICogICAtIGBcInVzZXJcImAgLSBhbHdheXMgT0JPLiBQZXItdXNlciBhdHRyaWJ1dGlvbiBhbmQgcGVyLXVzZXIgR2VuaWUgLyBVbml0eVxuICogICAgIENhdGFsb2cgcm93IGZpbHRlcnMuIENvcnJlY3Qgd2hlbiBldmVyeSBjYWxsZXIgaXMgYSB3b3Jrc3BhY2UgbWVtYmVyLlxuICogICAtIGBcInNlcnZpY2UtcHJpbmNpcGFsXCJgIC0gYWx3YXlzIHRoZSBhcHAncyBvd24gaWRlbnRpdHkuIE5lZWRzIG5vIE9CT1xuICogICAgIHNjb3BlcyBhbmQgd29ya3MgZm9yIGFueSBjYWxsZXIsIGF0IHRoZSBjb3N0IG9mIHBlci11c2VyIGRhdGEgc2NvcGluZy5cbiAqICAgLSBgXCJhdXRvXCJgIC0gT0JPIHdoZW4gdGhlIHJlcXVlc3QgYWN0dWFsbHkgY2FycmllcyBhIHVzYWJsZSBPQk8gdG9rZW4sXG4gKiAgICAgdGhlIHNlcnZpY2UgcHJpbmNpcGFsIG90aGVyd2lzZS4gT25lIGRlcGxveW1lbnQgdGhlbiBzZXJ2ZXMgQk9USCBkb29yc1xuICogICAgIGNvcnJlY3RseTogZnJvbnQtZG9vciByZXF1ZXN0cyBrZWVwIGZ1bGwgcGVyLXVzZXIgc2NvcGluZywgd2hpbGUgdHVubmVsIC9cbiAqICAgICB3ZWJob29rIHJlcXVlc3RzIGRlZ3JhZGUgdG8gdGhlIHNlcnZpY2UgcHJpbmNpcGFsIGluc3RlYWQgb2YgNTAwaW5nLlxuICpcbiAqIGBcImF1dG9cImAgZGVjaWRlcyBwZXIgUkVRVUVTVCwgbm90IHBlciBib290LCBiZWNhdXNlIGEgc2luZ2xlIGNvbnRhaW5lciBzZXJ2ZXNcbiAqIGJvdGggZG9vcnMgYXQgb25jZSAtIHRoZSB0dW5uZWwgZ2F0ZSBhbmQgdGhlIHBsYXRmb3JtIGZyb250IGRvb3Igc2hhcmUgYSBwb3J0XG4gKiAoc2VlIGBAZGJ4LXRvb2xzL2NsaS10dW5uZWxgKS4gQSBib290LXRpbWUgZmxhZyB3b3VsZCBoYXZlIHRvIGJlIHdyb25nIGZvciBvbmVcbiAqIG9mIHRoZW0uXG4gKlxuICogV2hhdCB0aGUgc2VydmljZSBwcmluY2lwYWwgZG9lcyBOT1QgY2hhbmdlIGlzIFdITyB0aGUgcmVxdWVzdCBiZWxvbmdzIHRvLiBUaGVcbiAqIGNhbGxlcidzIGlkZW50aXR5IHN0aWxsIGFycml2ZXMgb24ge0BsaW5rIFVTRVJfSURfSEVBREVSfSAvXG4gKiB7QGxpbmsgVVNFUl9FTUFJTF9IRUFERVJ9LCBzbyBtZW1vcnkgdGhyZWFkcywgY2FjaGUgbmFtZXNwYWNlcywgYW5kIHRyYWNlXG4gKiBhdHRyaWJ1dGlvbiBzdGF5IHBlci11c2VyLiBPbmx5IHRoZSBEYXRhYnJpY2tzIGNyZWRlbnRpYWwgaXMgc2hhcmVkLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBDb25maWd1cmF0aW9uRXJyb3IgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBlbnYsIHN0cmluZywgdG9rZW4sIHR5cGUgRW52S2V5IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcblxuLyoqXG4gKiBIZWFkZXIgdGhlIERhdGFicmlja3MgQXBwcyBmcm9udCBkb29yIGZvcndhcmRzIHRoZSBjYWxsZXIncyBPQk8gdG9rZW4gb24uXG4gKiBJdHMgcHJlc2VuY2UgaXMgd2hhdCBtYWtlcyBgYXNVc2VyKHJlcSlgIHZpYWJsZSwgc28gaXQgaXMgdGhlIHNpZ25hbFxuICoge0BsaW5rIHVzZVNlcnZpY2VQcmluY2lwYWx9IHJlYWRzIGluIGBcImF1dG9cImAgbW9kZS5cbiAqXG4gKiBSZS1leHBvcnRlZCBmcm9tIGBAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlYCdzIGB0b2tlbmAgbW9kdWxlICh3aGljaCByZWFkcyB0aGVcbiAqIHNhbWUgaGVhZGVyIHRvIGRlY29kZSBPQXV0aCBzY29wZXMpIHJhdGhlciB0aGFuIHJlLXNwZWxsZWQsIHNvIHRoZSBuYW1lIGZvclxuICogdGhpcyB3aXJlIGNvbnRyYWN0IGV4aXN0cyBvbmNlLlxuICovXG5leHBvcnQgY29uc3QgQUNDRVNTX1RPS0VOX0hFQURFUiA9IHRva2VuLkFDQ0VTU19UT0tFTl9IRUFERVI7XG5cbi8qKiBIZWFkZXIgdGhlIERhdGFicmlja3MgQXBwcyBmcm9udCBkb29yIGZvcndhcmRzIHRoZSBjYWxsZXIncyB1c2VyIGlkIG9uLiAqL1xuZXhwb3J0IGNvbnN0IFVTRVJfSURfSEVBREVSID0gdG9rZW4uVVNFUl9JRF9IRUFERVI7XG5cbi8qKiBIZWFkZXIgdGhlIERhdGFicmlja3MgQXBwcyBmcm9udCBkb29yIGZvcndhcmRzIHRoZSBjYWxsZXIncyBlbWFpbCBvbi4gKi9cbmV4cG9ydCBjb25zdCBVU0VSX0VNQUlMX0hFQURFUiA9IHRva2VuLlVTRVJfRU1BSUxfSEVBREVSO1xuXG4vKiogSWRlbnRpdHkgYSByZXF1ZXN0J3MgRGF0YWJyaWNrcyBjYWxscyBydW4gYXMuIFNlZSB0aGUgbW9kdWxlIGRvY3MuICovXG5leHBvcnQgdHlwZSBJZGVudGl0eU1vZGUgPSBcInVzZXJcIiB8IFwic2VydmljZS1wcmluY2lwYWxcIiB8IFwiYXV0b1wiO1xuXG4vKiogRXZlcnkgYWNjZXB0ZWQge0BsaW5rIElkZW50aXR5TW9kZX0sIGluIHRoZSBvcmRlciBkb2NzIGFuZCBzY2hlbWFzIGxpc3QgdGhlbS4gKi9cbmV4cG9ydCBjb25zdCBJREVOVElUWV9NT0RFUzogcmVhZG9ubHkgSWRlbnRpdHlNb2RlW10gPSBbXCJ1c2VyXCIsIFwic2VydmljZS1wcmluY2lwYWxcIiwgXCJhdXRvXCJdO1xuXG4vKipcbiAqIERlZmF1bHQgbW9kZS4gYFwidXNlclwiYCBrZWVwcyBPQk8gdGhlIG9ubHkgaWRlbnRpdHkgdW5sZXNzIGFuIGFwcCBvcHRzIGluLCBzb1xuICogYWRvcHRpbmcgdGhpcyBvcHRpb24gY2FuIG5ldmVyIHNpbGVudGx5IHdpZGVuIGFuIGV4aXN0aW5nIGFwcCdzIGRhdGEgYWNjZXNzLlxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9JREVOVElUWV9NT0RFOiBJZGVudGl0eU1vZGUgPSBcInVzZXJcIjtcblxuLyoqIFRoZSBzdWJzZXQgb2YgYGV4cHJlc3MuUmVxdWVzdGAgdGhpcyBtb2R1bGUgcmVhZHMgLSBvbmUgaGVhZGVyIGxvb2t1cC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSGVhZGVyQmVhcmluZyB7XG4gIGhlYWRlcihuYW1lOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBhIGNvbmZpZ3VyZWQgbW9kZTogZXhwbGljaXQgY29uZmlnIHZhbHVlLCB0aGVuIHRoZSBmaXJzdCBub24tZW1wdHlcbiAqIHZhcmlhYmxlIGFtb25nIGBlbnZLZXlzYCwgdGhlbiB7QGxpbmsgREVGQVVMVF9JREVOVElUWV9NT0RFfS5cbiAqXG4gKiBBbiB1bnJlY29nbml6ZWQgdmFsdWUgdGhyb3dzIHJhdGhlciB0aGFuIGZhbGxpbmcgYmFjay4gRmFsbGluZyBiYWNrIHdvdWxkXG4gKiBzaWxlbnRseSBrZWVwIHNlcnZpbmcgT0JPIC0gYW5kIHRoZSBwcm9kdWN0aW9uIGBBdXRoZW50aWNhdGlvbkVycm9yYCBpdFxuICogcHJvZHVjZXMgLSB0byBleGFjdGx5IHRoZSBjYWxsZXJzIHRoZSBvcHRpb24gd2FzIHNldCB0byBhY2NvbW1vZGF0ZSwgYW5kIGFcbiAqIHR5cG8gKGBcIm9ib1wiYCwgYFwic3BcImApIGlzIHRoZSBsaWtlbGllc3Qgd2F5IHRvIGdldCBvbmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlSWRlbnRpdHlNb2RlKFxuICBjb25maWd1cmVkOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIGVudktleXM6IEVudktleSxcbiAgZmllbGQgPSBcImlkZW50aXR5XCIsXG4pOiBJZGVudGl0eU1vZGUge1xuICBjb25zdCByYXcgPSBlbnYuc3RyaW5nKGNvbmZpZ3VyZWQsIGVudktleXMpO1xuICBpZiAocmF3ID09PSBudWxsKSByZXR1cm4gREVGQVVMVF9JREVOVElUWV9NT0RFO1xuICBjb25zdCBtb2RlID0gcmF3LnRvTG93ZXJDYXNlKCkgYXMgSWRlbnRpdHlNb2RlO1xuICBpZiAoIUlERU5USVRZX01PREVTLmluY2x1ZGVzKG1vZGUpKSB7XG4gICAgY29uc3QgbmFtZXMgPSB0eXBlb2YgZW52S2V5cyA9PT0gXCJzdHJpbmdcIiA/IGVudktleXMgOiBlbnZLZXlzLmpvaW4oXCIgLyBcIik7XG4gICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcbiAgICAgIGAke2ZpZWxkfSBtdXN0IGJlIG9uZSBvZiAke0lERU5USVRZX01PREVTLmpvaW4oXCIgfCBcIil9IChlbnY6ICR7bmFtZXN9KWAsXG4gICAgICB7IGNvbnRleHQ6IHsgZmllbGQsIGVudlZhcjogbmFtZXMsIHJlY2VpdmVkOiByYXcgfSB9LFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIG1vZGU7XG59XG5cbi8qKlxuICogVGhlIE9CTyB0b2tlbiBvbiBgcmVxYCwgb3IgYHVuZGVmaW5lZGAuIFJlYWQgdGhyb3VnaCB0aGUgc2FtZSB0cmltIGFzIGV2ZXJ5XG4gKiBvdGhlciBoZWFkZXIsIHNvIGEgaGVhZGVyIHByZXNlbnQtYnV0LWJsYW5rICh3aGljaCBzb21lIHByb3hpZXMgZW1pdCBmb3IgYW5cbiAqIHVuc2V0IHVwc3RyZWFtIHZhbHVlKSBjb3VudHMgYXMgYWJzZW50IHJhdGhlciB0aGFuIGFzIGEgdG9rZW4gdGhhdCBmYWlscyBhdFxuICogdGhlIGZpcnN0IERhdGFicmlja3MgY2FsbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVlc3RBY2Nlc3NUb2tlbihyZXE6IEhlYWRlckJlYXJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gc3RyaW5nLnRyaW1Ub051bGwocmVxPy5oZWFkZXIoQUNDRVNTX1RPS0VOX0hFQURFUikpID8/IHVuZGVmaW5lZDtcbn1cblxuLyoqIFRoZSBmb3J3YXJkZWQgdXNlciBpZCBvbiBgcmVxYCwgb3IgYHVuZGVmaW5lZGAuICovXG5leHBvcnQgZnVuY3Rpb24gcmVxdWVzdFVzZXJJZChyZXE6IEhlYWRlckJlYXJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gc3RyaW5nLnRyaW1Ub051bGwocmVxPy5oZWFkZXIoVVNFUl9JRF9IRUFERVIpKSA/PyB1bmRlZmluZWQ7XG59XG5cbi8qKiBUaGUgZm9yd2FyZGVkIHVzZXIgZW1haWwgb24gYHJlcWAsIG9yIGB1bmRlZmluZWRgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVlc3RVc2VyRW1haWwocmVxOiBIZWFkZXJCZWFyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHN0cmluZy50cmltVG9OdWxsKHJlcT8uaGVhZGVyKFVTRVJfRU1BSUxfSEVBREVSKSkgPz8gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYHJlcWAgc2hvdWxkIHJ1biBpdHMgRGF0YWJyaWNrcyBjYWxscyBhcyB0aGUgYXBwIHNlcnZpY2UgcHJpbmNpcGFsXG4gKiByYXRoZXIgdGhhbiBPQk8uXG4gKlxuICogLSBgXCJzZXJ2aWNlLXByaW5jaXBhbFwiYCAtPiBhbHdheXMgYHRydWVgLlxuICogLSBgXCJ1c2VyXCJgIC0+IGFsd2F5cyBgZmFsc2VgLCBldmVuIHdpdGggbm8gdG9rZW4uIFRoZSBtb2RlIGlzIGFuIGV4cGxpY2l0XG4gKiAgIGFzc2VydGlvbiB0aGF0IGV2ZXJ5IGNhbGxlciBpcyBPQk8tY2FwYWJsZSwgc28gYSBtaXNzaW5nIHRva2VuIGlzIGEgcmVhbFxuICogICBlcnJvciBhbmQgbXVzdCBzdXJmYWNlIGFzIEFwcEtpdCdzIGBBdXRoZW50aWNhdGlvbkVycm9yYCByYXRoZXIgdGhhbiBiZWluZ1xuICogICBxdWlldGx5IGRvd25ncmFkZWQgdG8gc2hhcmVkIGRhdGEgYWNjZXNzLlxuICogLSBgXCJhdXRvXCJgIC0+IGB0cnVlYCBvbmx5IHdoZW4gdGhlIHJlcXVlc3QgY2FycmllcyBubyB1c2FibGUgT0JPIHRva2VuLlxuICpcbiAqIEEgcmVxdWVzdCBBcHBLaXQgd2lsbCBub3QgYWNjZXB0IGZvciBPQk8gYW55d2F5IChubyB0b2tlbikgY2FuIG5ldmVyIGJlXG4gKiBzZXJ2ZWQgYnkgZW50ZXJpbmcgYGFzVXNlcmAsIHNvIGluIGBcImF1dG9cImAgbW9kZSB0aGUgdG9rZW4gY2hlY2sgaXMgdGhlIHdob2xlXG4gKiBkZWNpc2lvbjogaXQgaXMgdGhlIHNhbWUgY29uZGl0aW9uIEFwcEtpdCBpdHNlbGYgYnJhbmNoZXMgb24sIGp1c3QgcmVzb2x2ZWRcbiAqIGJlZm9yZSBpdCBjYW4gdGhyb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1c2VTZXJ2aWNlUHJpbmNpcGFsKG1vZGU6IElkZW50aXR5TW9kZSwgcmVxPzogSGVhZGVyQmVhcmluZyk6IGJvb2xlYW4ge1xuICBpZiAobW9kZSA9PT0gXCJzZXJ2aWNlLXByaW5jaXBhbFwiKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKG1vZGUgPT09IFwidXNlclwiKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiByZXF1ZXN0QWNjZXNzVG9rZW4ocmVxKSA9PT0gdW5kZWZpbmVkO1xufVxuIl19
137
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRlbnRpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaWRlbnRpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvREc7QUFFSCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQWUsTUFBTSx3QkFBd0IsQ0FBQztBQUV6RTs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQztBQUU3RCw4RUFBOEU7QUFDOUUsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUM7QUFFbkQsNEVBQTRFO0FBQzVFLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQztBQUt6RCxvRkFBb0Y7QUFDcEYsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUE0QixDQUFDLE1BQU0sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUU3Rjs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBaUIsTUFBTSxDQUFDO0FBTzFEOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUNqQyxVQUE4QixFQUM5QixPQUFlLEVBQ2YsS0FBSyxHQUFHLFVBQVU7SUFFbEIsTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDNUMsSUFBSSxHQUFHLEtBQUssSUFBSTtRQUFFLE9BQU8scUJBQXFCLENBQUM7SUFDL0MsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLFdBQVcsRUFBa0IsQ0FBQztJQUMvQyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ25DLE1BQU0sS0FBSyxHQUFHLE9BQU8sT0FBTyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzFFLE1BQU0sSUFBSSxrQkFBa0IsQ0FDMUIsR0FBRyxLQUFLLG1CQUFtQixjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEtBQUssR0FBRyxFQUN2RSxFQUFFLE9BQU8sRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUNyRCxDQUFDO0lBQ0osQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUFDLEdBQThCO0lBQy9ELE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUMsSUFBSSxTQUFTLENBQUM7QUFDMUUsQ0FBQztBQUVELHNEQUFzRDtBQUN0RCxNQUFNLFVBQVUsYUFBYSxDQUFDLEdBQThCO0lBQzFELE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLElBQUksU0FBUyxDQUFDO0FBQ3JFLENBQUM7QUFFRCx5REFBeUQ7QUFDekQsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEdBQThCO0lBQzdELE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsSUFBSSxTQUFTLENBQUM7QUFDeEUsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxJQUFrQixFQUFFLEdBQW1CO0lBQ3pFLElBQUksSUFBSSxLQUFLLG1CQUFtQjtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQzlDLElBQUksSUFBSSxLQUFLLE1BQU07UUFBRSxPQUFPLEtBQUssQ0FBQztJQUNsQyxPQUFPLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxLQUFLLFNBQVMsQ0FBQztBQUMvQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBXaGljaCBEYXRhYnJpY2tzIGlkZW50aXR5IGEgcmVxdWVzdCdzIHdvcmtzcGFjZSBjYWxscyBydW4gYXMuXG4gKlxuICogQXBwS2l0IGdpdmVzIGEgcGx1Z2luIHR3byBpZGVudGl0aWVzOiB0aGUgYW1iaWVudCBTRVJWSUNFIGNvbnRleHQgKHRoZSBhcHAnc1xuICogb3duIHNlcnZpY2UgcHJpbmNpcGFsKSBhbmQgYSBwZXItcmVxdWVzdCBVU0VSIGNvbnRleHQgZW50ZXJlZCB3aXRoXG4gKiBgYXNVc2VyKHJlcSlgLCB3aGljaCBhdXRoZW50aWNhdGVzIGFzIHRoZSBjYWxsZXIgb24tYmVoYWxmLW9mIChPQk8pLiBUaGVcbiAqIGNob2ljZSBpcyBvbmUgY2FsbCwgc28gdGhlIHdob2xlIGRlY2lzaW9uIGlzIFwiZG8gd2UgZW50ZXIgYGFzVXNlcmAgZm9yIHRoaXNcbiAqIHJlcXVlc3RcIi5cbiAqXG4gKiBgYXNVc2VyKHJlcSlgIG5lZWRzIHRoZSBPQk8gdG9rZW4gdGhlIHBsYXRmb3JtIGZyb250IGRvb3IgZm9yd2FyZHMgb25cbiAqIHtAbGluayBBQ0NFU1NfVE9LRU5fSEVBREVSfS4gTWVhc3VyZWQgYWdhaW5zdCB0aGUgaW5zdGFsbGVkIEFwcEtpdCwgaXRzXG4gKiBiZWhhdmlvciB3aGVuIHRoYXQgaGVhZGVyIGlzIGFic2VudCBkZXBlbmRzIEVOVElSRUxZIG9uIGBOT0RFX0VOVmA6XG4gKlxuICogfCBgTk9ERV9FTlZgICAgIHwgbm8gYHgtZm9yd2FyZGVkLWFjY2Vzcy10b2tlbmAgICAgICAgICAgICAgICAgICAgICAgICB8XG4gKiB8IC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHxcbiAqIHwgYGRldmVsb3BtZW50YCB8IGxvZ3MgYSB3YXJuaW5nLCBzaWxlbnRseSBydW5zIGFzIHRoZSBzZXJ2aWNlIHByaW5jaXBhbCB8XG4gKiB8IGFueXRoaW5nIGVsc2UgfCB0aHJvd3MgYEF1dGhlbnRpY2F0aW9uRXJyb3I6IE1pc3NpbmcgdXNlciB0b2tlbmAgICAgICB8XG4gKlxuICogVGhhdCBwcm9kdWN0aW9uIHRocm93IGlzIGNvcnJlY3QgZm9yIGFuIGFwcCBiZWhpbmQgdGhlIERhdGFicmlja3MgZnJvbnQgZG9vcixcbiAqIHdoZXJlIGEgbWlzc2luZyB0b2tlbiBtZWFucyBzb21ldGhpbmcgaXMgd3JvbmcuIEl0IGlzIGZhdGFsIGZvciBhbiBhcHAgd2hvc2VcbiAqIHRyYWZmaWMgbGVnaXRpbWF0ZWx5IGFycml2ZXMgV0lUSE9VVCBvbmU6XG4gKlxuICogICAtIGEgcHVibGljIHR1bm5lbCAoYEBkYngtdG9vbHMvdHVubmVsYCksIHdoZXJlIGNhbGxlcnMgYXV0aGVudGljYXRlIGJ5XG4gKiAgICAgZW1haWwgT1RQIGFuZCBubyBPQk8gdG9rZW4gZXhpc3RzIHRvIGZvcndhcmQgLSB0aGUgZ2F0ZSBjYW4gcHJvdmUgV0hPIHRoZVxuICogICAgIGNhbGxlciBpcywgYnV0IGl0IGNhbm5vdCBtaW50IGEgRGF0YWJyaWNrcyBjcmVkZW50aWFsIGZvciB0aGVtO1xuICogICAtIGFueSByZXZlcnNlIHByb3h5LCB3ZWJob29rLCBvciBib3QgY2hhbm5lbCAoYFBPU1QgL2FwaS90ZWFtcy9tZXNzYWdlc2ApXG4gKiAgICAgdGhhdCBhdXRoZW50aWNhdGVzIGl0cyBvd24gd2F5LlxuICpcbiAqIFN1Y2ggYW4gYXBwIG11c3Qgbm90IHJ1biB3aXRoIGBOT0RFX0VOVj1kZXZlbG9wbWVudGAganVzdCB0byBnZXQgdGhlIGZhbGxiYWNrOlxuICogdGhhdCBmbGFnIGFsc28gcmVsYXhlcyBzZWN1cmUgY29va2llcywgQXBwS2l0J3Mgb3duIGRldiBhZmZvcmRhbmNlcywgYW5kXG4gKiBgYWxsb3dVbmF1dGhlbnRpY2F0ZWRgIGVzY2FwZSBoYXRjaGVzLiBIZW5jZSB7QGxpbmsgSWRlbnRpdHlNb2RlfTpcbiAqXG4gKiAgIC0gYFwidXNlclwiYCAtIGFsd2F5cyBPQk8uIFBlci11c2VyIGF0dHJpYnV0aW9uIGFuZCBwZXItdXNlciBHZW5pZSAvIFVuaXR5XG4gKiAgICAgQ2F0YWxvZyByb3cgZmlsdGVycy4gQ29ycmVjdCB3aGVuIGV2ZXJ5IGNhbGxlciBpcyBhIHdvcmtzcGFjZSBtZW1iZXIuXG4gKiAgIC0gYFwic2VydmljZS1wcmluY2lwYWxcImAgLSBhbHdheXMgdGhlIGFwcCdzIG93biBpZGVudGl0eS4gTmVlZHMgbm8gT0JPXG4gKiAgICAgc2NvcGVzIGFuZCB3b3JrcyBmb3IgYW55IGNhbGxlciwgYXQgdGhlIGNvc3Qgb2YgcGVyLXVzZXIgZGF0YSBzY29waW5nLlxuICogICAtIGBcImF1dG9cImAgLSBPQk8gd2hlbiB0aGUgcmVxdWVzdCBhY3R1YWxseSBjYXJyaWVzIGEgdXNhYmxlIE9CTyB0b2tlbixcbiAqICAgICB0aGUgc2VydmljZSBwcmluY2lwYWwgb3RoZXJ3aXNlLiBPbmUgZGVwbG95bWVudCB0aGVuIHNlcnZlcyBCT1RIIGRvb3JzXG4gKiAgICAgY29ycmVjdGx5OiBmcm9udC1kb29yIHJlcXVlc3RzIGtlZXAgZnVsbCBwZXItdXNlciBzY29waW5nLCB3aGlsZSB0dW5uZWwgL1xuICogICAgIHdlYmhvb2sgcmVxdWVzdHMgZGVncmFkZSB0byB0aGUgc2VydmljZSBwcmluY2lwYWwgaW5zdGVhZCBvZiA1MDBpbmcuXG4gKlxuICogYFwiYXV0b1wiYCBkZWNpZGVzIHBlciBSRVFVRVNULCBub3QgcGVyIGJvb3QsIGJlY2F1c2UgYSBzaW5nbGUgY29udGFpbmVyIHNlcnZlc1xuICogYm90aCBkb29ycyBhdCBvbmNlIC0gdGhlIHR1bm5lbCBnYXRlIGFuZCB0aGUgcGxhdGZvcm0gZnJvbnQgZG9vciBzaGFyZSBhIHBvcnRcbiAqIChzZWUgYEBkYngtdG9vbHMvdHVubmVsYCkuIEEgYm9vdC10aW1lIGZsYWcgd291bGQgaGF2ZSB0byBiZSB3cm9uZyBmb3Igb25lXG4gKiBvZiB0aGVtLlxuICpcbiAqIFdoYXQgdGhlIHNlcnZpY2UgcHJpbmNpcGFsIGRvZXMgTk9UIGNoYW5nZSBpcyBXSE8gdGhlIHJlcXVlc3QgYmVsb25ncyB0by4gVGhlXG4gKiBjYWxsZXIncyBpZGVudGl0eSBzdGlsbCBhcnJpdmVzIG9uIHtAbGluayBVU0VSX0lEX0hFQURFUn0gL1xuICoge0BsaW5rIFVTRVJfRU1BSUxfSEVBREVSfSwgc28gbWVtb3J5IHRocmVhZHMsIGNhY2hlIG5hbWVzcGFjZXMsIGFuZCB0cmFjZVxuICogYXR0cmlidXRpb24gc3RheSBwZXItdXNlci4gT25seSB0aGUgRGF0YWJyaWNrcyBjcmVkZW50aWFsIGlzIHNoYXJlZC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHsgZW52LCBzdHJpbmcsIHRva2VuLCB0eXBlIEVudktleSB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5cbi8qKlxuICogSGVhZGVyIHRoZSBEYXRhYnJpY2tzIEFwcHMgZnJvbnQgZG9vciBmb3J3YXJkcyB0aGUgY2FsbGVyJ3MgT0JPIHRva2VuIG9uLlxuICogSXRzIHByZXNlbmNlIGlzIHdoYXQgbWFrZXMgYGFzVXNlcihyZXEpYCB2aWFibGUsIHNvIGl0IGlzIHRoZSBzaWduYWxcbiAqIHtAbGluayB1c2VTZXJ2aWNlUHJpbmNpcGFsfSByZWFkcyBpbiBgXCJhdXRvXCJgIG1vZGUuXG4gKlxuICogUmUtZXhwb3J0ZWQgZnJvbSBgQGRieC10b29scy9zaGFyZWQtY29yZWAncyBgdG9rZW5gIG1vZHVsZSAod2hpY2ggcmVhZHMgdGhlXG4gKiBzYW1lIGhlYWRlciB0byBkZWNvZGUgT0F1dGggc2NvcGVzKSByYXRoZXIgdGhhbiByZS1zcGVsbGVkLCBzbyB0aGUgbmFtZSBmb3JcbiAqIHRoaXMgd2lyZSBjb250cmFjdCBleGlzdHMgb25jZS5cbiAqL1xuZXhwb3J0IGNvbnN0IEFDQ0VTU19UT0tFTl9IRUFERVIgPSB0b2tlbi5BQ0NFU1NfVE9LRU5fSEVBREVSO1xuXG4vKiogSGVhZGVyIHRoZSBEYXRhYnJpY2tzIEFwcHMgZnJvbnQgZG9vciBmb3J3YXJkcyB0aGUgY2FsbGVyJ3MgdXNlciBpZCBvbi4gKi9cbmV4cG9ydCBjb25zdCBVU0VSX0lEX0hFQURFUiA9IHRva2VuLlVTRVJfSURfSEVBREVSO1xuXG4vKiogSGVhZGVyIHRoZSBEYXRhYnJpY2tzIEFwcHMgZnJvbnQgZG9vciBmb3J3YXJkcyB0aGUgY2FsbGVyJ3MgZW1haWwgb24uICovXG5leHBvcnQgY29uc3QgVVNFUl9FTUFJTF9IRUFERVIgPSB0b2tlbi5VU0VSX0VNQUlMX0hFQURFUjtcblxuLyoqIElkZW50aXR5IGEgcmVxdWVzdCdzIERhdGFicmlja3MgY2FsbHMgcnVuIGFzLiBTZWUgdGhlIG1vZHVsZSBkb2NzLiAqL1xuZXhwb3J0IHR5cGUgSWRlbnRpdHlNb2RlID0gXCJ1c2VyXCIgfCBcInNlcnZpY2UtcHJpbmNpcGFsXCIgfCBcImF1dG9cIjtcblxuLyoqIEV2ZXJ5IGFjY2VwdGVkIHtAbGluayBJZGVudGl0eU1vZGV9LCBpbiB0aGUgb3JkZXIgZG9jcyBhbmQgc2NoZW1hcyBsaXN0IHRoZW0uICovXG5leHBvcnQgY29uc3QgSURFTlRJVFlfTU9ERVM6IHJlYWRvbmx5IElkZW50aXR5TW9kZVtdID0gW1widXNlclwiLCBcInNlcnZpY2UtcHJpbmNpcGFsXCIsIFwiYXV0b1wiXTtcblxuLyoqXG4gKiBEZWZhdWx0IG1vZGUuIGBcInVzZXJcImAga2VlcHMgT0JPIHRoZSBvbmx5IGlkZW50aXR5IHVubGVzcyBhbiBhcHAgb3B0cyBpbiwgc29cbiAqIGFkb3B0aW5nIHRoaXMgb3B0aW9uIGNhbiBuZXZlciBzaWxlbnRseSB3aWRlbiBhbiBleGlzdGluZyBhcHAncyBkYXRhIGFjY2Vzcy5cbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfSURFTlRJVFlfTU9ERTogSWRlbnRpdHlNb2RlID0gXCJ1c2VyXCI7XG5cbi8qKiBUaGUgc3Vic2V0IG9mIGBleHByZXNzLlJlcXVlc3RgIHRoaXMgbW9kdWxlIHJlYWRzIC0gb25lIGhlYWRlciBsb29rdXAuICovXG5leHBvcnQgaW50ZXJmYWNlIEhlYWRlckJlYXJpbmcge1xuICBoZWFkZXIobmFtZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJlc29sdmUgYSBjb25maWd1cmVkIG1vZGU6IGV4cGxpY2l0IGNvbmZpZyB2YWx1ZSwgdGhlbiB0aGUgZmlyc3Qgbm9uLWVtcHR5XG4gKiB2YXJpYWJsZSBhbW9uZyBgZW52S2V5c2AsIHRoZW4ge0BsaW5rIERFRkFVTFRfSURFTlRJVFlfTU9ERX0uXG4gKlxuICogQW4gdW5yZWNvZ25pemVkIHZhbHVlIHRocm93cyByYXRoZXIgdGhhbiBmYWxsaW5nIGJhY2suIEZhbGxpbmcgYmFjayB3b3VsZFxuICogc2lsZW50bHkga2VlcCBzZXJ2aW5nIE9CTyAtIGFuZCB0aGUgcHJvZHVjdGlvbiBgQXV0aGVudGljYXRpb25FcnJvcmAgaXRcbiAqIHByb2R1Y2VzIC0gdG8gZXhhY3RseSB0aGUgY2FsbGVycyB0aGUgb3B0aW9uIHdhcyBzZXQgdG8gYWNjb21tb2RhdGUsIGFuZCBhXG4gKiB0eXBvIChgXCJvYm9cImAsIGBcInNwXCJgKSBpcyB0aGUgbGlrZWxpZXN0IHdheSB0byBnZXQgb25lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUlkZW50aXR5TW9kZShcbiAgY29uZmlndXJlZDogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBlbnZLZXlzOiBFbnZLZXksXG4gIGZpZWxkID0gXCJpZGVudGl0eVwiLFxuKTogSWRlbnRpdHlNb2RlIHtcbiAgY29uc3QgcmF3ID0gZW52LnN0cmluZyhjb25maWd1cmVkLCBlbnZLZXlzKTtcbiAgaWYgKHJhdyA9PT0gbnVsbCkgcmV0dXJuIERFRkFVTFRfSURFTlRJVFlfTU9ERTtcbiAgY29uc3QgbW9kZSA9IHJhdy50b0xvd2VyQ2FzZSgpIGFzIElkZW50aXR5TW9kZTtcbiAgaWYgKCFJREVOVElUWV9NT0RFUy5pbmNsdWRlcyhtb2RlKSkge1xuICAgIGNvbnN0IG5hbWVzID0gdHlwZW9mIGVudktleXMgPT09IFwic3RyaW5nXCIgPyBlbnZLZXlzIDogZW52S2V5cy5qb2luKFwiIC8gXCIpO1xuICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoXG4gICAgICBgJHtmaWVsZH0gbXVzdCBiZSBvbmUgb2YgJHtJREVOVElUWV9NT0RFUy5qb2luKFwiIHwgXCIpfSAoZW52OiAke25hbWVzfSlgLFxuICAgICAgeyBjb250ZXh0OiB7IGZpZWxkLCBlbnZWYXI6IG5hbWVzLCByZWNlaXZlZDogcmF3IH0gfSxcbiAgICApO1xuICB9XG4gIHJldHVybiBtb2RlO1xufVxuXG4vKipcbiAqIFRoZSBPQk8gdG9rZW4gb24gYHJlcWAsIG9yIGB1bmRlZmluZWRgLiBSZWFkIHRocm91Z2ggdGhlIHNhbWUgdHJpbSBhcyBldmVyeVxuICogb3RoZXIgaGVhZGVyLCBzbyBhIGhlYWRlciBwcmVzZW50LWJ1dC1ibGFuayAod2hpY2ggc29tZSBwcm94aWVzIGVtaXQgZm9yIGFuXG4gKiB1bnNldCB1cHN0cmVhbSB2YWx1ZSkgY291bnRzIGFzIGFic2VudCByYXRoZXIgdGhhbiBhcyBhIHRva2VuIHRoYXQgZmFpbHMgYXRcbiAqIHRoZSBmaXJzdCBEYXRhYnJpY2tzIGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXF1ZXN0QWNjZXNzVG9rZW4ocmVxOiBIZWFkZXJCZWFyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHN0cmluZy50cmltVG9OdWxsKHJlcT8uaGVhZGVyKEFDQ0VTU19UT0tFTl9IRUFERVIpKSA/PyB1bmRlZmluZWQ7XG59XG5cbi8qKiBUaGUgZm9yd2FyZGVkIHVzZXIgaWQgb24gYHJlcWAsIG9yIGB1bmRlZmluZWRgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVlc3RVc2VySWQocmVxOiBIZWFkZXJCZWFyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHN0cmluZy50cmltVG9OdWxsKHJlcT8uaGVhZGVyKFVTRVJfSURfSEVBREVSKSkgPz8gdW5kZWZpbmVkO1xufVxuXG4vKiogVGhlIGZvcndhcmRlZCB1c2VyIGVtYWlsIG9uIGByZXFgLCBvciBgdW5kZWZpbmVkYC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXF1ZXN0VXNlckVtYWlsKHJlcTogSGVhZGVyQmVhcmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBzdHJpbmcudHJpbVRvTnVsbChyZXE/LmhlYWRlcihVU0VSX0VNQUlMX0hFQURFUikpID8/IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGByZXFgIHNob3VsZCBydW4gaXRzIERhdGFicmlja3MgY2FsbHMgYXMgdGhlIGFwcCBzZXJ2aWNlIHByaW5jaXBhbFxuICogcmF0aGVyIHRoYW4gT0JPLlxuICpcbiAqIC0gYFwic2VydmljZS1wcmluY2lwYWxcImAgLT4gYWx3YXlzIGB0cnVlYC5cbiAqIC0gYFwidXNlclwiYCAtPiBhbHdheXMgYGZhbHNlYCwgZXZlbiB3aXRoIG5vIHRva2VuLiBUaGUgbW9kZSBpcyBhbiBleHBsaWNpdFxuICogICBhc3NlcnRpb24gdGhhdCBldmVyeSBjYWxsZXIgaXMgT0JPLWNhcGFibGUsIHNvIGEgbWlzc2luZyB0b2tlbiBpcyBhIHJlYWxcbiAqICAgZXJyb3IgYW5kIG11c3Qgc3VyZmFjZSBhcyBBcHBLaXQncyBgQXV0aGVudGljYXRpb25FcnJvcmAgcmF0aGVyIHRoYW4gYmVpbmdcbiAqICAgcXVpZXRseSBkb3duZ3JhZGVkIHRvIHNoYXJlZCBkYXRhIGFjY2Vzcy5cbiAqIC0gYFwiYXV0b1wiYCAtPiBgdHJ1ZWAgb25seSB3aGVuIHRoZSByZXF1ZXN0IGNhcnJpZXMgbm8gdXNhYmxlIE9CTyB0b2tlbi5cbiAqXG4gKiBBIHJlcXVlc3QgQXBwS2l0IHdpbGwgbm90IGFjY2VwdCBmb3IgT0JPIGFueXdheSAobm8gdG9rZW4pIGNhbiBuZXZlciBiZVxuICogc2VydmVkIGJ5IGVudGVyaW5nIGBhc1VzZXJgLCBzbyBpbiBgXCJhdXRvXCJgIG1vZGUgdGhlIHRva2VuIGNoZWNrIGlzIHRoZSB3aG9sZVxuICogZGVjaXNpb246IGl0IGlzIHRoZSBzYW1lIGNvbmRpdGlvbiBBcHBLaXQgaXRzZWxmIGJyYW5jaGVzIG9uLCBqdXN0IHJlc29sdmVkXG4gKiBiZWZvcmUgaXQgY2FuIHRocm93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlU2VydmljZVByaW5jaXBhbChtb2RlOiBJZGVudGl0eU1vZGUsIHJlcT86IEhlYWRlckJlYXJpbmcpOiBib29sZWFuIHtcbiAgaWYgKG1vZGUgPT09IFwic2VydmljZS1wcmluY2lwYWxcIikgcmV0dXJuIHRydWU7XG4gIGlmIChtb2RlID09PSBcInVzZXJcIikgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gcmVxdWVzdEFjY2Vzc1Rva2VuKHJlcSkgPT09IHVuZGVmaW5lZDtcbn1cbiJdfQ==
@@ -0,0 +1,152 @@
1
+ /**
2
+ * The `createApp` INTERCEPTOR context: an in-process handle an app hands to
3
+ * add-ons (the tunnel, chiefly) so they can read the env auto-configuration
4
+ * computed, hook AppKit's lifecycle, and supervise sibling child processes as one
5
+ * unit - concurrently-style, where any death takes the whole set down.
6
+ *
7
+ * An interceptor is a plain function `(ctx) => void | Promise<void>` passed to
8
+ * {@link CreateAppConfig.interceptor} ("one or many"). {@link createApp} runs each
9
+ * one AFTER auto-configuration has populated `process.env` but as part of booting
10
+ * the app, so an interceptor sees the resolved connection and can bind processes
11
+ * before or during setup.
12
+ *
13
+ * The names here mirror AppKit's own vocabulary rather than inventing parallel
14
+ * ones: {@link LifecycleEvent} and {@link InterceptorContext.onLifecycle} are the
15
+ * exact shape of `PluginContext.onLifecycle` (`setup:complete` / `server:ready` /
16
+ * `shutdown`). The bridge that makes that hook reachable from OUTSIDE a plugin -
17
+ * where interceptors run - is {@link lifecycleBridge}, a tiny internal plugin
18
+ * {@link createApp} injects to capture `this.context` and relay its events.
19
+ *
20
+ * @module
21
+ */
22
+ import type { ChildProcess } from "node:child_process";
23
+ import { Plugin, type BasePluginConfig } from "@databricks/appkit";
24
+ import type { LakebaseConnection } from "./lakebase-resolver.ts";
25
+ /**
26
+ * AppKit's plugin-lifecycle events, verbatim from `PluginContext`
27
+ * (`node_modules/@databricks/appkit/.../core/plugin-context.d.ts`). Re-declared
28
+ * structurally rather than imported because `PluginContext` is not in the
29
+ * package's `exports` map (the same reason {@link PluginContextLike} exists in
30
+ * `./plugin`).
31
+ *
32
+ * - `setup:complete` - every plugin's `setup()` has resolved.
33
+ * - `server:ready` - the `server()` plugin is listening (never fires for a
34
+ * serverless app, e.g. the tunnel gate).
35
+ * - `shutdown` - the app is tearing down.
36
+ */
37
+ export type LifecycleEvent = "setup:complete" | "server:ready" | "shutdown";
38
+ /** A lifecycle subscriber. Errors are logged, not propagated (matches AppKit). */
39
+ export type LifecycleHandler = () => void | Promise<void>;
40
+ /**
41
+ * The env auto-configuration resolved before boot, exposed to interceptors so
42
+ * they read COMPUTED values instead of re-reading `process.env` themselves.
43
+ *
44
+ * `lakebase` is the resolved Postgres connection when Lakebase auto-config ran
45
+ * (see `create-app`'s `autoConfigure`), else `undefined`. `databricksHost` is the
46
+ * workspace host as resolved into the environment (`DATABRICKS_HOST`), which the
47
+ * tunnel interceptor both reads and, when it must, sets.
48
+ */
49
+ export interface ResolvedAppEnv {
50
+ /** Resolved Lakebase connection, when auto-config resolved one. */
51
+ readonly lakebase?: LakebaseConnection;
52
+ /** Resolved Databricks workspace host (`DATABRICKS_HOST`), when known. */
53
+ readonly databricksHost?: string;
54
+ }
55
+ /**
56
+ * A process {@link InterceptorContext.bindProcess} can supervise. A bare
57
+ * `node:child_process` `ChildProcess` (e.g. portr) satisfies this, and so does
58
+ * `@dbx-tools/core`'s `spawn()` result (a `ChildProcessResult` IS a
59
+ * `ChildProcess`) - one code path handles both.
60
+ */
61
+ export type BindableProcess = Pick<ChildProcess, "pid" | "kill" | "killed" | "once">;
62
+ /**
63
+ * The handle passed to each interceptor.
64
+ *
65
+ * @example
66
+ * import { createApp } from "@dbx-tools/appkit";
67
+ *
68
+ * await createApp({
69
+ * plugins: [server()],
70
+ * interceptor: (ctx) => {
71
+ * const portr = spawnPortr(ctx.env.databricksHost);
72
+ * ctx.bindProcess(portr); // app <-> portr live/die together
73
+ * ctx.onLifecycle("shutdown", () => portr.kill("SIGTERM"));
74
+ * },
75
+ * });
76
+ */
77
+ export interface InterceptorContext {
78
+ /** The env auto-configuration computed before boot. */
79
+ readonly env: ResolvedAppEnv;
80
+ /**
81
+ * Subscribe to an AppKit lifecycle event. Mirrors `PluginContext.onLifecycle`;
82
+ * the injected {@link lifecycleBridge} relays the real events here once the app
83
+ * boots. A handler registered for an event that already fired is NOT called
84
+ * retroactively (same semantics as AppKit).
85
+ */
86
+ onLifecycle(event: LifecycleEvent, fn: LifecycleHandler): void;
87
+ /**
88
+ * Broadcast a termination signal from the main app to every bound process.
89
+ * Called automatically when this process receives `SIGINT`/`SIGTERM`/`SIGHUP`;
90
+ * exposed so an interceptor can trigger teardown itself.
91
+ */
92
+ broadcastSignal(signal: NodeJS.Signals): void;
93
+ /**
94
+ * Supervise a child process alongside the app, concurrently-style: signals pass
95
+ * through, and if EITHER the child or the app dies the whole set comes down.
96
+ * Generalizes the tunnel's old hand-rolled `superviseExit`. Safe to call for
97
+ * several children; teardown is idempotent.
98
+ */
99
+ bindProcess(child: BindableProcess): void;
100
+ }
101
+ /** A single interceptor, or several. The `createApp` `interceptor?:` option. */
102
+ export type Interceptor = (ctx: InterceptorContext) => void | Promise<void>;
103
+ /**
104
+ * The mutable machinery behind an {@link InterceptorContext}. Split out so
105
+ * {@link createInterceptorContext} can hand the public context to interceptors
106
+ * while `create-app` retains the `emitLifecycle` side-channel the bridge drives.
107
+ */
108
+ export interface InterceptorRuntime {
109
+ /** The context handed to each interceptor. */
110
+ readonly context: InterceptorContext;
111
+ /** Fire a lifecycle event to every subscriber (called by {@link lifecycleBridge}). */
112
+ emitLifecycle(event: LifecycleEvent): Promise<void>;
113
+ }
114
+ /**
115
+ * Build an {@link InterceptorContext} + its {@link InterceptorRuntime}.
116
+ *
117
+ * Teardown is the generalized `superviseExit`: the first child exit or main-process
118
+ * termination signal flips a one-shot guard, `SIGTERM`s the other bound children,
119
+ * then `process.exit`s after {@link TEARDOWN_GRACE_MS} (an `unref`'d timer, so it
120
+ * never itself holds the loop open). The process-signal listeners are installed
121
+ * lazily on the first `bindProcess` so an app that binds nothing is untouched.
122
+ */
123
+ export declare function createInterceptorContext(env: ResolvedAppEnv): InterceptorRuntime;
124
+ /** Config for {@link LifecycleBridgePlugin}: the sink its captured events flow to. */
125
+ interface LifecycleBridgeConfig extends BasePluginConfig {
126
+ /** The runtime whose `emitLifecycle` receives the real AppKit events. */
127
+ runtime?: InterceptorRuntime;
128
+ }
129
+ /**
130
+ * The internal plugin {@link createApp} injects to make AppKit's lifecycle
131
+ * reachable from interceptor code. On `setup()` it reads its own `this.context`
132
+ * (the real `PluginContext`) and forwards each {@link LifecycleEvent} to the
133
+ * interceptor runtime, so `ctx.onLifecycle(...)` handlers fire on the genuine
134
+ * events. It owns no routes, config surface, or exports.
135
+ */
136
+ export declare class LifecycleBridgePlugin extends Plugin<LifecycleBridgeConfig> {
137
+ static manifest: {
138
+ name: "dbxToolsLifecycleBridge";
139
+ displayName: string;
140
+ description: string;
141
+ stability: "beta";
142
+ hidden: true;
143
+ resources: {
144
+ required: never[];
145
+ optional: never[];
146
+ };
147
+ };
148
+ setup(): Promise<void>;
149
+ }
150
+ /** Factory for the injected {@link LifecycleBridgePlugin}. */
151
+ export declare const lifecycleBridge: import("@databricks/appkit").ToPlugin<typeof LifecycleBridgePlugin, LifecycleBridgeConfig, "dbxToolsLifecycleBridge">;
152
+ export {};
@@ -0,0 +1,141 @@
1
+ /**
2
+ * The `createApp` INTERCEPTOR context: an in-process handle an app hands to
3
+ * add-ons (the tunnel, chiefly) so they can read the env auto-configuration
4
+ * computed, hook AppKit's lifecycle, and supervise sibling child processes as one
5
+ * unit - concurrently-style, where any death takes the whole set down.
6
+ *
7
+ * An interceptor is a plain function `(ctx) => void | Promise<void>` passed to
8
+ * {@link CreateAppConfig.interceptor} ("one or many"). {@link createApp} runs each
9
+ * one AFTER auto-configuration has populated `process.env` but as part of booting
10
+ * the app, so an interceptor sees the resolved connection and can bind processes
11
+ * before or during setup.
12
+ *
13
+ * The names here mirror AppKit's own vocabulary rather than inventing parallel
14
+ * ones: {@link LifecycleEvent} and {@link InterceptorContext.onLifecycle} are the
15
+ * exact shape of `PluginContext.onLifecycle` (`setup:complete` / `server:ready` /
16
+ * `shutdown`). The bridge that makes that hook reachable from OUTSIDE a plugin -
17
+ * where interceptors run - is {@link lifecycleBridge}, a tiny internal plugin
18
+ * {@link createApp} injects to capture `this.context` and relay its events.
19
+ *
20
+ * @module
21
+ */
22
+ import { Plugin, toPlugin } from "@databricks/appkit";
23
+ import { log } from "@dbx-tools/shared-core";
24
+ const logger = log.logger("interceptor");
25
+ /** How long bound children get to exit on `SIGTERM` before the app force-exits. */
26
+ const TEARDOWN_GRACE_MS = 3000;
27
+ /** The signals that trigger teardown when the MAIN process receives them. */
28
+ const TEARDOWN_SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
29
+ /**
30
+ * Build an {@link InterceptorContext} + its {@link InterceptorRuntime}.
31
+ *
32
+ * Teardown is the generalized `superviseExit`: the first child exit or main-process
33
+ * termination signal flips a one-shot guard, `SIGTERM`s the other bound children,
34
+ * then `process.exit`s after {@link TEARDOWN_GRACE_MS} (an `unref`'d timer, so it
35
+ * never itself holds the loop open). The process-signal listeners are installed
36
+ * lazily on the first `bindProcess` so an app that binds nothing is untouched.
37
+ */
38
+ export function createInterceptorContext(env) {
39
+ const handlers = new Map();
40
+ const children = new Set();
41
+ let shuttingDown = false;
42
+ let signalsBound = false;
43
+ const teardown = (code) => {
44
+ if (shuttingDown)
45
+ return;
46
+ shuttingDown = true;
47
+ for (const child of children) {
48
+ if (!child.killed)
49
+ child.kill("SIGTERM");
50
+ }
51
+ setTimeout(() => process.exit(code), TEARDOWN_GRACE_MS).unref();
52
+ };
53
+ const broadcastSignal = (signal) => {
54
+ for (const child of children) {
55
+ if (!child.killed)
56
+ child.kill(signal);
57
+ }
58
+ teardown(0);
59
+ };
60
+ const bindProcessSignals = () => {
61
+ if (signalsBound)
62
+ return;
63
+ signalsBound = true;
64
+ for (const signal of TEARDOWN_SIGNALS) {
65
+ process.on(signal, () => broadcastSignal(signal));
66
+ }
67
+ };
68
+ const bindProcess = (child) => {
69
+ bindProcessSignals();
70
+ children.add(child);
71
+ child.once("exit", (code) => {
72
+ logger.warn("bound process exited; tearing down the app", { code });
73
+ teardown(typeof code === "number" ? code : 1);
74
+ });
75
+ };
76
+ const onLifecycle = (event, fn) => {
77
+ const list = handlers.get(event);
78
+ if (list)
79
+ list.push(fn);
80
+ else
81
+ handlers.set(event, [fn]);
82
+ };
83
+ const emitLifecycle = async (event) => {
84
+ const list = handlers.get(event);
85
+ if (!list)
86
+ return;
87
+ for (const fn of list) {
88
+ try {
89
+ await fn();
90
+ }
91
+ catch (error) {
92
+ // Match AppKit: a failing lifecycle handler is logged, never fatal, and
93
+ // never blocks its siblings.
94
+ logger.warn("lifecycle handler failed", { event, error });
95
+ }
96
+ }
97
+ };
98
+ const context = {
99
+ env,
100
+ onLifecycle,
101
+ broadcastSignal,
102
+ bindProcess,
103
+ };
104
+ return { context, emitLifecycle };
105
+ }
106
+ function hasOnLifecycle(context) {
107
+ return typeof context?.onLifecycle === "function";
108
+ }
109
+ /**
110
+ * The internal plugin {@link createApp} injects to make AppKit's lifecycle
111
+ * reachable from interceptor code. On `setup()` it reads its own `this.context`
112
+ * (the real `PluginContext`) and forwards each {@link LifecycleEvent} to the
113
+ * interceptor runtime, so `ctx.onLifecycle(...)` handlers fire on the genuine
114
+ * events. It owns no routes, config surface, or exports.
115
+ */
116
+ export class LifecycleBridgePlugin extends Plugin {
117
+ static manifest = {
118
+ name: "dbxToolsLifecycleBridge",
119
+ displayName: "Lifecycle Bridge",
120
+ description: "Relays AppKit lifecycle events to the createApp interceptor context.",
121
+ stability: "beta",
122
+ hidden: true,
123
+ resources: { required: [], optional: [] },
124
+ };
125
+ async setup() {
126
+ const runtime = this.config.runtime;
127
+ if (!runtime)
128
+ return;
129
+ if (!hasOnLifecycle(this.context)) {
130
+ logger.debug("no PluginContext.onLifecycle to bridge; interceptor lifecycle events inert");
131
+ return;
132
+ }
133
+ const events = ["setup:complete", "server:ready", "shutdown"];
134
+ for (const event of events) {
135
+ this.context.onLifecycle(event, () => runtime.emitLifecycle(event));
136
+ }
137
+ }
138
+ }
139
+ /** Factory for the injected {@link LifecycleBridgePlugin}. */
140
+ export const lifecycleBridge = toPlugin(LifecycleBridgePlugin);
141
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJjZXB0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBR0gsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQThDLE1BQU0sb0JBQW9CLENBQUM7QUFDbEcsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRzdDLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7QUFzRnpDLG1GQUFtRjtBQUNuRixNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQztBQUUvQiw2RUFBNkU7QUFDN0UsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFVLENBQUM7QUFjbEU7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLFVBQVUsd0JBQXdCLENBQUMsR0FBbUI7SUFDMUQsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQXNDLENBQUM7SUFDL0QsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQW1CLENBQUM7SUFDNUMsSUFBSSxZQUFZLEdBQUcsS0FBSyxDQUFDO0lBQ3pCLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztJQUV6QixNQUFNLFFBQVEsR0FBRyxDQUFDLElBQVksRUFBUSxFQUFFO1FBQ3RDLElBQUksWUFBWTtZQUFFLE9BQU87UUFDekIsWUFBWSxHQUFHLElBQUksQ0FBQztRQUNwQixLQUFLLE1BQU0sS0FBSyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTTtnQkFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzNDLENBQUM7UUFDRCxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxp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QixXQUFXLEVBQUUsc0VBQXNFO1FBQ25GLFNBQVMsRUFBRSxNQUFNO1FBQ2pCLE1BQU0sRUFBRSxJQUFJO1FBQ1osU0FBUyxFQUFFLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFO0tBQ1UsQ0FBQztJQUU3QyxLQUFLLENBQUMsS0FBSztRQUNsQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQztRQUNwQyxJQUFJLENBQUMsT0FBTztZQUFFLE9BQU87UUFDckIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNsQyxNQUFNLENBQUMsS0FBSyxDQUFDLDRFQUE0RSxDQUFDLENBQUM7WUFDM0YsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLE1BQU0sR0FBcUIsQ0FBQyxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDaEYsS0FBSyxNQUFNLEtBQUssSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUMzQixJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7SUFDSCxDQUFDOztBQUdILDhEQUE4RDtBQUM5RCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDLHFCQUFxQixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFRoZSBgY3JlYXRlQXBwYCBJTlRFUkNFUFRPUiBjb250ZXh0OiBhbiBpbi1wcm9jZXNzIGhhbmRsZSBhbiBhcHAgaGFuZHMgdG9cbiAqIGFkZC1vbnMgKHRoZSB0dW5uZWwsIGNoaWVmbHkpIHNvIHRoZXkgY2FuIHJlYWQgdGhlIGVudiBhdXRvLWNvbmZpZ3VyYXRpb25cbiAqIGNvbXB1dGVkLCBob29rIEFwcEtpdCdzIGxpZmVjeWNsZSwgYW5kIHN1cGVydmlzZSBzaWJsaW5nIGNoaWxkIHByb2Nlc3NlcyBhcyBvbmVcbiAqIHVuaXQgLSBjb25jdXJyZW50bHktc3R5bGUsIHdoZXJlIGFueSBkZWF0aCB0YWtlcyB0aGUgd2hvbGUgc2V0IGRvd24uXG4gKlxuICogQW4gaW50ZXJjZXB0b3IgaXMgYSBwbGFpbiBmdW5jdGlvbiBgKGN0eCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD5gIHBhc3NlZCB0b1xuICoge0BsaW5rIENyZWF0ZUFwcENvbmZpZy5pbnRlcmNlcHRvcn0gKFwib25lIG9yIG1hbnlcIikuIHtAbGluayBjcmVhdGVBcHB9IHJ1bnMgZWFjaFxuICogb25lIEFGVEVSIGF1dG8tY29uZmlndXJhdGlvbiBoYXMgcG9wdWxhdGVkIGBwcm9jZXNzLmVudmAgYnV0IGFzIHBhcnQgb2YgYm9vdGluZ1xuICogdGhlIGFwcCwgc28gYW4gaW50ZXJjZXB0b3Igc2VlcyB0aGUgcmVzb2x2ZWQgY29ubmVjdGlvbiBhbmQgY2FuIGJpbmQgcHJvY2Vzc2VzXG4gKiBiZWZvcmUgb3IgZHVyaW5nIHNldHVwLlxuICpcbiAqIFRoZSBuYW1lcyBoZXJlIG1pcnJvciBBcHBLaXQncyBvd24gdm9jYWJ1bGFyeSByYXRoZXIgdGhhbiBpbnZlbnRpbmcgcGFyYWxsZWxcbiAqIG9uZXM6IHtAbGluayBMaWZlY3ljbGVFdmVudH0gYW5kIHtAbGluayBJbnRlcmNlcHRvckNvbnRleHQub25MaWZlY3ljbGV9IGFyZSB0aGVcbiAqIGV4YWN0IHNoYXBlIG9mIGBQbHVnaW5Db250ZXh0Lm9uTGlmZWN5Y2xlYCAoYHNldHVwOmNvbXBsZXRlYCAvIGBzZXJ2ZXI6cmVhZHlgIC9cbiAqIGBzaHV0ZG93bmApLiBUaGUgYnJpZGdlIHRoYXQgbWFrZXMgdGhhdCBob29rIHJlYWNoYWJsZSBmcm9tIE9VVFNJREUgYSBwbHVnaW4gLVxuICogd2hlcmUgaW50ZXJjZXB0b3JzIHJ1biAtIGlzIHtAbGluayBsaWZlY3ljbGVCcmlkZ2V9LCBhIHRpbnkgaW50ZXJuYWwgcGx1Z2luXG4gKiB7QGxpbmsgY3JlYXRlQXBwfSBpbmplY3RzIHRvIGNhcHR1cmUgYHRoaXMuY29udGV4dGAgYW5kIHJlbGF5IGl0cyBldmVudHMuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB0eXBlIHsgQ2hpbGRQcm9jZXNzIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgUGx1Z2luLCB0b1BsdWdpbiwgdHlwZSBCYXNlUGx1Z2luQ29uZmlnLCB0eXBlIFBsdWdpbk1hbmlmZXN0IH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHsgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHsgTGFrZWJhc2VDb25uZWN0aW9uIH0gZnJvbSBcIi4vbGFrZWJhc2UtcmVzb2x2ZXIudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImludGVyY2VwdG9yXCIpO1xuXG4vKipcbiAqIEFwcEtpdCdzIHBsdWdpbi1saWZlY3ljbGUgZXZlbnRzLCB2ZXJiYXRpbSBmcm9tIGBQbHVnaW5Db250ZXh0YFxuICogKGBub2RlX21vZHVsZXMvQGRhdGFicmlja3MvYXBwa2l0Ly4uLi9jb3JlL3BsdWdpbi1jb250ZXh0LmQudHNgKS4gUmUtZGVjbGFyZWRcbiAqIHN0cnVjdHVyYWxseSByYXRoZXIgdGhhbiBpbXBvcnRlZCBiZWNhdXNlIGBQbHVnaW5Db250ZXh0YCBpcyBub3QgaW4gdGhlXG4gKiBwYWNrYWdlJ3MgYGV4cG9ydHNgIG1hcCAodGhlIHNhbWUgcmVhc29uIHtAbGluayBQbHVnaW5Db250ZXh0TGlrZX0gZXhpc3RzIGluXG4gKiBgLi9wbHVnaW5gKS5cbiAqXG4gKiAtIGBzZXR1cDpjb21wbGV0ZWAgLSBldmVyeSBwbHVnaW4ncyBgc2V0dXAoKWAgaGFzIHJlc29sdmVkLlxuICogLSBgc2VydmVyOnJlYWR5YCAtIHRoZSBgc2VydmVyKClgIHBsdWdpbiBpcyBsaXN0ZW5pbmcgKG5ldmVyIGZpcmVzIGZvciBhXG4gKiAgIHNlcnZlcmxlc3MgYXBwLCBlLmcuIHRoZSB0dW5uZWwgZ2F0ZSkuXG4gKiAtIGBzaHV0ZG93bmAgLSB0aGUgYXBwIGlzIHRlYXJpbmcgZG93bi5cbiAqL1xuZXhwb3J0IHR5cGUgTGlmZWN5Y2xlRXZlbnQgPSBcInNldHVwOmNvbXBsZXRlXCIgfCBcInNlcnZlcjpyZWFkeVwiIHwgXCJzaHV0ZG93blwiO1xuXG4vKiogQSBsaWZlY3ljbGUgc3Vic2NyaWJlci4gRXJyb3JzIGFyZSBsb2dnZWQsIG5vdCBwcm9wYWdhdGVkIChtYXRjaGVzIEFwcEtpdCkuICovXG5leHBvcnQgdHlwZSBMaWZlY3ljbGVIYW5kbGVyID0gKCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG5cbi8qKlxuICogVGhlIGVudiBhdXRvLWNvbmZpZ3VyYXRpb24gcmVzb2x2ZWQgYmVmb3JlIGJvb3QsIGV4cG9zZWQgdG8gaW50ZXJjZXB0b3JzIHNvXG4gKiB0aGV5IHJlYWQgQ09NUFVURUQgdmFsdWVzIGluc3RlYWQgb2YgcmUtcmVhZGluZyBgcHJvY2Vzcy5lbnZgIHRoZW1zZWx2ZXMuXG4gKlxuICogYGxha2ViYXNlYCBpcyB0aGUgcmVzb2x2ZWQgUG9zdGdyZXMgY29ubmVjdGlvbiB3aGVuIExha2ViYXNlIGF1dG8tY29uZmlnIHJhblxuICogKHNlZSBgY3JlYXRlLWFwcGAncyBgYXV0b0NvbmZpZ3VyZWApLCBlbHNlIGB1bmRlZmluZWRgLiBgZGF0YWJyaWNrc0hvc3RgIGlzIHRoZVxuICogd29ya3NwYWNlIGhvc3QgYXMgcmVzb2x2ZWQgaW50byB0aGUgZW52aXJvbm1lbnQgKGBEQVRBQlJJQ0tTX0hPU1RgKSwgd2hpY2ggdGhlXG4gKiB0dW5uZWwgaW50ZXJjZXB0b3IgYm90aCByZWFkcyBhbmQsIHdoZW4gaXQgbXVzdCwgc2V0cy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXNvbHZlZEFwcEVudiB7XG4gIC8qKiBSZXNvbHZlZCBMYWtlYmFzZSBjb25uZWN0aW9uLCB3aGVuIGF1dG8tY29uZmlnIHJlc29sdmVkIG9uZS4gKi9cbiAgcmVhZG9ubHkgbGFrZWJhc2U/OiBMYWtlYmFzZUNvbm5lY3Rpb247XG4gIC8qKiBSZXNvbHZlZCBEYXRhYnJpY2tzIHdvcmtzcGFjZSBob3N0IChgREFUQUJSSUNLU19IT1NUYCksIHdoZW4ga25vd24uICovXG4gIHJlYWRvbmx5IGRhdGFicmlja3NIb3N0Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEEgcHJvY2VzcyB7QGxpbmsgSW50ZXJjZXB0b3JDb250ZXh0LmJpbmRQcm9jZXNzfSBjYW4gc3VwZXJ2aXNlLiBBIGJhcmVcbiAqIGBub2RlOmNoaWxkX3Byb2Nlc3NgIGBDaGlsZFByb2Nlc3NgIChlLmcuIHBvcnRyKSBzYXRpc2ZpZXMgdGhpcywgYW5kIHNvIGRvZXNcbiAqIGBAZGJ4LXRvb2xzL2NvcmVgJ3MgYHNwYXduKClgIHJlc3VsdCAoYSBgQ2hpbGRQcm9jZXNzUmVzdWx0YCBJUyBhXG4gKiBgQ2hpbGRQcm9jZXNzYCkgLSBvbmUgY29kZSBwYXRoIGhhbmRsZXMgYm90aC5cbiAqL1xuZXhwb3J0IHR5cGUgQmluZGFibGVQcm9jZXNzID0gUGljazxDaGlsZFByb2Nlc3MsIFwicGlkXCIgfCBcImtpbGxcIiB8IFwia2lsbGVkXCIgfCBcIm9uY2VcIj47XG5cbi8qKlxuICogVGhlIGhhbmRsZSBwYXNzZWQgdG8gZWFjaCBpbnRlcmNlcHRvci5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IHsgY3JlYXRlQXBwIH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG4gKlxuICogYXdhaXQgY3JlYXRlQXBwKHtcbiAqICAgcGx1Z2luczogW3NlcnZlcigpXSxcbiAqICAgaW50ZXJjZXB0b3I6IChjdHgpID0+IHtcbiAqICAgICBjb25zdCBwb3J0ciA9IHNwYXduUG9ydHIoY3R4LmVudi5kYXRhYnJpY2tzSG9zdCk7XG4gKiAgICAgY3R4LmJpbmRQcm9jZXNzKHBvcnRyKTsgICAgICAgICAgICAvLyBhcHAgPC0+IHBvcnRyIGxpdmUvZGllIHRvZ2V0aGVyXG4gKiAgICAgY3R4Lm9uTGlmZWN5Y2xlKFwic2h1dGRvd25cIiwgKCkgPT4gcG9ydHIua2lsbChcIlNJR1RFUk1cIikpO1xuICogICB9LFxuICogfSk7XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW50ZXJjZXB0b3JDb250ZXh0IHtcbiAgLyoqIFRoZSBlbnYgYXV0by1jb25maWd1cmF0aW9uIGNvbXB1dGVkIGJlZm9yZSBib290LiAqL1xuICByZWFkb25seSBlbnY6IFJlc29sdmVkQXBwRW52O1xuICAvKipcbiAgICogU3Vic2NyaWJlIHRvIGFuIEFwcEtpdCBsaWZlY3ljbGUgZXZlbnQuIE1pcnJvcnMgYFBsdWdpbkNvbnRleHQub25MaWZlY3ljbGVgO1xuICAgKiB0aGUgaW5qZWN0ZWQge0BsaW5rIGxpZmVjeWNsZUJyaWRnZX0gcmVsYXlzIHRoZSByZWFsIGV2ZW50cyBoZXJlIG9uY2UgdGhlIGFwcFxuICAgKiBib290cy4gQSBoYW5kbGVyIHJlZ2lzdGVyZWQgZm9yIGFuIGV2ZW50IHRoYXQgYWxyZWFkeSBmaXJlZCBpcyBOT1QgY2FsbGVkXG4gICAqIHJldHJvYWN0aXZlbHkgKHNhbWUgc2VtYW50aWNzIGFzIEFwcEtpdCkuXG4gICAqL1xuICBvbkxpZmVjeWNsZShldmVudDogTGlmZWN5Y2xlRXZlbnQsIGZuOiBMaWZlY3ljbGVIYW5kbGVyKTogdm9pZDtcbiAgLyoqXG4gICAqIEJyb2FkY2FzdCBhIHRlcm1pbmF0aW9uIHNpZ25hbCBmcm9tIHRoZSBtYWluIGFwcCB0byBldmVyeSBib3VuZCBwcm9jZXNzLlxuICAgKiBDYWxsZWQgYXV0b21hdGljYWxseSB3aGVuIHRoaXMgcHJvY2VzcyByZWNlaXZlcyBgU0lHSU5UYC9gU0lHVEVSTWAvYFNJR0hVUGA7XG4gICAqIGV4cG9zZWQgc28gYW4gaW50ZXJjZXB0b3IgY2FuIHRyaWdnZXIgdGVhcmRvd24gaXRzZWxmLlxuICAgKi9cbiAgYnJvYWRjYXN0U2lnbmFsKHNpZ25hbDogTm9kZUpTLlNpZ25hbHMpOiB2b2lkO1xuICAvKipcbiAgICogU3VwZXJ2aXNlIGEgY2hpbGQgcHJvY2VzcyBhbG9uZ3NpZGUgdGhlIGFwcCwgY29uY3VycmVudGx5LXN0eWxlOiBzaWduYWxzIHBhc3NcbiAgICogdGhyb3VnaCwgYW5kIGlmIEVJVEhFUiB0aGUgY2hpbGQgb3IgdGhlIGFwcCBkaWVzIHRoZSB3aG9sZSBzZXQgY29tZXMgZG93bi5cbiAgICogR2VuZXJhbGl6ZXMgdGhlIHR1bm5lbCdzIG9sZCBoYW5kLXJvbGxlZCBgc3VwZXJ2aXNlRXhpdGAuIFNhZmUgdG8gY2FsbCBmb3JcbiAgICogc2V2ZXJhbCBjaGlsZHJlbjsgdGVhcmRvd24gaXMgaWRlbXBvdGVudC5cbiAgICovXG4gIGJpbmRQcm9jZXNzKGNoaWxkOiBCaW5kYWJsZVByb2Nlc3MpOiB2b2lkO1xufVxuXG4vKiogQSBzaW5nbGUgaW50ZXJjZXB0b3IsIG9yIHNldmVyYWwuIFRoZSBgY3JlYXRlQXBwYCBgaW50ZXJjZXB0b3I/OmAgb3B0aW9uLiAqL1xuZXhwb3J0IHR5cGUgSW50ZXJjZXB0b3IgPSAoY3R4OiBJbnRlcmNlcHRvckNvbnRleHQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+O1xuXG4vKiogSG93IGxvbmcgYm91bmQgY2hpbGRyZW4gZ2V0IHRvIGV4aXQgb24gYFNJR1RFUk1gIGJlZm9yZSB0aGUgYXBwIGZvcmNlLWV4aXRzLiAqL1xuY29uc3QgVEVBUkRPV05fR1JBQ0VfTVMgPSAzMDAwO1xuXG4vKiogVGhlIHNpZ25hbHMgdGhhdCB0cmlnZ2VyIHRlYXJkb3duIHdoZW4gdGhlIE1BSU4gcHJvY2VzcyByZWNlaXZlcyB0aGVtLiAqL1xuY29uc3QgVEVBUkRPV05fU0lHTkFMUyA9IFtcIlNJR0lOVFwiLCBcIlNJR1RFUk1cIiwgXCJTSUdIVVBcIl0gYXMgY29uc3Q7XG5cbi8qKlxuICogVGhlIG11dGFibGUgbWFjaGluZXJ5IGJlaGluZCBhbiB7QGxpbmsgSW50ZXJjZXB0b3JDb250ZXh0fS4gU3BsaXQgb3V0IHNvXG4gKiB7QGxpbmsgY3JlYXRlSW50ZXJjZXB0b3JDb250ZXh0fSBjYW4gaGFuZCB0aGUgcHVibGljIGNvbnRleHQgdG8gaW50ZXJjZXB0b3JzXG4gKiB3aGlsZSBgY3JlYXRlLWFwcGAgcmV0YWlucyB0aGUgYGVtaXRMaWZlY3ljbGVgIHNpZGUtY2hhbm5lbCB0aGUgYnJpZGdlIGRyaXZlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbnRlcmNlcHRvclJ1bnRpbWUge1xuICAvKiogVGhlIGNvbnRleHQgaGFuZGVkIHRvIGVhY2ggaW50ZXJjZXB0b3IuICovXG4gIHJlYWRvbmx5IGNvbnRleHQ6IEludGVyY2VwdG9yQ29udGV4dDtcbiAgLyoqIEZpcmUgYSBsaWZlY3ljbGUgZXZlbnQgdG8gZXZlcnkgc3Vic2NyaWJlciAoY2FsbGVkIGJ5IHtAbGluayBsaWZlY3ljbGVCcmlkZ2V9KS4gKi9cbiAgZW1pdExpZmVjeWNsZShldmVudDogTGlmZWN5Y2xlRXZlbnQpOiBQcm9taXNlPHZvaWQ+O1xufVxuXG4vKipcbiAqIEJ1aWxkIGFuIHtAbGluayBJbnRlcmNlcHRvckNvbnRleHR9ICsgaXRzIHtAbGluayBJbnRlcmNlcHRvclJ1bnRpbWV9LlxuICpcbiAqIFRlYXJkb3duIGlzIHRoZSBnZW5lcmFsaXplZCBgc3VwZXJ2aXNlRXhpdGA6IHRoZSBmaXJzdCBjaGlsZCBleGl0IG9yIG1haW4tcHJvY2Vzc1xuICogdGVybWluYXRpb24gc2lnbmFsIGZsaXBzIGEgb25lLXNob3QgZ3VhcmQsIGBTSUdURVJNYHMgdGhlIG90aGVyIGJvdW5kIGNoaWxkcmVuLFxuICogdGhlbiBgcHJvY2Vzcy5leGl0YHMgYWZ0ZXIge0BsaW5rIFRFQVJET1dOX0dSQUNFX01TfSAoYW4gYHVucmVmYCdkIHRpbWVyLCBzbyBpdFxuICogbmV2ZXIgaXRzZWxmIGhvbGRzIHRoZSBsb29wIG9wZW4pLiBUaGUgcHJvY2Vzcy1zaWduYWwgbGlzdGVuZXJzIGFyZSBpbnN0YWxsZWRcbiAqIGxhemlseSBvbiB0aGUgZmlyc3QgYGJpbmRQcm9jZXNzYCBzbyBhbiBhcHAgdGhhdCBiaW5kcyBub3RoaW5nIGlzIHVudG91Y2hlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUludGVyY2VwdG9yQ29udGV4dChlbnY6IFJlc29sdmVkQXBwRW52KTogSW50ZXJjZXB0b3JSdW50aW1lIHtcbiAgY29uc3QgaGFuZGxlcnMgPSBuZXcgTWFwPExpZmVjeWNsZUV2ZW50LCBMaWZlY3ljbGVIYW5kbGVyW10+KCk7XG4gIGNvbnN0IGNoaWxkcmVuID0gbmV3IFNldDxCaW5kYWJsZVByb2Nlc3M+KCk7XG4gIGxldCBzaHV0dGluZ0Rvd24gPSBmYWxzZTtcbiAgbGV0IHNpZ25hbHNCb3VuZCA9IGZhbHNlO1xuXG4gIGNvbnN0IHRlYXJkb3duID0gKGNvZGU6IG51bWJlcik6IHZvaWQgPT4ge1xuICAgIGlmIChzaHV0dGluZ0Rvd24pIHJldHVybjtcbiAgICBzaHV0dGluZ0Rvd24gPSB0cnVlO1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgY2hpbGRyZW4pIHtcbiAgICAgIGlmICghY2hpbGQua2lsbGVkKSBjaGlsZC5raWxsKFwiU0lHVEVSTVwiKTtcbiAgICB9XG4gICAgc2V0VGltZW91dCgoKSA9PiBwcm9jZXNzLmV4aXQoY29kZSksIFRFQVJET1dOX0dSQUNFX01TKS51bnJlZigpO1xuICB9O1xuXG4gIGNvbnN0IGJyb2FkY2FzdFNpZ25hbCA9IChzaWduYWw6IE5vZGVKUy5TaWduYWxzKTogdm9pZCA9PiB7XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBjaGlsZHJlbikge1xuICAgICAgaWYgKCFjaGlsZC5raWxsZWQpIGNoaWxkLmtpbGwoc2lnbmFsKTtcbiAgICB9XG4gICAgdGVhcmRvd24oMCk7XG4gIH07XG5cbiAgY29uc3QgYmluZFByb2Nlc3NTaWduYWxzID0gKCk6IHZvaWQgPT4ge1xuICAgIGlmIChzaWduYWxzQm91bmQpIHJldHVybjtcbiAgICBzaWduYWxzQm91bmQgPSB0cnVlO1xuICAgIGZvciAoY29uc3Qgc2lnbmFsIG9mIFRFQVJET1dOX1NJR05BTFMpIHtcbiAgICAgIHByb2Nlc3Mub24oc2lnbmFsLCAoKSA9PiBicm9hZGNhc3RTaWduYWwoc2lnbmFsKSk7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGJpbmRQcm9jZXNzID0gKGNoaWxkOiBCaW5kYWJsZVByb2Nlc3MpOiB2b2lkID0+IHtcbiAgICBiaW5kUHJvY2Vzc1NpZ25hbHMoKTtcbiAgICBjaGlsZHJlbi5hZGQoY2hpbGQpO1xuICAgIGNoaWxkLm9uY2UoXCJleGl0XCIsIChjb2RlKSA9PiB7XG4gICAgICBsb2dnZXIud2FybihcImJvdW5kIHByb2Nlc3MgZXhpdGVkOyB0ZWFyaW5nIGRvd24gdGhlIGFwcFwiLCB7IGNvZGUgfSk7XG4gICAgICB0ZWFyZG93bih0eXBlb2YgY29kZSA9PT0gXCJudW1iZXJcIiA/IGNvZGUgOiAxKTtcbiAgICB9KTtcbiAgfTtcblxuICBjb25zdCBvbkxpZmVjeWNsZSA9IChldmVudDogTGlmZWN5Y2xlRXZlbnQsIGZuOiBMaWZlY3ljbGVIYW5kbGVyKTogdm9pZCA9PiB7XG4gICAgY29uc3QgbGlzdCA9IGhhbmRsZXJzLmdldChldmVudCk7XG4gICAgaWYgKGxpc3QpIGxpc3QucHVzaChmbik7XG4gICAgZWxzZSBoYW5kbGVycy5zZXQoZXZlbnQsIFtmbl0pO1xuICB9O1xuXG4gIGNvbnN0IGVtaXRMaWZlY3ljbGUgPSBhc3luYyAoZXZlbnQ6IExpZmVjeWNsZUV2ZW50KTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgY29uc3QgbGlzdCA9IGhhbmRsZXJzLmdldChldmVudCk7XG4gICAgaWYgKCFsaXN0KSByZXR1cm47XG4gICAgZm9yIChjb25zdCBmbiBvZiBsaXN0KSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBmbigpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgLy8gTWF0Y2ggQXBwS2l0OiBhIGZhaWxpbmcgbGlmZWN5Y2xlIGhhbmRsZXIgaXMgbG9nZ2VkLCBuZXZlciBmYXRhbCwgYW5kXG4gICAgICAgIC8vIG5ldmVyIGJsb2NrcyBpdHMgc2libGluZ3MuXG4gICAgICAgIGxvZ2dlci53YXJuKFwibGlmZWN5Y2xlIGhhbmRsZXIgZmFpbGVkXCIsIHsgZXZlbnQsIGVycm9yIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBjb25zdCBjb250ZXh0OiBJbnRlcmNlcHRvckNvbnRleHQgPSB7XG4gICAgZW52LFxuICAgIG9uTGlmZWN5Y2xlLFxuICAgIGJyb2FkY2FzdFNpZ25hbCxcbiAgICBiaW5kUHJvY2VzcyxcbiAgfTtcblxuICByZXR1cm4geyBjb250ZXh0LCBlbWl0TGlmZWN5Y2xlIH07XG59XG5cbi8qKiBDb25maWcgZm9yIHtAbGluayBMaWZlY3ljbGVCcmlkZ2VQbHVnaW59OiB0aGUgc2luayBpdHMgY2FwdHVyZWQgZXZlbnRzIGZsb3cgdG8uICovXG5pbnRlcmZhY2UgTGlmZWN5Y2xlQnJpZGdlQ29uZmlnIGV4dGVuZHMgQmFzZVBsdWdpbkNvbmZpZyB7XG4gIC8qKiBUaGUgcnVudGltZSB3aG9zZSBgZW1pdExpZmVjeWNsZWAgcmVjZWl2ZXMgdGhlIHJlYWwgQXBwS2l0IGV2ZW50cy4gKi9cbiAgcnVudGltZT86IEludGVyY2VwdG9yUnVudGltZTtcbn1cblxuLyoqXG4gKiBTdHJ1Y3R1cmFsIHNoYXBlIG9mIHRoZSBgUGx1Z2luQ29udGV4dC5vbkxpZmVjeWNsZWAgd2UgYnJpZGdlLiBNaXJyb3JzIG9ubHkgdGhlXG4gKiBvbmUgbWV0aG9kIHdlIHRvdWNoIChsaWtlIHtAbGluayBQbHVnaW5Db250ZXh0TGlrZX0gaW4gYC4vcGx1Z2luYCksIHNpbmNlXG4gKiBBcHBLaXQncyBgUGx1Z2luQ29udGV4dGAgaXMgbm90IGltcG9ydGFibGUgZnJvbSB0aGUgcGFja2FnZSdzIGBleHBvcnRzYC5cbiAqL1xuaW50ZXJmYWNlIExpZmVjeWNsZUNvbnRleHRMaWtlIHtcbiAgb25MaWZlY3ljbGUoZXZlbnQ6IExpZmVjeWNsZUV2ZW50LCBmbjogTGlmZWN5Y2xlSGFuZGxlcik6IHZvaWQ7XG59XG5cbmZ1bmN0aW9uIGhhc09uTGlmZWN5Y2xlKGNvbnRleHQ6IHVua25vd24pOiBjb250ZXh0IGlzIExpZmVjeWNsZUNvbnRleHRMaWtlIHtcbiAgcmV0dXJuIHR5cGVvZiAoY29udGV4dCBhcyBMaWZlY3ljbGVDb250ZXh0TGlrZSB8IHVuZGVmaW5lZCk/Lm9uTGlmZWN5Y2xlID09PSBcImZ1bmN0aW9uXCI7XG59XG5cbi8qKlxuICogVGhlIGludGVybmFsIHBsdWdpbiB7QGxpbmsgY3JlYXRlQXBwfSBpbmplY3RzIHRvIG1ha2UgQXBwS2l0J3MgbGlmZWN5Y2xlXG4gKiByZWFjaGFibGUgZnJvbSBpbnRlcmNlcHRvciBjb2RlLiBPbiBgc2V0dXAoKWAgaXQgcmVhZHMgaXRzIG93biBgdGhpcy5jb250ZXh0YFxuICogKHRoZSByZWFsIGBQbHVnaW5Db250ZXh0YCkgYW5kIGZvcndhcmRzIGVhY2gge0BsaW5rIExpZmVjeWNsZUV2ZW50fSB0byB0aGVcbiAqIGludGVyY2VwdG9yIHJ1bnRpbWUsIHNvIGBjdHgub25MaWZlY3ljbGUoLi4uKWAgaGFuZGxlcnMgZmlyZSBvbiB0aGUgZ2VudWluZVxuICogZXZlbnRzLiBJdCBvd25zIG5vIHJvdXRlcywgY29uZmlnIHN1cmZhY2UsIG9yIGV4cG9ydHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBMaWZlY3ljbGVCcmlkZ2VQbHVnaW4gZXh0ZW5kcyBQbHVnaW48TGlmZWN5Y2xlQnJpZGdlQ29uZmlnPiB7XG4gIHN0YXRpYyBtYW5pZmVzdCA9IHtcbiAgICBuYW1lOiBcImRieFRvb2xzTGlmZWN5Y2xlQnJpZGdlXCIsXG4gICAgZGlzcGxheU5hbWU6IFwiTGlmZWN5Y2xlIEJyaWRnZVwiLFxuICAgIGRlc2NyaXB0aW9uOiBcIlJlbGF5cyBBcHBLaXQgbGlmZWN5Y2xlIGV2ZW50cyB0byB0aGUgY3JlYXRlQXBwIGludGVyY2VwdG9yIGNvbnRleHQuXCIsXG4gICAgc3RhYmlsaXR5OiBcImJldGFcIixcbiAgICBoaWRkZW46IHRydWUsXG4gICAgcmVzb3VyY2VzOiB7IHJlcXVpcmVkOiBbXSwgb3B0aW9uYWw6IFtdIH0sXG4gIH0gc2F0aXNmaWVzIFBsdWdpbk1hbmlmZXN0PFwiZGJ4VG9vbHNMaWZlY3ljbGVCcmlkZ2VcIj47XG5cbiAgb3ZlcnJpZGUgYXN5bmMgc2V0dXAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcnVudGltZSA9IHRoaXMuY29uZmlnLnJ1bnRpbWU7XG4gICAgaWYgKCFydW50aW1lKSByZXR1cm47XG4gICAgaWYgKCFoYXNPbkxpZmVjeWNsZSh0aGlzLmNvbnRleHQpKSB7XG4gICAgICBsb2dnZXIuZGVidWcoXCJubyBQbHVnaW5Db250ZXh0Lm9uTGlmZWN5Y2xlIHRvIGJyaWRnZTsgaW50ZXJjZXB0b3IgbGlmZWN5Y2xlIGV2ZW50cyBpbmVydFwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZXZlbnRzOiBMaWZlY3ljbGVFdmVudFtdID0gW1wic2V0dXA6Y29tcGxldGVcIiwgXCJzZXJ2ZXI6cmVhZHlcIiwgXCJzaHV0ZG93blwiXTtcbiAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGV2ZW50cykge1xuICAgICAgdGhpcy5jb250ZXh0Lm9uTGlmZWN5Y2xlKGV2ZW50LCAoKSA9PiBydW50aW1lLmVtaXRMaWZlY3ljbGUoZXZlbnQpKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqIEZhY3RvcnkgZm9yIHRoZSBpbmplY3RlZCB7QGxpbmsgTGlmZWN5Y2xlQnJpZGdlUGx1Z2lufS4gKi9cbmV4cG9ydCBjb25zdCBsaWZlY3ljbGVCcmlkZ2UgPSB0b1BsdWdpbihMaWZlY3ljbGVCcmlkZ2VQbHVnaW4pO1xuIl19
@@ -1 +1 @@
1
- {"root":["../src/appkit.ts","../src/config.ts","../src/create-app.ts","../src/databricks.ts","../src/identity.ts","../src/lakebase-resolver.ts","../src/pgaddress.ts","../src/plugin.ts","../src/provision.ts","../index.ts"],"version":"5.9.3"}
1
+ {"root":["../src/appkit.ts","../src/config.ts","../src/create-app.ts","../src/databricks.ts","../src/identity.ts","../src/interceptor.ts","../src/lakebase-resolver.ts","../src/pgaddress.ts","../src/plugin.ts","../src/provision.ts","../index.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -28,8 +28,8 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@databricks/sdk-experimental": "^0.17.0",
31
- "@dbx-tools/core": "0.6.59",
32
- "@dbx-tools/shared-core": "0.6.59",
31
+ "@dbx-tools/core": "0.6.61",
32
+ "@dbx-tools/shared-core": "0.6.61",
33
33
  "yaml": "^2.9.0",
34
34
  "zod": "4.3.6"
35
35
  },
@@ -47,7 +47,7 @@
47
47
  "./package.json": "./package.json"
48
48
  }
49
49
  },
50
- "version": "0.6.59",
50
+ "version": "0.6.61",
51
51
  "types": "./lib/index.d.ts",
52
52
  "type": "module",
53
53
  "exports": {
package/src/create-app.ts CHANGED
@@ -27,6 +27,13 @@ import { createApp as appkitCreateApp } from "@databricks/appkit";
27
27
  import type { PluginMap } from "@databricks/appkit/dist/shared/src/plugin";
28
28
  import { async, log } from "@dbx-tools/shared-core";
29
29
 
30
+ import {
31
+ createInterceptorContext,
32
+ type Interceptor,
33
+ type InterceptorRuntime,
34
+ lifecycleBridge,
35
+ type ResolvedAppEnv,
36
+ } from "./interceptor.ts";
30
37
  import { applyLakebaseEnv, type LakebaseConnection } from "./lakebase-resolver.ts";
31
38
  import { provisionCacheSchema } from "./provision.ts";
32
39
 
@@ -63,6 +70,13 @@ export type CreateAppConfig<T extends AppKitPlugins = AppKitPlugins> = Omit<
63
70
  onPluginsReady?: (appkit: PluginMap<T>) => void | Promise<void>;
64
71
  /** Auto-configuration to run before AppKit boots. Defaults to `"provision"`. */
65
72
  autoConfigure?: AutoConfigureMode | false;
73
+ /**
74
+ * One or many {@link Interceptor}s handed an {@link InterceptorContext} once
75
+ * auto-configuration has computed the env. Each receives the resolved env, an
76
+ * AppKit-lifecycle hook, and `bindProcess` for concurrently-style supervision -
77
+ * see `./interceptor`. The tunnel is the primary consumer.
78
+ */
79
+ interceptor?: Interceptor | Interceptor[];
66
80
  };
67
81
 
68
82
  const logger = log.logger("create-app");
@@ -103,7 +117,7 @@ function usesPlugin<T extends AppKitPlugins>(
103
117
  export async function autoConfigure<T extends AppKitPlugins>(
104
118
  config?: CreateAppConfig<T>,
105
119
  signal?: AbortSignal,
106
- ): Promise<void> {
120
+ ): Promise<LakebaseConnection | undefined> {
107
121
  const mode = config?.autoConfigure ?? DEFAULT_AUTO_CONFIGURE;
108
122
  const explicit = config?.autoConfigure !== undefined;
109
123
  const lakebasePluginPresent = usesPlugin(config, LAKEBASE_PLUGIN);
@@ -114,7 +128,7 @@ export async function autoConfigure<T extends AppKitPlugins>(
114
128
  provisioned: false,
115
129
  skippedReason: mode === false ? "disabled" : "no lakebase plugin",
116
130
  });
117
- return;
131
+ return undefined;
118
132
  }
119
133
 
120
134
  const controller = new AbortController();
@@ -122,8 +136,9 @@ export async function autoConfigure<T extends AppKitPlugins>(
122
136
  async.tieAbortSignal(controller, AbortSignal.timeout(AUTO_CONFIGURE_TIMEOUT_MS));
123
137
 
124
138
  const provision = mode === "provision";
125
- await autoConfigureLakebase(provision, controller.signal);
139
+ const resolved = await autoConfigureLakebase(provision, controller.signal);
126
140
  logger.info("ready", { autoConfigure: mode, lakebasePluginPresent, provisioned: provision });
141
+ return resolved;
127
142
  }
128
143
 
129
144
  /**
@@ -156,10 +171,31 @@ function redactLakebaseConnection(resolved: LakebaseConnection): Record<string,
156
171
  };
157
172
  }
158
173
 
174
+ /** Build the {@link ResolvedAppEnv} interceptors read, from the auto-config result. */
175
+ function resolvedAppEnv(lakebase: LakebaseConnection | undefined): ResolvedAppEnv {
176
+ return {
177
+ ...(lakebase ? { lakebase } : {}),
178
+ ...(process.env.DATABRICKS_HOST ? { databricksHost: process.env.DATABRICKS_HOST } : {}),
179
+ };
180
+ }
181
+
182
+ /** Normalize the `interceptor?: Interceptor | Interceptor[]` option to an array. */
183
+ function interceptorList(interceptor: CreateAppConfig["interceptor"]): Interceptor[] {
184
+ if (!interceptor) return [];
185
+ return Array.isArray(interceptor) ? interceptor : [interceptor];
186
+ }
187
+
159
188
  /**
160
189
  * Auto-configuring drop-in for AppKit's `createApp`: same config, same typed
161
190
  * plugin-export map, with {@link autoConfigure} run first.
162
191
  *
192
+ * When {@link CreateAppConfig.interceptor}s are given, each is invoked with an
193
+ * {@link InterceptorContext} AFTER auto-configuration computes the env and BEFORE
194
+ * AppKit boots - so an interceptor can read the resolved connection, register
195
+ * lifecycle handlers, and `bindProcess` a child. A hidden {@link lifecycleBridge}
196
+ * plugin is injected so those `onLifecycle` handlers fire on the genuine AppKit
197
+ * events; it has no exports, so the returned {@link PluginMap} is unchanged.
198
+ *
163
199
  * @example
164
200
  * import { createApp } from "@dbx-tools/appkit";
165
201
  * import { lakebase, server } from "@databricks/appkit";
@@ -169,8 +205,26 @@ function redactLakebaseConnection(resolved: LakebaseConnection): Record<string,
169
205
  export async function createApp<T extends AppKitPlugins>(
170
206
  config?: CreateAppConfig<T>,
171
207
  ): Promise<PluginMap<T>> {
172
- await autoConfigure(config);
208
+ const lakebase = await autoConfigure(config);
173
209
  const appConfig = { ...config };
174
210
  delete appConfig.autoConfigure;
211
+ delete appConfig.interceptor;
212
+
213
+ const interceptors = interceptorList(config?.interceptor);
214
+ if (interceptors.length === 0) {
215
+ return appkitCreateApp<T>(appConfig);
216
+ }
217
+
218
+ // Build the context from the computed env, run each interceptor (they register
219
+ // lifecycle handlers + bind processes), then inject the bridge that relays the
220
+ // REAL AppKit lifecycle into `runtime.emitLifecycle` during its `setup()`.
221
+ const runtime: InterceptorRuntime = createInterceptorContext(resolvedAppEnv(lakebase));
222
+ for (const interceptor of interceptors) {
223
+ await interceptor(runtime.context);
224
+ }
225
+ // Append the bridge to the plugins tuple. It is hidden and exports nothing, so
226
+ // the returned map still matches `PluginMap<T>`; the cast (through `unknown`) is
227
+ // only because appending widens the tuple type beyond `T`.
228
+ appConfig.plugins = [...(appConfig.plugins ?? []), lifecycleBridge({ runtime })] as unknown as T;
175
229
  return appkitCreateApp<T>(appConfig);
176
230
  }
package/src/identity.ts CHANGED
@@ -20,7 +20,7 @@
20
20
  * where a missing token means something is wrong. It is fatal for an app whose
21
21
  * traffic legitimately arrives WITHOUT one:
22
22
  *
23
- * - a public tunnel (`@dbx-tools/cli-tunnel`), where callers authenticate by
23
+ * - a public tunnel (`@dbx-tools/tunnel`), where callers authenticate by
24
24
  * email OTP and no OBO token exists to forward - the gate can prove WHO the
25
25
  * caller is, but it cannot mint a Databricks credential for them;
26
26
  * - any reverse proxy, webhook, or bot channel (`POST /api/teams/messages`)
@@ -41,7 +41,7 @@
41
41
  *
42
42
  * `"auto"` decides per REQUEST, not per boot, because a single container serves
43
43
  * both doors at once - the tunnel gate and the platform front door share a port
44
- * (see `@dbx-tools/cli-tunnel`). A boot-time flag would have to be wrong for one
44
+ * (see `@dbx-tools/tunnel`). A boot-time flag would have to be wrong for one
45
45
  * of them.
46
46
  *
47
47
  * What the service principal does NOT change is WHO the request belongs to. The
@@ -0,0 +1,261 @@
1
+ /**
2
+ * The `createApp` INTERCEPTOR context: an in-process handle an app hands to
3
+ * add-ons (the tunnel, chiefly) so they can read the env auto-configuration
4
+ * computed, hook AppKit's lifecycle, and supervise sibling child processes as one
5
+ * unit - concurrently-style, where any death takes the whole set down.
6
+ *
7
+ * An interceptor is a plain function `(ctx) => void | Promise<void>` passed to
8
+ * {@link CreateAppConfig.interceptor} ("one or many"). {@link createApp} runs each
9
+ * one AFTER auto-configuration has populated `process.env` but as part of booting
10
+ * the app, so an interceptor sees the resolved connection and can bind processes
11
+ * before or during setup.
12
+ *
13
+ * The names here mirror AppKit's own vocabulary rather than inventing parallel
14
+ * ones: {@link LifecycleEvent} and {@link InterceptorContext.onLifecycle} are the
15
+ * exact shape of `PluginContext.onLifecycle` (`setup:complete` / `server:ready` /
16
+ * `shutdown`). The bridge that makes that hook reachable from OUTSIDE a plugin -
17
+ * where interceptors run - is {@link lifecycleBridge}, a tiny internal plugin
18
+ * {@link createApp} injects to capture `this.context` and relay its events.
19
+ *
20
+ * @module
21
+ */
22
+
23
+ import type { ChildProcess } from "node:child_process";
24
+ import { Plugin, toPlugin, type BasePluginConfig, type PluginManifest } from "@databricks/appkit";
25
+ import { log } from "@dbx-tools/shared-core";
26
+ import type { LakebaseConnection } from "./lakebase-resolver.ts";
27
+
28
+ const logger = log.logger("interceptor");
29
+
30
+ /**
31
+ * AppKit's plugin-lifecycle events, verbatim from `PluginContext`
32
+ * (`node_modules/@databricks/appkit/.../core/plugin-context.d.ts`). Re-declared
33
+ * structurally rather than imported because `PluginContext` is not in the
34
+ * package's `exports` map (the same reason {@link PluginContextLike} exists in
35
+ * `./plugin`).
36
+ *
37
+ * - `setup:complete` - every plugin's `setup()` has resolved.
38
+ * - `server:ready` - the `server()` plugin is listening (never fires for a
39
+ * serverless app, e.g. the tunnel gate).
40
+ * - `shutdown` - the app is tearing down.
41
+ */
42
+ export type LifecycleEvent = "setup:complete" | "server:ready" | "shutdown";
43
+
44
+ /** A lifecycle subscriber. Errors are logged, not propagated (matches AppKit). */
45
+ export type LifecycleHandler = () => void | Promise<void>;
46
+
47
+ /**
48
+ * The env auto-configuration resolved before boot, exposed to interceptors so
49
+ * they read COMPUTED values instead of re-reading `process.env` themselves.
50
+ *
51
+ * `lakebase` is the resolved Postgres connection when Lakebase auto-config ran
52
+ * (see `create-app`'s `autoConfigure`), else `undefined`. `databricksHost` is the
53
+ * workspace host as resolved into the environment (`DATABRICKS_HOST`), which the
54
+ * tunnel interceptor both reads and, when it must, sets.
55
+ */
56
+ export interface ResolvedAppEnv {
57
+ /** Resolved Lakebase connection, when auto-config resolved one. */
58
+ readonly lakebase?: LakebaseConnection;
59
+ /** Resolved Databricks workspace host (`DATABRICKS_HOST`), when known. */
60
+ readonly databricksHost?: string;
61
+ }
62
+
63
+ /**
64
+ * A process {@link InterceptorContext.bindProcess} can supervise. A bare
65
+ * `node:child_process` `ChildProcess` (e.g. portr) satisfies this, and so does
66
+ * `@dbx-tools/core`'s `spawn()` result (a `ChildProcessResult` IS a
67
+ * `ChildProcess`) - one code path handles both.
68
+ */
69
+ export type BindableProcess = Pick<ChildProcess, "pid" | "kill" | "killed" | "once">;
70
+
71
+ /**
72
+ * The handle passed to each interceptor.
73
+ *
74
+ * @example
75
+ * import { createApp } from "@dbx-tools/appkit";
76
+ *
77
+ * await createApp({
78
+ * plugins: [server()],
79
+ * interceptor: (ctx) => {
80
+ * const portr = spawnPortr(ctx.env.databricksHost);
81
+ * ctx.bindProcess(portr); // app <-> portr live/die together
82
+ * ctx.onLifecycle("shutdown", () => portr.kill("SIGTERM"));
83
+ * },
84
+ * });
85
+ */
86
+ export interface InterceptorContext {
87
+ /** The env auto-configuration computed before boot. */
88
+ readonly env: ResolvedAppEnv;
89
+ /**
90
+ * Subscribe to an AppKit lifecycle event. Mirrors `PluginContext.onLifecycle`;
91
+ * the injected {@link lifecycleBridge} relays the real events here once the app
92
+ * boots. A handler registered for an event that already fired is NOT called
93
+ * retroactively (same semantics as AppKit).
94
+ */
95
+ onLifecycle(event: LifecycleEvent, fn: LifecycleHandler): void;
96
+ /**
97
+ * Broadcast a termination signal from the main app to every bound process.
98
+ * Called automatically when this process receives `SIGINT`/`SIGTERM`/`SIGHUP`;
99
+ * exposed so an interceptor can trigger teardown itself.
100
+ */
101
+ broadcastSignal(signal: NodeJS.Signals): void;
102
+ /**
103
+ * Supervise a child process alongside the app, concurrently-style: signals pass
104
+ * through, and if EITHER the child or the app dies the whole set comes down.
105
+ * Generalizes the tunnel's old hand-rolled `superviseExit`. Safe to call for
106
+ * several children; teardown is idempotent.
107
+ */
108
+ bindProcess(child: BindableProcess): void;
109
+ }
110
+
111
+ /** A single interceptor, or several. The `createApp` `interceptor?:` option. */
112
+ export type Interceptor = (ctx: InterceptorContext) => void | Promise<void>;
113
+
114
+ /** How long bound children get to exit on `SIGTERM` before the app force-exits. */
115
+ const TEARDOWN_GRACE_MS = 3000;
116
+
117
+ /** The signals that trigger teardown when the MAIN process receives them. */
118
+ const TEARDOWN_SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"] as const;
119
+
120
+ /**
121
+ * The mutable machinery behind an {@link InterceptorContext}. Split out so
122
+ * {@link createInterceptorContext} can hand the public context to interceptors
123
+ * while `create-app` retains the `emitLifecycle` side-channel the bridge drives.
124
+ */
125
+ export interface InterceptorRuntime {
126
+ /** The context handed to each interceptor. */
127
+ readonly context: InterceptorContext;
128
+ /** Fire a lifecycle event to every subscriber (called by {@link lifecycleBridge}). */
129
+ emitLifecycle(event: LifecycleEvent): Promise<void>;
130
+ }
131
+
132
+ /**
133
+ * Build an {@link InterceptorContext} + its {@link InterceptorRuntime}.
134
+ *
135
+ * Teardown is the generalized `superviseExit`: the first child exit or main-process
136
+ * termination signal flips a one-shot guard, `SIGTERM`s the other bound children,
137
+ * then `process.exit`s after {@link TEARDOWN_GRACE_MS} (an `unref`'d timer, so it
138
+ * never itself holds the loop open). The process-signal listeners are installed
139
+ * lazily on the first `bindProcess` so an app that binds nothing is untouched.
140
+ */
141
+ export function createInterceptorContext(env: ResolvedAppEnv): InterceptorRuntime {
142
+ const handlers = new Map<LifecycleEvent, LifecycleHandler[]>();
143
+ const children = new Set<BindableProcess>();
144
+ let shuttingDown = false;
145
+ let signalsBound = false;
146
+
147
+ const teardown = (code: number): void => {
148
+ if (shuttingDown) return;
149
+ shuttingDown = true;
150
+ for (const child of children) {
151
+ if (!child.killed) child.kill("SIGTERM");
152
+ }
153
+ setTimeout(() => process.exit(code), TEARDOWN_GRACE_MS).unref();
154
+ };
155
+
156
+ const broadcastSignal = (signal: NodeJS.Signals): void => {
157
+ for (const child of children) {
158
+ if (!child.killed) child.kill(signal);
159
+ }
160
+ teardown(0);
161
+ };
162
+
163
+ const bindProcessSignals = (): void => {
164
+ if (signalsBound) return;
165
+ signalsBound = true;
166
+ for (const signal of TEARDOWN_SIGNALS) {
167
+ process.on(signal, () => broadcastSignal(signal));
168
+ }
169
+ };
170
+
171
+ const bindProcess = (child: BindableProcess): void => {
172
+ bindProcessSignals();
173
+ children.add(child);
174
+ child.once("exit", (code) => {
175
+ logger.warn("bound process exited; tearing down the app", { code });
176
+ teardown(typeof code === "number" ? code : 1);
177
+ });
178
+ };
179
+
180
+ const onLifecycle = (event: LifecycleEvent, fn: LifecycleHandler): void => {
181
+ const list = handlers.get(event);
182
+ if (list) list.push(fn);
183
+ else handlers.set(event, [fn]);
184
+ };
185
+
186
+ const emitLifecycle = async (event: LifecycleEvent): Promise<void> => {
187
+ const list = handlers.get(event);
188
+ if (!list) return;
189
+ for (const fn of list) {
190
+ try {
191
+ await fn();
192
+ } catch (error) {
193
+ // Match AppKit: a failing lifecycle handler is logged, never fatal, and
194
+ // never blocks its siblings.
195
+ logger.warn("lifecycle handler failed", { event, error });
196
+ }
197
+ }
198
+ };
199
+
200
+ const context: InterceptorContext = {
201
+ env,
202
+ onLifecycle,
203
+ broadcastSignal,
204
+ bindProcess,
205
+ };
206
+
207
+ return { context, emitLifecycle };
208
+ }
209
+
210
+ /** Config for {@link LifecycleBridgePlugin}: the sink its captured events flow to. */
211
+ interface LifecycleBridgeConfig extends BasePluginConfig {
212
+ /** The runtime whose `emitLifecycle` receives the real AppKit events. */
213
+ runtime?: InterceptorRuntime;
214
+ }
215
+
216
+ /**
217
+ * Structural shape of the `PluginContext.onLifecycle` we bridge. Mirrors only the
218
+ * one method we touch (like {@link PluginContextLike} in `./plugin`), since
219
+ * AppKit's `PluginContext` is not importable from the package's `exports`.
220
+ */
221
+ interface LifecycleContextLike {
222
+ onLifecycle(event: LifecycleEvent, fn: LifecycleHandler): void;
223
+ }
224
+
225
+ function hasOnLifecycle(context: unknown): context is LifecycleContextLike {
226
+ return typeof (context as LifecycleContextLike | undefined)?.onLifecycle === "function";
227
+ }
228
+
229
+ /**
230
+ * The internal plugin {@link createApp} injects to make AppKit's lifecycle
231
+ * reachable from interceptor code. On `setup()` it reads its own `this.context`
232
+ * (the real `PluginContext`) and forwards each {@link LifecycleEvent} to the
233
+ * interceptor runtime, so `ctx.onLifecycle(...)` handlers fire on the genuine
234
+ * events. It owns no routes, config surface, or exports.
235
+ */
236
+ export class LifecycleBridgePlugin extends Plugin<LifecycleBridgeConfig> {
237
+ static manifest = {
238
+ name: "dbxToolsLifecycleBridge",
239
+ displayName: "Lifecycle Bridge",
240
+ description: "Relays AppKit lifecycle events to the createApp interceptor context.",
241
+ stability: "beta",
242
+ hidden: true,
243
+ resources: { required: [], optional: [] },
244
+ } satisfies PluginManifest<"dbxToolsLifecycleBridge">;
245
+
246
+ override async setup(): Promise<void> {
247
+ const runtime = this.config.runtime;
248
+ if (!runtime) return;
249
+ if (!hasOnLifecycle(this.context)) {
250
+ logger.debug("no PluginContext.onLifecycle to bridge; interceptor lifecycle events inert");
251
+ return;
252
+ }
253
+ const events: LifecycleEvent[] = ["setup:complete", "server:ready", "shutdown"];
254
+ for (const event of events) {
255
+ this.context.onLifecycle(event, () => runtime.emitLifecycle(event));
256
+ }
257
+ }
258
+ }
259
+
260
+ /** Factory for the injected {@link LifecycleBridgePlugin}. */
261
+ export const lifecycleBridge = toPlugin(LifecycleBridgePlugin);