@dbx-tools/search 0.6.107 → 0.6.111

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,73 @@
1
+ /**
2
+ * AppKit-compatible AI Search provider backed by Lakebase full-text search.
3
+ *
4
+ * @module
5
+ */
6
+ import { Plugin, type BasePluginConfig, type IAppRouter } from "@databricks/appkit";
7
+ import type { IndexConfig, SearchRequest, SearchResponse } from "@databricks/appkit/beta";
8
+ import type { SearchDocument } from "@dbx-tools/shared-search";
9
+ import type { JSONSchema7 } from "json-schema";
10
+ /** Per-alias Lakebase search configuration. */
11
+ export interface LakebaseAiSearchIndexConfig extends Omit<IndexConfig, "embeddingFn" | "endpointName" | "pagination" | "reranker"> {
12
+ /** Documents used to seed an empty full-text table during setup. */
13
+ documents?: SearchDocument[];
14
+ /** Document field indexed first. Defaults to `text`. */
15
+ textColumn?: string;
16
+ }
17
+ /** Configuration for the Lakebase implementation of AppKit AI Search. */
18
+ export interface LakebaseAiSearchConfig extends BasePluginConfig {
19
+ indexes?: Record<string, LakebaseAiSearchIndexConfig>;
20
+ /** PostgreSQL schema that owns the generated full-text tables. */
21
+ schema?: string;
22
+ /** Enable the document upsert route and exported method. */
23
+ allowWrite?: boolean;
24
+ }
25
+ /** Lakebase implementation of the native AppKit `aiSearch` contract. */
26
+ export declare class LakebaseAiSearchPlugin extends Plugin<LakebaseAiSearchConfig> {
27
+ static manifest: {
28
+ name: "aiSearch";
29
+ displayName: string;
30
+ description: string;
31
+ stability: "beta";
32
+ resources: {
33
+ required: never[];
34
+ optional: never[];
35
+ };
36
+ config: {
37
+ schema: JSONSchema7;
38
+ };
39
+ };
40
+ protected config: LakebaseAiSearchConfig;
41
+ private backend;
42
+ setup(): Promise<void>;
43
+ injectRoutes(router: IAppRouter): void;
44
+ /** Query one configured Lakebase full-text index using AppKit's response shape. */
45
+ query(alias: string, request: SearchRequest): Promise<SearchResponse<Record<string, unknown>>>;
46
+ /** Add or update documents in one configured Lakebase full-text index. */
47
+ addDocuments(alias: string, documents: SearchDocument[]): Promise<{
48
+ index: string;
49
+ count: number;
50
+ }>;
51
+ clientConfig(): {
52
+ indexes: {
53
+ alias: string;
54
+ queryType: "full_text";
55
+ pagination: boolean;
56
+ }[];
57
+ };
58
+ exports(): {
59
+ providerKind: "lakebase";
60
+ query: (alias: string, request: SearchRequest) => Promise<SearchResponse<Record<string, unknown>>>;
61
+ addDocuments: (alias: string, documents: SearchDocument[]) => Promise<{
62
+ index: string;
63
+ count: number;
64
+ }>;
65
+ };
66
+ shutdown(): Promise<void>;
67
+ private indexes;
68
+ private resolveIndex;
69
+ private requireBackend;
70
+ private project;
71
+ }
72
+ /** AppKit-compatible Lakebase AI Search provider. */
73
+ export declare const lakebaseAiSearch: import("@databricks/appkit").ToPlugin<typeof LakebaseAiSearchPlugin, LakebaseAiSearchConfig, "aiSearch">;
@@ -0,0 +1,191 @@
1
+ /**
2
+ * AppKit-compatible AI Search provider backed by Lakebase full-text search.
3
+ *
4
+ * @module
5
+ */
6
+ import { lakebase, Plugin, toPlugin, ValidationError, } from "@databricks/appkit";
7
+ import { plugin as appkitPlugin } from "@dbx-tools/appkit";
8
+ import { log, object, string } from "@dbx-tools/shared-core";
9
+ import { LakebaseSearchBackend } from "./lakebase.js";
10
+ const logger = log.logger("search/lakebase-plugin");
11
+ const CONFIG_SCHEMA = {
12
+ type: "object",
13
+ required: ["indexes"],
14
+ properties: {
15
+ indexes: {
16
+ type: "object",
17
+ additionalProperties: {
18
+ type: "object",
19
+ properties: {
20
+ indexName: { type: "string" },
21
+ columns: { type: "array", items: { type: "string" } },
22
+ numResults: { type: "number" },
23
+ queryType: { enum: ["full_text"] },
24
+ textColumn: { type: "string" },
25
+ documents: { type: "array", items: { type: "object" } },
26
+ },
27
+ },
28
+ },
29
+ schema: { type: "string" },
30
+ allowWrite: { type: "boolean" },
31
+ },
32
+ };
33
+ function routeParam(value) {
34
+ return Array.isArray(value) ? (value[0] ?? "") : value;
35
+ }
36
+ /** Lakebase implementation of the native AppKit `aiSearch` contract. */
37
+ export class LakebaseAiSearchPlugin extends Plugin {
38
+ static manifest = {
39
+ name: "aiSearch",
40
+ displayName: "Lakebase AI Search",
41
+ description: "AppKit AI Search contract backed by PostgreSQL full-text search",
42
+ stability: "beta",
43
+ resources: { required: [], optional: [] },
44
+ config: { schema: CONFIG_SCHEMA },
45
+ };
46
+ backend;
47
+ async setup() {
48
+ const lake = appkitPlugin.require(this.context, lakebase, this);
49
+ this.backend = new LakebaseSearchBackend(() => lake.exports().getPgConfig(), string.trimToNull(this.config.schema) ?? "public");
50
+ for (const index of this.indexes()) {
51
+ await this.backend.provision(index.indexName, {
52
+ textColumn: index.config.textColumn ?? "text",
53
+ ...(index.config.documents ? { seed: index.config.documents } : {}),
54
+ });
55
+ }
56
+ logger.info("ready", {
57
+ indexes: this.indexes().map((index) => index.alias),
58
+ schema: string.trimToNull(this.config.schema) ?? "public",
59
+ });
60
+ }
61
+ injectRoutes(router) {
62
+ this.route(router, {
63
+ name: "query",
64
+ method: "post",
65
+ path: "/:alias/query",
66
+ handler: async (req, res) => {
67
+ try {
68
+ res.json(await this.query(routeParam(req.params.alias), req.body));
69
+ }
70
+ catch (error) {
71
+ res.status(400).json({
72
+ error: error instanceof Error ? error.message : "Search failed",
73
+ plugin: this.name,
74
+ });
75
+ }
76
+ },
77
+ });
78
+ this.route(router, {
79
+ name: "getConfig",
80
+ method: "get",
81
+ path: "/:alias/config",
82
+ handler: async (req, res) => {
83
+ const index = this.resolveIndex(routeParam(req.params.alias));
84
+ res.json({
85
+ alias: index.alias,
86
+ columns: index.config.columns,
87
+ queryType: "full_text",
88
+ numResults: index.config.numResults ?? 20,
89
+ reranker: false,
90
+ pagination: false,
91
+ });
92
+ },
93
+ });
94
+ if (this.config.allowWrite) {
95
+ this.route(router, {
96
+ name: "addDocuments",
97
+ method: "post",
98
+ path: "/:alias/documents",
99
+ handler: async (req, res) => {
100
+ const documents = Array.isArray(req.body?.documents)
101
+ ? req.body.documents.filter(object.isRecord)
102
+ : [];
103
+ res.json(await this.addDocuments(routeParam(req.params.alias), documents));
104
+ },
105
+ });
106
+ }
107
+ }
108
+ /** Query one configured Lakebase full-text index using AppKit's response shape. */
109
+ async query(alias, request) {
110
+ if (!request.queryText) {
111
+ throw new ValidationError("Lakebase AI Search requires queryText");
112
+ }
113
+ if (request.queryVector) {
114
+ throw new ValidationError("Lakebase AI Search does not accept queryVector");
115
+ }
116
+ if (request.queryType && request.queryType !== "full_text") {
117
+ throw new ValidationError("Lakebase AI Search supports only full_text queries");
118
+ }
119
+ const index = this.resolveIndex(alias);
120
+ const startedAt = performance.now();
121
+ const result = await this.requireBackend().search(index.indexName, request.queryText, {
122
+ limit: request.numResults ?? index.config.numResults ?? 20,
123
+ ...(request.filters ? { filter: request.filters } : {}),
124
+ });
125
+ const columns = request.columns ?? index.config.columns;
126
+ return {
127
+ results: result.hits.map((hit) => ({
128
+ score: hit.score,
129
+ data: this.project({ id: hit.id, ...hit.fields }, columns),
130
+ })),
131
+ totalCount: result.count,
132
+ queryTimeMs: Math.max(0, performance.now() - startedAt),
133
+ queryType: "full_text",
134
+ nextPageToken: null,
135
+ };
136
+ }
137
+ /** Add or update documents in one configured Lakebase full-text index. */
138
+ async addDocuments(alias, documents) {
139
+ if (!this.config.allowWrite) {
140
+ throw new ValidationError("Lakebase AI Search writes are disabled");
141
+ }
142
+ const index = this.resolveIndex(alias);
143
+ return this.requireBackend().addDocuments(index.indexName, documents.filter(object.isRecord), index.config.textColumn ?? "text");
144
+ }
145
+ clientConfig() {
146
+ return {
147
+ indexes: this.indexes().map((index) => ({
148
+ alias: index.alias,
149
+ queryType: "full_text",
150
+ pagination: false,
151
+ })),
152
+ };
153
+ }
154
+ exports() {
155
+ return {
156
+ providerKind: "lakebase",
157
+ query: this.query.bind(this),
158
+ addDocuments: this.addDocuments.bind(this),
159
+ };
160
+ }
161
+ async shutdown() {
162
+ await this.backend?.close();
163
+ this.backend = undefined;
164
+ }
165
+ indexes() {
166
+ return Object.entries(this.config.indexes ?? {}).map(([alias, config]) => ({
167
+ alias,
168
+ indexName: string.trimToNull(config.indexName) ?? alias,
169
+ config,
170
+ }));
171
+ }
172
+ resolveIndex(alias) {
173
+ const index = this.indexes().find((candidate) => candidate.alias === alias);
174
+ if (!index)
175
+ throw new ValidationError(`Unknown AI Search index alias "${alias}"`);
176
+ return index;
177
+ }
178
+ requireBackend() {
179
+ if (!this.backend)
180
+ throw new ValidationError("Lakebase AI Search is not initialized");
181
+ return this.backend;
182
+ }
183
+ project(data, columns) {
184
+ if (!columns?.length)
185
+ return data;
186
+ return Object.fromEntries(columns.filter((column) => column in data).map((column) => [column, data[column]]));
187
+ }
188
+ }
189
+ /** AppKit-compatible Lakebase AI Search provider. */
190
+ export const lakebaseAiSearch = toPlugin(LakebaseAiSearchPlugin);
191
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFrZWJhc2UtcGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xha2ViYXNlLXBsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBRUgsT0FBTyxFQUNMLFFBQVEsRUFDUixNQUFNLEVBQ04sUUFBUSxFQUNSLGVBQWUsR0FJaEIsTUFBTSxvQkFBb0IsQ0FBQztBQUU1QixPQUFPLEVBQUUsTUFBTSxJQUFJLFlBQVksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzNELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBSTdELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUV0RCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLHdCQUF3QixDQUFDLENBQUM7QUFzQnBELE1BQU0sYUFBYSxHQUFnQjtJQUNqQyxJQUFJLEVBQUUsUUFBUTtJQUNkLFFBQVEsRUFBRSxDQUFDLFNBQVMsQ0FBQztJQUNyQixVQUFVLEVBQUU7UUFDVixPQUFPLEVBQUU7WUFDUCxJQUFJLEVBQUUsUUFBUTtZQUNkLG9CQUFvQixFQUFFO2dCQUNwQixJQUFJLEVBQUUsUUFBUTtnQkFDZCxVQUFVLEVBQUU7b0JBQ1YsU0FBUyxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtvQkFDN0IsT0FBTyxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQUU7b0JBQ3JELFVBQVUsRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUU7b0JBQzlCLFNBQVMsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLFdBQVcsQ0FBQyxFQUFFO29CQUNsQyxVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFO29CQUM5QixTQUFTLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsRUFBRTtpQkFDeEQ7YUFDRjtTQUNGO1FBQ0QsTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtRQUMxQixVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFO0tBQ2hDO0NBQ0YsQ0FBQztBQVFGLFNBQVMsVUFBVSxDQUFDLEtBQXdCO0lBQzFDLE9BQU8sS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztBQUN6RCxDQUFDO0FBRUQsd0VBQXdFO0FBQ3hFLE1BQU0sT0FBTyxzQkFBdUIsU0FBUSxNQUE4QjtJQUN4RSxNQUFNLENBQUMsUUFBUSxHQUFHO1FBQ2hCLElBQUksRUFBRSxVQUFVO1FBQ2hCLFdBQVcsRUFBRSxvQkFBb0I7UUFDakMsV0FBVyxFQUFFLGlFQUFpRTtRQUM5RSxTQUFTLEVBQUUsTUFBTTtRQUNqQixTQUFTLEVBQUUsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUU7UUFDekMsTUFBTSxFQUFFLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRTtLQUNHLENBQUM7SUFHL0IsT0FBTyxDQUFvQztJQUUxQyxLQUFLLENBQUMsS0FBSztRQUNsQixNQUFNLElBQUksR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxxQkFBcUIsQ0FDdEMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUNsQyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksUUFBUSxDQUNsRCxDQUFDO1FBQ0YsS0FBSyxNQUFNLEtBQUssSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQztZQUNuQyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUU7Z0JBQzVDLFVBQVUsRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLFVBQVUsSUFBSSxNQUFNO2dCQUM3QyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQzthQUNwRSxDQUFDLENBQUM7UUFDTCxDQUFDO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDbkIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUM7WUFDbkQsTUFBTSxFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxRQUFRO1NBQzFELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFUSxZQUFZLENBQUMsTUFBa0I7UUFDdEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUU7WUFDakIsSUFBSSxFQUFFLE9BQU87WUFDYixNQUFNLEVBQUUsTUFBTTtZQUNkLElBQUksRUFBRSxlQUFlO1lBQ3JCLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBb0IsRUFBRSxHQUFxQixFQUFFLEVBQUU7Z0JBQzdELElBQUksQ0FBQztvQkFDSCxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLENBQUMsSUFBcUIsQ0FBQyxDQUFDLENBQUM7Z0JBQ3RGLENBQUM7Z0JBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztvQkFDZixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQzt3QkFDbkIsS0FBSyxFQUFFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGVBQWU7d0JBQy9ELE1BQU0sRUFBRSxJQUFJLENBQUMsSUFBSTtxQkFDbEIsQ0FBQyxDQUFDO2dCQUNMLENBQUM7WUFDSCxDQUFDO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUU7WUFDakIsSUFBSSxFQUFFLFdBQVc7WUFDakIsTUFBTSxFQUFFLEtBQUs7WUFDYixJQUFJLEVBQUUsZ0JBQWdCO1lBQ3RCLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBb0IsRUFBRSxHQUFxQixFQUFFLEVBQUU7Z0JBQzdELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztnQkFDOUQsR0FBRyxDQUFDLElBQUksQ0FBQztvQkFDUCxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUs7b0JBQ2xCLE9BQU8sRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU87b0JBQzdCLFNBQVMsRUFBRSxXQUFXO29CQUN0QixVQUFVLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFVLElBQUksRUFBRTtvQkFDekMsUUFBUSxFQUFFLEtBQUs7b0JBQ2YsVUFBVSxFQUFFLEtBQUs7aUJBQ2xCLENBQUMsQ0FBQztZQUNMLENBQUM7U0FDRixDQUFDLENBQUM7UUFDSCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDM0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUU7Z0JBQ2pCLElBQUksRUFBRSxjQUFjO2dCQUNwQixNQUFNLEVBQUUsTUFBTTtnQkFDZCxJQUFJLEVBQUUsbUJBQW1CO2dCQUN6QixPQUFPLEVBQUUsS0FBSyxFQUFFLEdBQW9CLEVBQUUsR0FBcUIsRUFBRSxFQUFFO29CQUM3RCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDO3dCQUNsRCxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7d0JBQzVDLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQ1AsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztnQkFDN0UsQ0FBQzthQUNGLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0lBRUQsbUZBQW1GO0lBQ25GLEtBQUssQ0FBQyxLQUFLLENBQ1QsS0FBYSxFQUNiLE9BQXNCO1FBRXRCLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDdkIsTUFBTSxJQUFJLGVBQWUsQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFDO1FBQ3JFLENBQUM7UUFDRCxJQUFJLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN4QixNQUFNLElBQUksZUFBZSxDQUFDLGdEQUFnRCxDQUFDLENBQUM7UUFDOUUsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLFNBQVMsSUFBSSxPQUFPLENBQUMsU0FBUyxLQUFLLFdBQVcsRUFBRSxDQUFDO1lBQzNELE1BQU0sSUFBSSxlQUFlLENBQUMsb0RBQW9ELENBQUMsQ0FBQztRQUNsRixDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2QyxNQUFNLFNBQVMsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDcEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsRUFBRTtZQUNwRixLQUFLLEVBQUUsT0FBTyxDQUFDLFVBQVUsSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLFVBQVUsSUFBSSxFQUFFO1lBQzFELEdBQUcsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUN4RCxDQUFDLENBQUM7UUFDSCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO1FBQ3hELE9BQU87WUFDTCxPQUFPLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ2pDLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSztnQkFDaEIsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQUUsRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxPQUFPLENBQUM7YUFDM0QsQ0FBQyxDQUFDO1lBQ0gsVUFBVSxFQUFFLE1BQU0sQ0FBQyxLQUFLO1lBQ3hCLFdBQVcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxXQUFXLENBQUMsR0FBRyxFQUFFLEdBQUcsU0FBUyxDQUFDO1lBQ3ZELFNBQVMsRUFBRSxXQUFXO1lBQ3RCLGFBQWEsRUFBRSxJQUFJO1NBQ3BCLENBQUM7SUFDSixDQUFDO0lBRUQsMEVBQTBFO0lBQzFFLEtBQUssQ0FBQyxZQUFZLENBQUMsS0FBYSxFQUFFLFNBQTJCO1FBQzNELElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzVCLE1BQU0sSUFBSSxlQUFlLENBQUMsd0NBQXdDLENBQUMsQ0FBQztRQUN0RSxDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2QyxPQUFPLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxZQUFZLENBQ3ZDLEtBQUssQ0FBQyxTQUFTLEVBQ2YsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQ2pDLEtBQUssQ0FBQyxNQUFNLENBQUMsVUFBVSxJQUFJLE1BQU0sQ0FDbEMsQ0FBQztJQUNKLENBQUM7SUFFUSxZQUFZO1FBQ25CLE9BQU87WUFDTCxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDdEMsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLO2dCQUNsQixTQUFTLEVBQUUsV0FBb0I7Z0JBQy9CLFVBQVUsRUFBRSxLQUFLO2FBQ2xCLENBQUMsQ0FBQztTQUNKLENBQUM7SUFDSixDQUFDO0lBRUQsT0FBTztRQUNMLE9BQU87WUFDTCxZQUFZLEVBQUUsVUFBbUI7WUFDakMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUM1QixZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1NBQzNDLENBQUM7SUFDSixDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVE7UUFDWixNQUFNLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDNUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUM7SUFDM0IsQ0FBQztJQUVPLE9BQU87UUFDYixPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDekUsS0FBSztZQUNMLFNBQVMsRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxLQUFLO1lBQ3ZELE1BQU07U0FDUCxDQUFDLENBQUMsQ0FBQztJQUNOLENBQUM7SUFFTyxZQUFZLENBQUMsS0FBYTtRQUNoQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsS0FBSyxLQUFLLEtBQUssQ0FBQyxDQUFDO1FBQzVFLElBQUksQ0FBQyxLQUFLO1lBQUUsTUFBTSxJQUFJLGVBQWUsQ0FBQyxrQ0FBa0MsS0FBSyxHQUFHLENBQUMsQ0FBQztRQUNsRixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFTyxjQUFjO1FBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTztZQUFFLE1BQU0sSUFBSSxlQUFlLENBQUMsdUNBQXVDLENBQUMsQ0FBQztRQUN0RixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDdEIsQ0FBQztJQUVPLE9BQU8sQ0FDYixJQUE2QixFQUM3QixPQUE2QjtRQUU3QixJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU07WUFBRSxPQUFPLElBQUksQ0FBQztRQUNsQyxPQUFPLE1BQU0sQ0FBQyxXQUFXLENBQ3ZCLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQ25GLENBQUM7SUFDSixDQUFDOztBQUdILHFEQUFxRDtBQUNyRCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsc0JBQXNCLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQXBwS2l0LWNvbXBhdGlibGUgQUkgU2VhcmNoIHByb3ZpZGVyIGJhY2tlZCBieSBMYWtlYmFzZSBmdWxsLXRleHQgc2VhcmNoLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQge1xuICBsYWtlYmFzZSxcbiAgUGx1Z2luLFxuICB0b1BsdWdpbixcbiAgVmFsaWRhdGlvbkVycm9yLFxuICB0eXBlIEJhc2VQbHVnaW5Db25maWcsXG4gIHR5cGUgSUFwcFJvdXRlcixcbiAgdHlwZSBQbHVnaW5NYW5pZmVzdCxcbn0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHR5cGUgeyBJbmRleENvbmZpZywgU2VhcmNoUmVxdWVzdCwgU2VhcmNoUmVzcG9uc2UgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0L2JldGFcIjtcbmltcG9ydCB7IHBsdWdpbiBhcyBhcHBraXRQbHVnaW4gfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbmltcG9ydCB7IGxvZywgb2JqZWN0LCBzdHJpbmcgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBTZWFyY2hEb2N1bWVudCB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1zZWFyY2hcIjtcbmltcG9ydCB0eXBlIGV4cHJlc3MgZnJvbSBcImV4cHJlc3NcIjtcbmltcG9ydCB0eXBlIHsgSlNPTlNjaGVtYTcgfSBmcm9tIFwianNvbi1zY2hlbWFcIjtcbmltcG9ydCB7IExha2ViYXNlU2VhcmNoQmFja2VuZCB9IGZyb20gXCIuL2xha2ViYXNlLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJzZWFyY2gvbGFrZWJhc2UtcGx1Z2luXCIpO1xuXG4vKiogUGVyLWFsaWFzIExha2ViYXNlIHNlYXJjaCBjb25maWd1cmF0aW9uLiAqL1xuZXhwb3J0IGludGVyZmFjZSBMYWtlYmFzZUFpU2VhcmNoSW5kZXhDb25maWcgZXh0ZW5kcyBPbWl0PFxuICBJbmRleENvbmZpZyxcbiAgXCJlbWJlZGRpbmdGblwiIHwgXCJlbmRwb2ludE5hbWVcIiB8IFwicGFnaW5hdGlvblwiIHwgXCJyZXJhbmtlclwiXG4+IHtcbiAgLyoqIERvY3VtZW50cyB1c2VkIHRvIHNlZWQgYW4gZW1wdHkgZnVsbC10ZXh0IHRhYmxlIGR1cmluZyBzZXR1cC4gKi9cbiAgZG9jdW1lbnRzPzogU2VhcmNoRG9jdW1lbnRbXTtcbiAgLyoqIERvY3VtZW50IGZpZWxkIGluZGV4ZWQgZmlyc3QuIERlZmF1bHRzIHRvIGB0ZXh0YC4gKi9cbiAgdGV4dENvbHVtbj86IHN0cmluZztcbn1cblxuLyoqIENvbmZpZ3VyYXRpb24gZm9yIHRoZSBMYWtlYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBBcHBLaXQgQUkgU2VhcmNoLiAqL1xuZXhwb3J0IGludGVyZmFjZSBMYWtlYmFzZUFpU2VhcmNoQ29uZmlnIGV4dGVuZHMgQmFzZVBsdWdpbkNvbmZpZyB7XG4gIGluZGV4ZXM/OiBSZWNvcmQ8c3RyaW5nLCBMYWtlYmFzZUFpU2VhcmNoSW5kZXhDb25maWc+O1xuICAvKiogUG9zdGdyZVNRTCBzY2hlbWEgdGhhdCBvd25zIHRoZSBnZW5lcmF0ZWQgZnVsbC10ZXh0IHRhYmxlcy4gKi9cbiAgc2NoZW1hPzogc3RyaW5nO1xuICAvKiogRW5hYmxlIHRoZSBkb2N1bWVudCB1cHNlcnQgcm91dGUgYW5kIGV4cG9ydGVkIG1ldGhvZC4gKi9cbiAgYWxsb3dXcml0ZT86IGJvb2xlYW47XG59XG5cbmNvbnN0IENPTkZJR19TQ0hFTUE6IEpTT05TY2hlbWE3ID0ge1xuICB0eXBlOiBcIm9iamVjdFwiLFxuICByZXF1aXJlZDogW1wiaW5kZXhlc1wiXSxcbiAgcHJvcGVydGllczoge1xuICAgIGluZGV4ZXM6IHtcbiAgICAgIHR5cGU6IFwib2JqZWN0XCIsXG4gICAgICBhZGRpdGlvbmFsUHJvcGVydGllczoge1xuICAgICAgICB0eXBlOiBcIm9iamVjdFwiLFxuICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgaW5kZXhOYW1lOiB7IHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgICBjb2x1bW5zOiB7IHR5cGU6IFwiYXJyYXlcIiwgaXRlbXM6IHsgdHlwZTogXCJzdHJpbmdcIiB9IH0sXG4gICAgICAgICAgbnVtUmVzdWx0czogeyB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgICAgICAgcXVlcnlUeXBlOiB7IGVudW06IFtcImZ1bGxfdGV4dFwiXSB9LFxuICAgICAgICAgIHRleHRDb2x1bW46IHsgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgICAgICAgIGRvY3VtZW50czogeyB0eXBlOiBcImFycmF5XCIsIGl0ZW1zOiB7IHR5cGU6IFwib2JqZWN0XCIgfSB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICAgIHNjaGVtYTogeyB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgYWxsb3dXcml0ZTogeyB0eXBlOiBcImJvb2xlYW5cIiB9LFxuICB9LFxufTtcblxuaW50ZXJmYWNlIFJlc29sdmVkTGFrZWJhc2VJbmRleCB7XG4gIGFsaWFzOiBzdHJpbmc7XG4gIGluZGV4TmFtZTogc3RyaW5nO1xuICBjb25maWc6IExha2ViYXNlQWlTZWFyY2hJbmRleENvbmZpZztcbn1cblxuZnVuY3Rpb24gcm91dGVQYXJhbSh2YWx1ZTogc3RyaW5nIHwgc3RyaW5nW10pOiBzdHJpbmcge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyAodmFsdWVbMF0gPz8gXCJcIikgOiB2YWx1ZTtcbn1cblxuLyoqIExha2ViYXNlIGltcGxlbWVudGF0aW9uIG9mIHRoZSBuYXRpdmUgQXBwS2l0IGBhaVNlYXJjaGAgY29udHJhY3QuICovXG5leHBvcnQgY2xhc3MgTGFrZWJhc2VBaVNlYXJjaFBsdWdpbiBleHRlbmRzIFBsdWdpbjxMYWtlYmFzZUFpU2VhcmNoQ29uZmlnPiB7XG4gIHN0YXRpYyBtYW5pZmVzdCA9IHtcbiAgICBuYW1lOiBcImFpU2VhcmNoXCIsXG4gICAgZGlzcGxheU5hbWU6IFwiTGFrZWJhc2UgQUkgU2VhcmNoXCIsXG4gICAgZGVzY3JpcHRpb246IFwiQXBwS2l0IEFJIFNlYXJjaCBjb250cmFjdCBiYWNrZWQgYnkgUG9zdGdyZVNRTCBmdWxsLXRleHQgc2VhcmNoXCIsXG4gICAgc3RhYmlsaXR5OiBcImJldGFcIixcbiAgICByZXNvdXJjZXM6IHsgcmVxdWlyZWQ6IFtdLCBvcHRpb25hbDogW10gfSxcbiAgICBjb25maWc6IHsgc2NoZW1hOiBDT05GSUdfU0NIRU1BIH0sXG4gIH0gc2F0aXNmaWVzIFBsdWdpbk1hbmlmZXN0PFwiYWlTZWFyY2hcIj47XG5cbiAgZGVjbGFyZSBwcm90ZWN0ZWQgY29uZmlnOiBMYWtlYmFzZUFpU2VhcmNoQ29uZmlnO1xuICBwcml2YXRlIGJhY2tlbmQ6IExha2ViYXNlU2VhcmNoQmFja2VuZCB8IHVuZGVmaW5lZDtcblxuICBvdmVycmlkZSBhc3luYyBzZXR1cCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBsYWtlID0gYXBwa2l0UGx1Z2luLnJlcXVpcmUodGhpcy5jb250ZXh0LCBsYWtlYmFzZSwgdGhpcyk7XG4gICAgdGhpcy5iYWNrZW5kID0gbmV3IExha2ViYXNlU2VhcmNoQmFja2VuZChcbiAgICAgICgpID0+IGxha2UuZXhwb3J0cygpLmdldFBnQ29uZmlnKCksXG4gICAgICBzdHJpbmcudHJpbVRvTnVsbCh0aGlzLmNvbmZpZy5zY2hlbWEpID8/IFwicHVibGljXCIsXG4gICAgKTtcbiAgICBmb3IgKGNvbnN0IGluZGV4IG9mIHRoaXMuaW5kZXhlcygpKSB7XG4gICAgICBhd2FpdCB0aGlzLmJhY2tlbmQucHJvdmlzaW9uKGluZGV4LmluZGV4TmFtZSwge1xuICAgICAgICB0ZXh0Q29sdW1uOiBpbmRleC5jb25maWcudGV4dENvbHVtbiA/PyBcInRleHRcIixcbiAgICAgICAgLi4uKGluZGV4LmNvbmZpZy5kb2N1bWVudHMgPyB7IHNlZWQ6IGluZGV4LmNvbmZpZy5kb2N1bWVudHMgfSA6IHt9KSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBsb2dnZXIuaW5mbyhcInJlYWR5XCIsIHtcbiAgICAgIGluZGV4ZXM6IHRoaXMuaW5kZXhlcygpLm1hcCgoaW5kZXgpID0+IGluZGV4LmFsaWFzKSxcbiAgICAgIHNjaGVtYTogc3RyaW5nLnRyaW1Ub051bGwodGhpcy5jb25maWcuc2NoZW1hKSA/PyBcInB1YmxpY1wiLFxuICAgIH0pO1xuICB9XG5cbiAgb3ZlcnJpZGUgaW5qZWN0Um91dGVzKHJvdXRlcjogSUFwcFJvdXRlcik6IHZvaWQge1xuICAgIHRoaXMucm91dGUocm91dGVyLCB7XG4gICAgICBuYW1lOiBcInF1ZXJ5XCIsXG4gICAgICBtZXRob2Q6IFwicG9zdFwiLFxuICAgICAgcGF0aDogXCIvOmFsaWFzL3F1ZXJ5XCIsXG4gICAgICBoYW5kbGVyOiBhc3luYyAocmVxOiBleHByZXNzLlJlcXVlc3QsIHJlczogZXhwcmVzcy5SZXNwb25zZSkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHJlcy5qc29uKGF3YWl0IHRoaXMucXVlcnkocm91dGVQYXJhbShyZXEucGFyYW1zLmFsaWFzKSwgcmVxLmJvZHkgYXMgU2VhcmNoUmVxdWVzdCkpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHtcbiAgICAgICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFwiU2VhcmNoIGZhaWxlZFwiLFxuICAgICAgICAgICAgcGx1Z2luOiB0aGlzLm5hbWUsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZShyb3V0ZXIsIHtcbiAgICAgIG5hbWU6IFwiZ2V0Q29uZmlnXCIsXG4gICAgICBtZXRob2Q6IFwiZ2V0XCIsXG4gICAgICBwYXRoOiBcIi86YWxpYXMvY29uZmlnXCIsXG4gICAgICBoYW5kbGVyOiBhc3luYyAocmVxOiBleHByZXNzLlJlcXVlc3QsIHJlczogZXhwcmVzcy5SZXNwb25zZSkgPT4ge1xuICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMucmVzb2x2ZUluZGV4KHJvdXRlUGFyYW0ocmVxLnBhcmFtcy5hbGlhcykpO1xuICAgICAgICByZXMuanNvbih7XG4gICAgICAgICAgYWxpYXM6IGluZGV4LmFsaWFzLFxuICAgICAgICAgIGNvbHVtbnM6IGluZGV4LmNvbmZpZy5jb2x1bW5zLFxuICAgICAgICAgIHF1ZXJ5VHlwZTogXCJmdWxsX3RleHRcIixcbiAgICAgICAgICBudW1SZXN1bHRzOiBpbmRleC5jb25maWcubnVtUmVzdWx0cyA/PyAyMCxcbiAgICAgICAgICByZXJhbmtlcjogZmFsc2UsXG4gICAgICAgICAgcGFnaW5hdGlvbjogZmFsc2UsXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICB9KTtcbiAgICBpZiAodGhpcy5jb25maWcuYWxsb3dXcml0ZSkge1xuICAgICAgdGhpcy5yb3V0ZShyb3V0ZXIsIHtcbiAgICAgICAgbmFtZTogXCJhZGREb2N1bWVudHNcIixcbiAgICAgICAgbWV0aG9kOiBcInBvc3RcIixcbiAgICAgICAgcGF0aDogXCIvOmFsaWFzL2RvY3VtZW50c1wiLFxuICAgICAgICBoYW5kbGVyOiBhc3luYyAocmVxOiBleHByZXNzLlJlcXVlc3QsIHJlczogZXhwcmVzcy5SZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGRvY3VtZW50cyA9IEFycmF5LmlzQXJyYXkocmVxLmJvZHk/LmRvY3VtZW50cylcbiAgICAgICAgICAgID8gcmVxLmJvZHkuZG9jdW1lbnRzLmZpbHRlcihvYmplY3QuaXNSZWNvcmQpXG4gICAgICAgICAgICA6IFtdO1xuICAgICAgICAgIHJlcy5qc29uKGF3YWl0IHRoaXMuYWRkRG9jdW1lbnRzKHJvdXRlUGFyYW0ocmVxLnBhcmFtcy5hbGlhcyksIGRvY3VtZW50cykpO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFF1ZXJ5IG9uZSBjb25maWd1cmVkIExha2ViYXNlIGZ1bGwtdGV4dCBpbmRleCB1c2luZyBBcHBLaXQncyByZXNwb25zZSBzaGFwZS4gKi9cbiAgYXN5bmMgcXVlcnkoXG4gICAgYWxpYXM6IHN0cmluZyxcbiAgICByZXF1ZXN0OiBTZWFyY2hSZXF1ZXN0LFxuICApOiBQcm9taXNlPFNlYXJjaFJlc3BvbnNlPFJlY29yZDxzdHJpbmcsIHVua25vd24+Pj4ge1xuICAgIGlmICghcmVxdWVzdC5xdWVyeVRleHQpIHtcbiAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXCJMYWtlYmFzZSBBSSBTZWFyY2ggcmVxdWlyZXMgcXVlcnlUZXh0XCIpO1xuICAgIH1cbiAgICBpZiAocmVxdWVzdC5xdWVyeVZlY3Rvcikge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcIkxha2ViYXNlIEFJIFNlYXJjaCBkb2VzIG5vdCBhY2NlcHQgcXVlcnlWZWN0b3JcIik7XG4gICAgfVxuICAgIGlmIChyZXF1ZXN0LnF1ZXJ5VHlwZSAmJiByZXF1ZXN0LnF1ZXJ5VHlwZSAhPT0gXCJmdWxsX3RleHRcIikge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcIkxha2ViYXNlIEFJIFNlYXJjaCBzdXBwb3J0cyBvbmx5IGZ1bGxfdGV4dCBxdWVyaWVzXCIpO1xuICAgIH1cbiAgICBjb25zdCBpbmRleCA9IHRoaXMucmVzb2x2ZUluZGV4KGFsaWFzKTtcbiAgICBjb25zdCBzdGFydGVkQXQgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJlcXVpcmVCYWNrZW5kKCkuc2VhcmNoKGluZGV4LmluZGV4TmFtZSwgcmVxdWVzdC5xdWVyeVRleHQsIHtcbiAgICAgIGxpbWl0OiByZXF1ZXN0Lm51bVJlc3VsdHMgPz8gaW5kZXguY29uZmlnLm51bVJlc3VsdHMgPz8gMjAsXG4gICAgICAuLi4ocmVxdWVzdC5maWx0ZXJzID8geyBmaWx0ZXI6IHJlcXVlc3QuZmlsdGVycyB9IDoge30pLFxuICAgIH0pO1xuICAgIGNvbnN0IGNvbHVtbnMgPSByZXF1ZXN0LmNvbHVtbnMgPz8gaW5kZXguY29uZmlnLmNvbHVtbnM7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJlc3VsdHM6IHJlc3VsdC5oaXRzLm1hcCgoaGl0KSA9PiAoe1xuICAgICAgICBzY29yZTogaGl0LnNjb3JlLFxuICAgICAgICBkYXRhOiB0aGlzLnByb2plY3QoeyBpZDogaGl0LmlkLCAuLi5oaXQuZmllbGRzIH0sIGNvbHVtbnMpLFxuICAgICAgfSkpLFxuICAgICAgdG90YWxDb3VudDogcmVzdWx0LmNvdW50LFxuICAgICAgcXVlcnlUaW1lTXM6IE1hdGgubWF4KDAsIHBlcmZvcm1hbmNlLm5vdygpIC0gc3RhcnRlZEF0KSxcbiAgICAgIHF1ZXJ5VHlwZTogXCJmdWxsX3RleHRcIixcbiAgICAgIG5leHRQYWdlVG9rZW46IG51bGwsXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBBZGQgb3IgdXBkYXRlIGRvY3VtZW50cyBpbiBvbmUgY29uZmlndXJlZCBMYWtlYmFzZSBmdWxsLXRleHQgaW5kZXguICovXG4gIGFzeW5jIGFkZERvY3VtZW50cyhhbGlhczogc3RyaW5nLCBkb2N1bWVudHM6IFNlYXJjaERvY3VtZW50W10pIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnLmFsbG93V3JpdGUpIHtcbiAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXCJMYWtlYmFzZSBBSSBTZWFyY2ggd3JpdGVzIGFyZSBkaXNhYmxlZFwiKTtcbiAgICB9XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLnJlc29sdmVJbmRleChhbGlhcyk7XG4gICAgcmV0dXJuIHRoaXMucmVxdWlyZUJhY2tlbmQoKS5hZGREb2N1bWVudHMoXG4gICAgICBpbmRleC5pbmRleE5hbWUsXG4gICAgICBkb2N1bWVudHMuZmlsdGVyKG9iamVjdC5pc1JlY29yZCksXG4gICAgICBpbmRleC5jb25maWcudGV4dENvbHVtbiA/PyBcInRleHRcIixcbiAgICApO1xuICB9XG5cbiAgb3ZlcnJpZGUgY2xpZW50Q29uZmlnKCkge1xuICAgIHJldHVybiB7XG4gICAgICBpbmRleGVzOiB0aGlzLmluZGV4ZXMoKS5tYXAoKGluZGV4KSA9PiAoe1xuICAgICAgICBhbGlhczogaW5kZXguYWxpYXMsXG4gICAgICAgIHF1ZXJ5VHlwZTogXCJmdWxsX3RleHRcIiBhcyBjb25zdCxcbiAgICAgICAgcGFnaW5hdGlvbjogZmFsc2UsXG4gICAgICB9KSksXG4gICAgfTtcbiAgfVxuXG4gIGV4cG9ydHMoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHByb3ZpZGVyS2luZDogXCJsYWtlYmFzZVwiIGFzIGNvbnN0LFxuICAgICAgcXVlcnk6IHRoaXMucXVlcnkuYmluZCh0aGlzKSxcbiAgICAgIGFkZERvY3VtZW50czogdGhpcy5hZGREb2N1bWVudHMuYmluZCh0aGlzKSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgc2h1dGRvd24oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5iYWNrZW5kPy5jbG9zZSgpO1xuICAgIHRoaXMuYmFja2VuZCA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHByaXZhdGUgaW5kZXhlcygpOiBSZXNvbHZlZExha2ViYXNlSW5kZXhbXSB7XG4gICAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKHRoaXMuY29uZmlnLmluZGV4ZXMgPz8ge30pLm1hcCgoW2FsaWFzLCBjb25maWddKSA9PiAoe1xuICAgICAgYWxpYXMsXG4gICAgICBpbmRleE5hbWU6IHN0cmluZy50cmltVG9OdWxsKGNvbmZpZy5pbmRleE5hbWUpID8/IGFsaWFzLFxuICAgICAgY29uZmlnLFxuICAgIH0pKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVzb2x2ZUluZGV4KGFsaWFzOiBzdHJpbmcpOiBSZXNvbHZlZExha2ViYXNlSW5kZXgge1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5pbmRleGVzKCkuZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUuYWxpYXMgPT09IGFsaWFzKTtcbiAgICBpZiAoIWluZGV4KSB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGBVbmtub3duIEFJIFNlYXJjaCBpbmRleCBhbGlhcyBcIiR7YWxpYXN9XCJgKTtcbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICBwcml2YXRlIHJlcXVpcmVCYWNrZW5kKCk6IExha2ViYXNlU2VhcmNoQmFja2VuZCB7XG4gICAgaWYgKCF0aGlzLmJhY2tlbmQpIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXCJMYWtlYmFzZSBBSSBTZWFyY2ggaXMgbm90IGluaXRpYWxpemVkXCIpO1xuICAgIHJldHVybiB0aGlzLmJhY2tlbmQ7XG4gIH1cblxuICBwcml2YXRlIHByb2plY3QoXG4gICAgZGF0YTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgY29sdW1uczogc3RyaW5nW10gfCB1bmRlZmluZWQsXG4gICk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgICBpZiAoIWNvbHVtbnM/Lmxlbmd0aCkgcmV0dXJuIGRhdGE7XG4gICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIGNvbHVtbnMuZmlsdGVyKChjb2x1bW4pID0+IGNvbHVtbiBpbiBkYXRhKS5tYXAoKGNvbHVtbikgPT4gW2NvbHVtbiwgZGF0YVtjb2x1bW5dXSksXG4gICAgKTtcbiAgfVxufVxuXG4vKiogQXBwS2l0LWNvbXBhdGlibGUgTGFrZWJhc2UgQUkgU2VhcmNoIHByb3ZpZGVyLiAqL1xuZXhwb3J0IGNvbnN0IGxha2ViYXNlQWlTZWFyY2ggPSB0b1BsdWdpbihMYWtlYmFzZUFpU2VhcmNoUGx1Z2luKTtcbiJdfQ==
@@ -1,7 +1,6 @@
1
1
  /**
2
- * A Lakebase (Postgres) full-text search backend - the FALLBACK used when no
3
- * Databricks Vector Search endpoint/index is configured but a Lakebase pool is
4
- * available. It provisions a single table per index, indexes a generated
2
+ * Lakebase (Postgres) full-text runtime behind `lakebaseAiSearch`. It provisions
3
+ * a single table per index alias, indexes a generated
5
4
  * `tsvector`, and answers queries with a prefix `to_tsquery` + `ts_rank`.
6
5
  *
7
6
  * Queries are compiled rather than passed through `websearch_to_tsquery`,
@@ -24,7 +23,7 @@
24
23
  *
25
24
  * @module
26
25
  */
