@dbx-tools/appkit 0.9.5 → 0.9.7
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 +10 -10
- package/index.ts +12 -6
- package/lib/index.d.ts +12 -6
- package/lib/index.js +9 -5
- package/lib/src/_cache-storage.js +10 -24
- package/lib/src/appkit.js +5 -5
- package/lib/src/brand-context.js +11 -0
- package/lib/src/bundle.d.ts +8 -8
- package/lib/src/bundle.js +8 -8
- package/lib/src/databricks.js +3 -3
- package/lib/src/identity.js +7 -7
- package/lib/src/lakebase-resolver.d.ts +1 -1
- package/lib/src/lakebase-resolver.js +22 -21
- package/lib/src/migration.d.ts +17 -0
- package/lib/src/migration.js +28 -0
- package/lib/src/pgaddress.d.ts +24 -97
- package/lib/src/pgaddress.js +32 -161
- package/lib/src/plugin-execution.d.ts +17 -0
- package/lib/src/plugin-execution.js +28 -0
- package/lib/src/{plugin.d.ts → plugin-registry.d.ts} +9 -13
- package/lib/src/plugin-registry.js +97 -0
- package/lib/src/provision.js +5 -5
- package/lib/src/tool-provider.d.ts +17 -0
- package/lib/src/tool-provider.js +20 -0
- package/lib/src/toolkit-entries.js +34 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -4
- package/src/_cache-storage.ts +12 -25
- package/src/appkit.ts +4 -6
- package/src/brand-context.ts +13 -0
- package/src/bundle.ts +11 -11
- package/src/databricks.ts +2 -2
- package/src/identity.ts +6 -6
- package/src/lakebase-resolver.ts +21 -20
- package/src/migration.ts +40 -0
- package/src/pgaddress.ts +46 -196
- package/src/plugin-execution.ts +42 -0
- package/src/{plugin.ts → plugin-registry.ts} +14 -17
- package/src/provision.ts +4 -4
- package/src/tool-provider.ts +34 -0
- package/lib/src/brand.js +0 -11
- package/lib/src/plugin.js +0 -97
- package/lib/src/toolkit.js +0 -34
- package/src/brand.ts +0 -13
- /package/lib/src/{brand.d.ts → brand-context.d.ts} +0 -0
- /package/lib/src/{toolkit.d.ts → toolkit-entries.d.ts} +0 -0
- /package/src/{toolkit.ts → toolkit-entries.ts} +0 -0
package/lib/src/pgaddress.d.ts
CHANGED
|
@@ -1,104 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Lakebase PostgreSQL address parsing backed by `@dbx-tools/core-rs`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Lakebase resolver to discover.
|
|
8
|
-
*
|
|
9
|
-
* Recognized formats:
|
|
10
|
-
*
|
|
11
|
-
* - **Postgres URI** -
|
|
12
|
-
* `postgresql://user@host:port/db?sslmode=require` (also `postgres://`).
|
|
13
|
-
* Yields `user`, `host`, `port`, `database`, `sslMode`.
|
|
14
|
-
*
|
|
15
|
-
* - **Canonical endpoint resource path** -
|
|
16
|
-
* `projects/{p}/branches/{b}/endpoints/{e}` -
|
|
17
|
-
* yields `project`, `branch`, `endpointId`, and the original string as
|
|
18
|
-
* `endpoint` (already in lakebase's expected form).
|
|
19
|
-
*
|
|
20
|
-
* - **Database resource path** -
|
|
21
|
-
* `projects/{p}/branches/{b}/databases/{d}` -
|
|
22
|
-
* yields `project`, `branch`, and `databaseResourceId` (the UC
|
|
23
|
-
* resource leaf, not `PGDATABASE`; the resolver looks up the real
|
|
24
|
-
* Postgres name via REST).
|
|
25
|
-
*
|
|
26
|
-
* - **Branch resource path** -
|
|
27
|
-
* `projects/{p}/branches/{b}` - yields `project`, `branch`.
|
|
28
|
-
*
|
|
29
|
-
* - **Project resource path** -
|
|
30
|
-
* `projects/{p}` - yields `project`.
|
|
31
|
-
*
|
|
32
|
-
* - **Bare hostname** -
|
|
33
|
-
* `ep-steep-forest-e199v43w.database.eastus2.azuredatabricks.net` -
|
|
34
|
-
* yields `host` only; the resolver reverse-looks up the owning
|
|
35
|
-
* endpoint to recover the resource path.
|
|
36
|
-
*
|
|
37
|
-
* - **Bare project id** -
|
|
38
|
-
* `dbx-tools-demo` (1-63 chars, lowercase letters/digits/hyphens) -
|
|
39
|
-
* yields `project`.
|
|
40
|
-
*
|
|
41
|
-
* Returns an empty object for inputs it doesn't recognize.
|
|
4
|
+
* Rust owns the recognized URL, resource-path, hostname, project-id, and SSL
|
|
5
|
+
* mode rules. This module preserves AppKit's existing namespace, string SSL
|
|
6
|
+
* spelling, sparse records, and nullable input compatibility.
|
|
42
7
|
*
|
|
43
8
|
* @module
|
|
44
9
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
export type SslMode =
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
branch?: string;
|
|
58
|
-
/**
|
|
59
|
-
* Canonical endpoint resource path (`projects/.../endpoints/...`), from
|
|
60
|
-
* `LAKEBASE_ENDPOINT`. Defaults to the branch's read-write endpoint.
|
|
61
|
-
*/
|
|
62
|
-
endpoint?: string;
|
|
63
|
-
/** Postgres database name (`PGDATABASE`). Defaults to `databricks_postgres`. */
|
|
64
|
-
database?: string;
|
|
65
|
-
/** Postgres hostname (`PGHOST`). Defaults to the resolved endpoint's host. */
|
|
66
|
-
host?: string;
|
|
67
|
-
/** Postgres port (`PGPORT`). Defaults to 5432. */
|
|
68
|
-
port?: number;
|
|
69
|
-
/** Postgres TLS mode (`PGSSLMODE`). Defaults to `require`. */
|
|
70
|
-
sslMode?: SslMode;
|
|
71
|
-
}
|
|
72
|
-
/** Pieces recovered from parsing a single address or resource-path input. */
|
|
73
|
-
export interface ParsedAddress extends LakebaseConnectionInputs {
|
|
74
|
-
/** Endpoint leaf id (last segment of an endpoint resource path). */
|
|
75
|
-
endpointId?: string;
|
|
76
|
-
/**
|
|
77
|
-
* Database resource id leaf from a `.../databases/{id}` path. Not the
|
|
78
|
-
* Postgres database name.
|
|
79
|
-
*/
|
|
80
|
-
databaseResourceId?: string;
|
|
81
|
-
/** Postgres user (URI-decoded if encoded). */
|
|
82
|
-
user?: string;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Parse a Lakebase connection input into whatever pieces it carries.
|
|
86
|
-
* See module docstring for the supported formats. Returns `{}` for
|
|
87
|
-
* `undefined`, empty strings, and unrecognized inputs.
|
|
88
|
-
*
|
|
89
|
-
* @example
|
|
90
|
-
* import { pgaddress } from "@dbx-tools/appkit";
|
|
91
|
-
*
|
|
92
|
-
* pgaddress.parseAddress("projects/demo/branches/production/endpoints/ep-1");
|
|
93
|
-
* // { project: "demo", branch: "production", endpointId: "ep-1", endpoint: "projects/..." }
|
|
94
|
-
*
|
|
95
|
-
* pgaddress.parseAddress("postgresql://me@ep-1.database.azuredatabricks.net/app?sslmode=require");
|
|
96
|
-
* // { host: "ep-1.database.azuredatabricks.net", user: "me", database: "app", sslMode: "require" }
|
|
97
|
-
*/
|
|
98
|
-
export declare function parseAddress(input: string | undefined | null): ParsedAddress;
|
|
10
|
+
import { SslMode as NativeSslMode, type ParsedAddress as NativeParsedAddress } from "@dbx-tools/core-rs";
|
|
11
|
+
type NativeSslModeName = Extract<keyof typeof NativeSslMode, string>;
|
|
12
|
+
/** PostgreSQL TLS mode in `PGSSLMODE` spelling. */
|
|
13
|
+
export type SslMode = Lowercase<NativeSslModeName>;
|
|
14
|
+
/** Postgres TLS modes accepted by the native parser, in `PGSSLMODE` spelling. */
|
|
15
|
+
export declare const SSL_MODES: readonly SslMode[];
|
|
16
|
+
/** Native parser output with AppKit's existing string SSL spelling. */
|
|
17
|
+
export type ParsedAddress = {
|
|
18
|
+
[Key in keyof NativeParsedAddress]: Key extends "sslMode" ? SslMode | undefined : NativeParsedAddress[Key];
|
|
19
|
+
};
|
|
20
|
+
/** Inputs shared by parsing and Lakebase connection resolution. */
|
|
21
|
+
export type LakebaseConnectionInputs = ParsedAddress;
|
|
99
22
|
/**
|
|
100
|
-
* Parse a Lakebase
|
|
101
|
-
*
|
|
102
|
-
* project ids).
|
|
23
|
+
* Parse a PostgreSQL URL, Lakebase resource path, hostname, or project id.
|
|
24
|
+
* Returns an empty record when the input is absent or unrecognized.
|
|
103
25
|
*/
|
|
104
|
-
export declare function
|
|
26
|
+
export declare function parseAddress(input: string | null | undefined): ParsedAddress;
|
|
27
|
+
/** Parse a canonical Lakebase `projects/...` resource path. */
|
|
28
|
+
export declare function parseResourcePath(input: string | null | undefined): ParsedAddress;
|
|
29
|
+
/** Normalize a PostgreSQL TLS mode through the native address parser. */
|
|
30
|
+
export declare function parseSslMode(input: string | null | undefined): SslMode | undefined;
|
|
31
|
+
export {};
|
package/lib/src/pgaddress.js
CHANGED
|
@@ -1,173 +1,44 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Lakebase PostgreSQL address parsing backed by `@dbx-tools/core-rs`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Lakebase resolver to discover.
|
|
8
|
-
*
|
|
9
|
-
* Recognized formats:
|
|
10
|
-
*
|
|
11
|
-
* - **Postgres URI** -
|
|
12
|
-
* `postgresql://user@host:port/db?sslmode=require` (also `postgres://`).
|
|
13
|
-
* Yields `user`, `host`, `port`, `database`, `sslMode`.
|
|
14
|
-
*
|
|
15
|
-
* - **Canonical endpoint resource path** -
|
|
16
|
-
* `projects/{p}/branches/{b}/endpoints/{e}` -
|
|
17
|
-
* yields `project`, `branch`, `endpointId`, and the original string as
|
|
18
|
-
* `endpoint` (already in lakebase's expected form).
|
|
19
|
-
*
|
|
20
|
-
* - **Database resource path** -
|
|
21
|
-
* `projects/{p}/branches/{b}/databases/{d}` -
|
|
22
|
-
* yields `project`, `branch`, and `databaseResourceId` (the UC
|
|
23
|
-
* resource leaf, not `PGDATABASE`; the resolver looks up the real
|
|
24
|
-
* Postgres name via REST).
|
|
25
|
-
*
|
|
26
|
-
* - **Branch resource path** -
|
|
27
|
-
* `projects/{p}/branches/{b}` - yields `project`, `branch`.
|
|
28
|
-
*
|
|
29
|
-
* - **Project resource path** -
|
|
30
|
-
* `projects/{p}` - yields `project`.
|
|
31
|
-
*
|
|
32
|
-
* - **Bare hostname** -
|
|
33
|
-
* `ep-steep-forest-e199v43w.database.eastus2.azuredatabricks.net` -
|
|
34
|
-
* yields `host` only; the resolver reverse-looks up the owning
|
|
35
|
-
* endpoint to recover the resource path.
|
|
36
|
-
*
|
|
37
|
-
* - **Bare project id** -
|
|
38
|
-
* `dbx-tools-demo` (1-63 chars, lowercase letters/digits/hyphens) -
|
|
39
|
-
* yields `project`.
|
|
40
|
-
*
|
|
41
|
-
* Returns an empty object for inputs it doesn't recognize.
|
|
4
|
+
* Rust owns the recognized URL, resource-path, hostname, project-id, and SSL
|
|
5
|
+
* mode rules. This module preserves AppKit's existing namespace, string SSL
|
|
6
|
+
* spelling, sparse records, and nullable input compatibility.
|
|
42
7
|
*
|
|
43
8
|
* @module
|
|
44
9
|
*/
|
|
45
|
-
import {
|
|
46
|
-
/** Postgres TLS modes accepted by
|
|
47
|
-
export const SSL_MODES =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
10
|
+
import { parseAddress as parseNativeAddress, parseResourcePath as parseNativeResourcePath, SslMode as NativeSslMode, } from "@dbx-tools/core-rs";
|
|
11
|
+
/** Postgres TLS modes accepted by the native parser, in `PGSSLMODE` spelling. */
|
|
12
|
+
export const SSL_MODES = Object.keys(NativeSslMode)
|
|
13
|
+
.filter((name) => Number.isNaN(Number(name)))
|
|
14
|
+
.map((name) => name.toLowerCase());
|
|
15
|
+
function sslModeName(mode) {
|
|
16
|
+
return mode === undefined ? undefined : NativeSslMode[mode].toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
function normalizeAddress(address) {
|
|
19
|
+
const normalized = { ...address, sslMode: sslModeName(address.sslMode) };
|
|
20
|
+
for (const key of Object.keys(normalized)) {
|
|
21
|
+
if (normalized[key] === undefined)
|
|
22
|
+
delete normalized[key];
|
|
23
|
+
}
|
|
24
|
+
return normalized;
|
|
25
|
+
}
|
|
51
26
|
/**
|
|
52
|
-
* Parse a Lakebase
|
|
53
|
-
*
|
|
54
|
-
* `undefined`, empty strings, and unrecognized inputs.
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* import { pgaddress } from "@dbx-tools/appkit";
|
|
58
|
-
*
|
|
59
|
-
* pgaddress.parseAddress("projects/demo/branches/production/endpoints/ep-1");
|
|
60
|
-
* // { project: "demo", branch: "production", endpointId: "ep-1", endpoint: "projects/..." }
|
|
61
|
-
*
|
|
62
|
-
* pgaddress.parseAddress("postgresql://me@ep-1.database.azuredatabricks.net/app?sslmode=require");
|
|
63
|
-
* // { host: "ep-1.database.azuredatabricks.net", user: "me", database: "app", sslMode: "require" }
|
|
27
|
+
* Parse a PostgreSQL URL, Lakebase resource path, hostname, or project id.
|
|
28
|
+
* Returns an empty record when the input is absent or unrecognized.
|
|
64
29
|
*/
|
|
65
30
|
export function parseAddress(input) {
|
|
66
|
-
|
|
67
|
-
return {};
|
|
68
|
-
const s = input.trim();
|
|
69
|
-
if (!s)
|
|
70
|
-
return {};
|
|
71
|
-
if (URL_SCHEME_RE.test(s))
|
|
72
|
-
return parseUri(s);
|
|
73
|
-
if (s.startsWith("projects/"))
|
|
74
|
-
return parseResourcePathSegments(s);
|
|
75
|
-
// Resource ids never contain dots; a dotted input must be a hostname.
|
|
76
|
-
if (HOSTNAME_HINT_RE.test(s) && s.includes("."))
|
|
77
|
-
return { host: s };
|
|
78
|
-
if (PROJECT_ID_RE.test(s))
|
|
79
|
-
return { project: s };
|
|
80
|
-
return {};
|
|
31
|
+
return normalizeAddress(parseNativeAddress(input ?? undefined));
|
|
81
32
|
}
|
|
82
|
-
/**
|
|
83
|
-
* Parse a Lakebase `projects/...` resource path. Returns `{}` when the
|
|
84
|
-
* input is not a resource path (so bare branch ids are not mistaken for
|
|
85
|
-
* project ids).
|
|
86
|
-
*/
|
|
33
|
+
/** Parse a canonical Lakebase `projects/...` resource path. */
|
|
87
34
|
export function parseResourcePath(input) {
|
|
88
|
-
|
|
89
|
-
return {};
|
|
90
|
-
const s = input.trim();
|
|
91
|
-
if (!s.startsWith("projects/"))
|
|
92
|
-
return {};
|
|
93
|
-
return parseResourcePathSegments(s);
|
|
94
|
-
}
|
|
95
|
-
function parseUri(s) {
|
|
96
|
-
let url;
|
|
97
|
-
try {
|
|
98
|
-
url = new URL(s);
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
return {};
|
|
102
|
-
}
|
|
103
|
-
const target = url.pathname.replace(/^\//, "");
|
|
104
|
-
const decodedTarget = target ? decodeURIComponent(target) : "";
|
|
105
|
-
const result = decodedTarget.startsWith("projects/")
|
|
106
|
-
? parseResourcePathSegments(decodedTarget)
|
|
107
|
-
: {};
|
|
108
|
-
if (url.hostname)
|
|
109
|
-
result.host = url.hostname;
|
|
110
|
-
const port = object.toNumber(url.port);
|
|
111
|
-
if (port !== undefined)
|
|
112
|
-
result.port = port;
|
|
113
|
-
if (url.username) {
|
|
114
|
-
try {
|
|
115
|
-
result.user = decodeURIComponent(url.username);
|
|
116
|
-
}
|
|
117
|
-
catch {
|
|
118
|
-
result.user = url.username;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
if (decodedTarget && !result.project)
|
|
122
|
-
result.database = decodedTarget;
|
|
123
|
-
const sslmodeRaw = url.searchParams.get("sslmode") ?? url.searchParams.get("sslMode");
|
|
124
|
-
const sslmode = sslmodeRaw?.toLowerCase();
|
|
125
|
-
if (isSslMode(sslmode)) {
|
|
126
|
-
result.sslMode = sslmode;
|
|
127
|
-
}
|
|
128
|
-
return result;
|
|
35
|
+
return normalizeAddress(parseNativeResourcePath(input ?? undefined));
|
|
129
36
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
return {};
|
|
137
|
-
}
|
|
138
|
-
const project = parts[1];
|
|
139
|
-
if (!project) {
|
|
140
|
-
return {};
|
|
141
|
-
}
|
|
142
|
-
if (parts.length === 2) {
|
|
143
|
-
return { project };
|
|
144
|
-
}
|
|
145
|
-
if (parts.length === 4 && parts[2] === "branches" && parts[3]) {
|
|
146
|
-
return { project, branch: parts[3] };
|
|
147
|
-
}
|
|
148
|
-
if (parts.length === 6 &&
|
|
149
|
-
parts[2] === "branches" &&
|
|
150
|
-
parts[4] === "endpoints" &&
|
|
151
|
-
parts[3] &&
|
|
152
|
-
parts[5]) {
|
|
153
|
-
return {
|
|
154
|
-
project,
|
|
155
|
-
branch: parts[3],
|
|
156
|
-
endpointId: parts[5],
|
|
157
|
-
endpoint: s,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
if (parts.length === 6 &&
|
|
161
|
-
parts[2] === "branches" &&
|
|
162
|
-
parts[4] === "databases" &&
|
|
163
|
-
parts[3] &&
|
|
164
|
-
parts[5]) {
|
|
165
|
-
return {
|
|
166
|
-
project,
|
|
167
|
-
branch: parts[3],
|
|
168
|
-
databaseResourceId: parts[5],
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
return {};
|
|
37
|
+
/** Normalize a PostgreSQL TLS mode through the native address parser. */
|
|
38
|
+
export function parseSslMode(input) {
|
|
39
|
+
if (input === undefined || input === null || input.trim() === "")
|
|
40
|
+
return undefined;
|
|
41
|
+
const query = encodeURIComponent(input.trim());
|
|
42
|
+
return sslModeName(parseNativeAddress(`postgresql://localhost?sslmode=${query}`).sslMode);
|
|
172
43
|
}
|
|
173
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGdhZGRyZXNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BnYWRkcmVzcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTJDRztBQUVILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVoRCwrRUFBK0U7QUFDL0UsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFHLENBQUMsU0FBUyxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQVUsQ0FBQztBQTBDbkUsTUFBTSxhQUFhLEdBQUcsOEJBQThCLENBQUM7QUFDckQsTUFBTSxhQUFhLEdBQUcsd0NBQXdDLENBQUM7QUFDL0QsTUFBTSxnQkFBZ0IsR0FBRyw4Q0FBOEMsQ0FBQztBQUV4RTs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FBQyxLQUFnQztJQUMzRCxJQUFJLENBQUMsS0FBSztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ3RCLE1BQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN2QixJQUFJLENBQUMsQ0FBQztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBRWxCLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFBRSxPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QyxJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDO1FBQUUsT0FBTyx5QkFBeUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuRSxzRUFBc0U7SUFDdEUsSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUM7UUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ3BFLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7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RUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ2hCLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7U0FDN0IsQ0FBQztJQUNKLENBQUM7SUFFRCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEZsZXhpYmxlIGFkZHJlc3MgcGFyc2VyIGZvciBMYWtlYmFzZSBQb3N0Z3JlcyBjb25uZWN0aW9uIGlucHV0cy5cbiAqXG4gKiBBY2NlcHRzIHdoYXRldmVyIHNoYXBlIGEgdXNlciBpcyBsaWtlbHkgdG8gcGFzdGUgaW50b1xuICogYExBS0VCQVNFX0VORFBPSU5UYCAob3IgdGhlIG1hdGNoaW5nIGNvbmZpZyBmaWVsZCkgYW5kIGV4dHJhY3RzXG4gKiBldmVyeSByZWNvZ25pemFibGUgcGllY2UuIFdoYXRldmVyIGl0IGNhbid0IHJlY292ZXIgaXMgbGVmdCBmb3IgdGhlXG4gKiBMYWtlYmFzZSByZXNvbHZlciB0byBkaXNjb3Zlci5cbiAqXG4gKiBSZWNvZ25pemVkIGZvcm1hdHM6XG4gKlxuICogLSAqKlBvc3RncmVzIFVSSSoqIC1cbiAqICAgYHBvc3RncmVzcWw6Ly91c2VyQGhvc3Q6cG9ydC9kYj9zc2xtb2RlPXJlcXVpcmVgIChhbHNvIGBwb3N0Z3JlczovL2ApLlxuICogICBZaWVsZHMgYHVzZXJgLCBgaG9zdGAsIGBwb3J0YCwgYGRhdGFiYXNlYCwgYHNzbE1vZGVgLlxuICpcbiAqIC0gKipDYW5vbmljYWwgZW5kcG9pbnQgcmVzb3VyY2UgcGF0aCoqIC1cbiAqICAgYHByb2plY3RzL3twfS9icmFuY2hlcy97Yn0vZW5kcG9pbnRzL3tlfWAgLVxuICogICB5aWVsZHMgYHByb2plY3RgLCBgYnJhbmNoYCwgYGVuZHBvaW50SWRgLCBhbmQgdGhlIG9yaWdpbmFsIHN0cmluZyBhc1xuICogICBgZW5kcG9pbnRgIChhbHJlYWR5IGluIGxha2ViYXNlJ3MgZXhwZWN0ZWQgZm9ybSkuXG4gKlxuICogLSAqKkRhdGFiYXNlIHJlc291cmNlIHBhdGgqKiAtXG4gKiAgIGBwcm9qZWN0cy97cH0vYnJhbmNoZXMve2J9L2RhdGFiYXNlcy97ZH1gIC1cbiAqICAgeWllbGRzIGBwcm9qZWN0YCwgYGJyYW5jaGAsIGFuZCBgZGF0YWJhc2VSZXNvdXJjZUlkYCAodGhlIFVDXG4gKiAgIHJlc291cmNlIGxlYWYsIG5vdCBgUEdEQVRBQkFTRWA7IHRoZSByZXNvbHZlciBsb29rcyB1cCB0aGUgcmVhbFxuICogICBQb3N0Z3JlcyBuYW1lIHZpYSBSRVNUKS5cbiAqXG4gKiAtICoqQnJhbmNoIHJlc291cmNlIHBhdGgqKiAtXG4gKiAgIGBwcm9qZWN0cy97cH0vYnJhbmNoZXMve2J9YCAtIHlpZWxkcyBgcHJvamVjdGAsIGBicmFuY2hgLlxuICpcbiAqIC0gKipQcm9qZWN0IHJlc291cmNlIHBhdGgqKiAtXG4gKiAgIGBwcm9qZWN0cy97cH1gIC0geWllbGRzIGBwcm9qZWN0YC5cbiAqXG4gKiAtICoqQmFyZSBob3N0bmFtZSoqIC1cbiAqICAgYGVwLXN0ZWVwLWZvcmVzdC1lMTk5djQzdy5kYXRhYmFzZS5lYXN0dXMyLmF6dXJlZGF0YWJyaWNrcy5uZXRgIC1cbiAqICAgeWllbGRzIGBob3N0YCBvbmx5OyB0aGUgcmVzb2x2ZXIgcmV2ZXJzZS1sb29rcyB1cCB0aGUgb3duaW5nXG4gKiAgIGVuZHBvaW50IHRvIHJlY292ZXIgdGhlIHJlc291cmNlIHBhdGguXG4gKlxuICogLSAqKkJhcmUgcHJvamVjdCBpZCoqIC1cbiAqICAgYGRieC10b29scy1kZW1vYCAoMS02MyBjaGFycywgbG93ZXJjYXNlIGxldHRlcnMvZGlnaXRzL2h5cGhlbnMpIC1cbiAqICAgeWllbGRzIGBwcm9qZWN0YC5cbiAqXG4gKiBSZXR1cm5zIGFuIGVtcHR5IG9iamVjdCBmb3IgaW5wdXRzIGl0IGRvZXNuJ3QgcmVjb2duaXplLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBvYmplY3QgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuXG4vKiogUG9zdGdyZXMgVExTIG1vZGVzIGFjY2VwdGVkIGJ5IHtAbGluayBTc2xNb2RlfSwgaW4gYFBHU1NMTU9ERWAgc3BlbGxpbmcuICovXG5leHBvcnQgY29uc3QgU1NMX01PREVTID0gW1wicmVxdWlyZVwiLCBcImRpc2FibGVcIiwgXCJwcmVmZXJcIl0gYXMgY29uc3Q7XG5cbi8qKiBQb3N0Z3JlcyBUTFMgbW9kZSBwYXNzZWQgdGhyb3VnaCB0byBgcGdgLiAqL1xuZXhwb3J0IHR5cGUgU3NsTW9kZSA9ICh0eXBlb2YgU1NMX01PREVTKVtudW1iZXJdO1xuXG4vKipcbiAqIE9wdGlvbmFsIExha2ViYXNlIFBvc3RncmVzIGNvbm5lY3Rpb24gZmllbGRzIHNoYXJlZCBieSBwYXJzZWQgYWRkcmVzc2VzLFxuICogcmVzb2x2ZXIvZW52IGlucHV0cywgYW5kIHJlc29sdmVkIGNvbm5lY3Rpb25zLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIExha2ViYXNlQ29ubmVjdGlvbklucHV0cyB7XG4gIC8qKiBMYWtlYmFzZSBwcm9qZWN0IGlkLiBSZXNvbHZlZCBmcm9tIHRoZSB3b3Jrc3BhY2Ugd2hlbiB1bnNldC4gKi9cbiAgcHJvamVjdD86IHN0cmluZztcbiAgLyoqIEJyYW5jaCBpZCB3aXRoaW4gdGhlIHByb2plY3QuIERlZmF1bHRzIHRvIHRoZSBwcm9qZWN0J3MgZGVmYXVsdCBicmFuY2guICovXG4gIGJyYW5jaD86IHN0cmluZztcbiAgLyoqXG4gICAqIENhbm9uaWNhbCBlbmRwb2ludCByZXNvdXJjZSBwYXRoIChgcHJvamVjdHMvLi4uL2VuZHBvaW50cy8uLi5gKSwgZnJvbVxuICAgKiBgTEFLRUJBU0VfRU5EUE9JTlRgLiBEZWZhdWx0cyB0byB0aGUgYnJhbmNoJ3MgcmVhZC13cml0ZSBlbmRwb2ludC5cbiAgICovXG4gIGVuZHBvaW50Pzogc3RyaW5nO1xuICAvKiogUG9zdGdyZXMgZGF0YWJhc2UgbmFtZSAoYFBHREFUQUJBU0VgKS4gRGVmYXVsdHMgdG8gYGRhdGFicmlja3NfcG9zdGdyZXNgLiAqL1xuICBkYXRhYmFzZT86IHN0cmluZztcbiAgLyoqIFBvc3RncmVzIGhvc3RuYW1lIChgUEdIT1NUYCkuIERlZmF1bHRzIHRvIHRoZSByZXNvbHZlZCBlbmRwb2ludCdzIGhvc3QuICovXG4gIGhvc3Q/OiBzdHJpbmc7XG4gIC8qKiBQb3N0Z3JlcyBwb3J0IChgUEdQT1JUYCkuIERlZmF1bHRzIHRvIDU0MzIuICovXG4gIHBvcnQ/OiBudW1iZXI7XG4gIC8qKiBQb3N0Z3JlcyBUTFMgbW9kZSAoYFBHU1NMTU9ERWApLiBEZWZhdWx0cyB0byBgcmVxdWlyZWAuICovXG4gIHNzbE1vZGU/OiBTc2xNb2RlO1xufVxuXG4vKiogUGllY2VzIHJlY292ZXJlZCBmcm9tIHBhcnNpbmcgYSBzaW5nbGUgYWRkcmVzcyBvciByZXNvdXJjZS1wYXRoIGlucHV0LiAqL1xuZXhwb3J0IGludGVyZmFjZSBQYXJzZWRBZGRyZXNzIGV4dGVuZHMgTGFrZWJhc2VDb25uZWN0aW9uSW5wdXRzIHtcbiAgLyoqIEVuZHBvaW50IGxlYWYgaWQgKGxhc3Qgc2VnbWVudCBvZiBhbiBlbmRwb2ludCByZXNvdXJjZSBwYXRoKS4gKi9cbiAgZW5kcG9pbnRJZD86IHN0cmluZztcbiAgLyoqXG4gICAqIERhdGFiYXNlIHJlc291cmNlIGlkIGxlYWYgZnJvbSBhIGAuLi4vZGF0YWJhc2VzL3tpZH1gIHBhdGguIE5vdCB0aGVcbiAgICogUG9zdGdyZXMgZGF0YWJhc2UgbmFtZS5cbiAgICovXG4gIGRhdGFiYXNlUmVzb3VyY2VJZD86IHN0cmluZztcbiAgLyoqIFBvc3RncmVzIHVzZXIgKFVSSS1kZWNvZGVkIGlmIGVuY29kZWQpLiAqL1xuICB1c2VyPzogc3RyaW5nO1xufVxuXG5jb25zdCBVUkxfU0NIRU1FX1JFID0gL14ocG9zdGdyZXN8cG9zdGdyZXNxbCk6XFwvXFwvL2k7XG5jb25zdCBQUk9KRUNUX0lEX1JFID0gL15bYS16XVthLXowLTktXXswLDYxfVthLXowLTldJHxeW2Etel0kLztcbmNvbnN0IEhPU1ROQU1FX0hJTlRfUkUgPSAvXlthLXowLTldW2EtejAtOS1dKihcXC5bYS16MC05XVthLXowLTktXSopKyQvaTtcblxuLyoqXG4gKiBQYXJzZSBhIExha2ViYXNlIGNvbm5lY3Rpb24gaW5wdXQgaW50byB3aGF0ZXZlciBwaWVjZXMgaXQgY2Fycmllcy5cbiAqIFNlZSBtb2R1bGUgZG9jc3RyaW5nIGZvciB0aGUgc3VwcG9ydGVkIGZvcm1hdHMuIFJldHVybnMgYHt9YCBmb3JcbiAqIGB1bmRlZmluZWRgLCBlbXB0eSBzdHJpbmdzLCBhbmQgdW5yZWNvZ25pemVkIGlucHV0cy5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IHsgcGdhZGRyZXNzIH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG4gKlxuICogcGdhZGRyZXNzLnBhcnNlQWRkcmVzcyhcInByb2plY3RzL2RlbW8vYnJhbmNoZXMvcHJvZHVjdGlvbi9lbmRwb2ludHMvZXAtMVwiKTtcbiAqIC8vIHsgcHJvamVjdDogXCJkZW1vXCIsIGJyYW5jaDogXCJwcm9kdWN0aW9uXCIsIGVuZHBvaW50SWQ6IFwiZXAtMVwiLCBlbmRwb2ludDogXCJwcm9qZWN0cy8uLi5cIiB9XG4gKlxuICogcGdhZGRyZXNzLnBhcnNlQWRkcmVzcyhcInBvc3RncmVzcWw6Ly9tZUBlcC0xLmRhdGFiYXNlLmF6dXJlZGF0YWJyaWNrcy5uZXQvYXBwP3NzbG1vZGU9cmVxdWlyZVwiKTtcbiAqIC8vIHsgaG9zdDogXCJlcC0xLmRhdGFiYXNlLmF6dXJlZGF0YWJyaWNrcy5uZXRcIiwgdXNlcjogXCJtZVwiLCBkYXRhYmFzZTogXCJhcHBcIiwgc3NsTW9kZTogXCJyZXF1aXJlXCIgfVxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VBZGRyZXNzKGlucHV0OiBzdHJpbmcgfCB1bmRlZmluZWQgfCBudWxsKTogUGFyc2VkQWRkcmVzcyB7XG4gIGlmICghaW5wdXQpIHJldHVybiB7fTtcbiAgY29uc3QgcyA9IGlucHV0LnRyaW0oKTtcbiAgaWYgKCFzKSByZXR1cm4ge307XG5cbiAgaWYgKFVSTF9TQ0hFTUVfUkUudGVzdChzKSkgcmV0dXJuIHBhcnNlVXJpKHMpO1xuICBpZiAocy5zdGFydHNXaXRoKFwicHJvamVjdHMvXCIpKSByZXR1cm4gcGFyc2VSZXNvdXJjZVBhdGhTZWdtZW50cyhzKTtcbiAgLy8gUmVzb3VyY2UgaWRzIG5ldmVyIGNvbnRhaW4gZG90czsgYSBkb3R0ZWQgaW5wdXQgbXVzdCBiZSBhIGhvc3RuYW1lLlxuICBpZiAoSE9TVE5BTUVfSElOVF9SRS50ZXN0KHMpICYmIHMuaW5jbHVkZXMoXCIuXCIpKSByZXR1cm4geyBob3N0OiBzIH07XG4gIGlmIChQUk9KRUNUX0lEX1JFLnRlc3QocykpIHJldHVybiB7IHByb2plY3Q6IHMgfTtcbiAgcmV0dXJuIHt9O1xufVxuXG4vKipcbiAqIFBhcnNlIGEgTGFrZWJhc2UgYHByb2plY3RzLy4uLmAgcmVzb3VyY2UgcGF0aC4gUmV0dXJucyBge31gIHdoZW4gdGhlXG4gKiBpbnB1dCBpcyBub3QgYSByZXNvdXJjZSBwYXRoIChzbyBiYXJlIGJyYW5jaCBpZHMgYXJlIG5vdCBtaXN0YWtlbiBmb3JcbiAqIHByb2plY3QgaWRzKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUmVzb3VyY2VQYXRoKGlucHV0OiBzdHJpbmcgfCB1bmRlZmluZWQgfCBudWxsKTogUGFyc2VkQWRkcmVzcyB7XG4gIGlmICghaW5wdXQpIHJldHVybiB7fTtcbiAgY29uc3QgcyA9IGlucHV0LnRyaW0oKTtcbiAgaWYgKCFzLnN0YXJ0c1dpdGgoXCJwcm9qZWN0cy9cIikpIHJldHVybiB7fTtcbiAgcmV0dXJuIHBhcnNlUmVzb3VyY2VQYXRoU2VnbWVudHMocyk7XG59XG5cbmZ1bmN0aW9uIHBhcnNlVXJpKHM6IHN0cmluZyk6IFBhcnNlZEFkZHJlc3Mge1xuICBsZXQgdXJsOiBVUkw7XG4gIHRyeSB7XG4gICAgdXJsID0gbmV3IFVSTChzKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG4gIGNvbnN0IHRhcmdldCA9IHVybC5wYXRobmFtZS5yZXBsYWNlKC9eXFwvLywgXCJcIik7XG4gIGNvbnN0IGRlY29kZWRUYXJnZXQgPSB0YXJnZXQgPyBkZWNvZGVVUklDb21wb25lbnQodGFyZ2V0KSA6IFwiXCI7XG4gIGNvbnN0IHJlc3VsdDogUGFyc2VkQWRkcmVzcyA9IGRlY29kZWRUYXJnZXQuc3RhcnRzV2l0aChcInByb2plY3RzL1wiKVxuICAgID8gcGFyc2VSZXNvdXJjZVBhdGhTZWdtZW50cyhkZWNvZGVkVGFyZ2V0KVxuICAgIDoge307XG4gIGlmICh1cmwuaG9zdG5hbWUpIHJlc3VsdC5ob3N0ID0gdXJsLmhvc3RuYW1lO1xuICBjb25zdCBwb3J0ID0gb2JqZWN0LnRvTnVtYmVyKHVybC5wb3J0KTtcbiAgaWYgKHBvcnQgIT09IHVuZGVmaW5lZCkgcmVzdWx0LnBvcnQgPSBwb3J0O1xuICBpZiAodXJsLnVzZXJuYW1lKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdC51c2VyID0gZGVjb2RlVVJJQ29tcG9uZW50KHVybC51c2VybmFtZSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXN1bHQudXNlciA9IHVybC51c2VybmFtZTtcbiAgICB9XG4gIH1cbiAgaWYgKGRlY29kZWRUYXJnZXQgJiYgIXJlc3VsdC5wcm9qZWN0KSByZXN1bHQuZGF0YWJhc2UgPSBkZWNvZGVkVGFyZ2V0O1xuICBjb25zdCBzc2xtb2RlUmF3ID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoXCJzc2xtb2RlXCIpID8/IHVybC5zZWFyY2hQYXJhbXMuZ2V0KFwic3NsTW9kZVwiKTtcbiAgY29uc3Qgc3NsbW9kZSA9IHNzbG1vZGVSYXc/LnRvTG93ZXJDYXNlKCk7XG4gIGlmIChpc1NzbE1vZGUoc3NsbW9kZSkpIHtcbiAgICByZXN1bHQuc3NsTW9kZSA9IHNzbG1vZGU7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gaXNTc2xNb2RlKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiB2YWx1ZSBpcyBTc2xNb2RlIHtcbiAgcmV0dXJuIFNTTF9NT0RFUy5zb21lKChtb2RlKSA9PiBtb2RlID09PSB2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIHBhcnNlUmVzb3VyY2VQYXRoU2VnbWVudHMoczogc3RyaW5nKTogUGFyc2VkQWRkcmVzcyB7XG4gIGNvbnN0IHBhcnRzID0gcy5zcGxpdChcIi9cIik7XG4gIGlmIChwYXJ0c1swXSAhPT0gXCJwcm9qZWN0c1wiIHx8IHBhcnRzLmxlbmd0aCA8IDIpIHtcbiAgICByZXR1cm4ge307XG4gIH1cblxuICBjb25zdCBwcm9qZWN0ID0gcGFydHNbMV07XG4gIGlmICghcHJvamVjdCkge1xuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIGlmIChwYXJ0cy5sZW5ndGggPT09IDIpIHtcbiAgICByZXR1cm4geyBwcm9qZWN0IH07XG4gIH1cblxuICBpZiAocGFydHMubGVuZ3RoID09PSA0ICYmIHBhcnRzWzJdID09PSBcImJyYW5jaGVzXCIgJiYgcGFydHNbM10pIHtcbiAgICByZXR1cm4geyBwcm9qZWN0LCBicmFuY2g6IHBhcnRzWzNdIH07XG4gIH1cblxuICBpZiAoXG4gICAgcGFydHMubGVuZ3RoID09PSA2ICYmXG4gICAgcGFydHNbMl0gPT09IFwiYnJhbmNoZXNcIiAmJlxuICAgIHBhcnRzWzRdID09PSBcImVuZHBvaW50c1wiICYmXG4gICAgcGFydHNbM10gJiZcbiAgICBwYXJ0c1s1XVxuICApIHtcbiAgICByZXR1cm4ge1xuICAgICAgcHJvamVjdCxcbiAgICAgIGJyYW5jaDogcGFydHNbM10sXG4gICAgICBlbmRwb2ludElkOiBwYXJ0c1s1XSxcbiAgICAgIGVuZHBvaW50OiBzLFxuICAgIH07XG4gIH1cblxuICBpZiAoXG4gICAgcGFydHMubGVuZ3RoID09PSA2ICYmXG4gICAgcGFydHNbMl0gPT09IFwiYnJhbmNoZXNcIiAmJlxuICAgIHBhcnRzWzRdID09PSBcImRhdGFiYXNlc1wiICYmXG4gICAgcGFydHNbM10gJiZcbiAgICBwYXJ0c1s1XVxuICApIHtcbiAgICByZXR1cm4ge1xuICAgICAgcHJvamVjdCxcbiAgICAgIGJyYW5jaDogcGFydHNbM10sXG4gICAgICBkYXRhYmFzZVJlc291cmNlSWQ6IHBhcnRzWzVdLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge307XG59XG4iXX0=
|
|
44
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGdhZGRyZXNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BnYWRkcmVzcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7R0FRRztBQUVILE9BQU8sRUFDTCxZQUFZLElBQUksa0JBQWtCLEVBQ2xDLGlCQUFpQixJQUFJLHVCQUF1QixFQUM1QyxPQUFPLElBQUksYUFBYSxHQUV6QixNQUFNLG9CQUFvQixDQUFDO0FBTzVCLGlGQUFpRjtBQUNqRixNQUFNLENBQUMsTUFBTSxTQUFTLEdBQXVCLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDO0tBQ3BFLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBNkIsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7S0FDdkUsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFhLENBQUMsQ0FBQztBQVloRCxTQUFTLFdBQVcsQ0FBQyxJQUFvQztJQUN2RCxPQUFPLElBQUksS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUUsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBYyxDQUFDO0FBQ3pGLENBQUM7QUFFRCxTQUFTLGdCQUFnQixDQUFDLE9BQTRCO0lBQ3BELE1BQU0sVUFBVSxHQUFHLEVBQUUsR0FBRyxPQUFPLEVBQUUsT0FBTyxFQUFFLFdBQVcsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQW1CLENBQUM7SUFDMUYsS0FBSyxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBNEIsRUFBRSxDQUFDO1FBQ3JFLElBQUksVUFBVSxDQUFDLEdBQUcsQ0FBQyxLQUFLLFNBQVM7WUFBRSxPQUFPLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBQ0QsT0FBTyxVQUFVLENBQUM7QUFDcEIsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsS0FBZ0M7SUFDM0QsT0FBTyxnQkFBZ0IsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQztBQUNsRSxDQUFDO0FBRUQsK0RBQStEO0FBQy9ELE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxLQUFnQztJQUNoRSxPQUFPLGdCQUFnQixDQUFDLHVCQUF1QixDQUFDLEtBQUssSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBQ3ZFLENBQUM7QUFFRCx5RUFBeUU7QUFDekUsTUFBTSxVQUFVLFlBQVksQ0FBQyxLQUFnQztJQUMzRCxJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ25GLE1BQU0sS0FBSyxHQUFHLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQy9DLE9BQU8sV0FBVyxDQUFDLGtCQUFrQixDQUFDLGtDQUFrQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQzVGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIExha2ViYXNlIFBvc3RncmVTUUwgYWRkcmVzcyBwYXJzaW5nIGJhY2tlZCBieSBgQGRieC10b29scy9jb3JlLXJzYC5cbiAqXG4gKiBSdXN0IG93bnMgdGhlIHJlY29nbml6ZWQgVVJMLCByZXNvdXJjZS1wYXRoLCBob3N0bmFtZSwgcHJvamVjdC1pZCwgYW5kIFNTTFxuICogbW9kZSBydWxlcy4gVGhpcyBtb2R1bGUgcHJlc2VydmVzIEFwcEtpdCdzIGV4aXN0aW5nIG5hbWVzcGFjZSwgc3RyaW5nIFNTTFxuICogc3BlbGxpbmcsIHNwYXJzZSByZWNvcmRzLCBhbmQgbnVsbGFibGUgaW5wdXQgY29tcGF0aWJpbGl0eS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHtcbiAgcGFyc2VBZGRyZXNzIGFzIHBhcnNlTmF0aXZlQWRkcmVzcyxcbiAgcGFyc2VSZXNvdXJjZVBhdGggYXMgcGFyc2VOYXRpdmVSZXNvdXJjZVBhdGgsXG4gIFNzbE1vZGUgYXMgTmF0aXZlU3NsTW9kZSxcbiAgdHlwZSBQYXJzZWRBZGRyZXNzIGFzIE5hdGl2ZVBhcnNlZEFkZHJlc3MsXG59IGZyb20gXCJAZGJ4LXRvb2xzL2NvcmUtcnNcIjtcblxudHlwZSBOYXRpdmVTc2xNb2RlTmFtZSA9IEV4dHJhY3Q8a2V5b2YgdHlwZW9mIE5hdGl2ZVNzbE1vZGUsIHN0cmluZz47XG5cbi8qKiBQb3N0Z3JlU1FMIFRMUyBtb2RlIGluIGBQR1NTTE1PREVgIHNwZWxsaW5nLiAqL1xuZXhwb3J0IHR5cGUgU3NsTW9kZSA9IExvd2VyY2FzZTxOYXRpdmVTc2xNb2RlTmFtZT47XG5cbi8qKiBQb3N0Z3JlcyBUTFMgbW9kZXMgYWNjZXB0ZWQgYnkgdGhlIG5hdGl2ZSBwYXJzZXIsIGluIGBQR1NTTE1PREVgIHNwZWxsaW5nLiAqL1xuZXhwb3J0IGNvbnN0IFNTTF9NT0RFUzogcmVhZG9ubHkgU3NsTW9kZVtdID0gT2JqZWN0LmtleXMoTmF0aXZlU3NsTW9kZSlcbiAgLmZpbHRlcigobmFtZSk6IG5hbWUgaXMgTmF0aXZlU3NsTW9kZU5hbWUgPT4gTnVtYmVyLmlzTmFOKE51bWJlcihuYW1lKSkpXG4gIC5tYXAoKG5hbWUpID0+IG5hbWUudG9Mb3dlckNhc2UoKSBhcyBTc2xNb2RlKTtcblxuLyoqIE5hdGl2ZSBwYXJzZXIgb3V0cHV0IHdpdGggQXBwS2l0J3MgZXhpc3Rpbmcgc3RyaW5nIFNTTCBzcGVsbGluZy4gKi9cbmV4cG9ydCB0eXBlIFBhcnNlZEFkZHJlc3MgPSB7XG4gIFtLZXkgaW4ga2V5b2YgTmF0aXZlUGFyc2VkQWRkcmVzc106IEtleSBleHRlbmRzIFwic3NsTW9kZVwiXG4gICAgPyBTc2xNb2RlIHwgdW5kZWZpbmVkXG4gICAgOiBOYXRpdmVQYXJzZWRBZGRyZXNzW0tleV07XG59O1xuXG4vKiogSW5wdXRzIHNoYXJlZCBieSBwYXJzaW5nIGFuZCBMYWtlYmFzZSBjb25uZWN0aW9uIHJlc29sdXRpb24uICovXG5leHBvcnQgdHlwZSBMYWtlYmFzZUNvbm5lY3Rpb25JbnB1dHMgPSBQYXJzZWRBZGRyZXNzO1xuXG5mdW5jdGlvbiBzc2xNb2RlTmFtZShtb2RlOiBOYXRpdmVQYXJzZWRBZGRyZXNzW1wic3NsTW9kZVwiXSk6IFNzbE1vZGUgfCB1bmRlZmluZWQge1xuICByZXR1cm4gbW9kZSA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogKE5hdGl2ZVNzbE1vZGVbbW9kZV0udG9Mb3dlckNhc2UoKSBhcyBTc2xNb2RlKTtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplQWRkcmVzcyhhZGRyZXNzOiBOYXRpdmVQYXJzZWRBZGRyZXNzKTogUGFyc2VkQWRkcmVzcyB7XG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSB7IC4uLmFkZHJlc3MsIHNzbE1vZGU6IHNzbE1vZGVOYW1lKGFkZHJlc3Muc3NsTW9kZSkgfSBhcyBQYXJzZWRBZGRyZXNzO1xuICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhub3JtYWxpemVkKSBhcyAoa2V5b2YgUGFyc2VkQWRkcmVzcylbXSkge1xuICAgIGlmIChub3JtYWxpemVkW2tleV0gPT09IHVuZGVmaW5lZCkgZGVsZXRlIG5vcm1hbGl6ZWRba2V5XTtcbiAgfVxuICByZXR1cm4gbm9ybWFsaXplZDtcbn1cblxuLyoqXG4gKiBQYXJzZSBhIFBvc3RncmVTUUwgVVJMLCBMYWtlYmFzZSByZXNvdXJjZSBwYXRoLCBob3N0bmFtZSwgb3IgcHJvamVjdCBpZC5cbiAqIFJldHVybnMgYW4gZW1wdHkgcmVjb3JkIHdoZW4gdGhlIGlucHV0IGlzIGFic2VudCBvciB1bnJlY29nbml6ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUFkZHJlc3MoaW5wdXQ6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBQYXJzZWRBZGRyZXNzIHtcbiAgcmV0dXJuIG5vcm1hbGl6ZUFkZHJlc3MocGFyc2VOYXRpdmVBZGRyZXNzKGlucHV0ID8/IHVuZGVmaW5lZCkpO1xufVxuXG4vKiogUGFyc2UgYSBjYW5vbmljYWwgTGFrZWJhc2UgYHByb2plY3RzLy4uLmAgcmVzb3VyY2UgcGF0aC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVJlc291cmNlUGF0aChpbnB1dDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IFBhcnNlZEFkZHJlc3Mge1xuICByZXR1cm4gbm9ybWFsaXplQWRkcmVzcyhwYXJzZU5hdGl2ZVJlc291cmNlUGF0aChpbnB1dCA/PyB1bmRlZmluZWQpKTtcbn1cblxuLyoqIE5vcm1hbGl6ZSBhIFBvc3RncmVTUUwgVExTIG1vZGUgdGhyb3VnaCB0aGUgbmF0aXZlIGFkZHJlc3MgcGFyc2VyLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlU3NsTW9kZShpbnB1dDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IFNzbE1vZGUgfCB1bmRlZmluZWQge1xuICBpZiAoaW5wdXQgPT09IHVuZGVmaW5lZCB8fCBpbnB1dCA9PT0gbnVsbCB8fCBpbnB1dC50cmltKCkgPT09IFwiXCIpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IHF1ZXJ5ID0gZW5jb2RlVVJJQ29tcG9uZW50KGlucHV0LnRyaW0oKSk7XG4gIHJldHVybiBzc2xNb2RlTmFtZShwYXJzZU5hdGl2ZUFkZHJlc3MoYHBvc3RncmVzcWw6Ly9sb2NhbGhvc3Q/c3NsbW9kZT0ke3F1ZXJ5fWApLnNzbE1vZGUpO1xufVxuIl19
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** AppKit-specific adapters over the shared intercepted-execution contract. */
|
|
2
|
+
import { execution, type Logger } from "@dbx-tools/shared-core";
|
|
3
|
+
/** Inputs for one plugin operation routed through AppKit interceptors. */
|
|
4
|
+
export interface RunPluginExecutionOptions<T, Settings> {
|
|
5
|
+
readonly plugin: string;
|
|
6
|
+
readonly logger: Pick<Logger, "warn">;
|
|
7
|
+
readonly operation: string;
|
|
8
|
+
readonly settings: Settings;
|
|
9
|
+
readonly execute: execution.Executor<Settings>;
|
|
10
|
+
readonly fn: (signal?: AbortSignal) => Promise<T>;
|
|
11
|
+
readonly signal?: AbortSignal;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Run and unwrap one AppKit plugin operation with the shared stable failure
|
|
15
|
+
* message, structured warning, status context, and cancellation behavior.
|
|
16
|
+
*/
|
|
17
|
+
export declare function runPluginExecution<T, Settings>(options: RunPluginExecutionOptions<T, Settings>): Promise<T>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** AppKit-specific adapters over the shared intercepted-execution contract. */
|
|
2
|
+
import { ExecutionError } from "@databricks/appkit";
|
|
3
|
+
import { execution } from "@dbx-tools/shared-core";
|
|
4
|
+
/**
|
|
5
|
+
* Run and unwrap one AppKit plugin operation with the shared stable failure
|
|
6
|
+
* message, structured warning, status context, and cancellation behavior.
|
|
7
|
+
*/
|
|
8
|
+
export function runPluginExecution(options) {
|
|
9
|
+
return execution.run({
|
|
10
|
+
operation: options.operation,
|
|
11
|
+
settings: options.settings,
|
|
12
|
+
execute: options.execute,
|
|
13
|
+
fn: options.fn,
|
|
14
|
+
signal: options.signal,
|
|
15
|
+
canceled: ExecutionError.canceled,
|
|
16
|
+
failed: (failure) => {
|
|
17
|
+
options.logger.warn("execution-failed", {
|
|
18
|
+
operation: failure.operation,
|
|
19
|
+
status: failure.status,
|
|
20
|
+
error: failure.message,
|
|
21
|
+
});
|
|
22
|
+
return new ExecutionError(`${options.plugin}: ${failure.operation} failed`, {
|
|
23
|
+
context: { operation: failure.operation, status: failure.status },
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWV4ZWN1dGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wbHVnaW4tZXhlY3V0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtFQUErRTtBQUUvRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDcEQsT0FBTyxFQUFFLFNBQVMsRUFBZSxNQUFNLHdCQUF3QixDQUFDO0FBYWhFOzs7R0FHRztBQUNILE1BQU0sVUFBVSxrQkFBa0IsQ0FDaEMsT0FBK0M7SUFFL0MsT0FBTyxTQUFTLENBQUMsR0FBRyxDQUFDO1FBQ25CLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztRQUM1QixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7UUFDMUIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPO1FBQ3hCLEVBQUUsRUFBRSxPQUFPLENBQUMsRUFBRTtRQUNkLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTtRQUN0QixRQUFRLEVBQUUsY0FBYyxDQUFDLFFBQVE7UUFDakMsTUFBTSxFQUFFLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDbEIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUU7Z0JBQ3RDLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztnQkFDNUIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO2dCQUN0QixLQUFLLEVBQUUsT0FBTyxDQUFDLE9BQU87YUFDdkIsQ0FBQyxDQUFDO1lBQ0gsT0FBTyxJQUFJLGNBQWMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEtBQUssT0FBTyxDQUFDLFNBQVMsU0FBUyxFQUFFO2dCQUMxRSxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU0sRUFBRTthQUNsRSxDQUFDLENBQUM7UUFDTCxDQUFDO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBBcHBLaXQtc3BlY2lmaWMgYWRhcHRlcnMgb3ZlciB0aGUgc2hhcmVkIGludGVyY2VwdGVkLWV4ZWN1dGlvbiBjb250cmFjdC4gKi9cblxuaW1wb3J0IHsgRXhlY3V0aW9uRXJyb3IgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBleGVjdXRpb24sIHR5cGUgTG9nZ2VyIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcblxuLyoqIElucHV0cyBmb3Igb25lIHBsdWdpbiBvcGVyYXRpb24gcm91dGVkIHRocm91Z2ggQXBwS2l0IGludGVyY2VwdG9ycy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUnVuUGx1Z2luRXhlY3V0aW9uT3B0aW9uczxULCBTZXR0aW5ncz4ge1xuICByZWFkb25seSBwbHVnaW46IHN0cmluZztcbiAgcmVhZG9ubHkgbG9nZ2VyOiBQaWNrPExvZ2dlciwgXCJ3YXJuXCI+O1xuICByZWFkb25seSBvcGVyYXRpb246IHN0cmluZztcbiAgcmVhZG9ubHkgc2V0dGluZ3M6IFNldHRpbmdzO1xuICByZWFkb25seSBleGVjdXRlOiBleGVjdXRpb24uRXhlY3V0b3I8U2V0dGluZ3M+O1xuICByZWFkb25seSBmbjogKHNpZ25hbD86IEFib3J0U2lnbmFsKSA9PiBQcm9taXNlPFQ+O1xuICByZWFkb25seSBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbn1cblxuLyoqXG4gKiBSdW4gYW5kIHVud3JhcCBvbmUgQXBwS2l0IHBsdWdpbiBvcGVyYXRpb24gd2l0aCB0aGUgc2hhcmVkIHN0YWJsZSBmYWlsdXJlXG4gKiBtZXNzYWdlLCBzdHJ1Y3R1cmVkIHdhcm5pbmcsIHN0YXR1cyBjb250ZXh0LCBhbmQgY2FuY2VsbGF0aW9uIGJlaGF2aW9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuUGx1Z2luRXhlY3V0aW9uPFQsIFNldHRpbmdzPihcbiAgb3B0aW9uczogUnVuUGx1Z2luRXhlY3V0aW9uT3B0aW9uczxULCBTZXR0aW5ncz4sXG4pOiBQcm9taXNlPFQ+IHtcbiAgcmV0dXJuIGV4ZWN1dGlvbi5ydW4oe1xuICAgIG9wZXJhdGlvbjogb3B0aW9ucy5vcGVyYXRpb24sXG4gICAgc2V0dGluZ3M6IG9wdGlvbnMuc2V0dGluZ3MsXG4gICAgZXhlY3V0ZTogb3B0aW9ucy5leGVjdXRlLFxuICAgIGZuOiBvcHRpb25zLmZuLFxuICAgIHNpZ25hbDogb3B0aW9ucy5zaWduYWwsXG4gICAgY2FuY2VsZWQ6IEV4ZWN1dGlvbkVycm9yLmNhbmNlbGVkLFxuICAgIGZhaWxlZDogKGZhaWx1cmUpID0+IHtcbiAgICAgIG9wdGlvbnMubG9nZ2VyLndhcm4oXCJleGVjdXRpb24tZmFpbGVkXCIsIHtcbiAgICAgICAgb3BlcmF0aW9uOiBmYWlsdXJlLm9wZXJhdGlvbixcbiAgICAgICAgc3RhdHVzOiBmYWlsdXJlLnN0YXR1cyxcbiAgICAgICAgZXJyb3I6IGZhaWx1cmUubWVzc2FnZSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5ldyBFeGVjdXRpb25FcnJvcihgJHtvcHRpb25zLnBsdWdpbn06ICR7ZmFpbHVyZS5vcGVyYXRpb259IGZhaWxlZGAsIHtcbiAgICAgICAgY29udGV4dDogeyBvcGVyYXRpb246IGZhaWx1cmUub3BlcmF0aW9uLCBzdGF0dXM6IGZhaWx1cmUuc3RhdHVzIH0sXG4gICAgICB9KTtcbiAgICB9LFxuICB9KTtcbn1cbiJdfQ==
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
* @module
|
|
21
21
|
*/
|
|
22
|
+
import { type ToPlugin } from "@databricks/appkit";
|
|
22
23
|
import { type NameLike } from "@dbx-tools/shared-core";
|
|
23
24
|
/**
|
|
24
25
|
* Minimal structural shape of `this.context`. We mirror only the method we
|
|
@@ -29,22 +30,17 @@ import { type NameLike } from "@dbx-tools/shared-core";
|
|
|
29
30
|
export interface PluginContextLike {
|
|
30
31
|
getPlugins(): ReadonlyMap<string, unknown>;
|
|
31
32
|
}
|
|
32
|
-
type PluginData = {
|
|
33
|
-
plugin: abstract new (...args: never[]) => unknown;
|
|
34
|
-
name: string;
|
|
35
|
-
};
|
|
36
33
|
/**
|
|
37
34
|
* Structural shape of an AppKit plugin factory (the result of
|
|
38
35
|
* `toPlugin(SomePluginClass)`). Calling it returns a `PluginData` tuple whose
|
|
39
36
|
* `plugin` field is the *class constructor* and whose `name` field carries the
|
|
40
37
|
* registered plugin name as a literal string.
|
|
41
38
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* `lakebase`, `serving`, `genie`, or a user-defined `toPlugin(MyPlugin)`)
|
|
45
|
-
* satisfies it.
|
|
39
|
+
* Uses AppKit's public factory contract so changes to the upstream descriptor
|
|
40
|
+
* remain visible here.
|
|
46
41
|
*/
|
|
47
|
-
type
|
|
42
|
+
type PluginConstructor = abstract new (...args: never[]) => unknown;
|
|
43
|
+
type PluginDataFactory = ToPlugin<PluginConstructor, any, string>;
|
|
48
44
|
/**
|
|
49
45
|
* Maps a plugin factory back to the *instance* type of its plugin class.
|
|
50
46
|
* Mirrors the inline pattern users would otherwise write:
|
|
@@ -65,9 +61,9 @@ export declare function data<F extends PluginDataFactory, D extends ReturnType<F
|
|
|
65
61
|
*
|
|
66
62
|
* @example
|
|
67
63
|
* import { lakebase } from "@databricks/appkit";
|
|
68
|
-
* import {
|
|
64
|
+
* import { pluginRegistry } from "@dbx-tools/appkit";
|
|
69
65
|
*
|
|
70
|
-
* const lake =
|
|
66
|
+
* const lake = pluginRegistry.instance(this.context, lakebase);
|
|
71
67
|
* // ^^ inferred as LakebasePlugin | undefined
|
|
72
68
|
* lake?.exports().pool;
|
|
73
69
|
*/
|
|
@@ -82,9 +78,9 @@ export declare function instance<F extends PluginDataFactory>(ctx: PluginContext
|
|
|
82
78
|
*
|
|
83
79
|
* @example
|
|
84
80
|
* import { lakebase } from "@databricks/appkit";
|
|
85
|
-
* import {
|
|
81
|
+
* import { pluginRegistry } from "@dbx-tools/appkit";
|
|
86
82
|
*
|
|
87
|
-
* const pool =
|
|
83
|
+
* const pool = pluginRegistry.require(this.context, lakebase, "mastra").exports().pool;
|
|
88
84
|
*/
|
|
89
85
|
export declare function require<F extends PluginDataFactory>(ctx: PluginContextLike | undefined, factory: F, caller?: NameLike | string): PluginInstanceOf<F>;
|
|
90
86
|
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppKit plugin lookup: typed access to sibling plugins registered on the
|
|
3
|
+
* AppKit plugin context (`this.context` on any class that extends `Plugin`).
|
|
4
|
+
*
|
|
5
|
+
* Why these live here instead of in `@databricks/appkit`: AppKit exposes
|
|
6
|
+
* `this.context.getPlugins()`, which returns `ReadonlyMap<string, BasePlugin>`,
|
|
7
|
+
* but provides no typed lookup helper. Every caller ends up writing the same
|
|
8
|
+
* `as InstanceType<ReturnType<typeof someFactory>["plugin"]>` cast. These
|
|
9
|
+
* wrappers absorb that boilerplate.
|
|
10
|
+
*
|
|
11
|
+
* API shape: pass the plugin's factory (`lakebase`, `serving`, `genie`, or any
|
|
12
|
+
* `toPlugin(...)` result) directly. TypeScript infers both the instance type
|
|
13
|
+
* (so `.exports()` resolves) and the registered name (so the runtime lookup
|
|
14
|
+
* works) from that single value. No `<T>` annotation or string literal needed
|
|
15
|
+
* at the call site.
|
|
16
|
+
*
|
|
17
|
+
* Generic AppKit runtime (execution context, `WorkspaceClientLike`) lives in
|
|
18
|
+
* `./appkit`; this module is plugin-lookup only.
|
|
19
|
+
*
|
|
20
|
+
* @module
|
|
21
|
+
*/
|
|
22
|
+
import { ConfigurationError } from "@databricks/appkit";
|
|
23
|
+
import { log } from "@dbx-tools/shared-core";
|
|
24
|
+
const logger = log.logger("plugin");
|
|
25
|
+
/**
|
|
26
|
+
* Registry name returned by `factory().name`, keyed by the factory function.
|
|
27
|
+
* Typical AppKit factories return stable metadata; caching avoids invoking
|
|
28
|
+
* `factory()` on every sibling lookup (which would allocate a fresh descriptor
|
|
29
|
+
* tuple each time).
|
|
30
|
+
*/
|
|
31
|
+
const dataCache = new WeakMap();
|
|
32
|
+
/**
|
|
33
|
+
* Returns the static `{ plugin, name }` descriptor for an AppKit plugin
|
|
34
|
+
* factory, caching per factory so repeated lookups do not allocate.
|
|
35
|
+
*/
|
|
36
|
+
export function data(factory) {
|
|
37
|
+
const cached = dataCache.get(factory);
|
|
38
|
+
// The cache is keyed by the erased `PluginDataFactory` bound, so `WeakMap`
|
|
39
|
+
// hands back the widened descriptor; only the caller's `F` knows the exact
|
|
40
|
+
// descriptor type.
|
|
41
|
+
if (cached !== undefined) {
|
|
42
|
+
return cached;
|
|
43
|
+
}
|
|
44
|
+
const result = factory();
|
|
45
|
+
dataCache.set(factory, result);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Look up a sibling plugin instance from the AppKit plugin context, keyed off
|
|
50
|
+
* the factory's registered name and typed via its plugin class.
|
|
51
|
+
*
|
|
52
|
+
* Returns `undefined` when the context is missing or the plugin is not
|
|
53
|
+
* registered. For required siblings prefer {@link require}.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* import { lakebase } from "@databricks/appkit";
|
|
57
|
+
* import { pluginRegistry } from "@dbx-tools/appkit";
|
|
58
|
+
*
|
|
59
|
+
* const lake = pluginRegistry.instance(this.context, lakebase);
|
|
60
|
+
* // ^^ inferred as LakebasePlugin | undefined
|
|
61
|
+
* lake?.exports().pool;
|
|
62
|
+
*/
|
|
63
|
+
export function instance(ctx, factory) {
|
|
64
|
+
if (!ctx)
|
|
65
|
+
return undefined;
|
|
66
|
+
const name = data(factory).name;
|
|
67
|
+
// AppKit's registry is a `Map<string, unknown>`, so the instance type is only
|
|
68
|
+
// recoverable from the factory the caller passed.
|
|
69
|
+
return ctx.getPlugins().get(name);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Like {@link instance} but throws when the plugin is not registered. Use for
|
|
73
|
+
* siblings whose absence is a wiring bug rather than a runtime condition (e.g.
|
|
74
|
+
* requiring `lakebase` when the caller has `storage` / `memory` enabled).
|
|
75
|
+
*
|
|
76
|
+
* `caller` is prepended to the error message so cross-plugin failures are easy
|
|
77
|
+
* to attribute in logs.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* import { lakebase } from "@databricks/appkit";
|
|
81
|
+
* import { pluginRegistry } from "@dbx-tools/appkit";
|
|
82
|
+
*
|
|
83
|
+
* const pool = pluginRegistry.require(this.context, lakebase, "mastra").exports().pool;
|
|
84
|
+
*/
|
|
85
|
+
export function require(ctx, factory, caller) {
|
|
86
|
+
const found = instance(ctx, factory);
|
|
87
|
+
if (found)
|
|
88
|
+
return found;
|
|
89
|
+
const prefix = typeof caller === "string" ? `${caller}: ` : caller?.name ? `${caller.name}: ` : "";
|
|
90
|
+
const registeredName = data(factory).name;
|
|
91
|
+
logger.debug("required plugin not registered", {
|
|
92
|
+
plugin: registeredName,
|
|
93
|
+
registered: [...(ctx?.getPlugins().keys() ?? [])],
|
|
94
|
+
});
|
|
95
|
+
throw ConfigurationError.resourceNotFound(`${prefix}plugin '${registeredName}'`, `Add ${registeredName}() to the plugins passed to createApp.`);
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLXJlZ2lzdHJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BsdWdpbi1yZWdpc3RyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFFSCxPQUFPLEVBQUUsa0JBQWtCLEVBQWtDLE1BQU0sb0JBQW9CLENBQUM7QUFDeEYsT0FBTyxFQUFFLEdBQUcsRUFBaUIsTUFBTSx3QkFBd0IsQ0FBQztBQUU1RCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBa0NwQzs7Ozs7R0FLRztBQUNILE1BQU0sU0FBUyxHQUFHLElBQUksT0FBTyxFQUF1QyxDQUFDO0FBRXJFOzs7R0FHRztBQUNILE1BQU0sVUFBVSxJQUFJLENBQXVELE9BQVU7SUFDbkYsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN0QywyRUFBMkU7SUFDM0UsMkVBQTJFO0lBQzNFLG1CQUFtQjtJQUNuQixJQUFJLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUN6QixPQUFPLE1BQVcsQ0FBQztJQUNyQixDQUFDO0lBQ0QsTUFBTSxNQUFNLEdBQUcsT0FBTyxFQUFFLENBQUM7SUFDekIsU0FBUyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDL0IsT0FBTyxNQUFXLENBQUM7QUFDckIsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FDdEIsR0FBa0MsRUFDbEMsT0FBVTtJQUVWLElBQUksQ0FBQyxHQUFHO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDM0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNoQyw4RUFBOEU7SUFDOUUsa0RBQWtEO0lBQ2xELE9BQU8sR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQW9DLENBQUM7QUFDdkUsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLFVBQVUsT0FBTyxDQUNyQixHQUFrQyxFQUNsQyxPQUFVLEVBQ1YsTUFBMEI7SUFFMUIsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNyQyxJQUFJLEtBQUs7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUN4QixNQUFNLE1BQU0sR0FDVixPQUFPLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDdEYsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQztJQUMxQyxNQUFNLENBQUMsS0FBSyxDQUFDLGdDQUFnQyxFQUFFO1FBQzdDLE1BQU0sRUFBRSxjQUFjO1FBQ3RCLFVBQVUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxFQUFFLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7S0FDbEQsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxrQkFBa0IsQ0FBQyxnQkFBZ0IsQ0FDdkMsR0FBRyxNQUFNLFdBQVcsY0FBYyxHQUFHLEVBQ3JDLE9BQU8sY0FBYyx3Q0FBd0MsQ0FDOUQsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEFwcEtpdCBwbHVnaW4gbG9va3VwOiB0eXBlZCBhY2Nlc3MgdG8gc2libGluZyBwbHVnaW5zIHJlZ2lzdGVyZWQgb24gdGhlXG4gKiBBcHBLaXQgcGx1Z2luIGNvbnRleHQgKGB0aGlzLmNvbnRleHRgIG9uIGFueSBjbGFzcyB0aGF0IGV4dGVuZHMgYFBsdWdpbmApLlxuICpcbiAqIFdoeSB0aGVzZSBsaXZlIGhlcmUgaW5zdGVhZCBvZiBpbiBgQGRhdGFicmlja3MvYXBwa2l0YDogQXBwS2l0IGV4cG9zZXNcbiAqIGB0aGlzLmNvbnRleHQuZ2V0UGx1Z2lucygpYCwgd2hpY2ggcmV0dXJucyBgUmVhZG9ubHlNYXA8c3RyaW5nLCBCYXNlUGx1Z2luPmAsXG4gKiBidXQgcHJvdmlkZXMgbm8gdHlwZWQgbG9va3VwIGhlbHBlci4gRXZlcnkgY2FsbGVyIGVuZHMgdXAgd3JpdGluZyB0aGUgc2FtZVxuICogYGFzIEluc3RhbmNlVHlwZTxSZXR1cm5UeXBlPHR5cGVvZiBzb21lRmFjdG9yeT5bXCJwbHVnaW5cIl0+YCBjYXN0LiBUaGVzZVxuICogd3JhcHBlcnMgYWJzb3JiIHRoYXQgYm9pbGVycGxhdGUuXG4gKlxuICogQVBJIHNoYXBlOiBwYXNzIHRoZSBwbHVnaW4ncyBmYWN0b3J5IChgbGFrZWJhc2VgLCBgc2VydmluZ2AsIGBnZW5pZWAsIG9yIGFueVxuICogYHRvUGx1Z2luKC4uLilgIHJlc3VsdCkgZGlyZWN0bHkuIFR5cGVTY3JpcHQgaW5mZXJzIGJvdGggdGhlIGluc3RhbmNlIHR5cGVcbiAqIChzbyBgLmV4cG9ydHMoKWAgcmVzb2x2ZXMpIGFuZCB0aGUgcmVnaXN0ZXJlZCBuYW1lIChzbyB0aGUgcnVudGltZSBsb29rdXBcbiAqIHdvcmtzKSBmcm9tIHRoYXQgc2luZ2xlIHZhbHVlLiBObyBgPFQ+YCBhbm5vdGF0aW9uIG9yIHN0cmluZyBsaXRlcmFsIG5lZWRlZFxuICogYXQgdGhlIGNhbGwgc2l0ZS5cbiAqXG4gKiBHZW5lcmljIEFwcEtpdCBydW50aW1lIChleGVjdXRpb24gY29udGV4dCwgYFdvcmtzcGFjZUNsaWVudExpa2VgKSBsaXZlcyBpblxuICogYC4vYXBwa2l0YDsgdGhpcyBtb2R1bGUgaXMgcGx1Z2luLWxvb2t1cCBvbmx5LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBDb25maWd1cmF0aW9uRXJyb3IsIHR5cGUgUGx1Z2luRGF0YSwgdHlwZSBUb1BsdWdpbiB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGxvZywgdHlwZSBOYW1lTGlrZSB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJwbHVnaW5cIik7XG5cbi8qKlxuICogTWluaW1hbCBzdHJ1Y3R1cmFsIHNoYXBlIG9mIGB0aGlzLmNvbnRleHRgLiBXZSBtaXJyb3Igb25seSB0aGUgbWV0aG9kIHdlXG4gKiB0b3VjaCBpbnN0ZWFkIG9mIGRlcGVuZGluZyBvbiBBcHBLaXQncyBgUGx1Z2luQ29udGV4dGAgdHlwZSwgd2hpY2ggaXMgbm90XG4gKiBwYXJ0IG9mIHRoZSBwYWNrYWdlJ3MgYGV4cG9ydHNgIG1hcCBhbmQgdGhlcmVmb3JlIGNhbm5vdCBiZSBpbXBvcnRlZC4gQW55XG4gKiBjb21wYXRpYmxlIG9iamVjdCAocmVhbCBgUGx1Z2luQ29udGV4dGAsIG1vY2tzLCB0ZXN0cykgc2F0aXNmaWVzIHRoaXMgc2hhcGUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGx1Z2luQ29udGV4dExpa2Uge1xuICBnZXRQbHVnaW5zKCk6IFJlYWRvbmx5TWFwPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8qKlxuICogU3RydWN0dXJhbCBzaGFwZSBvZiBhbiBBcHBLaXQgcGx1Z2luIGZhY3RvcnkgKHRoZSByZXN1bHQgb2ZcbiAqIGB0b1BsdWdpbihTb21lUGx1Z2luQ2xhc3MpYCkuIENhbGxpbmcgaXQgcmV0dXJucyBhIGBQbHVnaW5EYXRhYCB0dXBsZSB3aG9zZVxuICogYHBsdWdpbmAgZmllbGQgaXMgdGhlICpjbGFzcyBjb25zdHJ1Y3RvciogYW5kIHdob3NlIGBuYW1lYCBmaWVsZCBjYXJyaWVzIHRoZVxuICogcmVnaXN0ZXJlZCBwbHVnaW4gbmFtZSBhcyBhIGxpdGVyYWwgc3RyaW5nLlxuICpcbiAqIFVzZXMgQXBwS2l0J3MgcHVibGljIGZhY3RvcnkgY29udHJhY3Qgc28gY2hhbmdlcyB0byB0aGUgdXBzdHJlYW0gZGVzY3JpcHRvclxuICogcmVtYWluIHZpc2libGUgaGVyZS5cbiAqL1xudHlwZSBQbHVnaW5Db25zdHJ1Y3RvciA9IGFic3RyYWN0IG5ldyAoLi4uYXJnczogbmV2ZXJbXSkgPT4gdW5rbm93bjtcbi8vIGBhbnlgIGRlbGliZXJhdGVseSBlcmFzZXMgdGhlIGZhY3Rvcnktc3BlY2lmaWMgY29uZmlnIHdoaWxlIEFwcEtpdCdzIHB1YmxpY1xuLy8gYFRvUGx1Z2luYCBhbmQgYFBsdWdpbkRhdGFgIHN0aWxsIG93biB0aGUgZGVzY3JpcHRvciBzaGFwZS5cbnR5cGUgUGx1Z2luRGF0YUZhY3RvcnkgPSBUb1BsdWdpbjxQbHVnaW5Db25zdHJ1Y3RvciwgYW55LCBzdHJpbmc+O1xudHlwZSBFcmFzZWRQbHVnaW5EYXRhID0gUGx1Z2luRGF0YTxQbHVnaW5Db25zdHJ1Y3RvciwgYW55LCBzdHJpbmc+O1xuXG4vKipcbiAqIE1hcHMgYSBwbHVnaW4gZmFjdG9yeSBiYWNrIHRvIHRoZSAqaW5zdGFuY2UqIHR5cGUgb2YgaXRzIHBsdWdpbiBjbGFzcy5cbiAqIE1pcnJvcnMgdGhlIGlubGluZSBwYXR0ZXJuIHVzZXJzIHdvdWxkIG90aGVyd2lzZSB3cml0ZTpcbiAqIGBJbnN0YW5jZVR5cGU8UmV0dXJuVHlwZTx0eXBlb2YgZmFjdG9yeT5bXCJwbHVnaW5cIl0+YC5cbiAqL1xudHlwZSBQbHVnaW5JbnN0YW5jZU9mPEYgZXh0ZW5kcyBQbHVnaW5EYXRhRmFjdG9yeT4gPSBJbnN0YW5jZVR5cGU8UmV0dXJuVHlwZTxGPltcInBsdWdpblwiXT47XG5cbi8qKlxuICogUmVnaXN0cnkgbmFtZSByZXR1cm5lZCBieSBgZmFjdG9yeSgpLm5hbWVgLCBrZXllZCBieSB0aGUgZmFjdG9yeSBmdW5jdGlvbi5cbiAqIFR5cGljYWwgQXBwS2l0IGZhY3RvcmllcyByZXR1cm4gc3RhYmxlIG1ldGFkYXRhOyBjYWNoaW5nIGF2b2lkcyBpbnZva2luZ1xuICogYGZhY3RvcnkoKWAgb24gZXZlcnkgc2libGluZyBsb29rdXAgKHdoaWNoIHdvdWxkIGFsbG9jYXRlIGEgZnJlc2ggZGVzY3JpcHRvclxuICogdHVwbGUgZWFjaCB0aW1lKS5cbiAqL1xuY29uc3QgZGF0YUNhY2hlID0gbmV3IFdlYWtNYXA8UGx1Z2luRGF0YUZhY3RvcnksIEVyYXNlZFBsdWdpbkRhdGE+KCk7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc3RhdGljIGB7IHBsdWdpbiwgbmFtZSB9YCBkZXNjcmlwdG9yIGZvciBhbiBBcHBLaXQgcGx1Z2luXG4gKiBmYWN0b3J5LCBjYWNoaW5nIHBlciBmYWN0b3J5IHNvIHJlcGVhdGVkIGxvb2t1cHMgZG8gbm90IGFsbG9jYXRlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGF0YTxGIGV4dGVuZHMgUGx1Z2luRGF0YUZhY3RvcnksIEQgZXh0ZW5kcyBSZXR1cm5UeXBlPEY+PihmYWN0b3J5OiBGKTogRCB7XG4gIGNvbnN0IGNhY2hlZCA9IGRhdGFDYWNoZS5nZXQoZmFjdG9yeSk7XG4gIC8vIFRoZSBjYWNoZSBpcyBrZXllZCBieSB0aGUgZXJhc2VkIGBQbHVnaW5EYXRhRmFjdG9yeWAgYm91bmQsIHNvIGBXZWFrTWFwYFxuICAvLyBoYW5kcyBiYWNrIHRoZSB3aWRlbmVkIGRlc2NyaXB0b3I7IG9ubHkgdGhlIGNhbGxlcidzIGBGYCBrbm93cyB0aGUgZXhhY3RcbiAgLy8gZGVzY3JpcHRvciB0eXBlLlxuICBpZiAoY2FjaGVkICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gY2FjaGVkIGFzIEQ7XG4gIH1cbiAgY29uc3QgcmVzdWx0ID0gZmFjdG9yeSgpO1xuICBkYXRhQ2FjaGUuc2V0KGZhY3RvcnksIHJlc3VsdCk7XG4gIHJldHVybiByZXN1bHQgYXMgRDtcbn1cblxuLyoqXG4gKiBMb29rIHVwIGEgc2libGluZyBwbHVnaW4gaW5zdGFuY2UgZnJvbSB0aGUgQXBwS2l0IHBsdWdpbiBjb250ZXh0LCBrZXllZCBvZmZcbiAqIHRoZSBmYWN0b3J5J3MgcmVnaXN0ZXJlZCBuYW1lIGFuZCB0eXBlZCB2aWEgaXRzIHBsdWdpbiBjbGFzcy5cbiAqXG4gKiBSZXR1cm5zIGB1bmRlZmluZWRgIHdoZW4gdGhlIGNvbnRleHQgaXMgbWlzc2luZyBvciB0aGUgcGx1Z2luIGlzIG5vdFxuICogcmVnaXN0ZXJlZC4gRm9yIHJlcXVpcmVkIHNpYmxpbmdzIHByZWZlciB7QGxpbmsgcmVxdWlyZX0uXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCB7IGxha2ViYXNlIH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuICogaW1wb3J0IHsgcGx1Z2luUmVnaXN0cnkgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbiAqXG4gKiBjb25zdCBsYWtlID0gcGx1Z2luUmVnaXN0cnkuaW5zdGFuY2UodGhpcy5jb250ZXh0LCBsYWtlYmFzZSk7XG4gKiAvLyAgICBeXiBpbmZlcnJlZCBhcyBMYWtlYmFzZVBsdWdpbiB8IHVuZGVmaW5lZFxuICogbGFrZT8uZXhwb3J0cygpLnBvb2w7XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnN0YW5jZTxGIGV4dGVuZHMgUGx1Z2luRGF0YUZhY3Rvcnk+KFxuICBjdHg6IFBsdWdpbkNvbnRleHRMaWtlIHwgdW5kZWZpbmVkLFxuICBmYWN0b3J5OiBGLFxuKTogUGx1Z2luSW5zdGFuY2VPZjxGPiB8IHVuZGVmaW5lZCB7XG4gIGlmICghY3R4KSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCBuYW1lID0gZGF0YShmYWN0b3J5KS5uYW1lO1xuICAvLyBBcHBLaXQncyByZWdpc3RyeSBpcyBhIGBNYXA8c3RyaW5nLCB1bmtub3duPmAsIHNvIHRoZSBpbnN0YW5jZSB0eXBlIGlzIG9ubHlcbiAgLy8gcmVjb3ZlcmFibGUgZnJvbSB0aGUgZmFjdG9yeSB0aGUgY2FsbGVyIHBhc3NlZC5cbiAgcmV0dXJuIGN0eC5nZXRQbHVnaW5zKCkuZ2V0KG5hbWUpIGFzIFBsdWdpbkluc3RhbmNlT2Y8Rj4gfCB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogTGlrZSB7QGxpbmsgaW5zdGFuY2V9IGJ1dCB0aHJvd3Mgd2hlbiB0aGUgcGx1Z2luIGlzIG5vdCByZWdpc3RlcmVkLiBVc2UgZm9yXG4gKiBzaWJsaW5ncyB3aG9zZSBhYnNlbmNlIGlzIGEgd2lyaW5nIGJ1ZyByYXRoZXIgdGhhbiBhIHJ1bnRpbWUgY29uZGl0aW9uIChlLmcuXG4gKiByZXF1aXJpbmcgYGxha2ViYXNlYCB3aGVuIHRoZSBjYWxsZXIgaGFzIGBzdG9yYWdlYCAvIGBtZW1vcnlgIGVuYWJsZWQpLlxuICpcbiAqIGBjYWxsZXJgIGlzIHByZXBlbmRlZCB0byB0aGUgZXJyb3IgbWVzc2FnZSBzbyBjcm9zcy1wbHVnaW4gZmFpbHVyZXMgYXJlIGVhc3lcbiAqIHRvIGF0dHJpYnV0ZSBpbiBsb2dzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgeyBsYWtlYmFzZSB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbiAqIGltcG9ydCB7IHBsdWdpblJlZ2lzdHJ5IH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG4gKlxuICogY29uc3QgcG9vbCA9IHBsdWdpblJlZ2lzdHJ5LnJlcXVpcmUodGhpcy5jb250ZXh0LCBsYWtlYmFzZSwgXCJtYXN0cmFcIikuZXhwb3J0cygpLnBvb2w7XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXF1aXJlPEYgZXh0ZW5kcyBQbHVnaW5EYXRhRmFjdG9yeT4oXG4gIGN0eDogUGx1Z2luQ29udGV4dExpa2UgfCB1bmRlZmluZWQsXG4gIGZhY3Rvcnk6IEYsXG4gIGNhbGxlcj86IE5hbWVMaWtlIHwgc3RyaW5nLFxuKTogUGx1Z2luSW5zdGFuY2VPZjxGPiB7XG4gIGNvbnN0IGZvdW5kID0gaW5zdGFuY2UoY3R4LCBmYWN0b3J5KTtcbiAgaWYgKGZvdW5kKSByZXR1cm4gZm91bmQ7XG4gIGNvbnN0IHByZWZpeCA9XG4gICAgdHlwZW9mIGNhbGxlciA9PT0gXCJzdHJpbmdcIiA/IGAke2NhbGxlcn06IGAgOiBjYWxsZXI/Lm5hbWUgPyBgJHtjYWxsZXIubmFtZX06IGAgOiBcIlwiO1xuICBjb25zdCByZWdpc3RlcmVkTmFtZSA9IGRhdGEoZmFjdG9yeSkubmFtZTtcbiAgbG9nZ2VyLmRlYnVnKFwicmVxdWlyZWQgcGx1Z2luIG5vdCByZWdpc3RlcmVkXCIsIHtcbiAgICBwbHVnaW46IHJlZ2lzdGVyZWROYW1lLFxuICAgIHJlZ2lzdGVyZWQ6IFsuLi4oY3R4Py5nZXRQbHVnaW5zKCkua2V5cygpID8/IFtdKV0sXG4gIH0pO1xuICB0aHJvdyBDb25maWd1cmF0aW9uRXJyb3IucmVzb3VyY2VOb3RGb3VuZChcbiAgICBgJHtwcmVmaXh9cGx1Z2luICcke3JlZ2lzdGVyZWROYW1lfSdgLFxuICAgIGBBZGQgJHtyZWdpc3RlcmVkTmFtZX0oKSB0byB0aGUgcGx1Z2lucyBwYXNzZWQgdG8gY3JlYXRlQXBwLmAsXG4gICk7XG59XG4iXX0=
|