@dbx-tools/appkit 0.6.59 → 0.6.60
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 +9 -2
- package/index.ts +3 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -1
- package/lib/src/create-app.d.ts +17 -1
- package/lib/src/create-app.js +42 -4
- package/lib/src/identity.d.ts +2 -2
- package/lib/src/identity.js +3 -3
- package/lib/src/interceptor.d.ts +152 -0
- package/lib/src/interceptor.js +141 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/create-app.ts +58 -4
- package/src/identity.ts +2 -2
- package/src/interceptor.ts +261 -0
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/
|
|
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/
|
|
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,
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssTUFBTSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFNBQVMsTUFBTSxxQkFBcUIsQ0FBQztBQUNqRCxPQUFPLEtBQUssVUFBVSxNQUFNLHFCQUFxQixDQUFDO0FBQ2xELE9BQU8sS0FBSyxRQUFRLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxLQUFLLFdBQVcsTUFBTSxzQkFBc0IsQ0FBQztBQUNwRCxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sNEJBQTRCLENBQUM7QUFDL0QsT0FBTyxLQUFLLFNBQVMsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLEtBQUssTUFBTSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFJaEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRW5ELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxjQUFjLEVBQUUsaUJBQWlCLEVBQUUsY0FBYyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFbEksT0FBTyxFQUFFLHFCQUFxQixFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRzlFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCAqIGFzIGFwcGtpdCBmcm9tIFwiLi9zcmMvYXBwa2l0LnRzXCI7XG5leHBvcnQgKiBhcyBjb25maWcgZnJvbSBcIi4vc3JjL2NvbmZpZy50c1wiO1xuZXhwb3J0ICogYXMgY3JlYXRlQXBwIGZyb20gXCIuL3NyYy9jcmVhdGUtYXBwLnRzXCI7XG5leHBvcnQgKiBhcyBkYXRhYnJpY2tzIGZyb20gXCIuL3NyYy9kYXRhYnJpY2tzLnRzXCI7XG5leHBvcnQgKiBhcyBpZGVudGl0eSBmcm9tIFwiLi9zcmMvaWRlbnRpdHkudHNcIjtcbmV4cG9ydCAqIGFzIGludGVyY2VwdG9yIGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0ICogYXMgbGFrZWJhc2VSZXNvbHZlciBmcm9tIFwiLi9zcmMvbGFrZWJhc2UtcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCAqIGFzIHBnYWRkcmVzcyBmcm9tIFwiLi9zcmMvcGdhZGRyZXNzLnRzXCI7XG5leHBvcnQgKiBhcyBwbHVnaW4gZnJvbSBcIi4vc3JjL3BsdWdpbi50c1wiO1xuZXhwb3J0ICogYXMgcHJvdmlzaW9uIGZyb20gXCIuL3NyYy9wcm92aXNpb24udHNcIjtcbmV4cG9ydCB0eXBlIHsgRXhlY3V0aW9uQ29udGV4dExpa2UsIFdvcmtzcGFjZUNsaWVudExpa2UgfSBmcm9tIFwiLi9zcmMvYXBwa2l0LnRzXCI7XG5leHBvcnQgdHlwZSB7IEJ1bmRsZVZhbGlkYXRlSnNvbiwgQ29uZmlnRmlsZSwgQ29uZmlnU291cmNlLCBDb25maWdNYXBWYWx1ZSwgUmVzb2x2ZUNvbmZpZ1ZhbHVlT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9jb25maWcudHNcIjtcbmV4cG9ydCB0eXBlIHsgQXV0b0NvbmZpZ3VyZU1vZGUsIENyZWF0ZUFwcENvbmZpZyB9IGZyb20gXCIuL3NyYy9jcmVhdGUtYXBwLnRzXCI7XG5leHBvcnQgeyBNQVhfVENQX1BPUlQgfSBmcm9tIFwiLi9zcmMvZGF0YWJyaWNrcy50c1wiO1xuZXhwb3J0IHR5cGUgeyBDb250ZXh0TGlrZSB9IGZyb20gXCIuL3NyYy9kYXRhYnJpY2tzLnRzXCI7XG5leHBvcnQgeyBBQ0NFU1NfVE9LRU5fSEVBREVSLCBVU0VSX0lEX0hFQURFUiwgVVNFUl9FTUFJTF9IRUFERVIsIElERU5USVRZX01PREVTLCBERUZBVUxUX0lERU5USVRZX01PREUgfSBmcm9tIFwiLi9zcmMvaWRlbnRpdHkudHNcIjtcbmV4cG9ydCB0eXBlIHsgSWRlbnRpdHlNb2RlLCBIZWFkZXJCZWFyaW5nIH0gZnJvbSBcIi4vc3JjL2lkZW50aXR5LnRzXCI7XG5leHBvcnQgeyBMaWZlY3ljbGVCcmlkZ2VQbHVnaW4sIGxpZmVjeWNsZUJyaWRnZSB9IGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0IHR5cGUgeyBMaWZlY3ljbGVFdmVudCwgTGlmZWN5Y2xlSGFuZGxlciwgUmVzb2x2ZWRBcHBFbnYsIEJpbmRhYmxlUHJvY2VzcywgSW50ZXJjZXB0b3JDb250ZXh0LCBJbnRlcmNlcHRvciwgSW50ZXJjZXB0b3JSdW50aW1lIH0gZnJvbSBcIi4vc3JjL2ludGVyY2VwdG9yLnRzXCI7XG5leHBvcnQgdHlwZSB7IExha2ViYXNlUmVzb2x2ZXJJbnB1dHMsIExha2ViYXNlQ29ubmVjdGlvbiB9IGZyb20gXCIuL3NyYy9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuZXhwb3J0IHsgU1NMX01PREVTIH0gZnJvbSBcIi4vc3JjL3BnYWRkcmVzcy50c1wiO1xuZXhwb3J0IHR5cGUgeyBTc2xNb2RlLCBMYWtlYmFzZUNvbm5lY3Rpb25JbnB1dHMsIFBhcnNlZEFkZHJlc3MgfSBmcm9tIFwiLi9zcmMvcGdhZGRyZXNzLnRzXCI7XG5leHBvcnQgdHlwZSB7IFBsdWdpbkNvbnRleHRMaWtlIH0gZnJvbSBcIi4vc3JjL3BsdWdpbi50c1wiO1xuIl19
|
package/lib/src/create-app.d.ts
CHANGED
|
@@ -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<
|
|
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";
|
package/lib/src/create-app.js
CHANGED
|
@@ -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==
|
package/lib/src/identity.d.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/
|
|
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/
|
|
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
|
package/lib/src/identity.js
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/
|
|
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/
|
|
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
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -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.
|
|
32
|
-
"@dbx-tools/shared-core": "0.6.
|
|
31
|
+
"@dbx-tools/core": "0.6.60",
|
|
32
|
+
"@dbx-tools/shared-core": "0.6.60",
|
|
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.
|
|
50
|
+
"version": "0.6.60",
|
|
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<
|
|
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/
|
|
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/
|
|
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);
|