27
- import type { SearchDocument, SearchResult, UpsertResult } from "@dbx-tools/shared-search";
26
+ import type { SearchDocument, SearchRequest, SearchResult, UpsertResult } from "@dbx-tools/shared-search";
28
27
  import { Pool, type PoolConfig } from "pg";
29
28
  /**
30
29
  * Split a search-box string into the terms a tsquery is built from, using the
@@ -59,6 +58,7 @@ export declare function toTsQuery(terms: readonly string[], operator?: "&" | "|"
59
58
  /** Options for a single-index Lakebase search (mirrors the client's `SearchOptions`). */
60
59
  export interface LakebaseSearchOptions {
61
60
  limit?: number;
61
+ filter?: SearchRequest["filter"];
62
62
  scoreThreshold?: number;
63
63
  signal?: AbortSignal;
64
64
  }
@@ -113,6 +113,8 @@ export declare class LakebaseSearchBackend {
113
113
  private searchText;
114
114
  /** A hit's `fields`: the stored document minus the reserved/internal keys. */
115
115
  private toFields;
116
+ /** Compile AppKit scalar/array filters against the stored JSON document. */
117
+ private filterClause;
116
118
  /** The fully-qualified table name for an index reference. */
117
119
  private tableFor;
118
120
  /** A safe bare table name derived from an index reference. */
@@ -1,7 +1,6 @@
1
1
  /**
2
- * A Lakebase (Postgres) full-text search backend - the FALLBACK used when no
3
- * Databricks Vector Search endpoint/index is configured but a Lakebase pool is
4
- * available. It provisions a single table per index, indexes a generated
2
+ * Lakebase (Postgres) full-text runtime behind `lakebaseAiSearch`. It provisions
3
+ * a single table per index alias, indexes a generated
5
4
  * `tsvector`, and answers queries with a prefix `to_tsquery` + `ts_rank`.
6
5
  *
7
6
  * Queries are compiled rather than passed through `websearch_to_tsquery`,
@@ -118,15 +117,24 @@ export class LakebaseSearchBackend {
118
117
  // An empty (or punctuation-only) box returns rows rather than nothing, so
119
118
  // the UI shows content before the user types - as a keyword index would.
120
119
  if (terms.length === 0) {
121
- const { rows } = await this.query(pool, `SELECT id, document, 0::float4 AS score FROM ${table} ORDER BY id LIMIT $1`, [limit], options.signal);
120
+ const filter = this.filterClause(options.filter, 1);
121
+ const limitPosition = filter.params.length + 1;
122
+ const { rows } = await this.query(pool, `SELECT id, document, 0::float4 AS score
123
+ FROM ${table}
124
+ WHERE TRUE${filter.sql}
125
+ ORDER BY id
126
+ LIMIT $${limitPosition}`, [...filter.params, limit], options.signal);
122
127
  return this.toResult(text, index, rows, options);
123
128
  }
124
129
  // Precise pass: every term must match, each as a prefix.
130
+ const strictFilter = this.filterClause(options.filter, 2);
131
+ const strictLimitPosition = strictFilter.params.length + 2;
125
132
  const strict = await this.query(pool, `SELECT id, document, ts_rank(search_vector, to_tsquery('english', $1)) AS score
126
133
  FROM ${table}
127
134
  WHERE search_vector @@ to_tsquery('english', $1)
135
+ ${strictFilter.sql}
128
136
  ORDER BY score DESC
129
- LIMIT $2`, [toTsQuery(terms), limit], options.signal);
137
+ LIMIT $${strictLimitPosition}`, [toTsQuery(terms), ...strictFilter.params, limit], options.signal);
130
138
  if (strict.rows.length > 0)
131
139
  return this.toResult(text, index, strict.rows, options);
132
140
  // Nothing matched EVERY term, so relax rather than return an empty box:
@@ -134,12 +142,15 @@ export class LakebaseSearchBackend {
134
142
  // fragment that is not a prefix (`telligence`) or a token the text-search
135
143
  // parser split differently than expected. Substring matching cannot use
136
144
  // the GIN index, which is why it only runs once the indexed pass fails.
145
+ const relaxedFilter = this.filterClause(options.filter, 3);
146
+ const relaxedLimitPosition = relaxedFilter.params.length + 3;
137
147
  const relaxed = await this.query(pool, `SELECT id, document, ts_rank(search_vector, to_tsquery('english', $1)) AS score
138
148
  FROM ${table}
139
- WHERE search_vector @@ to_tsquery('english', $1)
140
- OR search_text ILIKE ANY($2::text[])
149
+ WHERE (search_vector @@ to_tsquery('english', $1)
150
+ OR search_text ILIKE ANY($2::text[]))
151
+ ${relaxedFilter.sql}
141
152
  ORDER BY score DESC
142
- LIMIT $3`, [toTsQuery(terms, "|"), terms.map((term) => `%${term}%`), limit], options.signal);
153
+ LIMIT $${relaxedLimitPosition}`, [toTsQuery(terms, "|"), terms.map((term) => `%${term}%`), ...relaxedFilter.params, limit], options.signal);
143
154
  return this.toResult(text, index, relaxed.rows, options);
144
155
  }
145
156
  /** Shape raw rows into the `SearchResult` both backends return. */
@@ -200,6 +211,9 @@ export class LakebaseSearchBackend {
200
211
  document jsonb NOT NULL DEFAULT '{}'::jsonb,
201
212
  search_vector tsvector GENERATED ALWAYS AS (to_tsvector('english', search_text)) STORED
202
213
  )`, [], signal);
214
+ await this.query(pool, `ALTER TABLE ${table}
215
+ ADD COLUMN IF NOT EXISTS search_vector tsvector
216
+ GENERATED ALWAYS AS (to_tsvector('english', search_text)) STORED`, [], signal);
203
217
  await this.query(pool, `CREATE INDEX IF NOT EXISTS ${this.ident(`${this.bareName(table)}_fts`)}
204
218
  ON ${table} USING gin (search_vector)`, [], signal);
205
219
  this.provisioned.add(table);
@@ -241,6 +255,27 @@ export class LakebaseSearchBackend {
241
255
  }
242
256
  return fields;
243
257
  }
258
+ /** Compile AppKit scalar/array filters against the stored JSON document. */
259
+ filterClause(filter, startPosition) {
260
+ if (!filter || Object.keys(filter).length === 0)
261
+ return { sql: "", params: [] };
262
+ const clauses = [];
263
+ const params = [];
264
+ for (const [key, value] of Object.entries(filter)) {
265
+ const keyPosition = startPosition + params.length;
266
+ params.push(key);
267
+ const valuePosition = startPosition + params.length;
268
+ if (Array.isArray(value)) {
269
+ params.push(value.map(String));
270
+ clauses.push(`document ->> $${keyPosition} = ANY($${valuePosition}::text[])`);
271
+ }
272
+ else {
273
+ params.push(String(value));
274
+ clauses.push(`document ->> $${keyPosition} = $${valuePosition}`);
275
+ }
276
+ }
277
+ return { sql: ` AND ${clauses.join(" AND ")}`, params };
278
+ }
244
279
  /** The fully-qualified table name for an index reference. */
245
280
  tableFor(index) {
246
281
  return `${this.ident(this.schema)}.${this.ident(this.bareName(index))}`;
@@ -248,10 +283,7 @@ export class LakebaseSearchBackend {
248
283
  /** A safe bare table name derived from an index reference. */
249
284
  bareName(reference) {
250
285
  const last = reference.split(".").filter(Boolean).pop() ?? reference;
251
- const slug = last
252
- .toLowerCase()
253
- .replace(/[^a-z0-9_]+/g, "_")
254
- .replace(/^_+|_+$/g, "");
286
+ const slug = string.toSlug(last).replace(/-/g, "_");
255
287
  return slug.length > 0 ? slug : "documents";
256
288
  }
257
289
  /** Quote a Postgres identifier. */
@@ -282,4 +314,4 @@ export class LakebaseSearchBackend {
282
314
  }
283
315
  }
284
316
  }
285
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFrZWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGFrZWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5Qkc7QUFFSCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDcEQsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFPN0QsT0FBTyxFQUFFLElBQUksRUFBbUIsTUFBTSxJQUFJLENBQUM7QUFFM0MsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBRTdDLHVGQUF1RjtBQUN2RixNQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQztBQUVyRjs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUNILE1BQU0sVUFBVSxhQUFhLENBQUMsS0FBYTtJQUN6QyxPQUFPO1FBQ0wsR0FBRyxNQUFNLENBQUMsbUJBQW1CLENBQUMsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssQ0FBQztLQUM1RixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLEtBQXdCLEVBQUUsV0FBc0IsR0FBRztJQUMzRSxPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDO0FBQ2hFLENBQUM7QUF5QkQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLHFCQUFxQjtJQU1iO0lBQ0E7SUFFQTtJ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O1FBRXBCLElBQUksTUFBTSxFQUFFLE9BQU87WUFBRSxNQUFNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNyRCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNwQyxJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUM7UUFDckIsTUFBTSxPQUFPLEdBQUcsR0FBRyxFQUFFO1lBQ25CLElBQUksUUFBUTtnQkFBRSxPQUFPO1lBQ3JCLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDaEIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2QixDQUFDLENBQUM7UUFDRixNQUFNLEVBQUUsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDL0MsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsSUFBVyxFQUFFLENBQUM7UUFDdEMsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsTUFBTSxFQUFFLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUM5QyxJQUFJLENBQUMsUUFBUTtnQkFBRSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDbEMsQ0FBQztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQSBMYWtlYmFzZSAoUG9zdGdyZXMpIGZ1bGwtdGV4dCBzZWFyY2ggYmFja2VuZCAtIHRoZSBGQUxMQkFDSyB1c2VkIHdoZW4gbm9cbiAqIERhdGFicmlja3MgVmVjdG9yIFNlYXJjaCBlbmRwb2ludC9pbmRleCBpcyBjb25maWd1cmVkIGJ1dCBhIExha2ViYXNlIHBvb2wgaXNcbiAqIGF2YWlsYWJsZS4gSXQgcHJvdmlzaW9ucyBhIHNpbmdsZSB0YWJsZSBwZXIgaW5kZXgsIGluZGV4ZXMgYSBnZW5lcmF0ZWRcbiAqIGB0c3ZlY3RvcmAsIGFuZCBhbnN3ZXJzIHF1ZXJpZXMgd2l0aCBhIHByZWZpeCBgdG9fdHNxdWVyeWAgKyBgdHNfcmFua2AuXG4gKlxuICogUXVlcmllcyBhcmUgY29tcGlsZWQgcmF0aGVyIHRoYW4gcGFzc2VkIHRocm91Z2ggYHdlYnNlYXJjaF90b190c3F1ZXJ5YCxcbiAqIGJlY2F1c2UgYSBzZWFyY2ggYm94IG5lZWRzIHR3byB0aGluZ3MgdGhhdCBmdW5jdGlvbiBkb2VzIG5vdCBnaXZlOlxuICogcHVuY3R1YXRpb24taW5zZW5zaXRpdml0eSAoc28gYHN0b3JlLWludGVsbGlnZW5jZWAgbWF0Y2hlcyB0aGUgc2FtZSByb3dzIGFzXG4gKiBgc3RvcmUgaW50ZWxsaWdlbmNlYCkgYW5kIHByZWZpeCBtYXRjaGluZyAoc28gYGludGVsYCByZWFjaGVzXG4gKiBgaW50ZWxsaWdlbmNlYCkuIFNlZSB7QGxpbmsgdG9TZWFyY2hUZXJtc30gLyB7QGxpbmsgdG9Uc1F1ZXJ5fS5cbiAqXG4gKiBUaGUgd2hvbGUgcG9pbnQgaXMgcGFyaXR5OiB0aGlzIGJhY2tlbmQgcmV0dXJucyB0aGUgRVhBQ1Qgc2FtZVxuICogYEBkYngtdG9vbHMvc2hhcmVkLXNlYXJjaGAgc2hhcGVzIChgU2VhcmNoUmVzdWx0YCAvIGBTZWFyY2hIaXRgIC9cbiAqIGBVcHNlcnRSZXN1bHRgKSBhcyB0aGUgVmVjdG9yIFNlYXJjaCBiYWNrZW5kLCBzbyB0aGUgY2xpZW50LCB0aGUgTWFzdHJhXG4gKiB0b29scywgdGhlIHJvdXRlcywgYW5kIHRoZSBSZWFjdCBzZWFyY2ggYm94IGNhbm5vdCB0ZWxsIHdoaWNoIG9uZSBhbnN3ZXJlZC5cbiAqIEEgaGl0J3MgYGlkYCBpcyB0aGUgcHJpbWFyeSBrZXksIGl0cyBgc2NvcmVgIGlzIHRoZSB0ZXh0LXJhbmssIGFuZCBgZmllbGRzYFxuICogaXMgdGhlIHN0b3JlZCBkb2N1bWVudCBtaW51cyB0aGUgaW50ZXJuYWwgY29sdW1ucy5cbiAqXG4gKiBUaGUgUG9zdGdyZXMgcG9vbCBpcyBidWlsdCB0aGUgc2FtZSB3YXkgYEBkYngtdG9vbHMvYXBwa2l0LW1hc3RyYWAgYnVpbGRzIGl0c1xuICogbWVtb3J5IHBvb2w6IHRoZSBBcHBLaXQgYGxha2ViYXNlYCBwbHVnaW4gcmVzb2x2ZXMgYSBzZXJ2aWNlLXByaW5jaXBhbFxuICogYFBvb2xDb25maWdgIChjb25uZWN0aW9uIHRhcmdldCArIE9BdXRoIHRva2VuLXJlZnJlc2ggYHBhc3N3b3JkYCBjYWxsYmFjayksXG4gKiBhbmQgdGhpcyBiYWNrZW5kIGNvbnN0cnVjdHMgYSBgcGcuUG9vbGAgZnJvbSBpdC4gSXQgbmV2ZXIgcmUtaW1wbGVtZW50cyBhdXRoLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBFeGVjdXRpb25FcnJvciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGxvZywgb2JqZWN0LCBzdHJpbmcgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUge1xuICBTZWFyY2hEb2N1bWVudCxcbiAgU2VhcmNoSGl0LFxuICBTZWFyY2hSZXN1bHQsXG4gIFVwc2VydFJlc3VsdCxcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLXNlYXJjaFwiO1xuaW1wb3J0IHsgUG9vbCwgdHlwZSBQb29sQ29uZmlnIH0gZnJvbSBcInBnXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJzZWFyY2gvbGFrZWJhc2VcIik7XG5cbi8qKiBUaGUgaW50ZXJuYWwgY29sdW1ucyBldmVyeSBzZWFyY2ggdGFibGUgY2FycmllcywgZXhjbHVkZWQgZnJvbSBhIGhpdCdzIGBmaWVsZHNgLiAqL1xuY29uc3QgUkVTRVJWRURfQ09MVU1OUyA9IG5ldyBTZXQoW1wiaWRcIiwgXCJzZWFyY2hfdGV4dFwiLCBcImRvY3VtZW50XCIsIFwic2VhcmNoX3ZlY3RvclwiXSk7XG5cbi8qKlxuICogU3BsaXQgYSBzZWFyY2gtYm94IHN0cmluZyBpbnRvIHRoZSB0ZXJtcyBhIHRzcXVlcnkgaXMgYnVpbHQgZnJvbSwgdXNpbmcgdGhlXG4gKiBzaGFyZWQgYEBkYngtdG9vbHMvc2hhcmVkLWNvcmVgIHRva2VuaXplciBzbyB0aGUgc3BsaXR0aW5nIHJ1bGVzIHN0YXlcbiAqIGNvbnNpc3RlbnQgd2l0aCB0aGUgcmVzdCBvZiB0aGUgdG9vbGtpdC5cbiAqXG4gKiBTcGxpdHRpbmcgb24gcHVuY3R1YXRpb24gaXMgd2hhdCBtYWtlcyBgc3RvcmUtaW50ZWxsaWdlbmNlYCBiZWhhdmUgbGlrZVxuICogYHN0b3JlIGludGVsbGlnZW5jZWAuIFBvc3RncmVzIGluZGV4ZXMgYSBoeXBoZW5hdGVkIHdvcmQgYXMgdGhlIGNvbXBvdW5kXG4gKiBsZXhlbWUgUExVUyBlYWNoIG9mIGl0cyBwYXJ0cywgYnV0IGNvbXBpbGVzIGEgaHlwaGVuYXRlZCBRVUVSWSB0byB0aGVcbiAqIGNvbXBvdW5kIGFsb25lIC0gc28gYHN0b3JlLWludGVsbGlnZW5jZWAgZGVtYW5kcyBhIGBzdG9yZS1pbnRlbGxpZ2AgbGV4ZW1lXG4gKiB0aGF0IGEgZG9jdW1lbnQgdGl0bGVkIGByYWNldHJhYy1zdG9yZS1pbnRlbGxpZ2VuY2VgIGRvZXMgbm90IGhhdmUsIGFuZCB0aGVcbiAqIHNlYXJjaCBzaWxlbnRseSByZXR1cm5zIG5vdGhpbmcgd2hpbGUgYHN0b3JlIGludGVsbGlnZW5jZWAgcmV0dXJuc1xuICogZXZlcnl0aGluZy4gU2FtZSBmb3IgYC5gIGFuZCBgX2AgaW4gYSB0YWJsZSByZWZlcmVuY2UuXG4gKlxuICogYGNhbWVsQ2FzZTogZmFsc2VgIGlzIGxvYWQtYmVhcmluZyByYXRoZXIgdGhhbiBhIGRlZmF1bHQ6IHRoZSBjYW1lbENhc2VcbiAqIHNwbGl0dGVyIGFsc28gYnJlYWtzIGRpZ2l0IHJ1bnMsIHR1cm5pbmcgYGdwdDRgIGludG8gYGdwdGAgKyBgNGAgYW5kIGBzM2BcbiAqIGludG8gYHNgICsgYDNgLiBQb3N0Z3JlcyBpbmRleGVzIGVhY2ggb2YgdGhvc2UgYXMgT05FIGxleGVtZSwgc28gbm8gbGV4ZW1lXG4gKiBldmVyIHN0YXJ0cyB3aXRoIHRoZSB0cmFpbGluZyBkaWdpdHMgYW5kIHRoZSBwcmVjaXNlIHBhc3MgY291bGQgbm90IG1hdGNoXG4gKiB0aGVtLiBLZWVwaW5nIHB1bmN0dWF0aW9uIGFzIHRoZSBvbmx5IGJvdW5kYXJ5IG1pcnJvcnMgaG93IHRoZSBpbmRleCB3YXNcbiAqIGJ1aWx0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9TZWFyY2hUZXJtcyhxdWVyeTogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gW1xuICAgIC4uLnN0cmluZy50b2tlbml6ZVdpdGhPcHRpb25zKHsgbG93ZXJDYXNlOiB0cnVlLCBjYW1lbENhc2U6IGZhbHNlLCBkaXN0aW5jdDogdHJ1ZSB9LCBxdWVyeSksXG4gIF07XG59XG5cbi8qKlxuICogQ29tcGlsZSB0ZXJtcyBpbnRvIGEgYHRvX3RzcXVlcnlgIGlucHV0IHdoZXJlIGV2ZXJ5IHRlcm0gaXMgYSBQUkVGSVgsIHNvIGFcbiAqIHBhcnRpYWxseSB0eXBlZCB3b3JkIHN0aWxsIG1hdGNoZXMgKGBpbnRlbDoqYCByZWFjaGVzIGBpbnRlbGxpZ2VuY2VgKS5cbiAqXG4gKiBUZXJtcyBjYXJyeSBvbmx5IGxldHRlcnMgYW5kIGRpZ2l0cyBieSBjb25zdHJ1Y3Rpb24sIHNvIG5vbmUgb2YgdHNxdWVyeSdzXG4gKiBvcGVyYXRvcnMgKGAmIHwgISAoICkgOiAqYCkgY2FuIHN1cnZpdmUgZnJvbSB1c2VyIGlucHV0IGludG8gdGhlIGNvbXBpbGVkXG4gKiBzdHJpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b1RzUXVlcnkodGVybXM6IHJlYWRvbmx5IHN0cmluZ1tdLCBvcGVyYXRvcjogXCImXCIgfCBcInxcIiA9IFwiJlwiKTogc3RyaW5nIHtcbiAgcmV0dXJuIHRlcm1zLm1hcCgodGVybSkgPT4gYCR7dGVybX06KmApLmpvaW4oYCAke29wZXJhdG9yfSBgKTtcbn1cblxuLyoqIE9wdGlvbnMgZm9yIGEgc2luZ2xlLWluZGV4IExha2ViYXNlIHNlYXJjaCAobWlycm9ycyB0aGUgY2xpZW50J3MgYFNlYXJjaE9wdGlvbnNgKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTGFrZWJhc2VTZWFyY2hPcHRpb25zIHtcbiAgbGltaXQ/OiBudW1iZXI7XG4gIHNjb3JlVGhyZXNob2xkPzogbnVtYmVyO1xuICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbn1cblxuLyoqIE9uZSByYXcgc2VhcmNoIHJvdyBiZWZvcmUgaXQgaXMgc2hhcGVkIGludG8gYSB7QGxpbmsgU2VhcmNoSGl0fS4gKi9cbmludGVyZmFjZSBTZWFyY2hSb3cge1xuICBpZDogc3RyaW5nO1xuICBkb2N1bWVudDogdW5rbm93bjtcbiAgc2NvcmU6IG51bWJlcjtcbn1cblxuLyoqIE9wdGlvbnMgZm9yIHByb3Zpc2lvbmluZyBhIExha2ViYXNlLWJhY2tlZCBpbmRleC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTGFrZWJhc2VQcm92aXNpb25PcHRpb25zIHtcbiAgLyoqIFRleHQgY29sdW1uIGVtYmVkZGVkIGludG8gdGhlIHNlYXJjaCB2ZWN0b3IuIERlZmF1bHRzIHRvIGB0ZXh0YC4gKi9cbiAgdGV4dENvbHVtbj86IHN0cmluZztcbiAgLyoqIERvY3VtZW50cyB0byBzZWVkIHdoZW4gdGhlIHRhYmxlIGlzIGVtcHR5LiAqL1xuICBzZWVkPzogU2VhcmNoRG9jdW1lbnRbXTtcbiAgc2lnbmFsPzogQWJvcnRTaWduYWw7XG59XG5cbi8qKlxuICogQSBQb3N0Z3JlcyBmdWxsLXRleHQgYmFja2VuZC4gT25lIGluc3RhbmNlIGlzIHNoYXJlZCBhY3Jvc3MgaW5kZXhlczsgZWFjaFxuICogaW5kZXggbWFwcyB0byBhIHRhYmxlIHdob3NlIG5hbWUgaXMgZGVyaXZlZCBmcm9tIHRoZSBpbmRleCByZWZlcmVuY2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBMYWtlYmFzZVNlYXJjaEJhY2tlbmQge1xuICBwcml2YXRlIHBvb2w6IFBvb2wgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgcG9vbFByb21pc2U6IFByb21pc2U8UG9vbD4gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvdmlzaW9uZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHBnQ29uZmlnRmFjdG9yeTogKCkgPT4gUHJvbWlzZTxQb29sQ29uZmlnPiB8IFBvb2xDb25maWcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzY2hlbWEgPSBcInB1YmxpY1wiLFxuICAgIC8qKiBIb3cgYSBwb29sIGlzIGJ1aWx0IGZyb20gdGhlIHJlc29sdmVkIGNvbmZpZy4gT3ZlcnJpZGFibGUgZm9yIHRlc3RzLiAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgcG9vbEZhY3Rvcnk6IChjb25maWc6IFBvb2xDb25maWcpID0+IFBvb2wgPSAoY29uZmlnKSA9PiBuZXcgUG9vbChjb25maWcpLFxuICApIHt9XG5cbiAgLyoqIExhemlseSBidWlsZCAoYW5kIGNhY2hlKSB0aGUgcGcgcG9vbCBmcm9tIHRoZSByZXNvbHZlZCBMYWtlYmFzZSBjb25maWcuICovXG4gIHByaXZhdGUgYXN5bmMgZ2V0UG9vbCgpOiBQcm9taXNlPFBvb2w+IHtcbiAgICBpZiAodGhpcy5wb29sKSByZXR1cm4gdGhpcy5wb29sO1xuICAgIHRoaXMucG9vbFByb21pc2UgPz89IChhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjb25maWcgPSBhd2FpdCB0aGlzLnBnQ29uZmlnRmFjdG9yeSgpO1xuICAgICAgY29uc3QgcG9vbCA9IHRoaXMucG9vbEZhY3RvcnkoY29uZmlnKTtcbiAgICAgIHRoaXMucG9vbCA9IHBvb2w7XG4gICAgICByZXR1cm4gcG9vbDtcbiAgICB9KSgpO1xuICAgIHJldHVybiB0aGlzLnBvb2xQcm9taXNlO1xuICB9XG5cbiAgLyoqIENsb3NlIHRoZSBwb29sIHNvIGEgcmVzdGFydGVkIGFwcCByZWJ1aWxkcyBpdC4gKi9cbiAgYXN5bmMgY2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcG9vbCA9IHRoaXMucG9vbDtcbiAgICB0aGlzLnBvb2wgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5wb29sUHJvbWlzZSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnByb3Zpc2lvbmVkLmNsZWFyKCk7XG4gICAgaWYgKHBvb2wpIGF3YWl0IHBvb2wuZW5kKCk7XG4gIH1cblxuICAvKipcbiAgICogU2VhcmNoIGEgTGFrZWJhc2UtYmFja2VkIGluZGV4LiBSZXR1cm5zIGhpdHMgc29ydGVkIG1vc3QtcmVsZXZhbnQtZmlyc3QsXG4gICAqIHNoYXBlZCBpZGVudGljYWxseSB0byB0aGUgVmVjdG9yIFNlYXJjaCBiYWNrZW5kLlxuICAgKi9cbiAgYXN5bmMgc2VhcmNoKFxuICAgIGluZGV4OiBzdHJpbmcsXG4gICAgcXVlcnk6IHN0cmluZyxcbiAgICBvcHRpb25zOiBMYWtlYmFzZVNlYXJjaE9wdGlvbnMgPSB7fSxcbiAgKTogUHJvbWlzZTxTZWFyY2hSZXN1bHQ+IHtcbiAgICBjb25zdCB0ZXh0ID0gc3RyaW5nLnRyaW1Ub0VtcHR5KHF1ZXJ5KTtcbiAgICBjb25zdCB0YWJsZSA9IHRoaXMudGFibGVGb3IoaW5kZXgpO1xuICAgIGNvbnN0IGxpbWl0ID0gb3B0aW9ucy5saW1pdCA/PyAxMDtcbiAgICBjb25zdCBwb29sID0gYXdhaXQgdGhpcy5nZXRQb29sKCk7XG4gICAgY29uc3QgdGVybXMgPSB0b1NlYXJjaFRlcm1zKHRleHQpO1xuXG4gICAgLy8gQW4gZW1wdHkgKG9yIHB1bmN0dWF0aW9uLW9ubHkpIGJveCByZXR1cm5zIHJvd3MgcmF0aGVyIHRoYW4gbm90aGluZywgc29cbiAgICAvLyB0aGUgVUkgc2hvd3MgY29udGVudCBiZWZvcmUgdGhlIHVzZXIgdHlwZXMgLSBhcyBhIGtleXdvcmQgaW5kZXggd291bGQuXG4gICAgaWYgKHRlcm1zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgY29uc3QgeyByb3dzIH0gPSBhd2FpdCB0aGlzLnF1ZXJ5PFNlYXJjaFJvdz4oXG4gICAgICAgIHBvb2wsXG4gICAgICAgIGBTRUxFQ1QgaWQsIGRvY3VtZW50LCAwOjpmbG9hdDQgQVMgc2NvcmUgRlJPTSAke3RhYmxlfSBPUkRFUiBCWSBpZCBMSU1JVCAkMWAsXG4gICAgICAgIFtsaW1pdF0sXG4gICAgICAgIG9wdGlvbnMuc2lnbmFsLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB0aGlzLnRvUmVzdWx0KHRleHQsIGluZGV4LCByb3dzLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICAvLyBQcmVjaXNlIHBhc3M6IGV2ZXJ5IHRlcm0gbXVzdCBtYXRjaCwgZWFjaCBhcyBhIHByZWZpeC5cbiAgICBjb25zdCBzdHJpY3QgPSBhd2FpdCB0aGlzLnF1ZXJ5PFNlYXJjaFJvdz4oXG4gICAgICBwb29sLFxuICAgICAgYFNFTEVDVCBpZCwgZG9jdW1lbnQsIHRzX3Jhbmsoc2VhcmNoX3ZlY3RvciwgdG9fdHNxdWVyeSgnZW5nbGlzaCcsICQxKSkgQVMgc2NvcmVcbiAgICAgICAgIEZST00gJHt0YWJsZX1cbiAgICAgICAgV0hFUkUgc2VhcmNoX3ZlY3RvciBAQCB0b190c3F1ZXJ5KCdlbmdsaXNoJywgJDEpXG4gICAgICAgIE9SREVSIEJZIHNjb3JlIERFU0NcbiAgICAgICAgTElNSVQgJDJgLFxuICAgICAgW3RvVHNRdWVyeSh0ZXJtcyksIGxpbWl0XSxcbiAgICAgIG9wdGlvbnMuc2lnbmFsLFxuICAgICk7XG4gICAgaWYgKHN0cmljdC5yb3dzLmxlbmd0aCA+IDApIHJldHVybiB0aGlzLnRvUmVzdWx0KHRleHQsIGluZGV4LCBzdHJpY3Qucm93cywgb3B0aW9ucyk7XG5cbiAgICAvLyBOb3RoaW5nIG1hdGNoZWQgRVZFUlkgdGVybSwgc28gcmVsYXggcmF0aGVyIHRoYW4gcmV0dXJuIGFuIGVtcHR5IGJveDpcbiAgICAvLyBhbnkgb25lIHRlcm0gaXMgZW5vdWdoLCBhbmQgYW4gYElMSUtFYCBwYXNzIGFkZGl0aW9uYWxseSBjYXRjaGVzIGFcbiAgICAvLyBmcmFnbWVudCB0aGF0IGlzIG5vdCBhIHByZWZpeCAoYHRlbGxpZ2VuY2VgKSBvciBhIHRva2VuIHRoZSB0ZXh0LXNlYXJjaFxuICAgIC8vIHBhcnNlciBzcGxpdCBkaWZmZXJlbnRseSB0aGFuIGV4cGVjdGVkLiBTdWJzdHJpbmcgbWF0Y2hpbmcgY2Fubm90IHVzZVxuICAgIC8vIHRoZSBHSU4gaW5kZXgsIHdoaWNoIGlzIHdoeSBpdCBvbmx5IHJ1bnMgb25jZSB0aGUgaW5kZXhlZCBwYXNzIGZhaWxzLlxuICAgIGNvbnN0IHJlbGF4ZWQgPSBhd2FpdCB0aGlzLnF1ZXJ5PFNlYXJjaFJvdz4oXG4gICAgICBwb29sLFxuICAgICAgYFNFTEVDVCBpZCwgZG9jdW1lbnQsIHRzX3Jhbmsoc2VhcmNoX3ZlY3RvciwgdG9fdHNxdWVyeSgnZW5nbGlzaCcsICQxKSkgQVMgc2NvcmVcbiAgICAgICAgIEZST00gJHt0YWJsZX1cbiAgICAgICAgV0hFUkUgc2VhcmNoX3ZlY3RvciBAQCB0b190c3F1ZXJ5KCdlbmdsaXNoJywgJDEpXG4gICAgICAgICAgIE9SIHNlYXJjaF90ZXh0IElMSUtFIEFOWSgkMjo6dGV4dFtdKVxuICAgICAgICBPUkRFUiBCWSBzY29yZSBERVNDXG4gICAgICAgIExJTUlUICQzYCxcbiAgICAgIFt0b1RzUXVlcnkodGVybXMsIFwifFwiKSwgdGVybXMubWFwKCh0ZXJtKSA9PiBgJSR7dGVybX0lYCksIGxpbWl0XSxcbiAgICAgIG9wdGlvbnMuc2lnbmFsLFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMudG9SZXN1bHQodGV4dCwgaW5kZXgsIHJlbGF4ZWQucm93cywgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogU2hhcGUgcmF3IHJvd3MgaW50byB0aGUgYFNlYXJjaFJlc3VsdGAgYm90aCBiYWNrZW5kcyByZXR1cm4uICovXG4gIHByaXZhdGUgdG9SZXN1bHQoXG4gICAgcXVlcnk6IHN0cmluZyxcbiAgICBpbmRleDogc3RyaW5nLFxuICAgIHJvd3M6IFNlYXJjaFJvd1tdLFxuICAgIG9wdGlvbnM6IExha2ViYXNlU2VhcmNoT3B0aW9ucyxcbiAgKTogU2VhcmNoUmVzdWx0IHtcbiAgICBjb25zdCBoaXRzOiBTZWFyY2hIaXRbXSA9IHJvd3NcbiAgICAgIC5tYXAoKHJvdykgPT4gKHtcbiAgICAgICAgaWQ6IFN0cmluZyhyb3cuaWQpLFxuICAgICAgICBzY29yZTogTnVtYmVyKHJvdy5zY29yZSkgfHwgMCxcbiAgICAgICAgZmllbGRzOiB0aGlzLnRvRmllbGRzKHJvdy5kb2N1bWVudCksXG4gICAgICB9KSlcbiAgICAgIC5maWx0ZXIoKGhpdCkgPT4gb3B0aW9ucy5zY29yZVRocmVzaG9sZCA9PT0gdW5kZWZpbmVkIHx8IGhpdC5zY29yZSA+PSBvcHRpb25zLnNjb3JlVGhyZXNob2xkKTtcbiAgICByZXR1cm4geyBxdWVyeSwgaW5kZXgsIGhpdHMsIGNvdW50OiBoaXRzLmxlbmd0aCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEVuc3VyZSB0aGUgdGFibGUgKyBmdWxsLXRleHQgaW5kZXggZXhpc3QgYW5kIHNlZWQgZG9jdW1lbnRzIHdoZW4gZW1wdHkuXG4gICAqIElkZW1wb3RlbnQsIHNvIGl0IGlzIHNhZmUgdG8gY2FsbCBvbiBldmVyeSBib290LlxuICAgKi9cbiAgYXN5bmMgcHJvdmlzaW9uKGluZGV4OiBzdHJpbmcsIG9wdGlvbnM6IExha2ViYXNlUHJvdmlzaW9uT3B0aW9ucyA9IHt9KTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB0YWJsZSA9IHRoaXMudGFibGVGb3IoaW5kZXgpO1xuICAgIGNvbnN0IHBvb2wgPSBhd2FpdCB0aGlzLmdldFBvb2woKTtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVRhYmxlKHBvb2wsIHRhYmxlLCBvcHRpb25zLnNpZ25hbCk7XG5cbiAgICBjb25zdCB7IHJvd3MgfSA9IGF3YWl0IHRoaXMucXVlcnk8eyBjb3VudDogc3RyaW5nIH0+KFxuICAgICAgcG9vbCxcbiAgICAgIGBTRUxFQ1QgY291bnQoKik6OnRleHQgQVMgY291bnQgRlJPTSAke3RhYmxlfWAsXG4gICAgICBbXSxcbiAgICAgIG9wdGlvbnMuc2lnbmFsLFxuICAgICk7XG4gICAgY29uc3QgZXhpc3RpbmcgPSBOdW1iZXIocm93c1swXT8uY291bnQgPz8gXCIwXCIpO1xuICAgIGNvbnN0IHNlZWQgPSBvcHRpb25zLnNlZWQgPz8gW107XG4gICAgaWYgKGV4aXN0aW5nID09PSAwICYmIHNlZWQubGVuZ3RoID4gMCkge1xuICAgICAgYXdhaXQgdGhpcy51cHNlcnQocG9vbCwgdGFibGUsIHNlZWQsIG9wdGlvbnMudGV4dENvbHVtbiA/PyBcInRleHRcIiwgb3B0aW9ucy5zaWduYWwpO1xuICAgICAgbG9nZ2VyLmluZm8oXCJpbmRleC1zZWVkZWRcIiwgeyBpbmRleCwgdGFibGUsIGNvdW50OiBzZWVkLmxlbmd0aCB9KTtcbiAgICAgIHJldHVybiBzZWVkLmxlbmd0aDtcbiAgICB9XG4gICAgcmV0dXJuIGV4aXN0aW5nO1xuICB9XG5cbiAgLyoqIEFkZCBvciB1cGRhdGUgZG9jdW1lbnRzIGJ5IHByaW1hcnkga2V5LiAqL1xuICBhc3luYyBhZGREb2N1bWVudHMoXG4gICAgaW5kZXg6IHN0cmluZyxcbiAgICBkb2N1bWVudHM6IFNlYXJjaERvY3VtZW50W10sXG4gICAgdGV4dENvbHVtbiA9IFwidGV4dFwiLFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICApOiBQcm9taXNlPFVwc2VydFJlc3VsdD4ge1xuICAgIGNvbnN0IHRhYmxlID0gdGhpcy50YWJsZUZvcihpbmRleCk7XG4gICAgY29uc3QgcG9vbCA9IGF3YWl0IHRoaXMuZ2V0UG9vbCgpO1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlVGFibGUocG9vbCwgdGFibGUsIHNpZ25hbCk7XG4gICAgYXdhaXQgdGhpcy51cHNlcnQocG9vbCwgdGFibGUsIGRvY3VtZW50cywgdGV4dENvbHVtbiwgc2lnbmFsKTtcbiAgICByZXR1cm4geyBpbmRleCwgY291bnQ6IGRvY3VtZW50cy5sZW5ndGggfTtcbiAgfVxuXG4gIC8qKiBEZWxldGUgZG9jdW1lbnRzIGJ5IHByaW1hcnkga2V5LiAqL1xuICBhc3luYyBkZWxldGVEb2N1bWVudHMoXG4gICAgaW5kZXg6IHN0cmluZyxcbiAgICBpZHM6IEFycmF5PHN0cmluZyB8IG51bWJlcj4sXG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4gICk6IFByb21pc2U8VXBzZXJ0UmVzdWx0PiB7XG4gICAgY29uc3QgdGFibGUgPSB0aGlzLnRhYmxlRm9yKGluZGV4KTtcbiAgICBjb25zdCBwb29sID0gYXdhaXQgdGhpcy5nZXRQb29sKCk7XG4gICAgYXdhaXQgdGhpcy5xdWVyeShwb29sLCBgREVMRVRFIEZST00gJHt0YWJsZX0gV0hFUkUgaWQgPSBBTlkoJDEpYCwgW2lkcy5tYXAoU3RyaW5nKV0sIHNpZ25hbCk7XG4gICAgcmV0dXJuIHsgaW5kZXgsIGNvdW50OiBpZHMubGVuZ3RoIH07XG4gIH1cblxuICAvKiogQ3JlYXRlIHRoZSB0YWJsZSArIEdJTiBpbmRleCBvbmNlIHBlciB0YWJsZSAobWVtb2l6ZWQgYWNyb3NzIGNhbGxzKS4gKi9cbiAgcHJpdmF0ZSBhc3luYyBlbnN1cmVUYWJsZShwb29sOiBQb29sLCB0YWJsZTogc3RyaW5nLCBzaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLnByb3Zpc2lvbmVkLmhhcyh0YWJsZSkpIHJldHVybjtcbiAgICAvLyBgZG9jdW1lbnRgIGhvbGRzIHRoZSB3aG9sZSByb3c7IGBzZWFyY2hfdGV4dGAgaXMgdGhlIGluZGV4ZWQgdGV4dDsgdGhlXG4gICAgLy8gZ2VuZXJhdGVkIGBzZWFyY2hfdmVjdG9yYCBrZWVwcyB0aGUgdHN2ZWN0b3IgaW4gbG9ja3N0ZXAgd2l0aCBpdCBzbyBhXG4gICAgLy8gd3JpdGUgbmV2ZXIgaGFzIHRvIGNvbXB1dGUgdGhlIHZlY3RvciBieSBoYW5kLlxuICAgIGF3YWl0IHRoaXMucXVlcnkocG9vbCwgYENSRUFURSBTQ0hFTUEgSUYgTk9UIEVYSVNUUyAke3RoaXMuaWRlbnQodGhpcy5zY2hlbWEpfWAsIFtdLCBzaWduYWwpO1xuICAgIGF3YWl0IHRoaXMucXVlcnkoXG4gICAgICBwb29sLFxuICAgICAgYENSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTICR7dGFibGV9IChcbiAgICAgICAgIGlkIHRleHQgUFJJTUFSWSBLRVksXG4gICAgICAgICBzZWFyY2hfdGV4dCB0ZXh0IE5PVCBOVUxMIERFRkFVTFQgJycsXG4gICAgICAgICBkb2N1bWVudCBqc29uYiBOT1QgTlVMTCBERUZBVUxUICd7fSc6Ompzb25iLFxuICAgICAgICAgc2VhcmNoX3ZlY3RvciB0c3ZlY3RvciBHRU5FUkFURUQgQUxXQVlTIEFTICh0b190c3ZlY3RvcignZW5nbGlzaCcsIHNlYXJjaF90ZXh0KSkgU1RPUkVEXG4gICAgICAgKWAsXG4gICAgICBbXSxcbiAgICAgIHNpZ25hbCxcbiAgICApO1xuICAgIGF3YWl0IHRoaXMucXVlcnkoXG4gICAgICBwb29sLFxuICAgICAgYENSRUFURSBJTkRFWCBJRiBOT1QgRVhJU1RTICR7dGhpcy5pZGVudChgJHt0aGlzLmJhcmVOYW1lKHRhYmxlKX1fZnRzYCl9XG4gICAgICAgICBPTiAke3RhYmxlfSBVU0lORyBnaW4gKHNlYXJjaF92ZWN0b3IpYCxcbiAgICAgIFtdLFxuICAgICAgc2lnbmFsLFxuICAgICk7XG4gICAgdGhpcy5wcm92aXNpb25lZC5hZGQodGFibGUpO1xuICAgIGxvZ2dlci5pbmZvKFwiaW5kZXgtY3JlYXRlZFwiLCB7IHRhYmxlIH0pO1xuICB9XG5cbiAgLyoqIFVwc2VydCByb3dzOiB0aGUgd2hvbGUgZG9jdW1lbnQgYXMganNvbmIgKyBhIGZsYXR0ZW5lZCB0ZXh0IGJsb2IgdG8gaW5kZXguICovXG4gIHByaXZhdGUgYXN5bmMgdXBzZXJ0KFxuICAgIHBvb2w6IFBvb2wsXG4gICAgdGFibGU6IHN0cmluZyxcbiAgICBkb2N1bWVudHM6IFNlYXJjaERvY3VtZW50W10sXG4gICAgdGV4dENvbHVtbjogc3RyaW5nLFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGNvbnN0IGRvYyBvZiBkb2N1bWVudHMpIHtcbiAgICAgIGNvbnN0IGlkID0gc3RyaW5nLnRyaW1Ub051bGwoU3RyaW5nKGRvYy5pZCA/PyBkb2MuSUQgPz8gXCJcIikpID8/IHVuZGVmaW5lZDtcbiAgICAgIGlmIChpZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFeGVjdXRpb25FcnJvcihcInNlYXJjaCAobGFrZWJhc2UpOiBhIGRvY3VtZW50IGlzIG1pc3NpbmcgYW4gYGlkYFwiLCB7XG4gICAgICAgICAgY29udGV4dDogeyBvcGVyYXRpb246IFwiYWRkRG9jdW1lbnRzXCIgfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBjb25zdCBzZWFyY2hUZXh0ID0gdGhpcy5zZWFyY2hUZXh0KGRvYywgdGV4dENvbHVtbik7XG4gICAgICBhd2FpdCB0aGlzLnF1ZXJ5KFxuICAgICAgICBwb29sLFxuICAgICAgICBgSU5TRVJUIElOVE8gJHt0YWJsZX0gKGlkLCBzZWFyY2hfdGV4dCwgZG9jdW1lbnQpXG4gICAgICAgICAgIFZBTFVFUyAoJDEsICQyLCAkMzo6anNvbmIpXG4gICAgICAgICBPTiBDT05GTElDVCAoaWQpIERPIFVQREFURVxuICAgICAgICAgICBTRVQgc2VhcmNoX3RleHQgPSBFWENMVURFRC5zZWFyY2hfdGV4dCwgZG9jdW1lbnQgPSBFWENMVURFRC5kb2N1bWVudGAsXG4gICAgICAgIFtpZCwgc2VhcmNoVGV4dCwgSlNPTi5zdHJpbmdpZnkoZG9jKV0sXG4gICAgICAgIHNpZ25hbCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFRoZSB0ZXh0IGEgcm93IGlzIGluZGV4ZWQgYnk6IHRoZSB0ZXh0IGNvbHVtbiBmaXJzdCwgdGhlbiBhbnkgb3RoZXIgc3RyaW5nIGZpZWxkLiAqL1xuICBwcml2YXRlIHNlYXJjaFRleHQoZG9jOiBTZWFyY2hEb2N1bWVudCwgdGV4dENvbHVtbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBwcmltYXJ5ID0gc3RyaW5nLnRyaW1Ub0VtcHR5KFN0cmluZyhkb2NbdGV4dENvbHVtbl0gPz8gXCJcIikpO1xuICAgIGNvbnN0IHJlc3QgPSBPYmplY3QuZW50cmllcyhkb2MpXG4gICAgICAuZmlsdGVyKChba2V5LCB2YWx1ZV0pID0+IGtleSAhPT0gdGV4dENvbHVtbiAmJiBrZXkgIT09IFwiaWRcIiAmJiB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIpXG4gICAgICAubWFwKChbLCB2YWx1ZV0pID0+IHZhbHVlIGFzIHN0cmluZyk7XG4gICAgcmV0dXJuIFtwcmltYXJ5LCAuLi5yZXN0XS5maWx0ZXIoQm9vbGVhbikuam9pbihcIlxcblwiKTtcbiAgfVxuXG4gIC8qKiBBIGhpdCdzIGBmaWVsZHNgOiB0aGUgc3RvcmVkIGRvY3VtZW50IG1pbnVzIHRoZSByZXNlcnZlZC9pbnRlcm5hbCBrZXlzLiAqL1xuICBwcml2YXRlIHRvRmllbGRzKGRvY3VtZW50OiB1bmtub3duKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICAgIGlmICghb2JqZWN0LmlzUmVjb3JkKGRvY3VtZW50KSkgcmV0dXJuIHt9O1xuICAgIGNvbnN0IGZpZWxkczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhkb2N1bWVudCkpIHtcbiAgICAgIGlmIChSRVNFUlZFRF9DT0xVTU5TLmhhcyhrZXkpKSBjb250aW51ZTtcbiAgICAgIGZpZWxkc1trZXldID0gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybiBmaWVsZHM7XG4gIH1cblxuICAvKiogVGhlIGZ1bGx5LXF1YWxpZmllZCB0YWJsZSBuYW1lIGZvciBhbiBpbmRleCByZWZlcmVuY2UuICovXG4gIHByaXZhdGUgdGFibGVGb3IoaW5kZXg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMuaWRlbnQodGhpcy5zY2hlbWEpfS4ke3RoaXMuaWRlbnQodGhpcy5iYXJlTmFtZShpbmRleCkpfWA7XG4gIH1cblxuICAvKiogQSBzYWZlIGJhcmUgdGFibGUgbmFtZSBkZXJpdmVkIGZyb20gYW4gaW5kZXggcmVmZXJlbmNlLiAqL1xuICBwcml2YXRlIGJhcmVOYW1lKHJlZmVyZW5jZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBsYXN0ID0gcmVmZXJlbmNlLnNwbGl0KFwiLlwiKS5maWx0ZXIoQm9vbGVhbikucG9wKCkgPz8gcmVmZXJlbmNlO1xuICAgIGNvbnN0IHNsdWcgPSBsYXN0XG4gICAgICAudG9Mb3dlckNhc2UoKVxuICAgICAgLnJlcGxhY2UoL1teYS16MC05X10rL2csIFwiX1wiKVxuICAgICAgLnJlcGxhY2UoL15fK3xfKyQvZywgXCJcIik7XG4gICAgcmV0dXJuIHNsdWcubGVuZ3RoID4gMCA/IHNsdWcgOiBcImRvY3VtZW50c1wiO1xuICB9XG5cbiAgLyoqIFF1b3RlIGEgUG9zdGdyZXMgaWRlbnRpZmllci4gKi9cbiAgcHJpdmF0ZSBpZGVudChuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBgXCIke25hbWUucmVwbGFjZSgvXCIvZywgJ1wiXCInKX1cImA7XG4gIH1cblxuICAvKiogUnVuIG9uZSBxdWVyeSB1bmRlciBleHRlcm5hbCBjYW5jZWxsYXRpb24uICovXG4gIHByaXZhdGUgYXN5bmMgcXVlcnk8VD4oXG4gICAgcG9vbDogUG9vbCxcbiAgICBzcWw6IHN0cmluZyxcbiAgICBwYXJhbXM6IHVua25vd25bXSxcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogUHJvbWlzZTx7IHJvd3M6IFRbXSB9PiB7XG4gICAgaWYgKHNpZ25hbD8uYWJvcnRlZCkgdGhyb3cgRXhlY3V0aW9uRXJyb3IuY2FuY2VsZWQoKTtcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBwb29sLmNvbm5lY3QoKTtcbiAgICBsZXQgcmVsZWFzZWQgPSBmYWxzZTtcbiAgICBjb25zdCBvbkFib3J0ID0gKCkgPT4ge1xuICAgICAgaWYgKHJlbGVhc2VkKSByZXR1cm47XG4gICAgICByZWxlYXNlZCA9IHRydWU7XG4gICAgICBjbGllbnQucmVsZWFzZSh0cnVlKTtcbiAgICB9O1xuICAgIHNpZ25hbD8uYWRkRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIG9uQWJvcnQsIHsgb25jZTogdHJ1ZSB9KTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY2xpZW50LnF1ZXJ5KHNxbCwgcGFyYW1zKTtcbiAgICAgIHJldHVybiB7IHJvd3M6IHJlc3VsdC5yb3dzIGFzIFRbXSB9O1xuICAgIH0gZmluYWxseSB7XG4gICAgICBzaWduYWw/LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBvbkFib3J0KTtcbiAgICAgIGlmICghcmVsZWFzZWQpIGNsaWVudC5yZWxlYXNlKCk7XG4gICAgfVxuICB9XG59XG4iXX0=
317
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFrZWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGFrZWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXdCRztBQUVILE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQVE3RCxPQUFPLEVBQUUsSUFBSSxFQUFtQixNQUFNLElBQUksQ0FBQztBQUUzQyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7QUFFN0MsdUZBQXVGO0FBQ3ZGLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxlQUFlLENBQUMsQ0FBQyxDQUFDO0FBRXJGOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxLQUFhO0lBQ3pDLE9BQU87UUFDTCxHQUFHLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxDQUFDO0tBQzVGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQUMsS0FBd0IsRUFBRSxXQUFzQixHQUFHO0lBQzNFLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLFFBQVEsR0FBRyxDQUFDLENBQUM7QUFDaEUsQ0FBQztBQTBCRDs7O0dBR0c7QUFDSCxNQUFNLE9BQU8scUJBQXFCO0lBTWI7SUFDQTtJQUVBO0lB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QU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdkIsQ0FBQyxDQUFDO1FBQ0YsTUFBTSxFQUFFLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUMzRCxJQUFJLENBQUM7WUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQy9DLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQVcsRUFBRSxDQUFDO1FBQ3RDLENBQUM7Z0JBQVMsQ0FBQztZQUNULE1BQU0sRUFBRSxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDOUMsSUFBSSxDQUFDLFFBQVE7Z0JBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2xDLENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIExha2ViYXNlIChQb3N0Z3JlcykgZnVsbC10ZXh0IHJ1bnRpbWUgYmVoaW5kIGBsYWtlYmFzZUFpU2VhcmNoYC4gSXQgcHJvdmlzaW9uc1xuICogYSBzaW5nbGUgdGFibGUgcGVyIGluZGV4IGFsaWFzLCBpbmRleGVzIGEgZ2VuZXJhdGVkXG4gKiBgdHN2ZWN0b3JgLCBhbmQgYW5zd2VycyBxdWVyaWVzIHdpdGggYSBwcmVmaXggYHRvX3RzcXVlcnlgICsgYHRzX3JhbmtgLlxuICpcbiAqIFF1ZXJpZXMgYXJlIGNvbXBpbGVkIHJhdGhlciB0aGFuIHBhc3NlZCB0aHJvdWdoIGB3ZWJzZWFyY2hfdG9fdHNxdWVyeWAsXG4gKiBiZWNhdXNlIGEgc2VhcmNoIGJveCBuZWVkcyB0d28gdGhpbmdzIHRoYXQgZnVuY3Rpb24gZG9lcyBub3QgZ2l2ZTpcbiAqIHB1bmN0dWF0aW9uLWluc2Vuc2l0aXZpdHkgKHNvIGBzdG9yZS1pbnRlbGxpZ2VuY2VgIG1hdGNoZXMgdGhlIHNhbWUgcm93cyBhc1xuICogYHN0b3JlIGludGVsbGlnZW5jZWApIGFuZCBwcmVmaXggbWF0Y2hpbmcgKHNvIGBpbnRlbGAgcmVhY2hlc1xuICogYGludGVsbGlnZW5jZWApLiBTZWUge0BsaW5rIHRvU2VhcmNoVGVybXN9IC8ge0BsaW5rIHRvVHNRdWVyeX0uXG4gKlxuICogVGhlIHdob2xlIHBvaW50IGlzIHBhcml0eTogdGhpcyBiYWNrZW5kIHJldHVybnMgdGhlIEVYQUNUIHNhbWVcbiAqIGBAZGJ4LXRvb2xzL3NoYXJlZC1zZWFyY2hgIHNoYXBlcyAoYFNlYXJjaFJlc3VsdGAgLyBgU2VhcmNoSGl0YCAvXG4gKiBgVXBzZXJ0UmVzdWx0YCkgYXMgdGhlIFZlY3RvciBTZWFyY2ggYmFja2VuZCwgc28gdGhlIGNsaWVudCwgdGhlIE1hc3RyYVxuICogdG9vbHMsIHRoZSByb3V0ZXMsIGFuZCB0aGUgUmVhY3Qgc2VhcmNoIGJveCBjYW5ub3QgdGVsbCB3aGljaCBvbmUgYW5zd2VyZWQuXG4gKiBBIGhpdCdzIGBpZGAgaXMgdGhlIHByaW1hcnkga2V5LCBpdHMgYHNjb3JlYCBpcyB0aGUgdGV4dC1yYW5rLCBhbmQgYGZpZWxkc2BcbiAqIGlzIHRoZSBzdG9yZWQgZG9jdW1lbnQgbWludXMgdGhlIGludGVybmFsIGNvbHVtbnMuXG4gKlxuICogVGhlIFBvc3RncmVzIHBvb2wgaXMgYnVpbHQgdGhlIHNhbWUgd2F5IGBAZGJ4LXRvb2xzL2FwcGtpdC1tYXN0cmFgIGJ1aWxkcyBpdHNcbiAqIG1lbW9yeSBwb29sOiB0aGUgQXBwS2l0IGBsYWtlYmFzZWAgcGx1Z2luIHJlc29sdmVzIGEgc2VydmljZS1wcmluY2lwYWxcbiAqIGBQb29sQ29uZmlnYCAoY29ubmVjdGlvbiB0YXJnZXQgKyBPQXV0aCB0b2tlbi1yZWZyZXNoIGBwYXNzd29yZGAgY2FsbGJhY2spLFxuICogYW5kIHRoaXMgYmFja2VuZCBjb25zdHJ1Y3RzIGEgYHBnLlBvb2xgIGZyb20gaXQuIEl0IG5ldmVyIHJlLWltcGxlbWVudHMgYXV0aC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgRXhlY3V0aW9uRXJyb3IgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBsb2csIG9iamVjdCwgc3RyaW5nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHtcbiAgU2VhcmNoRG9jdW1lbnQsXG4gIFNlYXJjaEhpdCxcbiAgU2VhcmNoUmVxdWVzdCxcbiAgU2VhcmNoUmVzdWx0LFxuICBVcHNlcnRSZXN1bHQsXG59IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1zZWFyY2hcIjtcbmltcG9ydCB7IFBvb2wsIHR5cGUgUG9vbENvbmZpZyB9IGZyb20gXCJwZ1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwic2VhcmNoL2xha2ViYXNlXCIpO1xuXG4vKiogVGhlIGludGVybmFsIGNvbHVtbnMgZXZlcnkgc2VhcmNoIHRhYmxlIGNhcnJpZXMsIGV4Y2x1ZGVkIGZyb20gYSBoaXQncyBgZmllbGRzYC4gKi9cbmNvbnN0IFJFU0VSVkVEX0NPTFVNTlMgPSBuZXcgU2V0KFtcImlkXCIsIFwic2VhcmNoX3RleHRcIiwgXCJkb2N1bWVudFwiLCBcInNlYXJjaF92ZWN0b3JcIl0pO1xuXG4vKipcbiAqIFNwbGl0IGEgc2VhcmNoLWJveCBzdHJpbmcgaW50byB0aGUgdGVybXMgYSB0c3F1ZXJ5IGlzIGJ1aWx0IGZyb20sIHVzaW5nIHRoZVxuICogc2hhcmVkIGBAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlYCB0b2tlbml6ZXIgc28gdGhlIHNwbGl0dGluZyBydWxlcyBzdGF5XG4gKiBjb25zaXN0ZW50IHdpdGggdGhlIHJlc3Qgb2YgdGhlIHRvb2xraXQuXG4gKlxuICogU3BsaXR0aW5nIG9uIHB1bmN0dWF0aW9uIGlzIHdoYXQgbWFrZXMgYHN0b3JlLWludGVsbGlnZW5jZWAgYmVoYXZlIGxpa2VcbiAqIGBzdG9yZSBpbnRlbGxpZ2VuY2VgLiBQb3N0Z3JlcyBpbmRleGVzIGEgaHlwaGVuYXRlZCB3b3JkIGFzIHRoZSBjb21wb3VuZFxuICogbGV4ZW1lIFBMVVMgZWFjaCBvZiBpdHMgcGFydHMsIGJ1dCBjb21waWxlcyBhIGh5cGhlbmF0ZWQgUVVFUlkgdG8gdGhlXG4gKiBjb21wb3VuZCBhbG9uZSAtIHNvIGBzdG9yZS1pbnRlbGxpZ2VuY2VgIGRlbWFuZHMgYSBgc3RvcmUtaW50ZWxsaWdgIGxleGVtZVxuICogdGhhdCBhIGRvY3VtZW50IHRpdGxlZCBgcmFjZXRyYWMtc3RvcmUtaW50ZWxsaWdlbmNlYCBkb2VzIG5vdCBoYXZlLCBhbmQgdGhlXG4gKiBzZWFyY2ggc2lsZW50bHkgcmV0dXJucyBub3RoaW5nIHdoaWxlIGBzdG9yZSBpbnRlbGxpZ2VuY2VgIHJldHVybnNcbiAqIGV2ZXJ5dGhpbmcuIFNhbWUgZm9yIGAuYCBhbmQgYF9gIGluIGEgdGFibGUgcmVmZXJlbmNlLlxuICpcbiAqIGBjYW1lbENhc2U6IGZhbHNlYCBpcyBsb2FkLWJlYXJpbmcgcmF0aGVyIHRoYW4gYSBkZWZhdWx0OiB0aGUgY2FtZWxDYXNlXG4gKiBzcGxpdHRlciBhbHNvIGJyZWFrcyBkaWdpdCBydW5zLCB0dXJuaW5nIGBncHQ0YCBpbnRvIGBncHRgICsgYDRgIGFuZCBgczNgXG4gKiBpbnRvIGBzYCArIGAzYC4gUG9zdGdyZXMgaW5kZXhlcyBlYWNoIG9mIHRob3NlIGFzIE9ORSBsZXhlbWUsIHNvIG5vIGxleGVtZVxuICogZXZlciBzdGFydHMgd2l0aCB0aGUgdHJhaWxpbmcgZGlnaXRzIGFuZCB0aGUgcHJlY2lzZSBwYXNzIGNvdWxkIG5vdCBtYXRjaFxuICogdGhlbS4gS2VlcGluZyBwdW5jdHVhdGlvbiBhcyB0aGUgb25seSBib3VuZGFyeSBtaXJyb3JzIGhvdyB0aGUgaW5kZXggd2FzXG4gKiBidWlsdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvU2VhcmNoVGVybXMocXVlcnk6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIFtcbiAgICAuLi5zdHJpbmcudG9rZW5pemVXaXRoT3B0aW9ucyh7IGxvd2VyQ2FzZTogdHJ1ZSwgY2FtZWxDYXNlOiBmYWxzZSwgZGlzdGluY3Q6IHRydWUgfSwgcXVlcnkpLFxuICBdO1xufVxuXG4vKipcbiAqIENvbXBpbGUgdGVybXMgaW50byBhIGB0b190c3F1ZXJ5YCBpbnB1dCB3aGVyZSBldmVyeSB0ZXJtIGlzIGEgUFJFRklYLCBzbyBhXG4gKiBwYXJ0aWFsbHkgdHlwZWQgd29yZCBzdGlsbCBtYXRjaGVzIChgaW50ZWw6KmAgcmVhY2hlcyBgaW50ZWxsaWdlbmNlYCkuXG4gKlxuICogVGVybXMgY2Fycnkgb25seSBsZXR0ZXJzIGFuZCBkaWdpdHMgYnkgY29uc3RydWN0aW9uLCBzbyBub25lIG9mIHRzcXVlcnknc1xuICogb3BlcmF0b3JzIChgJiB8ICEgKCApIDogKmApIGNhbiBzdXJ2aXZlIGZyb20gdXNlciBpbnB1dCBpbnRvIHRoZSBjb21waWxlZFxuICogc3RyaW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9Uc1F1ZXJ5KHRlcm1zOiByZWFkb25seSBzdHJpbmdbXSwgb3BlcmF0b3I6IFwiJlwiIHwgXCJ8XCIgPSBcIiZcIik6IHN0cmluZyB7XG4gIHJldHVybiB0ZXJtcy5tYXAoKHRlcm0pID0+IGAke3Rlcm19OipgKS5qb2luKGAgJHtvcGVyYXRvcn0gYCk7XG59XG5cbi8qKiBPcHRpb25zIGZvciBhIHNpbmdsZS1pbmRleCBMYWtlYmFzZSBzZWFyY2ggKG1pcnJvcnMgdGhlIGNsaWVudCdzIGBTZWFyY2hPcHRpb25zYCkuICovXG5leHBvcnQgaW50ZXJmYWNlIExha2ViYXNlU2VhcmNoT3B0aW9ucyB7XG4gIGxpbWl0PzogbnVtYmVyO1xuICBmaWx0ZXI/OiBTZWFyY2hSZXF1ZXN0W1wiZmlsdGVyXCJdO1xuICBzY29yZVRocmVzaG9sZD86IG51bWJlcjtcbiAgc2lnbmFsPzogQWJvcnRTaWduYWw7XG59XG5cbi8qKiBPbmUgcmF3IHNlYXJjaCByb3cgYmVmb3JlIGl0IGlzIHNoYXBlZCBpbnRvIGEge0BsaW5rIFNlYXJjaEhpdH0uICovXG5pbnRlcmZhY2UgU2VhcmNoUm93IHtcbiAgaWQ6IHN0cmluZztcbiAgZG9jdW1lbnQ6IHVua25vd247XG4gIHNjb3JlOiBudW1iZXI7XG59XG5cbi8qKiBPcHRpb25zIGZvciBwcm92aXNpb25pbmcgYSBMYWtlYmFzZS1iYWNrZWQgaW5kZXguICovXG5leHBvcnQgaW50ZXJmYWNlIExha2ViYXNlUHJvdmlzaW9uT3B0aW9ucyB7XG4gIC8qKiBUZXh0IGNvbHVtbiBlbWJlZGRlZCBpbnRvIHRoZSBzZWFyY2ggdmVjdG9yLiBEZWZhdWx0cyB0byBgdGV4dGAuICovXG4gIHRleHRDb2x1bW4/OiBzdHJpbmc7XG4gIC8qKiBEb2N1bWVudHMgdG8gc2VlZCB3aGVuIHRoZSB0YWJsZSBpcyBlbXB0eS4gKi9cbiAgc2VlZD86IFNlYXJjaERvY3VtZW50W107XG4gIHNpZ25hbD86IEFib3J0U2lnbmFsO1xufVxuXG4vKipcbiAqIEEgUG9zdGdyZXMgZnVsbC10ZXh0IGJhY2tlbmQuIE9uZSBpbnN0YW5jZSBpcyBzaGFyZWQgYWNyb3NzIGluZGV4ZXM7IGVhY2hcbiAqIGluZGV4IG1hcHMgdG8gYSB0YWJsZSB3aG9zZSBuYW1lIGlzIGRlcml2ZWQgZnJvbSB0aGUgaW5kZXggcmVmZXJlbmNlLlxuICovXG5leHBvcnQgY2xhc3MgTGFrZWJhc2VTZWFyY2hCYWNrZW5kIHtcbiAgcHJpdmF0ZSBwb29sOiBQb29sIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHBvb2xQcm9taXNlOiBQcm9taXNlPFBvb2w+IHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHJlYWRvbmx5IHByb3Zpc2lvbmVkID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBwZ0NvbmZpZ0ZhY3Rvcnk6ICgpID0+IFByb21pc2U8UG9vbENvbmZpZz4gfCBQb29sQ29uZmlnLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2NoZW1hID0gXCJwdWJsaWNcIixcbiAgICAvKiogSG93IGEgcG9vbCBpcyBidWlsdCBmcm9tIHRoZSByZXNvbHZlZCBjb25maWcuIE92ZXJyaWRhYmxlIGZvciB0ZXN0cy4gKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IHBvb2xGYWN0b3J5OiAoY29uZmlnOiBQb29sQ29uZmlnKSA9PiBQb29sID0gKGNvbmZpZykgPT4gbmV3IFBvb2woY29uZmlnKSxcbiAgKSB7fVxuXG4gIC8qKiBMYXppbHkgYnVpbGQgKGFuZCBjYWNoZSkgdGhlIHBnIHBvb2wgZnJvbSB0aGUgcmVzb2x2ZWQgTGFrZWJhc2UgY29uZmlnLiAqL1xuICBwcml2YXRlIGFzeW5jIGdldFBvb2woKTogUHJvbWlzZTxQb29sPiB7XG4gICAgaWYgKHRoaXMucG9vbCkgcmV0dXJuIHRoaXMucG9vbDtcbiAgICB0aGlzLnBvb2xQcm9taXNlID8/PSAoYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgY29uZmlnID0gYXdhaXQgdGhpcy5wZ0NvbmZpZ0ZhY3RvcnkoKTtcbiAgICAgIGNvbnN0IHBvb2wgPSB0aGlzLnBvb2xGYWN0b3J5KGNvbmZpZyk7XG4gICAgICB0aGlzLnBvb2wgPSBwb29sO1xuICAgICAgcmV0dXJuIHBvb2w7XG4gICAgfSkoKTtcbiAgICByZXR1cm4gdGhpcy5wb29sUHJvbWlzZTtcbiAgfVxuXG4gIC8qKiBDbG9zZSB0aGUgcG9vbCBzbyBhIHJlc3RhcnRlZCBhcHAgcmVidWlsZHMgaXQuICovXG4gIGFzeW5jIGNsb3NlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHBvb2wgPSB0aGlzLnBvb2w7XG4gICAgdGhpcy5wb29sID0gdW5kZWZpbmVkO1xuICAgIHRoaXMucG9vbFByb21pc2UgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5wcm92aXNpb25lZC5jbGVhcigpO1xuICAgIGlmIChwb29sKSBhd2FpdCBwb29sLmVuZCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlYXJjaCBhIExha2ViYXNlLWJhY2tlZCBpbmRleC4gUmV0dXJucyBoaXRzIHNvcnRlZCBtb3N0LXJlbGV2YW50LWZpcnN0LFxuICAgKiBzaGFwZWQgaWRlbnRpY2FsbHkgdG8gdGhlIFZlY3RvciBTZWFyY2ggYmFja2VuZC5cbiAgICovXG4gIGFzeW5jIHNlYXJjaChcbiAgICBpbmRleDogc3RyaW5nLFxuICAgIHF1ZXJ5OiBzdHJpbmcsXG4gICAgb3B0aW9uczogTGFrZWJhc2VTZWFyY2hPcHRpb25zID0ge30sXG4gICk6IFByb21pc2U8U2VhcmNoUmVzdWx0PiB7XG4gICAgY29uc3QgdGV4dCA9IHN0cmluZy50cmltVG9FbXB0eShxdWVyeSk7XG4gICAgY29uc3QgdGFibGUgPSB0aGlzLnRhYmxlRm9yKGluZGV4KTtcbiAgICBjb25zdCBsaW1pdCA9IG9wdGlvbnMubGltaXQgPz8gMTA7XG4gICAgY29uc3QgcG9vbCA9IGF3YWl0IHRoaXMuZ2V0UG9vbCgpO1xuICAgIGNvbnN0IHRlcm1zID0gdG9TZWFyY2hUZXJtcyh0ZXh0KTtcblxuICAgIC8vIEFuIGVtcHR5IChvciBwdW5jdHVhdGlvbi1vbmx5KSBib3ggcmV0dXJucyByb3dzIHJhdGhlciB0aGFuIG5vdGhpbmcsIHNvXG4gICAgLy8gdGhlIFVJIHNob3dzIGNvbnRlbnQgYmVmb3JlIHRoZSB1c2VyIHR5cGVzIC0gYXMgYSBrZXl3b3JkIGluZGV4IHdvdWxkLlxuICAgIGlmICh0ZXJtcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGNvbnN0IGZpbHRlciA9IHRoaXMuZmlsdGVyQ2xhdXNlKG9wdGlvbnMuZmlsdGVyLCAxKTtcbiAgICAgIGNvbnN0IGxpbWl0UG9zaXRpb24gPSBmaWx0ZXIucGFyYW1zLmxlbmd0aCArIDE7XG4gICAgICBjb25zdCB7IHJvd3MgfSA9IGF3YWl0IHRoaXMucXVlcnk8U2VhcmNoUm93PihcbiAgICAgICAgcG9vbCxcbiAgICAgICAgYFNFTEVDVCBpZCwgZG9jdW1lbnQsIDA6OmZsb2F0NCBBUyBzY29yZVxuICAgICAgICAgICBGUk9NICR7dGFibGV9XG4gICAgICAgICAgV0hFUkUgVFJVRSR7ZmlsdGVyLnNxbH1cbiAgICAgICAgICBPUkRFUiBCWSBpZFxuICAgICAgICAgIExJTUlUICQke2xpbWl0UG9zaXRpb259YCxcbiAgICAgICAgWy4uLmZpbHRlci5wYXJhbXMsIGxpbWl0XSxcbiAgICAgICAgb3B0aW9ucy5zaWduYWwsXG4gICAgICApO1xuICAgICAgcmV0dXJuIHRoaXMudG9SZXN1bHQodGV4dCwgaW5kZXgsIHJvd3MsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8vIFByZWNpc2UgcGFzczogZXZlcnkgdGVybSBtdXN0IG1hdGNoLCBlYWNoIGFzIGEgcHJlZml4LlxuICAgIGNvbnN0IHN0cmljdEZpbHRlciA9IHRoaXMuZmlsdGVyQ2xhdXNlKG9wdGlvbnMuZmlsdGVyLCAyKTtcbiAgICBjb25zdCBzdHJpY3RMaW1pdFBvc2l0aW9uID0gc3RyaWN0RmlsdGVyLnBhcmFtcy5sZW5ndGggKyAyO1xuICAgIGNvbnN0IHN0cmljdCA9IGF3YWl0IHRoaXMucXVlcnk8U2VhcmNoUm93PihcbiAgICAgIHBvb2wsXG4gICAgICBgU0VMRUNUIGlkLCBkb2N1bWVudCwgdHNfcmFuayhzZWFyY2hfdmVjdG9yLCB0b190c3F1ZXJ5KCdlbmdsaXNoJywgJDEpKSBBUyBzY29yZVxuICAgICAgICAgRlJPTSAke3RhYmxlfVxuICAgICAgICBXSEVSRSBzZWFyY2hfdmVjdG9yIEBAIHRvX3RzcXVlcnkoJ2VuZ2xpc2gnLCAkMSlcbiAgICAgICAgICAke3N0cmljdEZpbHRlci5zcWx9XG4gICAgICAgIE9SREVSIEJZIHNjb3JlIERFU0NcbiAgICAgICAgTElNSVQgJCR7c3RyaWN0TGltaXRQb3NpdGlvbn1gLFxuICAgICAgW3RvVHNRdWVyeSh0ZXJtcyksIC4uLnN0cmljdEZpbHRlci5wYXJhbXMsIGxpbWl0XSxcbiAgICAgIG9wdGlvbnMuc2lnbmFsLFxuICAgICk7XG4gICAgaWYgKHN0cmljdC5yb3dzLmxlbmd0aCA+IDApIHJldHVybiB0aGlzLnRvUmVzdWx0KHRleHQsIGluZGV4LCBzdHJpY3Qucm93cywgb3B0aW9ucyk7XG5cbiAgICAvLyBOb3RoaW5nIG1hdGNoZWQgRVZFUlkgdGVybSwgc28gcmVsYXggcmF0aGVyIHRoYW4gcmV0dXJuIGFuIGVtcHR5IGJveDpcbiAgICAvLyBhbnkgb25lIHRlcm0gaXMgZW5vdWdoLCBhbmQgYW4gYElMSUtFYCBwYXNzIGFkZGl0aW9uYWxseSBjYXRjaGVzIGFcbiAgICAvLyBmcmFnbWVudCB0aGF0IGlzIG5vdCBhIHByZWZpeCAoYHRlbGxpZ2VuY2VgKSBvciBhIHRva2VuIHRoZSB0ZXh0LXNlYXJjaFxuICAgIC8vIHBhcnNlciBzcGxpdCBkaWZmZXJlbnRseSB0aGFuIGV4cGVjdGVkLiBTdWJzdHJpbmcgbWF0Y2hpbmcgY2Fubm90IHVzZVxuICAgIC8vIHRoZSBHSU4gaW5kZXgsIHdoaWNoIGlzIHdoeSBpdCBvbmx5IHJ1bnMgb25jZSB0aGUgaW5kZXhlZCBwYXNzIGZhaWxzLlxuICAgIGNvbnN0IHJlbGF4ZWRGaWx0ZXIgPSB0aGlzLmZpbHRlckNsYXVzZShvcHRpb25zLmZpbHRlciwgMyk7XG4gICAgY29uc3QgcmVsYXhlZExpbWl0UG9zaXRpb24gPSByZWxheGVkRmlsdGVyLnBhcmFtcy5sZW5ndGggKyAzO1xuICAgIGNvbnN0IHJlbGF4ZWQgPSBhd2FpdCB0aGlzLnF1ZXJ5PFNlYXJjaFJvdz4oXG4gICAgICBwb29sLFxuICAgICAgYFNFTEVDVCBpZCwgZG9jdW1lbnQsIHRzX3Jhbmsoc2VhcmNoX3ZlY3RvciwgdG9fdHNxdWVyeSgnZW5nbGlzaCcsICQxKSkgQVMgc2NvcmVcbiAgICAgICAgIEZST00gJHt0YWJsZX1cbiAgICAgICAgV0hFUkUgKHNlYXJjaF92ZWN0b3IgQEAgdG9fdHNxdWVyeSgnZW5nbGlzaCcsICQxKVxuICAgICAgICAgICBPUiBzZWFyY2hfdGV4dCBJTElLRSBBTlkoJDI6OnRleHRbXSkpXG4gICAgICAgICAgJHtyZWxheGVkRmlsdGVyLnNxbH1cbiAgICAgICAgT1JERVIgQlkgc2NvcmUgREVTQ1xuICAgICAgICBMSU1JVCAkJHtyZWxheGVkTGltaXRQb3NpdGlvbn1gLFxuICAgICAgW3RvVHNRdWVyeSh0ZXJtcywgXCJ8XCIpLCB0ZXJtcy5tYXAoKHRlcm0pID0+IGAlJHt0ZXJtfSVgKSwgLi4ucmVsYXhlZEZpbHRlci5wYXJhbXMsIGxpbWl0XSxcbiAgICAgIG9wdGlvbnMuc2lnbmFsLFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMudG9SZXN1bHQodGV4dCwgaW5kZXgsIHJlbGF4ZWQucm93cywgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogU2hhcGUgcmF3IHJvd3MgaW50byB0aGUgYFNlYXJjaFJlc3VsdGAgYm90aCBiYWNrZW5kcyByZXR1cm4uICovXG4gIHByaXZhdGUgdG9SZXN1bHQoXG4gICAgcXVlcnk6IHN0cmluZyxcbiAgICBpbmRleDogc3RyaW5nLFxuICAgIHJvd3M6IFNlYXJjaFJvd1tdLFxuICAgIG9wdGlvbnM6IExha2ViYXNlU2VhcmNoT3B0aW9ucyxcbiAgKTogU2VhcmNoUmVzdWx0IHtcbiAgICBjb25zdCBoaXRzOiBTZWFyY2hIaXRbXSA9IHJvd3NcbiAgICAgIC5tYXAoKHJvdykgPT4gKHtcbiAgICAgICAgaWQ6IFN0cmluZyhyb3cuaWQpLFxuICAgICAgICBzY29yZTogTnVtYmVyKHJvdy5zY29yZSkgfHwgMCxcbiAgICAgICAgZmllbGRzOiB0aGlzLnRvRmllbGRzKHJvdy5kb2N1bWVudCksXG4gICAgICB9KSlcbiAgICAgIC5maWx0ZXIoKGhpdCkgPT4gb3B0aW9ucy5zY29yZVRocmVzaG9sZCA9PT0gdW5kZWZpbmVkIHx8IGhpdC5zY29yZSA+PSBvcHRpb25zLnNjb3JlVGhyZXNob2xkKTtcbiAgICByZXR1cm4geyBxdWVyeSwgaW5kZXgsIGhpdHMsIGNvdW50OiBoaXRzLmxlbmd0aCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEVuc3VyZSB0aGUgdGFibGUgKyBmdWxsLXRleHQgaW5kZXggZXhpc3QgYW5kIHNlZWQgZG9jdW1lbnRzIHdoZW4gZW1wdHkuXG4gICAqIElkZW1wb3RlbnQsIHNvIGl0IGlzIHNhZmUgdG8gY2FsbCBvbiBldmVyeSBib290LlxuICAgKi9cbiAgYXN5bmMgcHJvdmlzaW9uKGluZGV4OiBzdHJpbmcsIG9wdGlvbnM6IExha2ViYXNlUHJvdmlzaW9uT3B0aW9ucyA9IHt9KTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCB0YWJsZSA9IHRoaXMudGFibGVGb3IoaW5kZXgpO1xuICAgIGNvbnN0IHBvb2wgPSBhd2FpdCB0aGlzLmdldFBvb2woKTtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVRhYmxlKHBvb2wsIHRhYmxlLCBvcHRpb25zLnNpZ25hbCk7XG5cbiAgICBjb25zdCB7IHJvd3MgfSA9IGF3YWl0IHRoaXMucXVlcnk8eyBjb3VudDogc3RyaW5nIH0+KFxuICAgICAgcG9vbCxcbiAgICAgIGBTRUxFQ1QgY291bnQoKik6OnRleHQgQVMgY291bnQgRlJPTSAke3RhYmxlfWAsXG4gICAgICBbXSxcbiAgICAgIG9wdGlvbnMuc2lnbmFsLFxuICAgICk7XG4gICAgY29uc3QgZXhpc3RpbmcgPSBOdW1iZXIocm93c1swXT8uY291bnQgPz8gXCIwXCIpO1xuICAgIGNvbnN0IHNlZWQgPSBvcHRpb25zLnNlZWQgPz8gW107XG4gICAgaWYgKGV4aXN0aW5nID09PSAwICYmIHNlZWQubGVuZ3RoID4gMCkge1xuICAgICAgYXdhaXQgdGhpcy51cHNlcnQocG9vbCwgdGFibGUsIHNlZWQsIG9wdGlvbnMudGV4dENvbHVtbiA/PyBcInRleHRcIiwgb3B0aW9ucy5zaWduYWwpO1xuICAgICAgbG9nZ2VyLmluZm8oXCJpbmRleC1zZWVkZWRcIiwgeyBpbmRleCwgdGFibGUsIGNvdW50OiBzZWVkLmxlbmd0aCB9KTtcbiAgICAgIHJldHVybiBzZWVkLmxlbmd0aDtcbiAgICB9XG4gICAgcmV0dXJuIGV4aXN0aW5nO1xuICB9XG5cbiAgLyoqIEFkZCBvciB1cGRhdGUgZG9jdW1lbnRzIGJ5IHByaW1hcnkga2V5LiAqL1xuICBhc3luYyBhZGREb2N1bWVudHMoXG4gICAgaW5kZXg6IHN0cmluZyxcbiAgICBkb2N1bWVudHM6IFNlYXJjaERvY3VtZW50W10sXG4gICAgdGV4dENvbHVtbiA9IFwidGV4dFwiLFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICApOiBQcm9taXNlPFVwc2VydFJlc3VsdD4ge1xuICAgIGNvbnN0IHRhYmxlID0gdGhpcy50YWJsZUZvcihpbmRleCk7XG4gICAgY29uc3QgcG9vbCA9IGF3YWl0IHRoaXMuZ2V0UG9vbCgpO1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlVGFibGUocG9vbCwgdGFibGUsIHNpZ25hbCk7XG4gICAgYXdhaXQgdGhpcy51cHNlcnQocG9vbCwgdGFibGUsIGRvY3VtZW50cywgdGV4dENvbHVtbiwgc2lnbmFsKTtcbiAgICByZXR1cm4geyBpbmRleCwgY291bnQ6IGRvY3VtZW50cy5sZW5ndGggfTtcbiAgfVxuXG4gIC8qKiBEZWxldGUgZG9jdW1lbnRzIGJ5IHByaW1hcnkga2V5LiAqL1xuICBhc3luYyBkZWxldGVEb2N1bWVudHMoXG4gICAgaW5kZXg6IHN0cmluZyxcbiAgICBpZHM6IEFycmF5PHN0cmluZyB8IG51bWJlcj4sXG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4gICk6IFByb21pc2U8VXBzZXJ0UmVzdWx0PiB7XG4gICAgY29uc3QgdGFibGUgPSB0aGlzLnRhYmxlRm9yKGluZGV4KTtcbiAgICBjb25zdCBwb29sID0gYXdhaXQgdGhpcy5nZXRQb29sKCk7XG4gICAgYXdhaXQgdGhpcy5xdWVyeShwb29sLCBgREVMRVRFIEZST00gJHt0YWJsZX0gV0hFUkUgaWQgPSBBTlkoJDEpYCwgW2lkcy5tYXAoU3RyaW5nKV0sIHNpZ25hbCk7XG4gICAgcmV0dXJuIHsgaW5kZXgsIGNvdW50OiBpZHMubGVuZ3RoIH07XG4gIH1cblxuICAvKiogQ3JlYXRlIHRoZSB0YWJsZSArIEdJTiBpbmRleCBvbmNlIHBlciB0YWJsZSAobWVtb2l6ZWQgYWNyb3NzIGNhbGxzKS4gKi9cbiAgcHJpdmF0ZSBhc3luYyBlbnN1cmVUYWJsZShwb29sOiBQb29sLCB0YWJsZTogc3RyaW5nLCBzaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLnByb3Zpc2lvbmVkLmhhcyh0YWJsZSkpIHJldHVybjtcbiAgICAvLyBgZG9jdW1lbnRgIGhvbGRzIHRoZSB3aG9sZSByb3c7IGBzZWFyY2hfdGV4dGAgaXMgdGhlIGluZGV4ZWQgdGV4dDsgdGhlXG4gICAgLy8gZ2VuZXJhdGVkIGBzZWFyY2hfdmVjdG9yYCBrZWVwcyB0aGUgdHN2ZWN0b3IgaW4gbG9ja3N0ZXAgd2l0aCBpdCBzbyBhXG4gICAgLy8gd3JpdGUgbmV2ZXIgaGFzIHRvIGNvbXB1dGUgdGhlIHZlY3RvciBieSBoYW5kLlxuICAgIGF3YWl0IHRoaXMucXVlcnkocG9vbCwgYENSRUFURSBTQ0hFTUEgSUYgTk9UIEVYSVNUUyAke3RoaXMuaWRlbnQodGhpcy5zY2hlbWEpfWAsIFtdLCBzaWduYWwpO1xuICAgIGF3YWl0IHRoaXMucXVlcnkoXG4gICAgICBwb29sLFxuICAgICAgYENSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTICR7dGFibGV9IChcbiAgICAgICAgIGlkIHRleHQgUFJJTUFSWSBLRVksXG4gICAgICAgICBzZWFyY2hfdGV4dCB0ZXh0IE5PVCBOVUxMIERFRkFVTFQgJycsXG4gICAgICAgICBkb2N1bWVudCBqc29uYiBOT1QgTlVMTCBERUZBVUxUICd7fSc6Ompzb25iLFxuICAgICAgICAgc2VhcmNoX3ZlY3RvciB0c3ZlY3RvciBHRU5FUkFURUQgQUxXQVlTIEFTICh0b190c3ZlY3RvcignZW5nbGlzaCcsIHNlYXJjaF90ZXh0KSkgU1RPUkVEXG4gICAgICAgKWAsXG4gICAgICBbXSxcbiAgICAgIHNpZ25hbCxcbiAgICApO1xuICAgIGF3YWl0IHRoaXMucXVlcnkoXG4gICAgICBwb29sLFxuICAgICAgYEFMVEVSIFRBQkxFICR7dGFibGV9XG4gICAgICAgICBBREQgQ09MVU1OIElGIE5PVCBFWElTVFMgc2VhcmNoX3ZlY3RvciB0c3ZlY3RvclxuICAgICAgICAgR0VORVJBVEVEIEFMV0FZUyBBUyAodG9fdHN2ZWN0b3IoJ2VuZ2xpc2gnLCBzZWFyY2hfdGV4dCkpIFNUT1JFRGAsXG4gICAgICBbXSxcbiAgICAgIHNpZ25hbCxcbiAgICApO1xuICAgIGF3YWl0IHRoaXMucXVlcnkoXG4gICAgICBwb29sLFxuICAgICAgYENSRUFURSBJTkRFWCBJRiBOT1QgRVhJU1RTICR7dGhpcy5pZGVudChgJHt0aGlzLmJhcmVOYW1lKHRhYmxlKX1fZnRzYCl9XG4gICAgICAgICBPTiAke3RhYmxlfSBVU0lORyBnaW4gKHNlYXJjaF92ZWN0b3IpYCxcbiAgICAgIFtdLFxuICAgICAgc2lnbmFsLFxuICAgICk7XG4gICAgdGhpcy5wcm92aXNpb25lZC5hZGQodGFibGUpO1xuICAgIGxvZ2dlci5pbmZvKFwiaW5kZXgtY3JlYXRlZFwiLCB7IHRhYmxlIH0pO1xuICB9XG5cbiAgLyoqIFVwc2VydCByb3dzOiB0aGUgd2hvbGUgZG9jdW1lbnQgYXMganNvbmIgKyBhIGZsYXR0ZW5lZCB0ZXh0IGJsb2IgdG8gaW5kZXguICovXG4gIHByaXZhdGUgYXN5bmMgdXBzZXJ0KFxuICAgIHBvb2w6IFBvb2wsXG4gICAgdGFibGU6IHN0cmluZyxcbiAgICBkb2N1bWVudHM6IFNlYXJjaERvY3VtZW50W10sXG4gICAgdGV4dENvbHVtbjogc3RyaW5nLFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGNvbnN0IGRvYyBvZiBkb2N1bWVudHMpIHtcbiAgICAgIGNvbnN0IGlkID0gc3RyaW5nLnRyaW1Ub051bGwoU3RyaW5nKGRvYy5pZCA/PyBkb2MuSUQgPz8gXCJcIikpID8/IHVuZGVmaW5lZDtcbiAgICAgIGlmIChpZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFeGVjdXRpb25FcnJvcihcInNlYXJjaCAobGFrZWJhc2UpOiBhIGRvY3VtZW50IGlzIG1pc3NpbmcgYW4gYGlkYFwiLCB7XG4gICAgICAgICAgY29udGV4dDogeyBvcGVyYXRpb246IFwiYWRkRG9jdW1lbnRzXCIgfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBjb25zdCBzZWFyY2hUZXh0ID0gdGhpcy5zZWFyY2hUZXh0KGRvYywgdGV4dENvbHVtbik7XG4gICAgICBhd2FpdCB0aGlzLnF1ZXJ5KFxuICAgICAgICBwb29sLFxuICAgICAgICBgSU5TRVJUIElOVE8gJHt0YWJsZX0gKGlkLCBzZWFyY2hfdGV4dCwgZG9jdW1lbnQpXG4gICAgICAgICAgIFZBTFVFUyAoJDEsICQyLCAkMzo6anNvbmIpXG4gICAgICAgICBPTiBDT05GTElDVCAoaWQpIERPIFVQREFURVxuICAgICAgICAgICBTRVQgc2VhcmNoX3RleHQgPSBFWENMVURFRC5zZWFyY2hfdGV4dCwgZG9jdW1lbnQgPSBFWENMVURFRC5kb2N1bWVudGAsXG4gICAgICAgIFtpZCwgc2VhcmNoVGV4dCwgSlNPTi5zdHJpbmdpZnkoZG9jKV0sXG4gICAgICAgIHNpZ25hbCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFRoZSB0ZXh0IGEgcm93IGlzIGluZGV4ZWQgYnk6IHRoZSB0ZXh0IGNvbHVtbiBmaXJzdCwgdGhlbiBhbnkgb3RoZXIgc3RyaW5nIGZpZWxkLiAqL1xuICBwcml2YXRlIHNlYXJjaFRleHQoZG9jOiBTZWFyY2hEb2N1bWVudCwgdGV4dENvbHVtbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBwcmltYXJ5ID0gc3RyaW5nLnRyaW1Ub0VtcHR5KFN0cmluZyhkb2NbdGV4dENvbHVtbl0gPz8gXCJcIikpO1xuICAgIGNvbnN0IHJlc3QgPSBPYmplY3QuZW50cmllcyhkb2MpXG4gICAgICAuZmlsdGVyKChba2V5LCB2YWx1ZV0pID0+IGtleSAhPT0gdGV4dENvbHVtbiAmJiBrZXkgIT09IFwiaWRcIiAmJiB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIpXG4gICAgICAubWFwKChbLCB2YWx1ZV0pID0+IHZhbHVlIGFzIHN0cmluZyk7XG4gICAgcmV0dXJuIFtwcmltYXJ5LCAuLi5yZXN0XS5maWx0ZXIoQm9vbGVhbikuam9pbihcIlxcblwiKTtcbiAgfVxuXG4gIC8qKiBBIGhpdCdzIGBmaWVsZHNgOiB0aGUgc3RvcmVkIGRvY3VtZW50IG1pbnVzIHRoZSByZXNlcnZlZC9pbnRlcm5hbCBrZXlzLiAqL1xuICBwcml2YXRlIHRvRmllbGRzKGRvY3VtZW50OiB1bmtub3duKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICAgIGlmICghb2JqZWN0LmlzUmVjb3JkKGRvY3VtZW50KSkgcmV0dXJuIHt9O1xuICAgIGNvbnN0IGZpZWxkczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhkb2N1bWVudCkpIHtcbiAgICAgIGlmIChSRVNFUlZFRF9DT0xVTU5TLmhhcyhrZXkpKSBjb250aW51ZTtcbiAgICAgIGZpZWxkc1trZXldID0gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybiBmaWVsZHM7XG4gIH1cblxuICAvKiogQ29tcGlsZSBBcHBLaXQgc2NhbGFyL2FycmF5IGZpbHRlcnMgYWdhaW5zdCB0aGUgc3RvcmVkIEpTT04gZG9jdW1lbnQuICovXG4gIHByaXZhdGUgZmlsdGVyQ2xhdXNlKFxuICAgIGZpbHRlcjogU2VhcmNoUmVxdWVzdFtcImZpbHRlclwiXSxcbiAgICBzdGFydFBvc2l0aW9uOiBudW1iZXIsXG4gICk6IHsgc3FsOiBzdHJpbmc7IHBhcmFtczogdW5rbm93bltdIH0ge1xuICAgIGlmICghZmlsdGVyIHx8IE9iamVjdC5rZXlzKGZpbHRlcikubGVuZ3RoID09PSAwKSByZXR1cm4geyBzcWw6IFwiXCIsIHBhcmFtczogW10gfTtcbiAgICBjb25zdCBjbGF1c2VzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IHBhcmFtczogdW5rbm93bltdID0gW107XG4gICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoZmlsdGVyKSkge1xuICAgICAgY29uc3Qga2V5UG9zaXRpb24gPSBzdGFydFBvc2l0aW9uICsgcGFyYW1zLmxlbmd0aDtcbiAgICAgIHBhcmFtcy5wdXNoKGtleSk7XG4gICAgICBjb25zdCB2YWx1ZVBvc2l0aW9uID0gc3RhcnRQb3NpdGlvbiArIHBhcmFtcy5sZW5ndGg7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcGFyYW1zLnB1c2godmFsdWUubWFwKFN0cmluZykpO1xuICAgICAgICBjbGF1c2VzLnB1c2goYGRvY3VtZW50IC0+PiAkJHtrZXlQb3NpdGlvbn0gPSBBTlkoJCR7dmFsdWVQb3NpdGlvbn06OnRleHRbXSlgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhcmFtcy5wdXNoKFN0cmluZyh2YWx1ZSkpO1xuICAgICAgICBjbGF1c2VzLnB1c2goYGRvY3VtZW50IC0+PiAkJHtrZXlQb3NpdGlvbn0gPSAkJHt2YWx1ZVBvc2l0aW9ufWApO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyBzcWw6IGAgQU5EICR7Y2xhdXNlcy5qb2luKFwiIEFORCBcIil9YCwgcGFyYW1zIH07XG4gIH1cblxuICAvKiogVGhlIGZ1bGx5LXF1YWxpZmllZCB0YWJsZSBuYW1lIGZvciBhbiBpbmRleCByZWZlcmVuY2UuICovXG4gIHByaXZhdGUgdGFibGVGb3IoaW5kZXg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMuaWRlbnQodGhpcy5zY2hlbWEpfS4ke3RoaXMuaWRlbnQodGhpcy5iYXJlTmFtZShpbmRleCkpfWA7XG4gIH1cblxuICAvKiogQSBzYWZlIGJhcmUgdGFibGUgbmFtZSBkZXJpdmVkIGZyb20gYW4gaW5kZXggcmVmZXJlbmNlLiAqL1xuICBwcml2YXRlIGJhcmVOYW1lKHJlZmVyZW5jZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBsYXN0ID0gcmVmZXJlbmNlLnNwbGl0KFwiLlwiKS5maWx0ZXIoQm9vbGVhbikucG9wKCkgPz8gcmVmZXJlbmNlO1xuICAgIGNvbnN0IHNsdWcgPSBzdHJpbmcudG9TbHVnKGxhc3QpLnJlcGxhY2UoLy0vZywgXCJfXCIpO1xuICAgIHJldHVybiBzbHVnLmxlbmd0aCA+IDAgPyBzbHVnIDogXCJkb2N1bWVudHNcIjtcbiAgfVxuXG4gIC8qKiBRdW90ZSBhIFBvc3RncmVzIGlkZW50aWZpZXIuICovXG4gIHByaXZhdGUgaWRlbnQobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYFwiJHtuYW1lLnJlcGxhY2UoL1wiL2csICdcIlwiJyl9XCJgO1xuICB9XG5cbiAgLyoqIFJ1biBvbmUgcXVlcnkgdW5kZXIgZXh0ZXJuYWwgY2FuY2VsbGF0aW9uLiAqL1xuICBwcml2YXRlIGFzeW5jIHF1ZXJ5PFQ+KFxuICAgIHBvb2w6IFBvb2wsXG4gICAgc3FsOiBzdHJpbmcsXG4gICAgcGFyYW1zOiB1bmtub3duW10sXG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4gICk6IFByb21pc2U8eyByb3dzOiBUW10gfT4ge1xuICAgIGlmIChzaWduYWw/LmFib3J0ZWQpIHRocm93IEV4ZWN1dGlvbkVycm9yLmNhbmNlbGVkKCk7XG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgcG9vbC5jb25uZWN0KCk7XG4gICAgbGV0IHJlbGVhc2VkID0gZmFsc2U7XG4gICAgY29uc3Qgb25BYm9ydCA9ICgpID0+IHtcbiAgICAgIGlmIChyZWxlYXNlZCkgcmV0dXJuO1xuICAgICAgcmVsZWFzZWQgPSB0cnVlO1xuICAgICAgY2xpZW50LnJlbGVhc2UodHJ1ZSk7XG4gICAgfTtcbiAgICBzaWduYWw/LmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBvbkFib3J0LCB7IG9uY2U6IHRydWUgfSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNsaWVudC5xdWVyeShzcWwsIHBhcmFtcyk7XG4gICAgICByZXR1cm4geyByb3dzOiByZXN1bHQucm93cyBhcyBUW10gfTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgc2lnbmFsPy5yZW1vdmVFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgb25BYm9ydCk7XG4gICAgICBpZiAoIXJlbGVhc2VkKSBjbGllbnQucmVsZWFzZSgpO1xuICAgIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Adapter from AppKit's native AI Search provider to the dbx-tools extension
3
+ * contract used by federated search and agent tools.
4
+ *
5
+ * @module
6
+ */
7
+ import type { SearchRequest as AppKitSearchRequest, SearchResponse as AppKitSearchResponse } from "@databricks/appkit/beta";
8
+ import { type SearchDocument, type UpsertResult } from "@dbx-tools/shared-search";
9
+ import type { SearchReadBackend } from "./client.ts";
10
+ import { type ResolvedSearchConfig } from "./config.ts";
11
+ /** Minimal query surface exposed by AppKit's native `aiSearch` plugin. */
12
+ export interface AiSearchProvider {
13
+ providerKind?: "lakebase";
14
+ query(alias: string, request: AppKitSearchRequest): Promise<AppKitSearchResponse>;
15
+ addDocuments?(alias: string, documents: SearchDocument[]): Promise<UpsertResult>;
16
+ }
17
+ /** Build a read backend that delegates every Vector Search query to AppKit. */
18
+ export declare function nativeAiSearchBackend(provider: AiSearchProvider, config: ResolvedSearchConfig): SearchReadBackend;