@archont561/qgis-sdk 0.0.0 → 0.4.0
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/LICENSE +21 -0
- package/README.md +40 -30
- package/dist/bridge.d.ts +2 -0
- package/dist/bridge.js +31 -0
- package/dist/host.d.ts +2 -0
- package/dist/host.js +51 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.js +732 -0
- package/dist/react.d.ts +137 -0
- package/dist/react.js +214 -0
- package/dist/shared/chunk-2hwva3a3.js +14 -0
- package/dist/shared/chunk-8gawbn19.js +433 -0
- package/dist/shared/chunk-jjx14tgd.d.ts +55 -0
- package/dist/shared/chunk-khemhx86.d.ts +158 -0
- package/dist/shared/chunk-pdj2fxjb.d.ts +17 -0
- package/dist/shared/chunk-tmca1ynt.d.ts +87 -0
- package/dist/shared/chunk-vqyymknv.js +414 -0
- package/dist/shared/chunk-wtv4vt4q.d.ts +280 -0
- package/dist/testing.d.ts +131 -0
- package/dist/testing.js +366 -0
- package/package.json +62 -8
package/dist/index.js
ADDED
|
@@ -0,0 +1,732 @@
|
|
|
1
|
+
import {
|
|
2
|
+
STREAM_EVENT_KINDS,
|
|
3
|
+
isPlainRecord,
|
|
4
|
+
BRIDGE_PROTOCOL_VERSION2,
|
|
5
|
+
MAX_CALL_ID_LENGTH2,
|
|
6
|
+
QgisSdkBridgeProtocolError2,
|
|
7
|
+
QgisSdkBridgeTimeoutError2,
|
|
8
|
+
QgisSdkBridgeAbortedError2,
|
|
9
|
+
QgisSdkBridgeClosedError2,
|
|
10
|
+
QgisSdkBridgeSequenceError2,
|
|
11
|
+
QgisSdkBridgeStreamEndedError2,
|
|
12
|
+
QgisSdkBridgeRemoteError2,
|
|
13
|
+
parseInvokeReply2,
|
|
14
|
+
parseStreamFrame2,
|
|
15
|
+
BridgeClient2
|
|
16
|
+
} from "./shared/chunk-8gawbn19.js";
|
|
17
|
+
import {
|
|
18
|
+
HOST_OPERATIONS2,
|
|
19
|
+
createHost2
|
|
20
|
+
} from "./shared/chunk-vqyymknv.js";
|
|
21
|
+
import {
|
|
22
|
+
QgisSdkError2
|
|
23
|
+
} from "./shared/chunk-2hwva3a3.js";
|
|
24
|
+
// src/declarations.ts
|
|
25
|
+
var MAX_SAFE_INTEGER = 9007199254740991;
|
|
26
|
+
var MIN_SAFE_INTEGER = -9007199254740991;
|
|
27
|
+
var PLUGIN_DESCRIPTION_SCHEMA_VERSION = 1;
|
|
28
|
+
function isSafeJsonInteger(value) {
|
|
29
|
+
return typeof value === "number" && Number.isSafeInteger(value);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
class QgisSdkDeclarationError extends QgisSdkError2 {
|
|
33
|
+
constructor(message) {
|
|
34
|
+
super(message, "invalid_declaration");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class QgisSdkValidationIssue {
|
|
39
|
+
path;
|
|
40
|
+
code;
|
|
41
|
+
constructor(path, code) {
|
|
42
|
+
this.path = Object.freeze([...path]);
|
|
43
|
+
this.code = code;
|
|
44
|
+
}
|
|
45
|
+
toJSON() {
|
|
46
|
+
return {
|
|
47
|
+
path: [...this.path],
|
|
48
|
+
code: this.code
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class QgisSdkContractValidationError extends QgisSdkError2 {
|
|
54
|
+
direction;
|
|
55
|
+
issues;
|
|
56
|
+
constructor(direction, issues) {
|
|
57
|
+
const prefix = direction === "request" ? "Request" : "Result";
|
|
58
|
+
super(`${prefix} contract validation failed`, "contract_validation_failed");
|
|
59
|
+
this.direction = direction;
|
|
60
|
+
this.issues = Object.freeze([...issues]);
|
|
61
|
+
}
|
|
62
|
+
toJSON() {
|
|
63
|
+
return {
|
|
64
|
+
code: this.code,
|
|
65
|
+
direction: this.direction,
|
|
66
|
+
issues: this.issues.map((issue) => issue.toJSON())
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
var DECLARATION_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9_.-]*$/;
|
|
71
|
+
var PYTHON_IDENTIFIER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
72
|
+
function validateDeclarationId(value, label) {
|
|
73
|
+
if (typeof value !== "string" || !DECLARATION_ID_PATTERN.test(value)) {
|
|
74
|
+
throw new QgisSdkDeclarationError(`Invalid ${label} id: expected [a-zA-Z][a-zA-Z0-9_.-]*`);
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
function validateNonBlankTitle(value, id) {
|
|
79
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
80
|
+
throw new QgisSdkDeclarationError(`${id}: title must be a nonempty string`);
|
|
81
|
+
}
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
function parseOperationHead(raw, label) {
|
|
85
|
+
if (!isPlainRecord(raw)) {
|
|
86
|
+
throw new QgisSdkDeclarationError(`${label[0]?.toUpperCase()}${label.slice(1)} description must be an object`);
|
|
87
|
+
}
|
|
88
|
+
const id = validateDeclarationId(raw.id, label);
|
|
89
|
+
const title = validateNonBlankTitle(raw.title, id);
|
|
90
|
+
if (typeof raw.handler !== "string" || !PYTHON_IDENTIFIER_PATTERN.test(raw.handler)) {
|
|
91
|
+
throw new QgisSdkDeclarationError(`${id}: handler must be a valid Python identifier`);
|
|
92
|
+
}
|
|
93
|
+
if (!isPlainRecord(raw.request)) {
|
|
94
|
+
throw new QgisSdkDeclarationError(`${id}: request schema must be an object`);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
raw,
|
|
98
|
+
id,
|
|
99
|
+
title,
|
|
100
|
+
handler: raw.handler,
|
|
101
|
+
request: Object.freeze({ ...raw.request })
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function parseActionDescription(raw) {
|
|
105
|
+
const head = parseOperationHead(raw, "action");
|
|
106
|
+
if (!isPlainRecord(head.raw.result)) {
|
|
107
|
+
throw new QgisSdkDeclarationError(`${head.id}: result schema must be an object`);
|
|
108
|
+
}
|
|
109
|
+
return Object.freeze({
|
|
110
|
+
id: head.id,
|
|
111
|
+
title: head.title,
|
|
112
|
+
handler: head.handler,
|
|
113
|
+
request: head.request,
|
|
114
|
+
result: Object.freeze({ ...head.raw.result })
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function parseStreamDescription(raw) {
|
|
118
|
+
const head = parseOperationHead(raw, "stream");
|
|
119
|
+
const declared = head.raw.events;
|
|
120
|
+
if (!isPlainRecord(declared) || Object.keys(declared).length === 0) {
|
|
121
|
+
throw new QgisSdkDeclarationError(`${head.id}: events must map at least one event kind to a schema`);
|
|
122
|
+
}
|
|
123
|
+
const events = {};
|
|
124
|
+
for (const [kind, schema] of Object.entries(declared)) {
|
|
125
|
+
if (!STREAM_EVENT_KINDS.includes(kind)) {
|
|
126
|
+
throw new QgisSdkDeclarationError(`${head.id}: ${kind} is not a stream event kind`);
|
|
127
|
+
}
|
|
128
|
+
if (!isPlainRecord(schema)) {
|
|
129
|
+
throw new QgisSdkDeclarationError(`${head.id}: events.${kind} schema must be an object`);
|
|
130
|
+
}
|
|
131
|
+
events[kind] = Object.freeze({ ...schema });
|
|
132
|
+
}
|
|
133
|
+
return Object.freeze({
|
|
134
|
+
id: head.id,
|
|
135
|
+
title: head.title,
|
|
136
|
+
handler: head.handler,
|
|
137
|
+
request: head.request,
|
|
138
|
+
events: Object.freeze(events)
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function parsePluginDescription(input) {
|
|
142
|
+
let parsed = input;
|
|
143
|
+
if (typeof input === "string") {
|
|
144
|
+
try {
|
|
145
|
+
parsed = JSON.parse(input);
|
|
146
|
+
} catch {
|
|
147
|
+
throw new QgisSdkDeclarationError("Plugin description is not valid JSON");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (!isPlainRecord(parsed)) {
|
|
151
|
+
throw new QgisSdkDeclarationError("Plugin description must be an object");
|
|
152
|
+
}
|
|
153
|
+
if (parsed.schema_version !== PLUGIN_DESCRIPTION_SCHEMA_VERSION) {
|
|
154
|
+
throw new QgisSdkDeclarationError(`Unsupported plugin description schema_version: ${String(parsed.schema_version)}`);
|
|
155
|
+
}
|
|
156
|
+
const id = validateDeclarationId(parsed.id, "plugin");
|
|
157
|
+
const title = validateNonBlankTitle(parsed.title, id);
|
|
158
|
+
if (!Array.isArray(parsed.actions)) {
|
|
159
|
+
throw new QgisSdkDeclarationError(`${id}: actions must be an array`);
|
|
160
|
+
}
|
|
161
|
+
const declaredStreams = parsed.streams ?? [];
|
|
162
|
+
if (!Array.isArray(declaredStreams)) {
|
|
163
|
+
throw new QgisSdkDeclarationError(`${id}: streams must be an array`);
|
|
164
|
+
}
|
|
165
|
+
const seenIds = new Set;
|
|
166
|
+
const claim = (operationId, label) => {
|
|
167
|
+
if (seenIds.has(operationId)) {
|
|
168
|
+
throw new QgisSdkDeclarationError(`${id}: duplicate ${label} id ${operationId}`);
|
|
169
|
+
}
|
|
170
|
+
seenIds.add(operationId);
|
|
171
|
+
};
|
|
172
|
+
const actions = [];
|
|
173
|
+
for (const item of parsed.actions) {
|
|
174
|
+
const action = parseActionDescription(item);
|
|
175
|
+
claim(action.id, "action");
|
|
176
|
+
actions.push(action);
|
|
177
|
+
}
|
|
178
|
+
const streams = [];
|
|
179
|
+
for (const item of declaredStreams) {
|
|
180
|
+
const stream = parseStreamDescription(item);
|
|
181
|
+
claim(stream.id, "stream");
|
|
182
|
+
streams.push(stream);
|
|
183
|
+
}
|
|
184
|
+
const byId = (left, right) => left.id < right.id ? -1 : 1;
|
|
185
|
+
actions.sort(byId);
|
|
186
|
+
streams.sort(byId);
|
|
187
|
+
return Object.freeze({
|
|
188
|
+
schema_version: PLUGIN_DESCRIPTION_SCHEMA_VERSION,
|
|
189
|
+
id,
|
|
190
|
+
title,
|
|
191
|
+
actions: Object.freeze(actions),
|
|
192
|
+
streams: Object.freeze(streams)
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// src/validate.ts
|
|
196
|
+
class QgisSdkContractError extends QgisSdkError2 {
|
|
197
|
+
operation;
|
|
198
|
+
direction;
|
|
199
|
+
issues;
|
|
200
|
+
constructor(operation, direction, issues) {
|
|
201
|
+
const detail = issues[0] === undefined ? "" : `: ${describe(issues[0])}`;
|
|
202
|
+
super(`${operation}: the ${direction} does not match the declared contract${detail}`, "contract_validation_failed");
|
|
203
|
+
this.operation = operation;
|
|
204
|
+
this.direction = direction;
|
|
205
|
+
this.issues = Object.freeze([...issues]);
|
|
206
|
+
}
|
|
207
|
+
toJSON() {
|
|
208
|
+
return {
|
|
209
|
+
code: this.code,
|
|
210
|
+
operation: this.operation,
|
|
211
|
+
direction: this.direction,
|
|
212
|
+
issues: this.issues.map((issue) => issue.toJSON())
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function describe(issue) {
|
|
217
|
+
const where = issue.path.length === 0 ? "value" : issue.path.join(".");
|
|
218
|
+
return `${where} ${issue.code}`;
|
|
219
|
+
}
|
|
220
|
+
var PRIMITIVES = new Set([
|
|
221
|
+
"string",
|
|
222
|
+
"boolean",
|
|
223
|
+
"integer",
|
|
224
|
+
"number",
|
|
225
|
+
"null",
|
|
226
|
+
"array",
|
|
227
|
+
"object"
|
|
228
|
+
]);
|
|
229
|
+
var KNOWN_KEYWORDS = new Set([
|
|
230
|
+
"type",
|
|
231
|
+
"properties",
|
|
232
|
+
"required",
|
|
233
|
+
"additionalProperties",
|
|
234
|
+
"items",
|
|
235
|
+
"anyOf",
|
|
236
|
+
"enum",
|
|
237
|
+
"minimum",
|
|
238
|
+
"maximum",
|
|
239
|
+
"pattern",
|
|
240
|
+
"title",
|
|
241
|
+
"description"
|
|
242
|
+
]);
|
|
243
|
+
function validateAgainstSchema(value, schema, options = {}) {
|
|
244
|
+
const issues = [];
|
|
245
|
+
check(value, schema, options.path ?? [], options.allowUnknown === true, issues);
|
|
246
|
+
return issues;
|
|
247
|
+
}
|
|
248
|
+
function check(value, schema, path, allowUnknown, issues) {
|
|
249
|
+
if (!isPlainRecord(schema)) {
|
|
250
|
+
throw new QgisSdkDeclarationError(`${where(path)}: a schema must be an object`);
|
|
251
|
+
}
|
|
252
|
+
const unknown = Object.keys(schema).filter((key) => !KNOWN_KEYWORDS.has(key));
|
|
253
|
+
if (unknown.length > 0) {
|
|
254
|
+
throw new QgisSdkDeclarationError(`${where(path)}: unsupported schema keyword(s) ${unknown.sort().join(", ")}`);
|
|
255
|
+
}
|
|
256
|
+
if ("anyOf" in schema) {
|
|
257
|
+
const branches = schema.anyOf;
|
|
258
|
+
if (!Array.isArray(branches) || branches.length === 0) {
|
|
259
|
+
throw new QgisSdkDeclarationError(`${where(path)}: anyOf must be a nonempty list`);
|
|
260
|
+
}
|
|
261
|
+
for (const branch of branches) {
|
|
262
|
+
const attempt = [];
|
|
263
|
+
check(value, branch, path, allowUnknown, attempt);
|
|
264
|
+
if (attempt.length === 0) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
issues.push(new QgisSdkValidationIssue([...path], "any_of"));
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if ("enum" in schema) {
|
|
272
|
+
const choices = schema.enum;
|
|
273
|
+
if (!Array.isArray(choices)) {
|
|
274
|
+
throw new QgisSdkDeclarationError(`${where(path)}: enum must be a list`);
|
|
275
|
+
}
|
|
276
|
+
if (!choices.some((choice) => sameJson(choice, value))) {
|
|
277
|
+
issues.push(new QgisSdkValidationIssue([...path], "enum"));
|
|
278
|
+
}
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const declared = schema.type;
|
|
282
|
+
if (declared === undefined) {
|
|
283
|
+
throw new QgisSdkDeclarationError(`${where(path)}: a schema needs a type, anyOf or enum`);
|
|
284
|
+
}
|
|
285
|
+
if (typeof declared !== "string" || !PRIMITIVES.has(declared)) {
|
|
286
|
+
throw new QgisSdkDeclarationError(`${where(path)}: unsupported type ${JSON.stringify(declared)}`);
|
|
287
|
+
}
|
|
288
|
+
switch (declared) {
|
|
289
|
+
case "string":
|
|
290
|
+
checkString(value, schema, path, issues);
|
|
291
|
+
return;
|
|
292
|
+
case "boolean":
|
|
293
|
+
if (typeof value !== "boolean") {
|
|
294
|
+
issues.push(new QgisSdkValidationIssue([...path], "type"));
|
|
295
|
+
}
|
|
296
|
+
return;
|
|
297
|
+
case "integer":
|
|
298
|
+
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
299
|
+
issues.push(new QgisSdkValidationIssue([...path], "type"));
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
checkBounds(value, schema, path, issues);
|
|
303
|
+
return;
|
|
304
|
+
case "number":
|
|
305
|
+
if (typeof value !== "number") {
|
|
306
|
+
issues.push(new QgisSdkValidationIssue([...path], "type"));
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (!Number.isFinite(value)) {
|
|
310
|
+
issues.push(new QgisSdkValidationIssue([...path], "not_finite"));
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
checkBounds(value, schema, path, issues);
|
|
314
|
+
return;
|
|
315
|
+
case "null":
|
|
316
|
+
if (value !== null) {
|
|
317
|
+
issues.push(new QgisSdkValidationIssue([...path], "type"));
|
|
318
|
+
}
|
|
319
|
+
return;
|
|
320
|
+
case "array":
|
|
321
|
+
checkArray(value, schema, path, allowUnknown, issues);
|
|
322
|
+
return;
|
|
323
|
+
default:
|
|
324
|
+
checkObject(value, schema, path, allowUnknown, issues);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
function checkString(value, schema, path, issues) {
|
|
328
|
+
if (typeof value !== "string") {
|
|
329
|
+
issues.push(new QgisSdkValidationIssue([...path], "type"));
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const pattern = schema.pattern;
|
|
333
|
+
if (pattern === undefined || pattern === null) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
if (typeof pattern !== "string") {
|
|
337
|
+
throw new QgisSdkDeclarationError(`${where(path)}: pattern must be a string`);
|
|
338
|
+
}
|
|
339
|
+
let expression;
|
|
340
|
+
try {
|
|
341
|
+
expression = new RegExp(`^(?:${pattern})$`, "u");
|
|
342
|
+
} catch (error) {
|
|
343
|
+
throw new QgisSdkDeclarationError(`${where(path)}: pattern ${JSON.stringify(pattern)} is unusable: ${String(error)}`);
|
|
344
|
+
}
|
|
345
|
+
if (!expression.test(value)) {
|
|
346
|
+
issues.push(new QgisSdkValidationIssue([...path], "pattern"));
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
function checkBounds(value, schema, path, issues) {
|
|
350
|
+
const minimum = schema.minimum;
|
|
351
|
+
if (typeof minimum === "number" && value < minimum) {
|
|
352
|
+
issues.push(new QgisSdkValidationIssue([...path], "minimum"));
|
|
353
|
+
}
|
|
354
|
+
const maximum = schema.maximum;
|
|
355
|
+
if (typeof maximum === "number" && value > maximum) {
|
|
356
|
+
issues.push(new QgisSdkValidationIssue([...path], "maximum"));
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
function checkArray(value, schema, path, allowUnknown, issues) {
|
|
360
|
+
if (!Array.isArray(value)) {
|
|
361
|
+
issues.push(new QgisSdkValidationIssue([...path], "type"));
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const items = schema.items;
|
|
365
|
+
if (items === undefined || items === null) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
value.forEach((item, index) => {
|
|
369
|
+
check(item, items, [...path, index], allowUnknown, issues);
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
function checkObject(value, schema, path, allowUnknown, issues) {
|
|
373
|
+
if (!isPlainRecord(value)) {
|
|
374
|
+
issues.push(new QgisSdkValidationIssue([...path], "type"));
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const properties = schema.properties ?? {};
|
|
378
|
+
if (!isPlainRecord(properties)) {
|
|
379
|
+
throw new QgisSdkDeclarationError(`${where(path)}: properties must be an object`);
|
|
380
|
+
}
|
|
381
|
+
const required = schema.required ?? [];
|
|
382
|
+
if (!Array.isArray(required)) {
|
|
383
|
+
throw new QgisSdkDeclarationError(`${where(path)}: required must be a list`);
|
|
384
|
+
}
|
|
385
|
+
for (const key of required) {
|
|
386
|
+
if (typeof key === "string" && !(key in value)) {
|
|
387
|
+
issues.push(new QgisSdkValidationIssue([...path, key], "required"));
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
const strict = schema.additionalProperties === false && !allowUnknown;
|
|
391
|
+
for (const [key, item] of Object.entries(value)) {
|
|
392
|
+
if (Object.hasOwn(properties, key)) {
|
|
393
|
+
check(item, properties[key], [...path, key], allowUnknown, issues);
|
|
394
|
+
} else if (strict) {
|
|
395
|
+
issues.push(new QgisSdkValidationIssue([...path, key], "unknown_property"));
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
function sameJson(a, b) {
|
|
400
|
+
if (a === b) {
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
if (typeof a !== typeof b || a === null || b === null) {
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
if (Array.isArray(a)) {
|
|
407
|
+
return Array.isArray(b) && a.length === b.length && a.every((item, index) => sameJson(item, b[index]));
|
|
408
|
+
}
|
|
409
|
+
if (isPlainRecord(a) && isPlainRecord(b)) {
|
|
410
|
+
const keys = Object.keys(a);
|
|
411
|
+
return keys.length === Object.keys(b).length && keys.every((key) => Object.hasOwn(b, key) && sameJson(a[key], b[key]));
|
|
412
|
+
}
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
function where(path) {
|
|
416
|
+
return path.length === 0 ? "value" : path.join(".");
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// src/webchannel.ts
|
|
420
|
+
class QgisSdkWebChannelError extends QgisSdkError2 {
|
|
421
|
+
constructor(message) {
|
|
422
|
+
super(message, "no_web_channel");
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function scope() {
|
|
426
|
+
return globalThis;
|
|
427
|
+
}
|
|
428
|
+
function insideQgis() {
|
|
429
|
+
const page = scope();
|
|
430
|
+
return page.qt !== undefined && typeof page.QWebChannel === "function";
|
|
431
|
+
}
|
|
432
|
+
function createWebChannelTransport(objectName = "bridge") {
|
|
433
|
+
const page = scope();
|
|
434
|
+
const qt = page.qt;
|
|
435
|
+
const QWebChannel = page.QWebChannel;
|
|
436
|
+
if (qt === undefined || typeof QWebChannel !== "function") {
|
|
437
|
+
throw new QgisSdkWebChannelError("not inside a QGIS web view: window.qt is missing");
|
|
438
|
+
}
|
|
439
|
+
const listeners = new Set;
|
|
440
|
+
const queue = [];
|
|
441
|
+
let object = null;
|
|
442
|
+
let failure = null;
|
|
443
|
+
let closed = false;
|
|
444
|
+
const forward = (text) => {
|
|
445
|
+
if (closed) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
let parsed;
|
|
449
|
+
try {
|
|
450
|
+
parsed = JSON.parse(text);
|
|
451
|
+
} catch {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
for (const listener of [...listeners]) {
|
|
455
|
+
listener(parsed);
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
const ready = new Promise((resolve, reject) => {
|
|
459
|
+
new QWebChannel(qt.webChannelTransport, (channel) => {
|
|
460
|
+
const found = channel.objects[objectName];
|
|
461
|
+
if (found === undefined) {
|
|
462
|
+
failure = new QgisSdkWebChannelError(`the host registered no ${JSON.stringify(objectName)} channel object`);
|
|
463
|
+
queue.length = 0;
|
|
464
|
+
reject(failure);
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
if (closed) {
|
|
468
|
+
resolve();
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
object = found;
|
|
472
|
+
found.message.connect(forward);
|
|
473
|
+
for (const text of queue.splice(0)) {
|
|
474
|
+
found.receive(text);
|
|
475
|
+
}
|
|
476
|
+
resolve();
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
return {
|
|
480
|
+
ready,
|
|
481
|
+
send(message) {
|
|
482
|
+
if (closed) {
|
|
483
|
+
throw new QgisSdkWebChannelError("the web channel transport is closed");
|
|
484
|
+
}
|
|
485
|
+
if (failure !== null) {
|
|
486
|
+
throw failure;
|
|
487
|
+
}
|
|
488
|
+
const text = JSON.stringify(message);
|
|
489
|
+
if (object === null) {
|
|
490
|
+
queue.push(text);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
object.receive(text);
|
|
494
|
+
},
|
|
495
|
+
subscribe(listener) {
|
|
496
|
+
listeners.add(listener);
|
|
497
|
+
return () => {
|
|
498
|
+
listeners.delete(listener);
|
|
499
|
+
};
|
|
500
|
+
},
|
|
501
|
+
close() {
|
|
502
|
+
if (closed) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
closed = true;
|
|
506
|
+
queue.length = 0;
|
|
507
|
+
listeners.clear();
|
|
508
|
+
object?.message.disconnect(forward);
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// src/qgis-sdk.ts
|
|
514
|
+
var QGIS_SDK_MEMBERS = Object.freeze([
|
|
515
|
+
"client",
|
|
516
|
+
"host",
|
|
517
|
+
"schema",
|
|
518
|
+
"ready",
|
|
519
|
+
"close"
|
|
520
|
+
]);
|
|
521
|
+
var HOST_IDS = new Set(HOST_OPERATIONS2);
|
|
522
|
+
function parseHandshake(value) {
|
|
523
|
+
if (!isPlainRecord(value) || !Array.isArray(value.operations)) {
|
|
524
|
+
throw new QgisSdkBridgeProtocolError2("The handshake reply carries no operations list");
|
|
525
|
+
}
|
|
526
|
+
const operations = [];
|
|
527
|
+
for (const operation of value.operations) {
|
|
528
|
+
if (isPlainRecord(operation) && typeof operation.id === "string") {
|
|
529
|
+
operations.push(operation.id);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
return { operations };
|
|
533
|
+
}
|
|
534
|
+
function unwrapRequest(operation, request) {
|
|
535
|
+
if (request === undefined) {
|
|
536
|
+
return {};
|
|
537
|
+
}
|
|
538
|
+
if (!isPlainRecord(request)) {
|
|
539
|
+
throw new QgisSdkContractError(operation, "request", [
|
|
540
|
+
...validateAgainstSchema(request, { type: "object" })
|
|
541
|
+
]);
|
|
542
|
+
}
|
|
543
|
+
return request;
|
|
544
|
+
}
|
|
545
|
+
function checkedRequest(description, request) {
|
|
546
|
+
const payload = unwrapRequest(description.id, request);
|
|
547
|
+
const issues = validateAgainstSchema(payload, description.request);
|
|
548
|
+
if (issues.length > 0) {
|
|
549
|
+
throw new QgisSdkContractError(description.id, "request", issues);
|
|
550
|
+
}
|
|
551
|
+
return payload;
|
|
552
|
+
}
|
|
553
|
+
function operationMethod(client, action) {
|
|
554
|
+
return async (request, options) => {
|
|
555
|
+
const payload = checkedRequest(action, request);
|
|
556
|
+
const value = await client.invoke(action.id, payload, options);
|
|
557
|
+
const issues = validateAgainstSchema(value, action.result, {
|
|
558
|
+
allowUnknown: true
|
|
559
|
+
});
|
|
560
|
+
if (issues.length > 0) {
|
|
561
|
+
throw new QgisSdkContractError(action.id, "result", issues);
|
|
562
|
+
}
|
|
563
|
+
return value;
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
function streamMethod(client, stream) {
|
|
567
|
+
return async (request, handlers, options) => {
|
|
568
|
+
const payload = checkedRequest(stream, request);
|
|
569
|
+
let ended = false;
|
|
570
|
+
let violated = false;
|
|
571
|
+
let handle = null;
|
|
572
|
+
const end = (terminal) => {
|
|
573
|
+
if (ended) {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
ended = true;
|
|
577
|
+
handlers.onTerminal?.(terminal);
|
|
578
|
+
};
|
|
579
|
+
handle = await client.subscribe(stream.id, payload, {
|
|
580
|
+
onEvent: (event) => {
|
|
581
|
+
if (ended) {
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
const declared = stream.events[event.kind];
|
|
585
|
+
const issues = declared === undefined ? undefined : validateAgainstSchema(event.payload, declared, {
|
|
586
|
+
allowUnknown: true,
|
|
587
|
+
path: ["payload"]
|
|
588
|
+
});
|
|
589
|
+
if (issues !== undefined && issues.length === 0) {
|
|
590
|
+
handlers.onEvent?.(event);
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
const error = new QgisSdkContractError(stream.id, "event", issues ?? []);
|
|
594
|
+
end({ kind: "error", message: error.message });
|
|
595
|
+
if (handle === null) {
|
|
596
|
+
violated = true;
|
|
597
|
+
} else {
|
|
598
|
+
handle.close();
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
onTerminal: end
|
|
602
|
+
}, options);
|
|
603
|
+
if (violated) {
|
|
604
|
+
handle.close();
|
|
605
|
+
}
|
|
606
|
+
return handle;
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
function buildHost(client, granted) {
|
|
610
|
+
const host = createHost2(client);
|
|
611
|
+
return Object.freeze({
|
|
612
|
+
...host,
|
|
613
|
+
get granted() {
|
|
614
|
+
return granted();
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
function build(schema, options) {
|
|
619
|
+
if (options.client !== undefined && options.transport !== undefined) {
|
|
620
|
+
throw new QgisSdkDeclarationError("QgisSdk.fromBridgeSchema takes a client or a transport, not both");
|
|
621
|
+
}
|
|
622
|
+
const owned = options.client === undefined;
|
|
623
|
+
const transport = options.transport ?? (options.client === undefined ? createWebChannelTransport(options.channelObject ?? "bridge") : undefined);
|
|
624
|
+
const client = options.client ?? new BridgeClient2(transport, options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs });
|
|
625
|
+
let granted = Object.freeze([]);
|
|
626
|
+
const ready = client.handshake().then((value) => {
|
|
627
|
+
const handshake = parseHandshake(value);
|
|
628
|
+
granted = Object.freeze(handshake.operations.filter((id) => HOST_IDS.has(id)));
|
|
629
|
+
});
|
|
630
|
+
ready.catch(() => {
|
|
631
|
+
return;
|
|
632
|
+
});
|
|
633
|
+
const members = {
|
|
634
|
+
schema,
|
|
635
|
+
client,
|
|
636
|
+
host: buildHost(client, () => granted),
|
|
637
|
+
ready,
|
|
638
|
+
close: () => {
|
|
639
|
+
if (owned) {
|
|
640
|
+
client.close();
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
const namespaces = [];
|
|
645
|
+
for (const action of schema.actions) {
|
|
646
|
+
place(members, namespaces, action.id, operationMethod(client, action));
|
|
647
|
+
}
|
|
648
|
+
for (const stream of schema.streams) {
|
|
649
|
+
place(members, namespaces, stream.id, streamMethod(client, stream));
|
|
650
|
+
}
|
|
651
|
+
for (const namespace of namespaces) {
|
|
652
|
+
Object.freeze(namespace);
|
|
653
|
+
}
|
|
654
|
+
return Object.freeze(members);
|
|
655
|
+
}
|
|
656
|
+
function place(members, namespaces, id, method) {
|
|
657
|
+
const segments = id.split(".");
|
|
658
|
+
if (segments.some((segment) => segment === "")) {
|
|
659
|
+
throw new QgisSdkDeclarationError(`${id}: an operation id may not have an empty segment`);
|
|
660
|
+
}
|
|
661
|
+
const head = segments[0];
|
|
662
|
+
if (QGIS_SDK_MEMBERS.includes(head)) {
|
|
663
|
+
throw new QgisSdkDeclarationError(`${id}: an operation id may not start with a QgisSdk member (${QGIS_SDK_MEMBERS.join(", ")})`);
|
|
664
|
+
}
|
|
665
|
+
let node = members;
|
|
666
|
+
for (const [index, segment] of segments.entries()) {
|
|
667
|
+
const prefix = segments.slice(0, index + 1).join(".");
|
|
668
|
+
const existing = node[segment];
|
|
669
|
+
if (index === segments.length - 1) {
|
|
670
|
+
if (existing !== undefined) {
|
|
671
|
+
throw new QgisSdkDeclarationError(typeof existing === "function" ? `${id}: duplicate operation id` : `${id}: an operation id may not be a prefix of another declared id`);
|
|
672
|
+
}
|
|
673
|
+
node[segment] = method;
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
if (existing === undefined) {
|
|
677
|
+
const namespace = {};
|
|
678
|
+
namespaces.push(namespace);
|
|
679
|
+
node[segment] = namespace;
|
|
680
|
+
node = namespace;
|
|
681
|
+
} else if (typeof existing === "function") {
|
|
682
|
+
throw new QgisSdkDeclarationError(`${id}: ${prefix} is already an operation id; an id may not extend another`);
|
|
683
|
+
} else {
|
|
684
|
+
node = existing;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
var QgisSdk;
|
|
689
|
+
((QgisSdk) => {
|
|
690
|
+
function fromBridgeSchema(schema, options = {}) {
|
|
691
|
+
return build(schema, options);
|
|
692
|
+
}
|
|
693
|
+
QgisSdk.fromBridgeSchema = fromBridgeSchema;
|
|
694
|
+
})(QgisSdk ||= {});
|
|
695
|
+
// src/schema.ts
|
|
696
|
+
function defineBridgeSchema(input) {
|
|
697
|
+
return parsePluginDescription(input);
|
|
698
|
+
}
|
|
699
|
+
export {
|
|
700
|
+
BRIDGE_PROTOCOL_VERSION2 as BRIDGE_PROTOCOL_VERSION,
|
|
701
|
+
BridgeClient2 as BridgeClient,
|
|
702
|
+
MAX_CALL_ID_LENGTH2 as MAX_CALL_ID_LENGTH,
|
|
703
|
+
MAX_SAFE_INTEGER,
|
|
704
|
+
MIN_SAFE_INTEGER,
|
|
705
|
+
PLUGIN_DESCRIPTION_SCHEMA_VERSION,
|
|
706
|
+
QGIS_SDK_MEMBERS,
|
|
707
|
+
QgisSdk,
|
|
708
|
+
QgisSdkBridgeAbortedError2 as QgisSdkBridgeAbortedError,
|
|
709
|
+
QgisSdkBridgeClosedError2 as QgisSdkBridgeClosedError,
|
|
710
|
+
QgisSdkBridgeProtocolError2 as QgisSdkBridgeProtocolError,
|
|
711
|
+
QgisSdkBridgeRemoteError2 as QgisSdkBridgeRemoteError,
|
|
712
|
+
QgisSdkBridgeSequenceError2 as QgisSdkBridgeSequenceError,
|
|
713
|
+
QgisSdkBridgeStreamEndedError2 as QgisSdkBridgeStreamEndedError,
|
|
714
|
+
QgisSdkBridgeTimeoutError2 as QgisSdkBridgeTimeoutError,
|
|
715
|
+
QgisSdkContractError,
|
|
716
|
+
QgisSdkContractValidationError,
|
|
717
|
+
QgisSdkDeclarationError,
|
|
718
|
+
QgisSdkError2 as QgisSdkError,
|
|
719
|
+
QgisSdkValidationIssue,
|
|
720
|
+
QgisSdkWebChannelError,
|
|
721
|
+
createWebChannelTransport,
|
|
722
|
+
defineBridgeSchema,
|
|
723
|
+
insideQgis,
|
|
724
|
+
isSafeJsonInteger,
|
|
725
|
+
parseInvokeReply2 as parseInvokeReply,
|
|
726
|
+
parsePluginDescription,
|
|
727
|
+
parseStreamFrame2 as parseStreamFrame,
|
|
728
|
+
validateAgainstSchema
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
//# debugId=7555C93DA5D57B1A64756E2164756E21
|
|
732
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL2RlY2xhcmF0aW9ucy50cyIsICJzcmMvdmFsaWRhdGUudHMiLCAic3JjL3dlYmNoYW5uZWwudHMiLCAic3JjL3FnaXMtc2RrLnRzIiwgInNyYy9zY2hlbWEudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbCiAgICAiLyoqXG4gKiBUaGUgdmVyc2lvbiAxIHBsdWdpbi1kZXNjcmlwdGlvbiBjb250cmFjdCBhbmQgaXRzIHdpcmUgbGltaXRzLlxuICpcbiAqIE1pcnJvcnMgdGhlIFFHSVMtZnJlZSBgcWdpc19zZGsubW9kZWxzYCBhbmQgYHFnaXNfc2RrLmRlY2xhcmF0aW9uc2BcbiAqIChgc2NoZW1hX3ZlcnNpb24gPSAxYCkgY29udHJhY3RzIHdpdGhvdXQgaW1wb3J0aW5nIGJyb3dzZXIgb3IgUXQgZ2xvYmFscy5cbiAqIGBwYXJzZVBsdWdpbkRlc2NyaXB0aW9uYCBpcyB0aGUgYnJvd3Nlci1zaWRlIHJlYWRlciBvZiB3aGF0XG4gKiBgZGVzY3JpYmVfcGx1Z2luKGNscykudG9fanNvbigpYCBlbWl0czsgYHFnaXMtc2RrIGJyaWRnZSBnZW5lcmF0ZWAgaXMgdGhlXG4gKiBidWlsZC10aW1lIG9uZS5cbiAqL1xuXG5pbXBvcnQgeyBRZ2lzU2RrRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcbmltcG9ydCB7IGlzUGxhaW5SZWNvcmQsIFNUUkVBTV9FVkVOVF9LSU5EUyB9IGZyb20gXCIuL2ludGVybmFsXCI7XG5cbmV4cG9ydCBjb25zdCBNQVhfU0FGRV9JTlRFR0VSOiBudW1iZXIgPSA5XzAwN18xOTlfMjU0Xzc0MF85OTE7XG5leHBvcnQgY29uc3QgTUlOX1NBRkVfSU5URUdFUjogbnVtYmVyID0gLTlfMDA3XzE5OV8yNTRfNzQwXzk5MTtcbmV4cG9ydCBjb25zdCBQTFVHSU5fREVTQ1JJUFRJT05fU0NIRU1BX1ZFUlNJT046IDEgPSAxO1xuXG5leHBvcnQgdHlwZSBWYWxpZGF0aW9uRGlyZWN0aW9uID0gXCJyZXF1ZXN0XCIgfCBcInJlc3VsdFwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNlcmlhbGl6ZWRWYWxpZGF0aW9uSXNzdWUge1xuXHRyZWFkb25seSBwYXRoOiAoc3RyaW5nIHwgbnVtYmVyKVtdO1xuXHRyZWFkb25seSBjb2RlOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VyaWFsaXplZENvbnRyYWN0VmFsaWRhdGlvbkVycm9yIHtcblx0cmVhZG9ubHkgY29kZTogc3RyaW5nO1xuXHRyZWFkb25seSBkaXJlY3Rpb246IFZhbGlkYXRpb25EaXJlY3Rpb247XG5cdHJlYWRvbmx5IGlzc3VlczogU2VyaWFsaXplZFZhbGlkYXRpb25Jc3N1ZVtdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFjdGlvbkRlc2NyaXB0aW9uIHtcblx0cmVhZG9ubHkgaWQ6IHN0cmluZztcblx0cmVhZG9ubHkgdGl0bGU6IHN0cmluZztcblx0cmVhZG9ubHkgaGFuZGxlcjogc3RyaW5nO1xuXHRyZWFkb25seSByZXF1ZXN0OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj47XG5cdHJlYWRvbmx5IHJlc3VsdDogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+O1xufVxuXG4vKiogVGhlIGV2ZW50IGtpbmRzIGEgc3RyZWFtIG1heSBkZWNsYXJlOyB0aGUgZnJhbWUgY2FycmllcyB0aGUgc2FtZSB0aHJlZS4gKi9cbmV4cG9ydCB0eXBlIFN0cmVhbUV2ZW50S2luZCA9IFwiZGF0YVwiIHwgXCJwcm9ncmVzc1wiIHwgXCJzdGF0ZVwiO1xuXG4vKipcbiAqIEEgZGVjbGFyZWQgc3RyZWFtIChkZWNpc2lvbi0yOCk6IGEgcmVxdWVzdCBpbiwgb25lIHBheWxvYWQgc2NoZW1hIHBlclxuICogZGVjbGFyZWQgZXZlbnQga2luZCBvdXQuIFRoZXJlIGlzIG5vIGByZXN1bHRgOiB0aGUgcmVwbHkgdG8gYSBzdWJzY3JpcHRpb24gaXNcbiAqIHRoZSBwcm90b2NvbCdzIGFja25vd2xlZGdlbWVudCwgbm90IHNvbWV0aGluZyBhbiBhdXRob3IgZGVjbGFyZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RyZWFtRGVzY3JpcHRpb24ge1xuXHRyZWFkb25seSBpZDogc3RyaW5nO1xuXHRyZWFkb25seSB0aXRsZTogc3RyaW5nO1xuXHRyZWFkb25seSBoYW5kbGVyOiBzdHJpbmc7XG5cdHJlYWRvbmx5IHJlcXVlc3Q6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pjtcblx0cmVhZG9ubHkgZXZlbnRzOiBSZWFkb25seTxcblx0XHRQYXJ0aWFsPFJlY29yZDxTdHJlYW1FdmVudEtpbmQsIFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pj4+XG5cdD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGx1Z2luRGVzY3JpcHRpb24ge1xuXHRyZWFkb25seSBzY2hlbWFfdmVyc2lvbjogMTtcblx0cmVhZG9ubHkgaWQ6IHN0cmluZztcblx0cmVhZG9ubHkgdGl0bGU6IHN0cmluZztcblx0cmVhZG9ubHkgYWN0aW9uczogcmVhZG9ubHkgQWN0aW9uRGVzY3JpcHRpb25bXTtcblx0LyoqIERlY2xhcmVkIHN0cmVhbXM7IGEgZGVzY3JpcHRpb24gZnJvbSBhIGhvc3QgdGhhdCBwcmVkYXRlcyB0aGVtIGlzIGVtcHR5LiAqL1xuXHRyZWFkb25seSBzdHJlYW1zOiByZWFkb25seSBTdHJlYW1EZXNjcmlwdGlvbltdO1xufVxuXG4vKipcbiAqIFJldHVybiB3aGV0aGVyIGB2YWx1ZWAgaXMgYSBmaW5pdGUgaW50ZWdlciB3aXRoaW4gdGhlIEphdmFTY3JpcHQtc2FmZSB3aXJlIHJhbmdlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTYWZlSnNvbkludGVnZXIodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBudW1iZXIge1xuXHRyZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiICYmIE51bWJlci5pc1NhZmVJbnRlZ2VyKHZhbHVlKTtcbn1cblxuLyoqXG4gKiBBIGRlY2xhcmF0aW9uIGNhbm5vdCBiZSByZXByZXNlbnRlZCBvciBwYXJzZWQgaW4gdGhlIHZlcnNpb25lZCBjb250cmFjdC5cbiAqL1xuZXhwb3J0IGNsYXNzIFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yIGV4dGVuZHMgUWdpc1Nka0Vycm9yIHtcblx0cHVibGljIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuXHRcdHN1cGVyKG1lc3NhZ2UsIFwiaW52YWxpZF9kZWNsYXJhdGlvblwiKTtcblx0fVxufVxuXG4vKipcbiAqIFNhZmUsIHN0cnVjdHVyZWQgbG9jYXRpb24gYW5kIGNhdGVnb3J5IGZvciBhIHJlamVjdGVkIGNvbnRyYWN0IHZhbHVlLlxuICovXG5leHBvcnQgY2xhc3MgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZSB7XG5cdHB1YmxpYyByZWFkb25seSBwYXRoOiByZWFkb25seSAoc3RyaW5nIHwgbnVtYmVyKVtdO1xuXHRwdWJsaWMgcmVhZG9ubHkgY29kZTogc3RyaW5nO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihwYXRoOiByZWFkb25seSAoc3RyaW5nIHwgbnVtYmVyKVtdLCBjb2RlOiBzdHJpbmcpIHtcblx0XHR0aGlzLnBhdGggPSBPYmplY3QuZnJlZXplKFsuLi5wYXRoXSk7XG5cdFx0dGhpcy5jb2RlID0gY29kZTtcblx0fVxuXG5cdHB1YmxpYyB0b0pTT04oKTogU2VyaWFsaXplZFZhbGlkYXRpb25Jc3N1ZSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHBhdGg6IFsuLi50aGlzLnBhdGhdLFxuXHRcdFx0Y29kZTogdGhpcy5jb2RlLFxuXHRcdH07XG5cdH1cbn1cblxuLyoqXG4gKiBBIHJlcXVlc3Qgb3IgcmVzdWx0IGRpZCBub3Qgc2F0aXNmeSBpdHMgZGVjbGFyZWQgd2lyZSBjb250cmFjdC5cbiAqL1xuZXhwb3J0IGNsYXNzIFFnaXNTZGtDb250cmFjdFZhbGlkYXRpb25FcnJvciBleHRlbmRzIFFnaXNTZGtFcnJvciB7XG5cdHB1YmxpYyByZWFkb25seSBkaXJlY3Rpb246IFZhbGlkYXRpb25EaXJlY3Rpb247XG5cdHB1YmxpYyByZWFkb25seSBpc3N1ZXM6IHJlYWRvbmx5IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWVbXTtcblxuXHRwdWJsaWMgY29uc3RydWN0b3IoXG5cdFx0ZGlyZWN0aW9uOiBWYWxpZGF0aW9uRGlyZWN0aW9uLFxuXHRcdGlzc3VlczogcmVhZG9ubHkgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZVtdLFxuXHQpIHtcblx0XHRjb25zdCBwcmVmaXggPSBkaXJlY3Rpb24gPT09IFwicmVxdWVzdFwiID8gXCJSZXF1ZXN0XCIgOiBcIlJlc3VsdFwiO1xuXHRcdHN1cGVyKGAke3ByZWZpeH0gY29udHJhY3QgdmFsaWRhdGlvbiBmYWlsZWRgLCBcImNvbnRyYWN0X3ZhbGlkYXRpb25fZmFpbGVkXCIpO1xuXHRcdHRoaXMuZGlyZWN0aW9uID0gZGlyZWN0aW9uO1xuXHRcdHRoaXMuaXNzdWVzID0gT2JqZWN0LmZyZWV6ZShbLi4uaXNzdWVzXSk7XG5cdH1cblxuXHRwdWJsaWMgdG9KU09OKCk6IFNlcmlhbGl6ZWRDb250cmFjdFZhbGlkYXRpb25FcnJvciB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGNvZGU6IHRoaXMuY29kZSxcblx0XHRcdGRpcmVjdGlvbjogdGhpcy5kaXJlY3Rpb24sXG5cdFx0XHRpc3N1ZXM6IHRoaXMuaXNzdWVzLm1hcCgoaXNzdWUpID0+IGlzc3VlLnRvSlNPTigpKSxcblx0XHR9O1xuXHR9XG59XG5cbmNvbnN0IERFQ0xBUkFUSU9OX0lEX1BBVFRFUk4gPSAvXlthLXpBLVpdW2EtekEtWjAtOV8uLV0qJC87XG5jb25zdCBQWVRIT05fSURFTlRJRklFUl9QQVRURVJOID0gL15bYS16QS1aX11bYS16QS1aMC05X10qJC87XG5cbmZ1bmN0aW9uIHZhbGlkYXRlRGVjbGFyYXRpb25JZCh2YWx1ZTogdW5rbm93biwgbGFiZWw6IHN0cmluZyk6IHN0cmluZyB7XG5cdGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIgfHwgIURFQ0xBUkFUSU9OX0lEX1BBVFRFUk4udGVzdCh2YWx1ZSkpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRgSW52YWxpZCAke2xhYmVsfSBpZDogZXhwZWN0ZWQgW2EtekEtWl1bYS16QS1aMC05Xy4tXSpgLFxuXHRcdCk7XG5cdH1cblx0cmV0dXJuIHZhbHVlO1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZU5vbkJsYW5rVGl0bGUodmFsdWU6IHVua25vd24sIGlkOiBzdHJpbmcpOiBzdHJpbmcge1xuXHRpZiAodHlwZW9mIHZhbHVlICE9PSBcInN0cmluZ1wiIHx8IHZhbHVlLnRyaW0oKS5sZW5ndGggPT09IDApIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoYCR7aWR9OiB0aXRsZSBtdXN0IGJlIGEgbm9uZW1wdHkgc3RyaW5nYCk7XG5cdH1cblx0cmV0dXJuIHZhbHVlO1xufVxuXG5mdW5jdGlvbiBwYXJzZU9wZXJhdGlvbkhlYWQoXG5cdHJhdzogdW5rbm93bixcblx0bGFiZWw6IHN0cmluZyxcbik6IHtcblx0cmVhZG9ubHkgcmF3OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblx0cmVhZG9ubHkgaWQ6IHN0cmluZztcblx0cmVhZG9ubHkgdGl0bGU6IHN0cmluZztcblx0cmVhZG9ubHkgaGFuZGxlcjogc3RyaW5nO1xuXHRyZWFkb25seSByZXF1ZXN0OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj47XG59IHtcblx0aWYgKCFpc1BsYWluUmVjb3JkKHJhdykpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRgJHtsYWJlbFswXT8udG9VcHBlckNhc2UoKX0ke2xhYmVsLnNsaWNlKDEpfSBkZXNjcmlwdGlvbiBtdXN0IGJlIGFuIG9iamVjdGAsXG5cdFx0KTtcblx0fVxuXHRjb25zdCBpZCA9IHZhbGlkYXRlRGVjbGFyYXRpb25JZChyYXcuaWQsIGxhYmVsKTtcblx0Y29uc3QgdGl0bGUgPSB2YWxpZGF0ZU5vbkJsYW5rVGl0bGUocmF3LnRpdGxlLCBpZCk7XG5cdGlmIChcblx0XHR0eXBlb2YgcmF3LmhhbmRsZXIgIT09IFwic3RyaW5nXCIgfHxcblx0XHQhUFlUSE9OX0lERU5USUZJRVJfUEFUVEVSTi50ZXN0KHJhdy5oYW5kbGVyKVxuXHQpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRgJHtpZH06IGhhbmRsZXIgbXVzdCBiZSBhIHZhbGlkIFB5dGhvbiBpZGVudGlmaWVyYCxcblx0XHQpO1xuXHR9XG5cdGlmICghaXNQbGFpblJlY29yZChyYXcucmVxdWVzdCkpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRgJHtpZH06IHJlcXVlc3Qgc2NoZW1hIG11c3QgYmUgYW4gb2JqZWN0YCxcblx0XHQpO1xuXHR9XG5cdHJldHVybiB7XG5cdFx0cmF3LFxuXHRcdGlkLFxuXHRcdHRpdGxlLFxuXHRcdGhhbmRsZXI6IHJhdy5oYW5kbGVyLFxuXHRcdHJlcXVlc3Q6IE9iamVjdC5mcmVlemUoeyAuLi5yYXcucmVxdWVzdCB9KSxcblx0fTtcbn1cblxuZnVuY3Rpb24gcGFyc2VBY3Rpb25EZXNjcmlwdGlvbihyYXc6IHVua25vd24pOiBBY3Rpb25EZXNjcmlwdGlvbiB7XG5cdGNvbnN0IGhlYWQgPSBwYXJzZU9wZXJhdGlvbkhlYWQocmF3LCBcImFjdGlvblwiKTtcblx0aWYgKCFpc1BsYWluUmVjb3JkKGhlYWQucmF3LnJlc3VsdCkpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRgJHtoZWFkLmlkfTogcmVzdWx0IHNjaGVtYSBtdXN0IGJlIGFuIG9iamVjdGAsXG5cdFx0KTtcblx0fVxuXHRyZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG5cdFx0aWQ6IGhlYWQuaWQsXG5cdFx0dGl0bGU6IGhlYWQudGl0bGUsXG5cdFx0aGFuZGxlcjogaGVhZC5oYW5kbGVyLFxuXHRcdHJlcXVlc3Q6IGhlYWQucmVxdWVzdCxcblx0XHRyZXN1bHQ6IE9iamVjdC5mcmVlemUoeyAuLi5oZWFkLnJhdy5yZXN1bHQgfSksXG5cdH0pO1xufVxuXG5mdW5jdGlvbiBwYXJzZVN0cmVhbURlc2NyaXB0aW9uKHJhdzogdW5rbm93bik6IFN0cmVhbURlc2NyaXB0aW9uIHtcblx0Y29uc3QgaGVhZCA9IHBhcnNlT3BlcmF0aW9uSGVhZChyYXcsIFwic3RyZWFtXCIpO1xuXHRjb25zdCBkZWNsYXJlZCA9IGhlYWQucmF3LmV2ZW50cztcblx0aWYgKCFpc1BsYWluUmVjb3JkKGRlY2xhcmVkKSB8fCBPYmplY3Qua2V5cyhkZWNsYXJlZCkubGVuZ3RoID09PSAwKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0YCR7aGVhZC5pZH06IGV2ZW50cyBtdXN0IG1hcCBhdCBsZWFzdCBvbmUgZXZlbnQga2luZCB0byBhIHNjaGVtYWAsXG5cdFx0KTtcblx0fVxuXHRjb25zdCBldmVudHM6IFBhcnRpYWw8XG5cdFx0UmVjb3JkPFN0cmVhbUV2ZW50S2luZCwgUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+PlxuXHQ+ID0ge307XG5cdGZvciAoY29uc3QgW2tpbmQsIHNjaGVtYV0gb2YgT2JqZWN0LmVudHJpZXMoZGVjbGFyZWQpKSB7XG5cdFx0aWYgKCFTVFJFQU1fRVZFTlRfS0lORFMuaW5jbHVkZXMoa2luZCBhcyBTdHJlYW1FdmVudEtpbmQpKSB7XG5cdFx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRcdGAke2hlYWQuaWR9OiAke2tpbmR9IGlzIG5vdCBhIHN0cmVhbSBldmVudCBraW5kYCxcblx0XHRcdCk7XG5cdFx0fVxuXHRcdGlmICghaXNQbGFpblJlY29yZChzY2hlbWEpKSB7XG5cdFx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRcdGAke2hlYWQuaWR9OiBldmVudHMuJHtraW5kfSBzY2hlbWEgbXVzdCBiZSBhbiBvYmplY3RgLFxuXHRcdFx0KTtcblx0XHR9XG5cdFx0ZXZlbnRzW2tpbmQgYXMgU3RyZWFtRXZlbnRLaW5kXSA9IE9iamVjdC5mcmVlemUoeyAuLi5zY2hlbWEgfSk7XG5cdH1cblx0cmV0dXJuIE9iamVjdC5mcmVlemUoe1xuXHRcdGlkOiBoZWFkLmlkLFxuXHRcdHRpdGxlOiBoZWFkLnRpdGxlLFxuXHRcdGhhbmRsZXI6IGhlYWQuaGFuZGxlcixcblx0XHRyZXF1ZXN0OiBoZWFkLnJlcXVlc3QsXG5cdFx0ZXZlbnRzOiBPYmplY3QuZnJlZXplKGV2ZW50cyksXG5cdH0pO1xufVxuXG4vKipcbiAqIFBhcnNlIGFuZCB2YWxpZGF0ZSBhIHZlcnNpb24gMSBgUGx1Z2luRGVzY3JpcHRpb25gIGVtaXR0ZWQgYnkgYGRlc2NyaWJlX3BsdWdpbmAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVBsdWdpbkRlc2NyaXB0aW9uKFxuXHRpbnB1dDogc3RyaW5nIHwgUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+LFxuKTogUGx1Z2luRGVzY3JpcHRpb24ge1xuXHRsZXQgcGFyc2VkOiB1bmtub3duID0gaW5wdXQ7XG5cdGlmICh0eXBlb2YgaW5wdXQgPT09IFwic3RyaW5nXCIpIHtcblx0XHR0cnkge1xuXHRcdFx0cGFyc2VkID0gSlNPTi5wYXJzZShpbnB1dCk7XG5cdFx0fSBjYXRjaCB7XG5cdFx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXCJQbHVnaW4gZGVzY3JpcHRpb24gaXMgbm90IHZhbGlkIEpTT05cIik7XG5cdFx0fVxuXHR9XG5cdGlmICghaXNQbGFpblJlY29yZChwYXJzZWQpKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFwiUGx1Z2luIGRlc2NyaXB0aW9uIG11c3QgYmUgYW4gb2JqZWN0XCIpO1xuXHR9XG5cdGlmIChwYXJzZWQuc2NoZW1hX3ZlcnNpb24gIT09IFBMVUdJTl9ERVNDUklQVElPTl9TQ0hFTUFfVkVSU0lPTikge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGBVbnN1cHBvcnRlZCBwbHVnaW4gZGVzY3JpcHRpb24gc2NoZW1hX3ZlcnNpb246ICR7U3RyaW5nKHBhcnNlZC5zY2hlbWFfdmVyc2lvbil9YCxcblx0XHQpO1xuXHR9XG5cdGNvbnN0IGlkID0gdmFsaWRhdGVEZWNsYXJhdGlvbklkKHBhcnNlZC5pZCwgXCJwbHVnaW5cIik7XG5cdGNvbnN0IHRpdGxlID0gdmFsaWRhdGVOb25CbGFua1RpdGxlKHBhcnNlZC50aXRsZSwgaWQpO1xuXHRpZiAoIUFycmF5LmlzQXJyYXkocGFyc2VkLmFjdGlvbnMpKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKGAke2lkfTogYWN0aW9ucyBtdXN0IGJlIGFuIGFycmF5YCk7XG5cdH1cblx0Y29uc3QgZGVjbGFyZWRTdHJlYW1zID0gcGFyc2VkLnN0cmVhbXMgPz8gW107XG5cdGlmICghQXJyYXkuaXNBcnJheShkZWNsYXJlZFN0cmVhbXMpKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKGAke2lkfTogc3RyZWFtcyBtdXN0IGJlIGFuIGFycmF5YCk7XG5cdH1cblx0Ly8gQWN0aW9ucyBhbmQgc3RyZWFtcyBzaGFyZSBvbmUgaWQgbmFtZXNwYWNlIChkZWNpc2lvbi0yOCkuXG5cdGNvbnN0IHNlZW5JZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblx0Y29uc3QgY2xhaW0gPSAob3BlcmF0aW9uSWQ6IHN0cmluZywgbGFiZWw6IHN0cmluZyk6IHZvaWQgPT4ge1xuXHRcdGlmIChzZWVuSWRzLmhhcyhvcGVyYXRpb25JZCkpIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdFx0YCR7aWR9OiBkdXBsaWNhdGUgJHtsYWJlbH0gaWQgJHtvcGVyYXRpb25JZH1gLFxuXHRcdFx0KTtcblx0XHR9XG5cdFx0c2Vlbklkcy5hZGQob3BlcmF0aW9uSWQpO1xuXHR9O1xuXHRjb25zdCBhY3Rpb25zOiBBY3Rpb25EZXNjcmlwdGlvbltdID0gW107XG5cdGZvciAoY29uc3QgaXRlbSBvZiBwYXJzZWQuYWN0aW9ucykge1xuXHRcdGNvbnN0IGFjdGlvbiA9IHBhcnNlQWN0aW9uRGVzY3JpcHRpb24oaXRlbSk7XG5cdFx0Y2xhaW0oYWN0aW9uLmlkLCBcImFjdGlvblwiKTtcblx0XHRhY3Rpb25zLnB1c2goYWN0aW9uKTtcblx0fVxuXHRjb25zdCBzdHJlYW1zOiBTdHJlYW1EZXNjcmlwdGlvbltdID0gW107XG5cdGZvciAoY29uc3QgaXRlbSBvZiBkZWNsYXJlZFN0cmVhbXMpIHtcblx0XHRjb25zdCBzdHJlYW0gPSBwYXJzZVN0cmVhbURlc2NyaXB0aW9uKGl0ZW0pO1xuXHRcdGNsYWltKHN0cmVhbS5pZCwgXCJzdHJlYW1cIik7XG5cdFx0c3RyZWFtcy5wdXNoKHN0cmVhbSk7XG5cdH1cblx0Y29uc3QgYnlJZCA9IChcblx0XHRsZWZ0OiB7IHJlYWRvbmx5IGlkOiBzdHJpbmcgfSxcblx0XHRyaWdodDogeyByZWFkb25seSBpZDogc3RyaW5nIH0sXG5cdCk6IG51bWJlciA9PiAobGVmdC5pZCA8IHJpZ2h0LmlkID8gLTEgOiAxKTtcblx0YWN0aW9ucy5zb3J0KGJ5SWQpO1xuXHRzdHJlYW1zLnNvcnQoYnlJZCk7XG5cdHJldHVybiBPYmplY3QuZnJlZXplKHtcblx0XHRzY2hlbWFfdmVyc2lvbjogUExVR0lOX0RFU0NSSVBUSU9OX1NDSEVNQV9WRVJTSU9OLFxuXHRcdGlkLFxuXHRcdHRpdGxlLFxuXHRcdGFjdGlvbnM6IE9iamVjdC5mcmVlemUoYWN0aW9ucyksXG5cdFx0c3RyZWFtczogT2JqZWN0LmZyZWV6ZShzdHJlYW1zKSxcblx0fSk7XG59XG4iLAogICAgIi8qKlxuICogVmFsaWRhdGUgYSB2YWx1ZSBhZ2FpbnN0IHRoZSBzY2hlbWEgc3Vic2V0IGBkZXNjcmliZV9wbHVnaW5gIGVtaXRzLlxuICpcbiAqIFRoaXMgaXMgdGhlIFR5cGVTY3JpcHQgc2lkZSBvZiBgcWdpc19zZGsuYnJpZGdlLnNjaGVtYWA6IHRoZSBzYW1lIGNsb3NlZFxuICogZGlhbGVjdCAob2JqZWN0cyB3aXRoIGBwcm9wZXJ0aWVzYC9gcmVxdWlyZWRgL2BhZGRpdGlvbmFsUHJvcGVydGllc2AsIGFycmF5c1xuICogd2l0aCBgaXRlbXNgLCB0aGUgZml2ZSBKU09OIHByaW1pdGl2ZXMsIGBhbnlPZmAgYW5kIGBlbnVtYCwgdGhlIGludGVnZXJcbiAqIGJvdW5kcyBhbmQgYHBhdHRlcm5gKSBjaGVja2VkIHRoZSBzYW1lIHdheSwgc28gYFFnaXNTZGtgIHJlZnVzZXMgb24gdGhlIHBhZ2VcbiAqIGV4YWN0bHkgd2hhdCB0aGUgaG9zdCB3b3VsZCByZWZ1c2UgYSBtZXNzYWdlIGxhdGVyLiBBbnl0aGluZyBvdXRzaWRlIHRoZVxuICogZGlhbGVjdCBpcyBhIGRlY2xhcmF0aW9uIGZhdWx0IGFuZCB0aHJvd3M7IGEgdmFsdWUgdGhhdCBkb2VzIG5vdCBmaXQgaXMgYW5cbiAqIGlzc3VlIHRoZSBjYWxsZXIgcmVwb3J0cy5cbiAqXG4gKiBUaGUgdHdvIGFzeW1tZXRyaWVzIG9mIGRlY2lzaW9uLTIyIGhvbGQgaGVyZSB0b286IGEgcmVxdWVzdCBpcyBjaGVja2VkXG4gKiBzdHJpY3RseSAoYW4gdW5rbm93biBwcm9wZXJ0eSBpcyBhbiBpc3N1ZSB3aGVuIHRoZSBzY2hlbWEgY2xvc2VzIHRoZVxuICogb2JqZWN0KSwgYSByZXN1bHQgb3IgYW4gZXZlbnQgbGVuaWVudGx5IChgYWxsb3dVbmtub3duYCksIHNvIGEgaG9zdCBtYXkgYWRkXG4gKiBhIGZpZWxkIHdpdGhvdXQgYnJlYWtpbmcgYW4gb2xkZXIgcGFnZSB3aGlsZSBhIG1pc3Npbmcgb3IgbWlzdHlwZWQgZmllbGQgaXNcbiAqIHN0aWxsIGNhdWdodC5cbiAqL1xuXG5pbXBvcnQge1xuXHRRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcixcblx0UWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZSxcblx0dHlwZSBTZXJpYWxpemVkVmFsaWRhdGlvbklzc3VlLFxufSBmcm9tIFwiLi9kZWNsYXJhdGlvbnNcIjtcbmltcG9ydCB7IFFnaXNTZGtFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgaXNQbGFpblJlY29yZCB9IGZyb20gXCIuL2ludGVybmFsXCI7XG5cbi8qKiBPbmUgc2NoZW1hIG9mIHRoZSBkZWNsYXJlZCBkaWFsZWN0LCBhcyB0aGUgZGVzY3JpcHRpb24gY2FycmllcyBpdC4gKi9cbmV4cG9ydCB0eXBlIERlY2xhcmVkU2NoZW1hID0gUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+O1xuXG4vKiogT3B0aW9ucyBmb3Ige0BsaW5rIHZhbGlkYXRlQWdhaW5zdFNjaGVtYX0uICovXG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRlT3B0aW9ucyB7XG5cdC8qKiBJZ25vcmUgcHJvcGVydGllcyB0aGUgc2NoZW1hIGRvZXMgbm90IG5hbWUgKHJlc3VsdHMgYW5kIGV2ZW50cykuICovXG5cdHJlYWRvbmx5IGFsbG93VW5rbm93bj86IGJvb2xlYW47XG5cdC8qKiBXaGVyZSB0aGUgdmFsdWUgc2l0cywgcHJlZml4ZWQgdG8gZXZlcnkgaXNzdWUncyBwYXRoLiAqL1xuXHRyZWFkb25seSBwYXRoPzogcmVhZG9ubHkgKHN0cmluZyB8IG51bWJlcilbXTtcbn1cblxuLyoqIFdoaWNoIHNpZGUgb2YgYSBjYWxsIGEgY29udHJhY3QgaXNzdWUgYmVsb25ncyB0by4gKi9cbmV4cG9ydCB0eXBlIENvbnRyYWN0RGlyZWN0aW9uID0gXCJyZXF1ZXN0XCIgfCBcInJlc3VsdFwiIHwgXCJldmVudFwiO1xuXG4vKiogVGhlIEpTT04gZm9ybSBvZiB7QGxpbmsgUWdpc1Nka0NvbnRyYWN0RXJyb3J9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBTZXJpYWxpemVkQ29udHJhY3RFcnJvciB7XG5cdHJlYWRvbmx5IGNvZGU6IHN0cmluZztcblx0cmVhZG9ubHkgb3BlcmF0aW9uOiBzdHJpbmc7XG5cdHJlYWRvbmx5IGRpcmVjdGlvbjogQ29udHJhY3REaXJlY3Rpb247XG5cdHJlYWRvbmx5IGlzc3VlczogU2VyaWFsaXplZFZhbGlkYXRpb25Jc3N1ZVtdO1xufVxuXG4vKipcbiAqIEFuIGFyZ3VtZW50LCBhIHJlcGx5IG9yIGFuIGV2ZW50IGRvZXMgbm90IG1hdGNoIHRoZSBkZWNsYXJlZCBjb250cmFjdC5cbiAqXG4gKiBUaGUgY29kZSBpcyB0aGUgb25lIGJvdGggbGFuZ3VhZ2VzIHVzZSBmb3IgdGhpcyBjYXRlZ29yeSwgc28gYSBwYWdlIHRoYXRcbiAqIGFscmVhZHkgbWF0Y2hlcyBgY29udHJhY3RfdmFsaWRhdGlvbl9mYWlsZWRgIG5lZWRzIG5vIHNlY29uZCBicmFuY2guXG4gKi9cbmV4cG9ydCBjbGFzcyBRZ2lzU2RrQ29udHJhY3RFcnJvciBleHRlbmRzIFFnaXNTZGtFcnJvciB7XG5cdHB1YmxpYyByZWFkb25seSBvcGVyYXRpb246IHN0cmluZztcblx0cHVibGljIHJlYWRvbmx5IGRpcmVjdGlvbjogQ29udHJhY3REaXJlY3Rpb247XG5cdHB1YmxpYyByZWFkb25seSBpc3N1ZXM6IHJlYWRvbmx5IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWVbXTtcblxuXHRwdWJsaWMgY29uc3RydWN0b3IoXG5cdFx0b3BlcmF0aW9uOiBzdHJpbmcsXG5cdFx0ZGlyZWN0aW9uOiBDb250cmFjdERpcmVjdGlvbixcblx0XHRpc3N1ZXM6IHJlYWRvbmx5IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWVbXSxcblx0KSB7XG5cdFx0Y29uc3QgZGV0YWlsID0gaXNzdWVzWzBdID09PSB1bmRlZmluZWQgPyBcIlwiIDogYDogJHtkZXNjcmliZShpc3N1ZXNbMF0pfWA7XG5cdFx0c3VwZXIoXG5cdFx0XHRgJHtvcGVyYXRpb259OiB0aGUgJHtkaXJlY3Rpb259IGRvZXMgbm90IG1hdGNoIHRoZSBkZWNsYXJlZCBjb250cmFjdCR7ZGV0YWlsfWAsXG5cdFx0XHRcImNvbnRyYWN0X3ZhbGlkYXRpb25fZmFpbGVkXCIsXG5cdFx0KTtcblx0XHR0aGlzLm9wZXJhdGlvbiA9IG9wZXJhdGlvbjtcblx0XHR0aGlzLmRpcmVjdGlvbiA9IGRpcmVjdGlvbjtcblx0XHR0aGlzLmlzc3VlcyA9IE9iamVjdC5mcmVlemUoWy4uLmlzc3Vlc10pO1xuXHR9XG5cblx0cHVibGljIHRvSlNPTigpOiBTZXJpYWxpemVkQ29udHJhY3RFcnJvciB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGNvZGU6IHRoaXMuY29kZSxcblx0XHRcdG9wZXJhdGlvbjogdGhpcy5vcGVyYXRpb24sXG5cdFx0XHRkaXJlY3Rpb246IHRoaXMuZGlyZWN0aW9uLFxuXHRcdFx0aXNzdWVzOiB0aGlzLmlzc3Vlcy5tYXAoKGlzc3VlKSA9PiBpc3N1ZS50b0pTT04oKSksXG5cdFx0fTtcblx0fVxufVxuXG5mdW5jdGlvbiBkZXNjcmliZShpc3N1ZTogUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZSk6IHN0cmluZyB7XG5cdGNvbnN0IHdoZXJlID0gaXNzdWUucGF0aC5sZW5ndGggPT09IDAgPyBcInZhbHVlXCIgOiBpc3N1ZS5wYXRoLmpvaW4oXCIuXCIpO1xuXHRyZXR1cm4gYCR7d2hlcmV9ICR7aXNzdWUuY29kZX1gO1xufVxuXG5jb25zdCBQUklNSVRJVkVTOiBSZWFkb25seVNldDxzdHJpbmc+ID0gbmV3IFNldChbXG5cdFwic3RyaW5nXCIsXG5cdFwiYm9vbGVhblwiLFxuXHRcImludGVnZXJcIixcblx0XCJudW1iZXJcIixcblx0XCJudWxsXCIsXG5cdFwiYXJyYXlcIixcblx0XCJvYmplY3RcIixcbl0pO1xuXG5jb25zdCBLTk9XTl9LRVlXT1JEUzogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoW1xuXHRcInR5cGVcIixcblx0XCJwcm9wZXJ0aWVzXCIsXG5cdFwicmVxdWlyZWRcIixcblx0XCJhZGRpdGlvbmFsUHJvcGVydGllc1wiLFxuXHRcIml0ZW1zXCIsXG5cdFwiYW55T2ZcIixcblx0XCJlbnVtXCIsXG5cdFwibWluaW11bVwiLFxuXHRcIm1heGltdW1cIixcblx0XCJwYXR0ZXJuXCIsXG5cdFwidGl0bGVcIixcblx0XCJkZXNjcmlwdGlvblwiLFxuXSk7XG5cbnR5cGUgUGF0aCA9IHJlYWRvbmx5IChzdHJpbmcgfCBudW1iZXIpW107XG5cbi8qKlxuICogUmV0dXJuIGV2ZXJ5IGlzc3VlIGB2YWx1ZWAgaGFzIGFnYWluc3QgYHNjaGVtYWA7IGFuIGVtcHR5IGFycmF5IGlzIGEgbWF0Y2guXG4gKlxuICogVGhyb3dzIHtAbGluayBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcn0gd2hlbiBgc2NoZW1hYCBsZWF2ZXMgdGhlIGRlY2xhcmVkXG4gKiBkaWFsZWN0LCBiZWNhdXNlIHRoYXQgaXMgYSBmYXVsdCBpbiB0aGUgZGVjbGFyYXRpb24sIG5ldmVyIGluIHRoZSB2YWx1ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlQWdhaW5zdFNjaGVtYShcblx0dmFsdWU6IHVua25vd24sXG5cdHNjaGVtYTogRGVjbGFyZWRTY2hlbWEsXG5cdG9wdGlvbnM6IFZhbGlkYXRlT3B0aW9ucyA9IHt9LFxuKTogUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZVtdIHtcblx0Y29uc3QgaXNzdWVzOiBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlW10gPSBbXTtcblx0Y2hlY2soXG5cdFx0dmFsdWUsXG5cdFx0c2NoZW1hLFxuXHRcdG9wdGlvbnMucGF0aCA/PyBbXSxcblx0XHRvcHRpb25zLmFsbG93VW5rbm93biA9PT0gdHJ1ZSxcblx0XHRpc3N1ZXMsXG5cdCk7XG5cdHJldHVybiBpc3N1ZXM7XG59XG5cbmZ1bmN0aW9uIGNoZWNrKFxuXHR2YWx1ZTogdW5rbm93bixcblx0c2NoZW1hOiB1bmtub3duLFxuXHRwYXRoOiBQYXRoLFxuXHRhbGxvd1Vua25vd246IGJvb2xlYW4sXG5cdGlzc3VlczogUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZVtdLFxuKTogdm9pZCB7XG5cdGlmICghaXNQbGFpblJlY29yZChzY2hlbWEpKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0YCR7d2hlcmUocGF0aCl9OiBhIHNjaGVtYSBtdXN0IGJlIGFuIG9iamVjdGAsXG5cdFx0KTtcblx0fVxuXHRjb25zdCB1bmtub3duID0gT2JqZWN0LmtleXMoc2NoZW1hKS5maWx0ZXIoKGtleSkgPT4gIUtOT1dOX0tFWVdPUkRTLmhhcyhrZXkpKTtcblx0aWYgKHVua25vd24ubGVuZ3RoID4gMCkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke3doZXJlKHBhdGgpfTogdW5zdXBwb3J0ZWQgc2NoZW1hIGtleXdvcmQocykgJHt1bmtub3duLnNvcnQoKS5qb2luKFwiLCBcIil9YCxcblx0XHQpO1xuXHR9XG5cdGlmIChcImFueU9mXCIgaW4gc2NoZW1hKSB7XG5cdFx0Y29uc3QgYnJhbmNoZXMgPSBzY2hlbWEuYW55T2Y7XG5cdFx0aWYgKCFBcnJheS5pc0FycmF5KGJyYW5jaGVzKSB8fCBicmFuY2hlcy5sZW5ndGggPT09IDApIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdFx0YCR7d2hlcmUocGF0aCl9OiBhbnlPZiBtdXN0IGJlIGEgbm9uZW1wdHkgbGlzdGAsXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRmb3IgKGNvbnN0IGJyYW5jaCBvZiBicmFuY2hlcykge1xuXHRcdFx0Y29uc3QgYXR0ZW1wdDogUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZVtdID0gW107XG5cdFx0XHRjaGVjayh2YWx1ZSwgYnJhbmNoLCBwYXRoLCBhbGxvd1Vua25vd24sIGF0dGVtcHQpO1xuXHRcdFx0aWYgKGF0dGVtcHQubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHR9XG5cdFx0aXNzdWVzLnB1c2gobmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGhdLCBcImFueV9vZlwiKSk7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGlmIChcImVudW1cIiBpbiBzY2hlbWEpIHtcblx0XHRjb25zdCBjaG9pY2VzID0gc2NoZW1hLmVudW07XG5cdFx0aWYgKCFBcnJheS5pc0FycmF5KGNob2ljZXMpKSB7XG5cdFx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoYCR7d2hlcmUocGF0aCl9OiBlbnVtIG11c3QgYmUgYSBsaXN0YCk7XG5cdFx0fVxuXHRcdGlmICghY2hvaWNlcy5zb21lKChjaG9pY2UpID0+IHNhbWVKc29uKGNob2ljZSwgdmFsdWUpKSkge1xuXHRcdFx0aXNzdWVzLnB1c2gobmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGhdLCBcImVudW1cIikpO1xuXHRcdH1cblx0XHRyZXR1cm47XG5cdH1cblx0Y29uc3QgZGVjbGFyZWQgPSBzY2hlbWEudHlwZTtcblx0aWYgKGRlY2xhcmVkID09PSB1bmRlZmluZWQpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRgJHt3aGVyZShwYXRoKX06IGEgc2NoZW1hIG5lZWRzIGEgdHlwZSwgYW55T2Ygb3IgZW51bWAsXG5cdFx0KTtcblx0fVxuXHRpZiAodHlwZW9mIGRlY2xhcmVkICE9PSBcInN0cmluZ1wiIHx8ICFQUklNSVRJVkVTLmhhcyhkZWNsYXJlZCkpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRgJHt3aGVyZShwYXRoKX06IHVuc3VwcG9ydGVkIHR5cGUgJHtKU09OLnN0cmluZ2lmeShkZWNsYXJlZCl9YCxcblx0XHQpO1xuXHR9XG5cdHN3aXRjaCAoZGVjbGFyZWQpIHtcblx0XHRjYXNlIFwic3RyaW5nXCI6XG5cdFx0XHRjaGVja1N0cmluZyh2YWx1ZSwgc2NoZW1hLCBwYXRoLCBpc3N1ZXMpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdGNhc2UgXCJib29sZWFuXCI6XG5cdFx0XHRpZiAodHlwZW9mIHZhbHVlICE9PSBcImJvb2xlYW5cIikge1xuXHRcdFx0XHRpc3N1ZXMucHVzaChuZXcgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZShbLi4ucGF0aF0sIFwidHlwZVwiKSk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm47XG5cdFx0Y2FzZSBcImludGVnZXJcIjpcblx0XHRcdGlmICh0eXBlb2YgdmFsdWUgIT09IFwibnVtYmVyXCIgfHwgIU51bWJlci5pc0ludGVnZXIodmFsdWUpKSB7XG5cdFx0XHRcdGlzc3Vlcy5wdXNoKG5ldyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKFsuLi5wYXRoXSwgXCJ0eXBlXCIpKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0Y2hlY2tCb3VuZHModmFsdWUsIHNjaGVtYSwgcGF0aCwgaXNzdWVzKTtcblx0XHRcdHJldHVybjtcblx0XHRjYXNlIFwibnVtYmVyXCI6XG5cdFx0XHRpZiAodHlwZW9mIHZhbHVlICE9PSBcIm51bWJlclwiKSB7XG5cdFx0XHRcdGlzc3Vlcy5wdXNoKG5ldyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKFsuLi5wYXRoXSwgXCJ0eXBlXCIpKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCFOdW1iZXIuaXNGaW5pdGUodmFsdWUpKSB7XG5cdFx0XHRcdGlzc3Vlcy5wdXNoKG5ldyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKFsuLi5wYXRoXSwgXCJub3RfZmluaXRlXCIpKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0Y2hlY2tCb3VuZHModmFsdWUsIHNjaGVtYSwgcGF0aCwgaXNzdWVzKTtcblx0XHRcdHJldHVybjtcblx0XHRjYXNlIFwibnVsbFwiOlxuXHRcdFx0aWYgKHZhbHVlICE9PSBudWxsKSB7XG5cdFx0XHRcdGlzc3Vlcy5wdXNoKG5ldyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKFsuLi5wYXRoXSwgXCJ0eXBlXCIpKTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHRjYXNlIFwiYXJyYXlcIjpcblx0XHRcdGNoZWNrQXJyYXkodmFsdWUsIHNjaGVtYSwgcGF0aCwgYWxsb3dVbmtub3duLCBpc3N1ZXMpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdGRlZmF1bHQ6XG5cdFx0XHRjaGVja09iamVjdCh2YWx1ZSwgc2NoZW1hLCBwYXRoLCBhbGxvd1Vua25vd24sIGlzc3Vlcyk7XG5cdH1cbn1cblxuZnVuY3Rpb24gY2hlY2tTdHJpbmcoXG5cdHZhbHVlOiB1bmtub3duLFxuXHRzY2hlbWE6IERlY2xhcmVkU2NoZW1hLFxuXHRwYXRoOiBQYXRoLFxuXHRpc3N1ZXM6IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWVbXSxcbik6IHZvaWQge1xuXHRpZiAodHlwZW9mIHZhbHVlICE9PSBcInN0cmluZ1wiKSB7XG5cdFx0aXNzdWVzLnB1c2gobmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGhdLCBcInR5cGVcIikpO1xuXHRcdHJldHVybjtcblx0fVxuXHRjb25zdCBwYXR0ZXJuID0gc2NoZW1hLnBhdHRlcm47XG5cdGlmIChwYXR0ZXJuID09PSB1bmRlZmluZWQgfHwgcGF0dGVybiA9PT0gbnVsbCkge1xuXHRcdHJldHVybjtcblx0fVxuXHRpZiAodHlwZW9mIHBhdHRlcm4gIT09IFwic3RyaW5nXCIpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRgJHt3aGVyZShwYXRoKX06IHBhdHRlcm4gbXVzdCBiZSBhIHN0cmluZ2AsXG5cdFx0KTtcblx0fVxuXHRsZXQgZXhwcmVzc2lvbjogUmVnRXhwO1xuXHR0cnkge1xuXHRcdC8vIFB5dGhvbidzIHJlLmZ1bGxtYXRjaDogdGhlIHdob2xlIHN0cmluZywgd2l0aCB0aGUgdW5pY29kZSBmbGFnIHRoZVxuXHRcdC8vIGRlY2xhcmF0aW9uIHNpZGUgYWxyZWFkeSBhc3N1bWVzLlxuXHRcdGV4cHJlc3Npb24gPSBuZXcgUmVnRXhwKGBeKD86JHtwYXR0ZXJufSkkYCwgXCJ1XCIpO1xuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke3doZXJlKHBhdGgpfTogcGF0dGVybiAke0pTT04uc3RyaW5naWZ5KHBhdHRlcm4pfSBpcyB1bnVzYWJsZTogJHtTdHJpbmcoZXJyb3IpfWAsXG5cdFx0KTtcblx0fVxuXHRpZiAoIWV4cHJlc3Npb24udGVzdCh2YWx1ZSkpIHtcblx0XHRpc3N1ZXMucHVzaChuZXcgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZShbLi4ucGF0aF0sIFwicGF0dGVyblwiKSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gY2hlY2tCb3VuZHMoXG5cdHZhbHVlOiBudW1iZXIsXG5cdHNjaGVtYTogRGVjbGFyZWRTY2hlbWEsXG5cdHBhdGg6IFBhdGgsXG5cdGlzc3VlczogUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZVtdLFxuKTogdm9pZCB7XG5cdGNvbnN0IG1pbmltdW0gPSBzY2hlbWEubWluaW11bTtcblx0aWYgKHR5cGVvZiBtaW5pbXVtID09PSBcIm51bWJlclwiICYmIHZhbHVlIDwgbWluaW11bSkge1xuXHRcdGlzc3Vlcy5wdXNoKG5ldyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKFsuLi5wYXRoXSwgXCJtaW5pbXVtXCIpKTtcblx0fVxuXHRjb25zdCBtYXhpbXVtID0gc2NoZW1hLm1heGltdW07XG5cdGlmICh0eXBlb2YgbWF4aW11bSA9PT0gXCJudW1iZXJcIiAmJiB2YWx1ZSA+IG1heGltdW0pIHtcblx0XHRpc3N1ZXMucHVzaChuZXcgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZShbLi4ucGF0aF0sIFwibWF4aW11bVwiKSk7XG5cdH1cbn1cblxuZnVuY3Rpb24gY2hlY2tBcnJheShcblx0dmFsdWU6IHVua25vd24sXG5cdHNjaGVtYTogRGVjbGFyZWRTY2hlbWEsXG5cdHBhdGg6IFBhdGgsXG5cdGFsbG93VW5rbm93bjogYm9vbGVhbixcblx0aXNzdWVzOiBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlW10sXG4pOiB2b2lkIHtcblx0aWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuXHRcdGlzc3Vlcy5wdXNoKG5ldyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKFsuLi5wYXRoXSwgXCJ0eXBlXCIpKTtcblx0XHRyZXR1cm47XG5cdH1cblx0Y29uc3QgaXRlbXMgPSBzY2hlbWEuaXRlbXM7XG5cdGlmIChpdGVtcyA9PT0gdW5kZWZpbmVkIHx8IGl0ZW1zID09PSBudWxsKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdHZhbHVlLmZvckVhY2goKGl0ZW0sIGluZGV4KSA9PiB7XG5cdFx0Y2hlY2soaXRlbSwgaXRlbXMsIFsuLi5wYXRoLCBpbmRleF0sIGFsbG93VW5rbm93biwgaXNzdWVzKTtcblx0fSk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrT2JqZWN0KFxuXHR2YWx1ZTogdW5rbm93bixcblx0c2NoZW1hOiBEZWNsYXJlZFNjaGVtYSxcblx0cGF0aDogUGF0aCxcblx0YWxsb3dVbmtub3duOiBib29sZWFuLFxuXHRpc3N1ZXM6IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWVbXSxcbik6IHZvaWQge1xuXHRpZiAoIWlzUGxhaW5SZWNvcmQodmFsdWUpKSB7XG5cdFx0aXNzdWVzLnB1c2gobmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGhdLCBcInR5cGVcIikpO1xuXHRcdHJldHVybjtcblx0fVxuXHRjb25zdCBwcm9wZXJ0aWVzID0gc2NoZW1hLnByb3BlcnRpZXMgPz8ge307XG5cdGlmICghaXNQbGFpblJlY29yZChwcm9wZXJ0aWVzKSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke3doZXJlKHBhdGgpfTogcHJvcGVydGllcyBtdXN0IGJlIGFuIG9iamVjdGAsXG5cdFx0KTtcblx0fVxuXHRjb25zdCByZXF1aXJlZCA9IHNjaGVtYS5yZXF1aXJlZCA/PyBbXTtcblx0aWYgKCFBcnJheS5pc0FycmF5KHJlcXVpcmVkKSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke3doZXJlKHBhdGgpfTogcmVxdWlyZWQgbXVzdCBiZSBhIGxpc3RgLFxuXHRcdCk7XG5cdH1cblx0Zm9yIChjb25zdCBrZXkgb2YgcmVxdWlyZWQpIHtcblx0XHRpZiAodHlwZW9mIGtleSA9PT0gXCJzdHJpbmdcIiAmJiAhKGtleSBpbiB2YWx1ZSkpIHtcblx0XHRcdGlzc3Vlcy5wdXNoKG5ldyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKFsuLi5wYXRoLCBrZXldLCBcInJlcXVpcmVkXCIpKTtcblx0XHR9XG5cdH1cblx0Y29uc3Qgc3RyaWN0ID0gc2NoZW1hLmFkZGl0aW9uYWxQcm9wZXJ0aWVzID09PSBmYWxzZSAmJiAhYWxsb3dVbmtub3duO1xuXHRmb3IgKGNvbnN0IFtrZXksIGl0ZW1dIG9mIE9iamVjdC5lbnRyaWVzKHZhbHVlKSkge1xuXHRcdGlmIChPYmplY3QuaGFzT3duKHByb3BlcnRpZXMsIGtleSkpIHtcblx0XHRcdGNoZWNrKGl0ZW0sIHByb3BlcnRpZXNba2V5XSwgWy4uLnBhdGgsIGtleV0sIGFsbG93VW5rbm93biwgaXNzdWVzKTtcblx0XHR9IGVsc2UgaWYgKHN0cmljdCkge1xuXHRcdFx0aXNzdWVzLnB1c2goXG5cdFx0XHRcdG5ldyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKFsuLi5wYXRoLCBrZXldLCBcInVua25vd25fcHJvcGVydHlcIiksXG5cdFx0XHQpO1xuXHRcdH1cblx0fVxufVxuXG4vKiogSlNPTiBlcXVhbGl0eTogYHRydWVgIGlzIG5vdCBgMWAsIGFuZCBgMWAgaXMgYDEuMGAuICovXG5mdW5jdGlvbiBzYW1lSnNvbihhOiB1bmtub3duLCBiOiB1bmtub3duKTogYm9vbGVhbiB7XG5cdGlmIChhID09PSBiKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblx0aWYgKHR5cGVvZiBhICE9PSB0eXBlb2YgYiB8fCBhID09PSBudWxsIHx8IGIgPT09IG51bGwpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0aWYgKEFycmF5LmlzQXJyYXkoYSkpIHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0QXJyYXkuaXNBcnJheShiKSAmJlxuXHRcdFx0YS5sZW5ndGggPT09IGIubGVuZ3RoICYmXG5cdFx0XHRhLmV2ZXJ5KChpdGVtLCBpbmRleCkgPT4gc2FtZUpzb24oaXRlbSwgYltpbmRleF0pKVxuXHRcdCk7XG5cdH1cblx0aWYgKGlzUGxhaW5SZWNvcmQoYSkgJiYgaXNQbGFpblJlY29yZChiKSkge1xuXHRcdGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhhKTtcblx0XHRyZXR1cm4gKFxuXHRcdFx0a2V5cy5sZW5ndGggPT09IE9iamVjdC5rZXlzKGIpLmxlbmd0aCAmJlxuXHRcdFx0a2V5cy5ldmVyeSgoa2V5KSA9PiBPYmplY3QuaGFzT3duKGIsIGtleSkgJiYgc2FtZUpzb24oYVtrZXldLCBiW2tleV0pKVxuXHRcdCk7XG5cdH1cblx0cmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiB3aGVyZShwYXRoOiBQYXRoKTogc3RyaW5nIHtcblx0cmV0dXJuIHBhdGgubGVuZ3RoID09PSAwID8gXCJ2YWx1ZVwiIDogcGF0aC5qb2luKFwiLlwiKTtcbn1cbiIsCiAgICAiLyoqXG4gKiBUaGUgZGVmYXVsdCB0cmFuc3BvcnQ6IFF0J3MgV2ViQ2hhbm5lbCwgYXMgYSBRR0lTIHdlYiB2aWV3IGluamVjdHMgaXQuXG4gKlxuICogUUdJUyByZWdpc3RlcnMgb25lIG9iamVjdCBvbiB0aGUgY2hhbm5lbCAodGhlIGV4YW1wbGUgbmFtZXMgaXQgXCJicmlkZ2VcIjtcbiAqIHNlZSBgY3JlYXRlX2NoYW5uZWxfb2JqZWN0YCBpbiB0aGUgUHl0aG9uIHJ1bnRpbWUpLiBJdHMgYHJlY2VpdmVgIHNsb3QgdGFrZXNcbiAqIGEgSlNPTiBlbnZlbG9wZSBhbmQgaXRzIGBtZXNzYWdlYCBzaWduYWwgY2FycmllcyBldmVyeSByZXBseSBhbmQgc3RyZWFtXG4gKiBmcmFtZSBiYWNrLiBUaGUgY2hhbm5lbCBiZWNvbWVzIHJlYWR5IG9uIGEgbGF0ZXIgdHVybiwgc28gdGhpcyB0cmFuc3BvcnRcbiAqIGlzIGxhenk6IGEgYFFnaXNTZGtgIGJ1aWx0IGluIHRoZSBmaXJzdCBzdGF0ZW1lbnQgb2YgYSBwYWdlIGNhbiBzZW5kIGF0XG4gKiBvbmNlLCBhbmQgd2hhdCBpdCBzZW50IGlzIGRlbGl2ZXJlZCB3aGVuIHRoZSBjaGFubmVsIHJlcG9ydHMgcmVhZHkuXG4gKlxuICogVGhpcyBpcyB0aGUgb25lIG1vZHVsZSBvZiB0aGUgcm9vdCBlbnRyeSBwb2ludCB0aGF0IHJlYWRzIGEgYnJvd3NlciBnbG9iYWwsXG4gKiBhbmQgaXQgb25seSBkb2VzIHNvIHdoZW4gY2FsbGVkOiBpbXBvcnRpbmcgaXQgdG91Y2hlcyBub3RoaW5nLCBhbmQgYSBwYWdlXG4gKiB0aGF0IGlzIG5vdCBpbnNpZGUgUUdJUyBnZXRzIGEgc3luY2hyb25vdXMsIG5hbWVkIHJlZnVzYWwgaW5zdGVhZCBvZiBhIGhhbmcuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBXaXJlVHJhbnNwb3J0IH0gZnJvbSBcIi4vYnJpZGdlXCI7XG5pbXBvcnQgeyBRZ2lzU2RrRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcblxuaW50ZXJmYWNlIENoYW5uZWxPYmplY3Qge1xuXHRyZWNlaXZlKHRleHQ6IHN0cmluZyk6IHZvaWQ7XG5cdHJlYWRvbmx5IG1lc3NhZ2U6IHtcblx0XHRjb25uZWN0KGxpc3RlbmVyOiAodGV4dDogc3RyaW5nKSA9PiB2b2lkKTogdm9pZDtcblx0XHRkaXNjb25uZWN0KGxpc3RlbmVyOiAodGV4dDogc3RyaW5nKSA9PiB2b2lkKTogdm9pZDtcblx0fTtcbn1cblxuaW50ZXJmYWNlIENoYW5uZWwge1xuXHRyZWFkb25seSBvYmplY3RzOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBDaGFubmVsT2JqZWN0IHwgdW5kZWZpbmVkPj47XG59XG5cbmludGVyZmFjZSBRdFNjb3BlIHtcblx0cmVhZG9ubHkgcXQ/OiB7IHJlYWRvbmx5IHdlYkNoYW5uZWxUcmFuc3BvcnQ6IHVua25vd24gfTtcblx0cmVhZG9ubHkgUVdlYkNoYW5uZWw/OiBuZXcgKFxuXHRcdHRyYW5zcG9ydDogdW5rbm93bixcblx0XHRyZWFkeTogKGNoYW5uZWw6IENoYW5uZWwpID0+IHZvaWQsXG5cdCkgPT4gdW5rbm93bjtcbn1cblxuLyoqIFRoZSB3ZWIgdmlldyBkaWQgbm90IHByb3ZpZGUgYSB1c2FibGUgY2hhbm5lbC4gKi9cbmV4cG9ydCBjbGFzcyBRZ2lzU2RrV2ViQ2hhbm5lbEVycm9yIGV4dGVuZHMgUWdpc1Nka0Vycm9yIHtcblx0cHVibGljIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuXHRcdHN1cGVyKG1lc3NhZ2UsIFwibm9fd2ViX2NoYW5uZWxcIik7XG5cdH1cbn1cblxuLyoqIFRoZSB0cmFuc3BvcnQge0BsaW5rIGNyZWF0ZVdlYkNoYW5uZWxUcmFuc3BvcnR9IHJldHVybnMuICovXG5leHBvcnQgaW50ZXJmYWNlIFdlYkNoYW5uZWxUcmFuc3BvcnQgZXh0ZW5kcyBXaXJlVHJhbnNwb3J0IHtcblx0LyoqIFJlc29sdmVzIG9uY2UgdGhlIGNoYW5uZWwgb2JqZWN0IGFuc3dlcmVkOyByZWplY3RzIHdoZW4gaXQgbmV2ZXIgd2lsbC4gKi9cblx0cmVhZG9ubHkgcmVhZHk6IFByb21pc2U8dm9pZD47XG5cdC8qKiBTdG9wIGZvcndhcmRpbmcgbWVzc2FnZXM7IHNlbmRzIGFmdGVyIHRoaXMgdGhyb3cuICovXG5cdGNsb3NlKCk6IHZvaWQ7XG59XG5cbmZ1bmN0aW9uIHNjb3BlKCk6IFF0U2NvcGUge1xuXHRyZXR1cm4gZ2xvYmFsVGhpcyBhcyB1bmtub3duIGFzIFF0U2NvcGU7XG59XG5cbi8qKiBUcnVlIGluc2lkZSBhIFFHSVMgd2ViIHZpZXcsIHdoZXJlIFF0IGluamVjdGVkIGl0cyB0cmFuc3BvcnQgYW5kIHNjcmlwdC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnNpZGVRZ2lzKCk6IGJvb2xlYW4ge1xuXHRjb25zdCBwYWdlID0gc2NvcGUoKTtcblx0cmV0dXJuIHBhZ2UucXQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgcGFnZS5RV2ViQ2hhbm5lbCA9PT0gXCJmdW5jdGlvblwiO1xufVxuXG4vKipcbiAqIENvbm5lY3QgdG8gdGhlIGNoYW5uZWwgb2JqZWN0IGBvYmplY3ROYW1lYCBhbmQgcmV0dXJuIGEgdHJhbnNwb3J0IG9uIGl0LlxuICpcbiAqIFRocm93cyB7QGxpbmsgUWdpc1Nka1dlYkNoYW5uZWxFcnJvcn0gc3luY2hyb25vdXNseSBvdXRzaWRlIGEgUUdJUyB3ZWIgdmlldyxcbiAqIHNvIGEgcGFnZSBsZWFybnMgaW4gaXRzIGZpcnN0IHN0YXRlbWVudCB0aGF0IGl0IGhhcyBubyBob3N0IHRvIHRhbGsgdG8uXG4gKiBJbnNpZGUgb25lLCBtZXNzYWdlcyBzZW50IGJlZm9yZSB0aGUgY2hhbm5lbCBpcyByZWFkeSBhcmUgcXVldWVkIGFuZFxuICogZGVsaXZlcmVkIGluIG9yZGVyIG9uY2UgaXQgaXM7IGByZWFkeWAgcmVqZWN0cyAoYW5kIHF1ZXVlZCBzZW5kcyBhcmVcbiAqIGRyb3BwZWQpIHdoZW4gdGhlIGhvc3QgcmVnaXN0ZXJlZCBubyBvYmplY3QgdW5kZXIgdGhhdCBuYW1lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlV2ViQ2hhbm5lbFRyYW5zcG9ydChcblx0b2JqZWN0TmFtZSA9IFwiYnJpZGdlXCIsXG4pOiBXZWJDaGFubmVsVHJhbnNwb3J0IHtcblx0Y29uc3QgcGFnZSA9IHNjb3BlKCk7XG5cdGNvbnN0IHF0ID0gcGFnZS5xdDtcblx0Y29uc3QgUVdlYkNoYW5uZWwgPSBwYWdlLlFXZWJDaGFubmVsO1xuXHRpZiAocXQgPT09IHVuZGVmaW5lZCB8fCB0eXBlb2YgUVdlYkNoYW5uZWwgIT09IFwiZnVuY3Rpb25cIikge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrV2ViQ2hhbm5lbEVycm9yKFxuXHRcdFx0XCJub3QgaW5zaWRlIGEgUUdJUyB3ZWIgdmlldzogd2luZG93LnF0IGlzIG1pc3NpbmdcIixcblx0XHQpO1xuXHR9XG5cdGNvbnN0IGxpc3RlbmVycyA9IG5ldyBTZXQ8KG1lc3NhZ2U6IHVua25vd24pID0+IHZvaWQ+KCk7XG5cdGNvbnN0IHF1ZXVlOiBzdHJpbmdbXSA9IFtdO1xuXHRsZXQgb2JqZWN0OiBDaGFubmVsT2JqZWN0IHwgbnVsbCA9IG51bGw7XG5cdGxldCBmYWlsdXJlOiBRZ2lzU2RrV2ViQ2hhbm5lbEVycm9yIHwgbnVsbCA9IG51bGw7XG5cdGxldCBjbG9zZWQgPSBmYWxzZTtcblx0Y29uc3QgZm9yd2FyZCA9ICh0ZXh0OiBzdHJpbmcpOiB2b2lkID0+IHtcblx0XHRpZiAoY2xvc2VkKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGxldCBwYXJzZWQ6IHVua25vd247XG5cdFx0dHJ5IHtcblx0XHRcdHBhcnNlZCA9IEpTT04ucGFyc2UodGV4dCk7XG5cdFx0fSBjYXRjaCB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGZvciAoY29uc3QgbGlzdGVuZXIgb2YgWy4uLmxpc3RlbmVyc10pIHtcblx0XHRcdGxpc3RlbmVyKHBhcnNlZCk7XG5cdFx0fVxuXHR9O1xuXHRjb25zdCByZWFkeSA9IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblx0XHRuZXcgUVdlYkNoYW5uZWwocXQud2ViQ2hhbm5lbFRyYW5zcG9ydCwgKGNoYW5uZWwpID0+IHtcblx0XHRcdGNvbnN0IGZvdW5kID0gY2hhbm5lbC5vYmplY3RzW29iamVjdE5hbWVdO1xuXHRcdFx0aWYgKGZvdW5kID09PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0ZmFpbHVyZSA9IG5ldyBRZ2lzU2RrV2ViQ2hhbm5lbEVycm9yKFxuXHRcdFx0XHRcdGB0aGUgaG9zdCByZWdpc3RlcmVkIG5vICR7SlNPTi5zdHJpbmdpZnkob2JqZWN0TmFtZSl9IGNoYW5uZWwgb2JqZWN0YCxcblx0XHRcdFx0KTtcblx0XHRcdFx0cXVldWUubGVuZ3RoID0gMDtcblx0XHRcdFx0cmVqZWN0KGZhaWx1cmUpO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHRpZiAoY2xvc2VkKSB7XG5cdFx0XHRcdHJlc29sdmUoKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0b2JqZWN0ID0gZm91bmQ7XG5cdFx0XHRmb3VuZC5tZXNzYWdlLmNvbm5lY3QoZm9yd2FyZCk7XG5cdFx0XHRmb3IgKGNvbnN0IHRleHQgb2YgcXVldWUuc3BsaWNlKDApKSB7XG5cdFx0XHRcdGZvdW5kLnJlY2VpdmUodGV4dCk7XG5cdFx0XHR9XG5cdFx0XHRyZXNvbHZlKCk7XG5cdFx0fSk7XG5cdH0pO1xuXHRyZXR1cm4ge1xuXHRcdHJlYWR5LFxuXHRcdHNlbmQobWVzc2FnZTogdW5rbm93bik6IHZvaWQge1xuXHRcdFx0aWYgKGNsb3NlZCkge1xuXHRcdFx0XHR0aHJvdyBuZXcgUWdpc1Nka1dlYkNoYW5uZWxFcnJvcihcInRoZSB3ZWIgY2hhbm5lbCB0cmFuc3BvcnQgaXMgY2xvc2VkXCIpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKGZhaWx1cmUgIT09IG51bGwpIHtcblx0XHRcdFx0dGhyb3cgZmFpbHVyZTtcblx0XHRcdH1cblx0XHRcdGNvbnN0IHRleHQgPSBKU09OLnN0cmluZ2lmeShtZXNzYWdlKTtcblx0XHRcdGlmIChvYmplY3QgPT09IG51bGwpIHtcblx0XHRcdFx0cXVldWUucHVzaCh0ZXh0KTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0b2JqZWN0LnJlY2VpdmUodGV4dCk7XG5cdFx0fSxcblx0XHRzdWJzY3JpYmUobGlzdGVuZXI6IChtZXNzYWdlOiB1bmtub3duKSA9PiB2b2lkKTogKCkgPT4gdm9pZCB7XG5cdFx0XHRsaXN0ZW5lcnMuYWRkKGxpc3RlbmVyKTtcblx0XHRcdHJldHVybiAoKSA9PiB7XG5cdFx0XHRcdGxpc3RlbmVycy5kZWxldGUobGlzdGVuZXIpO1xuXHRcdFx0fTtcblx0XHR9LFxuXHRcdGNsb3NlKCk6IHZvaWQge1xuXHRcdFx0aWYgKGNsb3NlZCkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHRjbG9zZWQgPSB0cnVlO1xuXHRcdFx0cXVldWUubGVuZ3RoID0gMDtcblx0XHRcdGxpc3RlbmVycy5jbGVhcigpO1xuXHRcdFx0b2JqZWN0Py5tZXNzYWdlLmRpc2Nvbm5lY3QoZm9yd2FyZCk7XG5cdFx0fSxcblx0fTtcbn1cbiIsCiAgICAiLyoqXG4gKiBgUWdpc1Nka2A6IHRoZSBwYWdlLXNpZGUgb2JqZWN0IGEgcGx1Z2luJ3Mgd2ViIHZpZXcgdGFsa3MgdG8gUUdJUyB0aHJvdWdoLlxuICpcbiAqIFRocmVlIHN0YXRlbWVudHMgY29ubmVjdCBhIHBhZ2UgKGRlY2lzaW9uLTQ0KTpcbiAqXG4gKiBgYGB0c1xuICogaW1wb3J0IHNjaGVtYSBmcm9tIFwiLi9icmlkZ2Uuc2NoZW1hXCI7XG4gKiBjb25zdCBxZ2lzID0gUWdpc1Nkay5mcm9tQnJpZGdlU2NoZW1hKHNjaGVtYSk7XG4gKiBhd2FpdCBxZ2lzLnNpdGVzLnN1bW1hcnkoeyBsYXllcl9pZCB9KTtcbiAqIGBgYFxuICpcbiAqIFRoZSBzY2hlbWEgaXMgdGhlIGdlbmVyYXRlZCBgYnJpZGdlLnNjaGVtYS50c2A6IHRoZSBwbHVnaW4gZGVzY3JpcHRpb24gcGx1c1xuICogaXRzIGBPcGVyYXRpb25zYCBhbmQgYFN0cmVhbXNgIHR5cGVzLiBGcm9tIHRoZSBkZXNjcmlwdGlvbiB0aGUgU0RLIGJ1aWxkc1xuICogb25lIG1ldGhvZCBwZXIgZGVjbGFyZWQgYWN0aW9uIGFuZCBzdHJlYW0sIG5lc3RlZCB1bmRlciB0aGUgc2VnbWVudHMgb2YgaXRzXG4gKiBpZCAoYHNpdGVzLnN1bW1hcnlgIGlzIGBxZ2lzLnNpdGVzLnN1bW1hcnlgLCBgYnVmZmVyYCBpcyBgcWdpcy5idWZmZXJgKSxcbiAqIGFuZCBjaGVja3MgZXZlcnkgYXJndW1lbnQsIHJlcGx5IGFuZCBldmVudCBhZ2FpbnN0IHRoZSBkZWNsYXJlZCBzY2hlbWFzXG4gKiB3aXRoIHRoZSBzYW1lIHJ1bGVzIHRoZSBob3N0IGFwcGxpZXMgKGB2YWxpZGF0ZS50c2ApLiBGcm9tIHRoZSB0eXBlcyBpdCBnaXZlcyB0aG9zZVxuICogbWV0aG9kcyB0aGVpciBzaWduYXR1cmVzLCBzbyBhIHdyb25nIGFyZ3VtZW50IHNoYXBlIG9yIGFuIHVua25vd24gb3BlcmF0aW9uXG4gKiBpcyBhIGNvbXBpbGUgZXJyb3IgYW5kIGEgdmFsdWUgb3V0c2lkZSB0aGUgc2NoZW1hIGF0IHJ1biB0aW1lIGlzIGFcbiAqIHtAbGluayBRZ2lzU2RrQ29udHJhY3RFcnJvcn0uXG4gKlxuICogYGhvc3RgIGlzIHRoZSBjdXJhdGVkIGhvc3Qgc3VyZmFjZSBvZiBkZWNpc2lvbi0yNywgYnVpbHQgb24gdGhlIHNhbWUgY2xpZW50LFxuICogcGx1cyBgZ3JhbnRlZGA6IHRoZSBob3N0IG9wZXJhdGlvbiBpZHMgdGhlIGhhbmRzaGFrZSBhZHZlcnRpc2VkIGZvciB0aGlzXG4gKiB2aWV3LiBBIGNhbGwgb3V0c2lkZSB0aGUgZ3JhbnRzIGlzIG5vdCByZWZ1c2VkIGhlcmUgLSB0aGUgaG9zdCByZWZ1c2VzIGl0LFxuICogYW5kIHRoZSBwYWdlIHNlZXMgdGhlIGhvc3QncyBgbm90X2F1dGhvcml6ZWRgIC0gYnV0IGEgcGFnZSBjYW4gcmVhZCBgZ3JhbnRlZGBcbiAqIGFmdGVyIGByZWFkeWAgdG8gaGlkZSB3aGF0IGl0IG1heSBub3QgdXNlLlxuICovXG5cbmltcG9ydCB7XG5cdEJyaWRnZUNsaWVudCxcblx0dHlwZSBCcmlkZ2VTdHJlYW1UZXJtaW5hbCxcblx0dHlwZSBCcmlkZ2VTdWJzY3JpcHRpb24sXG5cdHR5cGUgSW52b2tlT3B0aW9ucyxcblx0UWdpc1Nka0JyaWRnZVByb3RvY29sRXJyb3IsXG5cdHR5cGUgV2lyZVRyYW5zcG9ydCxcbn0gZnJvbSBcIi4vYnJpZGdlXCI7XG5pbXBvcnQge1xuXHR0eXBlIEFjdGlvbkRlc2NyaXB0aW9uLFxuXHRRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcixcblx0dHlwZSBTdHJlYW1EZXNjcmlwdGlvbixcbn0gZnJvbSBcIi4vZGVjbGFyYXRpb25zXCI7XG5pbXBvcnQge1xuXHRjcmVhdGVIb3N0LFxuXHRIT1NUX09QRVJBVElPTlMsXG5cdHR5cGUgSG9zdE9wZXJhdGlvbklkLFxuXHR0eXBlIEhvc3RPcGVyYXRpb25zLFxufSBmcm9tIFwiLi9nZW5lcmF0ZWQvaG9zdFwiO1xuaW1wb3J0IHsgaXNQbGFpblJlY29yZCB9IGZyb20gXCIuL2ludGVybmFsXCI7XG5pbXBvcnQgdHlwZSB7XG5cdEJyaWRnZVNjaGVtYSxcblx0T3BlcmF0aW9uTWFwLFxuXHRPcGVyYXRpb25TaGFwZSxcblx0U3RyZWFtTWFwLFxuXHRTdHJlYW1TaGFwZSxcbn0gZnJvbSBcIi4vc2NoZW1hXCI7XG5pbXBvcnQgeyBRZ2lzU2RrQ29udHJhY3RFcnJvciwgdmFsaWRhdGVBZ2FpbnN0U2NoZW1hIH0gZnJvbSBcIi4vdmFsaWRhdGVcIjtcbmltcG9ydCB7IGNyZWF0ZVdlYkNoYW5uZWxUcmFuc3BvcnQgfSBmcm9tIFwiLi93ZWJjaGFubmVsXCI7XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgUWdpc1Nkay5mcm9tQnJpZGdlU2NoZW1hfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUWdpc1Nka09wdGlvbnMge1xuXHQvKiogQSB0cmFuc3BvcnQgdG8gc3BlYWsgdGhyb3VnaDsgZGVmYXVsdHMgdG8gdGhlIHBhZ2UncyBRV2ViQ2hhbm5lbC4gKi9cblx0cmVhZG9ubHkgdHJhbnNwb3J0PzogV2lyZVRyYW5zcG9ydDtcblx0LyoqIEEgY2xpZW50IHRoZSBjYWxsZXIgb3duczsgYGNsb3NlKClgIGxlYXZlcyBpdCBvcGVuLiBFeGNsdWRlcyBgdHJhbnNwb3J0YC4gKi9cblx0cmVhZG9ubHkgY2xpZW50PzogQnJpZGdlQ2xpZW50O1xuXHQvKiogUGVyLWNhbGwgdGltZW91dCBmb3IgYW4gb3duZWQgY2xpZW50LiAqL1xuXHRyZWFkb25seSB0aW1lb3V0TXM/OiBudW1iZXI7XG5cdC8qKiBUaGUgY2hhbm5lbCBvYmplY3QncyBuYW1lIHdoZW4gdGhlIGRlZmF1bHQgdHJhbnNwb3J0IGlzIHVzZWQuICovXG5cdHJlYWRvbmx5IGNoYW5uZWxPYmplY3Q/OiBzdHJpbmc7XG59XG5cbi8qKiBIYW5kbGVycyBmb3IgYSB0eXBlZCBzdHJlYW06IGV2ZW50cyBhcyBkZWNsYXJlZCwgdGhlbiBleGFjdGx5IG9uZSBlbmQuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0cmVhbUhhbmRsZXJzPEU+IHtcblx0cmVhZG9ubHkgb25FdmVudD86IChldmVudDogRSkgPT4gdm9pZDtcblx0cmVhZG9ubHkgb25UZXJtaW5hbD86ICh0ZXJtaW5hbDogQnJpZGdlU3RyZWFtVGVybWluYWwpID0+IHZvaWQ7XG59XG5cbi8qKiBBIGxpdmUgc3RyZWFtLCBhcyB0aGUgY2FsbGVyIGhvbGRzIGl0LiAqL1xuZXhwb3J0IHR5cGUgU3RyZWFtSGFuZGxlID0gQnJpZGdlU3Vic2NyaXB0aW9uO1xuXG4vKiogVGhlIG1ldGhvZCBvbmUgZGVjbGFyZWQgYWN0aW9uIGJlY29tZXM7IGFuIGVtcHR5IHJlcXVlc3QgbWF5IGJlIG9taXR0ZWQuICovXG5leHBvcnQgdHlwZSBPcGVyYXRpb25NZXRob2Q8T3AgZXh0ZW5kcyBPcGVyYXRpb25TaGFwZT4gPVxuXHQvLyBiaW9tZS1pZ25vcmUgbGludC9jb21wbGV4aXR5L25vQmFubmVkVHlwZXM6IGB7fWAgaXMgdGhlIHRlc3QgZm9yIFwibm90aGluZyByZXF1aXJlZFwiXG5cdHt9IGV4dGVuZHMgT3BbXCJyZXF1ZXN0XCJdXG5cdFx0PyAoXG5cdFx0XHRcdHJlcXVlc3Q/OiBPcFtcInJlcXVlc3RcIl0sXG5cdFx0XHRcdG9wdGlvbnM/OiBJbnZva2VPcHRpb25zLFxuXHRcdFx0KSA9PiBQcm9taXNlPE9wW1wicmVzdWx0XCJdPlxuXHRcdDogKFxuXHRcdFx0XHRyZXF1ZXN0OiBPcFtcInJlcXVlc3RcIl0sXG5cdFx0XHRcdG9wdGlvbnM/OiBJbnZva2VPcHRpb25zLFxuXHRcdFx0KSA9PiBQcm9taXNlPE9wW1wicmVzdWx0XCJdPjtcblxuLyoqIFRoZSBtZXRob2Qgb25lIGRlY2xhcmVkIHN0cmVhbSBiZWNvbWVzLiAqL1xuZXhwb3J0IHR5cGUgU3RyZWFtTWV0aG9kPFN0IGV4dGVuZHMgU3RyZWFtU2hhcGU+ID0gKFxuXHRyZXF1ZXN0OiBTdFtcInJlcXVlc3RcIl0sXG5cdGhhbmRsZXJzOiBTdHJlYW1IYW5kbGVyczxTdFtcImV2ZW50XCJdPixcblx0b3B0aW9ucz86IEludm9rZU9wdGlvbnMsXG4pID0+IFByb21pc2U8U3RyZWFtSGFuZGxlPjtcblxuLyoqIFdoYXQgdGhlIGhhbmRzaGFrZSB0b2xkIHRoaXMgcGFnZSBhYm91dCB0aGUgaG9zdCAoZGVjaXNpb24tMjcpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBRZ2lzU2RrSG9zdCBleHRlbmRzIEhvc3RPcGVyYXRpb25zIHtcblx0LyoqXG5cdCAqIFRoZSBob3N0IG9wZXJhdGlvbiBpZHMgdGhlIGhhbmRzaGFrZSBhZHZlcnRpc2VkIGZvciB0aGlzIHZpZXc7IGVtcHR5XG5cdCAqIHVudGlsIHtAbGluayBRZ2lzU2RrQ29yZS5yZWFkeX0gaGFzIHJlc29sdmVkLlxuXHQgKi9cblx0cmVhZG9ubHkgZ3JhbnRlZDogcmVhZG9ubHkgSG9zdE9wZXJhdGlvbklkW107XG59XG5cbi8qKiBUaGUgbWVtYmVycyBldmVyeSBgUWdpc1Nka2AgaGFzLCB3aGF0ZXZlciBpdHMgc2NoZW1hIGRlY2xhcmVzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBRZ2lzU2RrQ29yZTxPID0gT3BlcmF0aW9uTWFwLCBTID0gU3RyZWFtTWFwPiB7XG5cdC8qKiBUaGUgc2NoZW1hIHRoaXMgaW5zdGFuY2Ugd2FzIGJ1aWx0IGZyb20uICovXG5cdHJlYWRvbmx5IHNjaGVtYTogQnJpZGdlU2NoZW1hPE8sIFM+O1xuXHQvKiogVGhlIGNsaWVudCB1bmRlciB0aGUgbWV0aG9kcywgZm9yIHdoYXQgYSBtZXRob2QgZG9lcyBub3QgY292ZXIuICovXG5cdHJlYWRvbmx5IGNsaWVudDogQnJpZGdlQ2xpZW50O1xuXHQvKiogVGhlIGN1cmF0ZWQgaG9zdCBzdXJmYWNlLCBhbmQgd2hhdCB0aGlzIHZpZXcgd2FzIGdyYW50ZWQgb2YgaXQuICovXG5cdHJlYWRvbmx5IGhvc3Q6IFFnaXNTZGtIb3N0O1xuXHQvKiogUmVzb2x2ZXMgb25jZSB0aGUgaGFuZHNoYWtlIGFuc3dlcmVkOyByZWplY3RzIHdoZW4gdGhlIGhvc3QgcmVmdXNlZCBpdC4gKi9cblx0cmVhZG9ubHkgcmVhZHk6IFByb21pc2U8dm9pZD47XG5cdC8qKiBDbG9zZSBhbiBvd25lZCBjbGllbnQ7IGEgY2xpZW50IHRoZSBjYWxsZXIgcGFzc2VkIGluIGlzIGxlZnQgYWxvbmUuICovXG5cdGNsb3NlKCk6IHZvaWQ7XG59XG5cbi8qKiBUaGUgZmlyc3Qgc2VnbWVudCBvZiBhIGRvdHRlZCBpZCwgb3IgdGhlIHdob2xlIGlkIHdoZW4gaXQgaGFzIG5vbmUuICovXG50eXBlIEhlYWQ8SyBleHRlbmRzIHN0cmluZz4gPSBLIGV4dGVuZHMgYCR7aW5mZXIgSH0uJHtzdHJpbmd9YCA/IEggOiBLO1xuXG4vKiogVGhlIG1lbWJlcnMgb2YgYE1gIHVuZGVyIG9uZSBoZWFkLCBrZXllZCBieSB0aGUgcmVzdCBvZiB0aGVpciBpZHMuICovXG50eXBlIFVuZGVyPE0sIEggZXh0ZW5kcyBzdHJpbmc+ID0ge1xuXHRbSyBpbiBrZXlvZiBNICYgc3RyaW5nIGFzIEsgZXh0ZW5kcyBgJHtIfS4ke2luZmVyIFJlc3R9YFxuXHRcdD8gUmVzdFxuXHRcdDogbmV2ZXJdOiBNW0tdO1xufTtcblxuLyoqXG4gKiBUaGUgZGVjbGFyZWQgYWN0aW9ucyBhcyBhIHRyZWU6IGEgcGxhaW4gaWQgaXMgYSBtZXRob2QsIGEgZG90dGVkIGlkIG5lc3RzXG4gKiBvbmUgb2JqZWN0IHBlciBzZWdtZW50LiBBbiBpZCB0aGF0IGlzIGJvdGggYSBsZWFmIGFuZCBhIHByZWZpeCBvZiBhbm90aGVyXG4gKiBpcyByZWZ1c2VkIGF0IHJ1biB0aW1lLCBzbyB0aGUgdHlwZSBuZWVkIG5vdCBzYXkgd2hhdCBpdCB3b3VsZCBtZWFuLlxuICovXG5leHBvcnQgdHlwZSBPcGVyYXRpb25UcmVlPE8+ID0ge1xuXHRyZWFkb25seSBbSCBpbiBIZWFkPGtleW9mIE8gJiBzdHJpbmc+XTogSCBleHRlbmRzIGtleW9mIE9cblx0XHQ/IE9bSF0gZXh0ZW5kcyBPcGVyYXRpb25TaGFwZVxuXHRcdFx0PyBPcGVyYXRpb25NZXRob2Q8T1tIXT5cblx0XHRcdDogbmV2ZXJcblx0XHQ6IE9wZXJhdGlvblRyZWU8VW5kZXI8TywgSD4+O1xufTtcblxuLyoqIFRoZSBkZWNsYXJlZCBzdHJlYW1zIGFzIHRoZSBzYW1lIHRyZWUsIHdpdGggYSBzdHJlYW0gbWV0aG9kIGF0IGVhY2ggbGVhZi4gKi9cbmV4cG9ydCB0eXBlIFN0cmVhbVRyZWU8Uz4gPSB7XG5cdHJlYWRvbmx5IFtIIGluIEhlYWQ8a2V5b2YgUyAmIHN0cmluZz5dOiBIIGV4dGVuZHMga2V5b2YgU1xuXHRcdD8gU1tIXSBleHRlbmRzIFN0cmVhbVNoYXBlXG5cdFx0XHQ/IFN0cmVhbU1ldGhvZDxTW0hdPlxuXHRcdFx0OiBuZXZlclxuXHRcdDogU3RyZWFtVHJlZTxVbmRlcjxTLCBIPj47XG59O1xuXG4vKipcbiAqIEEgcGFnZSdzIGhhbmRsZSBvbiBRR0lTOiB0aGUgY29yZSwgcGx1cyBvbmUgbWV0aG9kIHBlciBkZWNsYXJlZCBvcGVyYXRpb25cbiAqIG5lc3RlZCB1bmRlciB0aGUgc2VnbWVudHMgb2YgaXRzIGlkLlxuICovXG5leHBvcnQgdHlwZSBRZ2lzU2RrPE8gPSBPcGVyYXRpb25NYXAsIFMgPSBTdHJlYW1NYXA+ID0gUWdpc1Nka0NvcmU8TywgUz4gJlxuXHRPcGVyYXRpb25UcmVlPE8+ICZcblx0U3RyZWFtVHJlZTxTPjtcblxuLyoqIE5hbWVzIHtAbGluayBRZ2lzU2RrQ29yZX0ga2VlcHM7IGEgZGVjbGFyZWQgaWQgbWF5IG5vdCBzdGFydCB3aXRoIG9uZS4gKi9cbmV4cG9ydCBjb25zdCBRR0lTX1NES19NRU1CRVJTOiByZWFkb25seSBzdHJpbmdbXSA9IE9iamVjdC5mcmVlemUoW1xuXHRcImNsaWVudFwiLFxuXHRcImhvc3RcIixcblx0XCJzY2hlbWFcIixcblx0XCJyZWFkeVwiLFxuXHRcImNsb3NlXCIsXG5dKTtcblxuY29uc3QgSE9TVF9JRFM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0PHN0cmluZz4oSE9TVF9PUEVSQVRJT05TKTtcblxuLyoqIFRoZSBoYW5kc2hha2UsIGFzIGZhciBhcyB0aGlzIG1vZHVsZSByZWFkcyBpdC4gKi9cbmludGVyZmFjZSBIYW5kc2hha2Uge1xuXHRyZWFkb25seSBvcGVyYXRpb25zOiByZWFkb25seSBzdHJpbmdbXTtcbn1cblxuZnVuY3Rpb24gcGFyc2VIYW5kc2hha2UodmFsdWU6IHVua25vd24pOiBIYW5kc2hha2Uge1xuXHRpZiAoIWlzUGxhaW5SZWNvcmQodmFsdWUpIHx8ICFBcnJheS5pc0FycmF5KHZhbHVlLm9wZXJhdGlvbnMpKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtCcmlkZ2VQcm90b2NvbEVycm9yKFxuXHRcdFx0XCJUaGUgaGFuZHNoYWtlIHJlcGx5IGNhcnJpZXMgbm8gb3BlcmF0aW9ucyBsaXN0XCIsXG5cdFx0KTtcblx0fVxuXHRjb25zdCBvcGVyYXRpb25zOiBzdHJpbmdbXSA9IFtdO1xuXHRmb3IgKGNvbnN0IG9wZXJhdGlvbiBvZiB2YWx1ZS5vcGVyYXRpb25zKSB7XG5cdFx0aWYgKGlzUGxhaW5SZWNvcmQob3BlcmF0aW9uKSAmJiB0eXBlb2Ygb3BlcmF0aW9uLmlkID09PSBcInN0cmluZ1wiKSB7XG5cdFx0XHRvcGVyYXRpb25zLnB1c2gob3BlcmF0aW9uLmlkKTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHsgb3BlcmF0aW9ucyB9O1xufVxuXG5mdW5jdGlvbiB1bndyYXBSZXF1ZXN0KFxuXHRvcGVyYXRpb246IHN0cmluZyxcblx0cmVxdWVzdDogdW5rbm93bixcbik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcblx0aWYgKHJlcXVlc3QgPT09IHVuZGVmaW5lZCkge1xuXHRcdHJldHVybiB7fTtcblx0fVxuXHRpZiAoIWlzUGxhaW5SZWNvcmQocmVxdWVzdCkpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0NvbnRyYWN0RXJyb3Iob3BlcmF0aW9uLCBcInJlcXVlc3RcIiwgW1xuXHRcdFx0Li4udmFsaWRhdGVBZ2FpbnN0U2NoZW1hKHJlcXVlc3QsIHsgdHlwZTogXCJvYmplY3RcIiB9KSxcblx0XHRdKTtcblx0fVxuXHRyZXR1cm4gcmVxdWVzdDtcbn1cblxuZnVuY3Rpb24gY2hlY2tlZFJlcXVlc3QoXG5cdGRlc2NyaXB0aW9uOiBBY3Rpb25EZXNjcmlwdGlvbiB8IFN0cmVhbURlc2NyaXB0aW9uLFxuXHRyZXF1ZXN0OiB1bmtub3duLFxuKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuXHRjb25zdCBwYXlsb2FkID0gdW53cmFwUmVxdWVzdChkZXNjcmlwdGlvbi5pZCwgcmVxdWVzdCk7XG5cdGNvbnN0IGlzc3VlcyA9IHZhbGlkYXRlQWdhaW5zdFNjaGVtYShwYXlsb2FkLCBkZXNjcmlwdGlvbi5yZXF1ZXN0KTtcblx0aWYgKGlzc3Vlcy5sZW5ndGggPiAwKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtDb250cmFjdEVycm9yKGRlc2NyaXB0aW9uLmlkLCBcInJlcXVlc3RcIiwgaXNzdWVzKTtcblx0fVxuXHRyZXR1cm4gcGF5bG9hZDtcbn1cblxuZnVuY3Rpb24gb3BlcmF0aW9uTWV0aG9kKFxuXHRjbGllbnQ6IEJyaWRnZUNsaWVudCxcblx0YWN0aW9uOiBBY3Rpb25EZXNjcmlwdGlvbixcbik6IChyZXF1ZXN0PzogdW5rbm93biwgb3B0aW9ucz86IEludm9rZU9wdGlvbnMpID0+IFByb21pc2U8dW5rbm93bj4ge1xuXHRyZXR1cm4gYXN5bmMgKHJlcXVlc3QsIG9wdGlvbnMpID0+IHtcblx0XHRjb25zdCBwYXlsb2FkID0gY2hlY2tlZFJlcXVlc3QoYWN0aW9uLCByZXF1ZXN0KTtcblx0XHRjb25zdCB2YWx1ZSA9IGF3YWl0IGNsaWVudC5pbnZva2UoYWN0aW9uLmlkLCBwYXlsb2FkLCBvcHRpb25zKTtcblx0XHRjb25zdCBpc3N1ZXMgPSB2YWxpZGF0ZUFnYWluc3RTY2hlbWEodmFsdWUsIGFjdGlvbi5yZXN1bHQsIHtcblx0XHRcdGFsbG93VW5rbm93bjogdHJ1ZSxcblx0XHR9KTtcblx0XHRpZiAoaXNzdWVzLmxlbmd0aCA+IDApIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrQ29udHJhY3RFcnJvcihhY3Rpb24uaWQsIFwicmVzdWx0XCIsIGlzc3Vlcyk7XG5cdFx0fVxuXHRcdHJldHVybiB2YWx1ZTtcblx0fTtcbn1cblxuZnVuY3Rpb24gc3RyZWFtTWV0aG9kKFxuXHRjbGllbnQ6IEJyaWRnZUNsaWVudCxcblx0c3RyZWFtOiBTdHJlYW1EZXNjcmlwdGlvbixcbik6IChcblx0cmVxdWVzdDogdW5rbm93bixcblx0aGFuZGxlcnM6IFN0cmVhbUhhbmRsZXJzPHVua25vd24+LFxuXHRvcHRpb25zPzogSW52b2tlT3B0aW9ucyxcbikgPT4gUHJvbWlzZTxTdHJlYW1IYW5kbGU+IHtcblx0cmV0dXJuIGFzeW5jIChyZXF1ZXN0LCBoYW5kbGVycywgb3B0aW9ucykgPT4ge1xuXHRcdGNvbnN0IHBheWxvYWQgPSBjaGVja2VkUmVxdWVzdChzdHJlYW0sIHJlcXVlc3QpO1xuXHRcdC8vIFRoZSB0eXBlZCBzdHJlYW0gZW5kcyBleGFjdGx5IG9uY2UsIGxpa2UgdGhlIHN1YnNjcmlwdGlvbiB1bmRlciBpdDogYVxuXHRcdC8vIGNvbnRyYWN0IHZpb2xhdGlvbiBlbmRzIGl0IGhlcmUsIGNsb3NlcyB0aGUgc3Vic2NyaXB0aW9uLCBhbmQgdGhlXG5cdFx0Ly8gYGRpc3Bvc2VkYCB0aGUgY2xpZW50IHRoZW4gcmVwb3J0cyBpcyBub3QgZGVsaXZlcmVkIGEgc2Vjb25kIHRpbWUuXG5cdFx0bGV0IGVuZGVkID0gZmFsc2U7XG5cdFx0bGV0IHZpb2xhdGVkID0gZmFsc2U7XG5cdFx0bGV0IGhhbmRsZTogU3RyZWFtSGFuZGxlIHwgbnVsbCA9IG51bGw7XG5cdFx0Y29uc3QgZW5kID0gKHRlcm1pbmFsOiBCcmlkZ2VTdHJlYW1UZXJtaW5hbCk6IHZvaWQgPT4ge1xuXHRcdFx0aWYgKGVuZGVkKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdGVuZGVkID0gdHJ1ZTtcblx0XHRcdGhhbmRsZXJzLm9uVGVybWluYWw/Lih0ZXJtaW5hbCk7XG5cdFx0fTtcblx0XHRoYW5kbGUgPSBhd2FpdCBjbGllbnQuc3Vic2NyaWJlKFxuXHRcdFx0c3RyZWFtLmlkLFxuXHRcdFx0cGF5bG9hZCxcblx0XHRcdHtcblx0XHRcdFx0b25FdmVudDogKGV2ZW50KSA9PiB7XG5cdFx0XHRcdFx0aWYgKGVuZGVkKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGNvbnN0IGRlY2xhcmVkID0gc3RyZWFtLmV2ZW50c1tldmVudC5raW5kXTtcblx0XHRcdFx0XHRjb25zdCBpc3N1ZXMgPVxuXHRcdFx0XHRcdFx0ZGVjbGFyZWQgPT09IHVuZGVmaW5lZFxuXHRcdFx0XHRcdFx0XHQ/IHVuZGVmaW5lZFxuXHRcdFx0XHRcdFx0XHQ6IHZhbGlkYXRlQWdhaW5zdFNjaGVtYShldmVudC5wYXlsb2FkLCBkZWNsYXJlZCwge1xuXHRcdFx0XHRcdFx0XHRcdFx0YWxsb3dVbmtub3duOiB0cnVlLFxuXHRcdFx0XHRcdFx0XHRcdFx0cGF0aDogW1wicGF5bG9hZFwiXSxcblx0XHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRpZiAoaXNzdWVzICE9PSB1bmRlZmluZWQgJiYgaXNzdWVzLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0XHRcdFx0aGFuZGxlcnMub25FdmVudD8uKGV2ZW50KTtcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0Y29uc3QgZXJyb3IgPSBuZXcgUWdpc1Nka0NvbnRyYWN0RXJyb3IoXG5cdFx0XHRcdFx0XHRzdHJlYW0uaWQsXG5cdFx0XHRcdFx0XHRcImV2ZW50XCIsXG5cdFx0XHRcdFx0XHRpc3N1ZXMgPz8gW10sXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRlbmQoeyBraW5kOiBcImVycm9yXCIsIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2UgfSk7XG5cdFx0XHRcdFx0aWYgKGhhbmRsZSA9PT0gbnVsbCkge1xuXHRcdFx0XHRcdFx0dmlvbGF0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRoYW5kbGUuY2xvc2UoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdG9uVGVybWluYWw6IGVuZCxcblx0XHRcdH0sXG5cdFx0XHRvcHRpb25zLFxuXHRcdCk7XG5cdFx0aWYgKHZpb2xhdGVkKSB7XG5cdFx0XHRoYW5kbGUuY2xvc2UoKTtcblx0XHR9XG5cdFx0cmV0dXJuIGhhbmRsZTtcblx0fTtcbn1cblxuZnVuY3Rpb24gYnVpbGRIb3N0KFxuXHRjbGllbnQ6IEJyaWRnZUNsaWVudCxcblx0Z3JhbnRlZDogKCkgPT4gcmVhZG9ubHkgSG9zdE9wZXJhdGlvbklkW10sXG4pOiBRZ2lzU2RrSG9zdCB7XG5cdGNvbnN0IGhvc3QgPSBjcmVhdGVIb3N0KGNsaWVudCk7XG5cdHJldHVybiBPYmplY3QuZnJlZXplKHtcblx0XHQuLi5ob3N0LFxuXHRcdGdldCBncmFudGVkKCk6IHJlYWRvbmx5IEhvc3RPcGVyYXRpb25JZFtdIHtcblx0XHRcdHJldHVybiBncmFudGVkKCk7XG5cdFx0fSxcblx0fSk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkPE8sIFM+KFxuXHRzY2hlbWE6IEJyaWRnZVNjaGVtYTxPLCBTPixcblx0b3B0aW9uczogUWdpc1Nka09wdGlvbnMsXG4pOiBRZ2lzU2RrPE8sIFM+IHtcblx0aWYgKG9wdGlvbnMuY2xpZW50ICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy50cmFuc3BvcnQgIT09IHVuZGVmaW5lZCkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdFwiUWdpc1Nkay5mcm9tQnJpZGdlU2NoZW1hIHRha2VzIGEgY2xpZW50IG9yIGEgdHJhbnNwb3J0LCBub3QgYm90aFwiLFxuXHRcdCk7XG5cdH1cblx0Y29uc3Qgb3duZWQgPSBvcHRpb25zLmNsaWVudCA9PT0gdW5kZWZpbmVkO1xuXHRjb25zdCB0cmFuc3BvcnQgPVxuXHRcdG9wdGlvbnMudHJhbnNwb3J0ID8/XG5cdFx0KG9wdGlvbnMuY2xpZW50ID09PSB1bmRlZmluZWRcblx0XHRcdD8gY3JlYXRlV2ViQ2hhbm5lbFRyYW5zcG9ydChvcHRpb25zLmNoYW5uZWxPYmplY3QgPz8gXCJicmlkZ2VcIilcblx0XHRcdDogdW5kZWZpbmVkKTtcblx0Y29uc3QgY2xpZW50ID1cblx0XHRvcHRpb25zLmNsaWVudCA/P1xuXHRcdG5ldyBCcmlkZ2VDbGllbnQoXG5cdFx0XHR0cmFuc3BvcnQgYXMgV2lyZVRyYW5zcG9ydCxcblx0XHRcdG9wdGlvbnMudGltZW91dE1zID09PSB1bmRlZmluZWQgPyB7fSA6IHsgdGltZW91dE1zOiBvcHRpb25zLnRpbWVvdXRNcyB9LFxuXHRcdCk7XG5cdGxldCBncmFudGVkOiByZWFkb25seSBIb3N0T3BlcmF0aW9uSWRbXSA9IE9iamVjdC5mcmVlemUoW10pO1xuXHRjb25zdCByZWFkeSA9IGNsaWVudC5oYW5kc2hha2UoKS50aGVuKCh2YWx1ZSkgPT4ge1xuXHRcdGNvbnN0IGhhbmRzaGFrZSA9IHBhcnNlSGFuZHNoYWtlKHZhbHVlKTtcblx0XHRncmFudGVkID0gT2JqZWN0LmZyZWV6ZShcblx0XHRcdGhhbmRzaGFrZS5vcGVyYXRpb25zLmZpbHRlcigoaWQpOiBpZCBpcyBIb3N0T3BlcmF0aW9uSWQgPT5cblx0XHRcdFx0SE9TVF9JRFMuaGFzKGlkKSxcblx0XHRcdCksXG5cdFx0KTtcblx0fSk7XG5cdC8vIEEgcGFnZSB0aGF0IG5ldmVyIGF3YWl0cyBgcmVhZHlgIHN0aWxsIHNlZXMgZXZlcnkgY2FsbCBmYWlsIG9uIGl0cyBvd247XG5cdC8vIHRoZSByZWplY3Rpb24gaXMgbm90IGxlZnQgdW5vYnNlcnZlZCBvbiB0b3Agb2YgdGhhdC5cblx0cmVhZHkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcblx0Y29uc3QgbWVtYmVyczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7XG5cdFx0c2NoZW1hLFxuXHRcdGNsaWVudCxcblx0XHRob3N0OiBidWlsZEhvc3QoY2xpZW50LCAoKSA9PiBncmFudGVkKSxcblx0XHRyZWFkeSxcblx0XHRjbG9zZTogKCk6IHZvaWQgPT4ge1xuXHRcdFx0aWYgKG93bmVkKSB7XG5cdFx0XHRcdGNsaWVudC5jbG9zZSgpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdH07XG5cdGNvbnN0IG5hbWVzcGFjZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W10gPSBbXTtcblx0Zm9yIChjb25zdCBhY3Rpb24gb2Ygc2NoZW1hLmFjdGlvbnMpIHtcblx0XHRwbGFjZShtZW1iZXJzLCBuYW1lc3BhY2VzLCBhY3Rpb24uaWQsIG9wZXJhdGlvbk1ldGhvZChjbGllbnQsIGFjdGlvbikpO1xuXHR9XG5cdGZvciAoY29uc3Qgc3RyZWFtIG9mIHNjaGVtYS5zdHJlYW1zKSB7XG5cdFx0cGxhY2UobWVtYmVycywgbmFtZXNwYWNlcywgc3RyZWFtLmlkLCBzdHJlYW1NZXRob2QoY2xpZW50LCBzdHJlYW0pKTtcblx0fVxuXHRmb3IgKGNvbnN0IG5hbWVzcGFjZSBvZiBuYW1lc3BhY2VzKSB7XG5cdFx0T2JqZWN0LmZyZWV6ZShuYW1lc3BhY2UpO1xuXHR9XG5cdHJldHVybiBPYmplY3QuZnJlZXplKG1lbWJlcnMpIGFzIHVua25vd24gYXMgUWdpc1NkazxPLCBTPjtcbn1cblxuLyoqXG4gKiBQdXQgb25lIG1ldGhvZCB3aGVyZSBpdHMgaWQgc2F5czogYGEuYi5jYCBiZWNvbWVzIGBtZW1iZXJzLmEuYi5jYCwgYnVpbGRpbmdcbiAqIHRoZSBvYmplY3RzIG9uIHRoZSB3YXkuIFR3byBpZHMgY2Fubm90IGJvdGggYmUgaG9uZXN0IHdoZW4gb25lIGlzIGEgcHJlZml4XG4gKiBvZiB0aGUgb3RoZXIgLSBgc2l0ZXNgIGNhbm5vdCBiZSBhIG1ldGhvZCBhbmQgaG9sZCBgc2l0ZXMuc3VtbWFyeWAgLSBhbmQgYVxuICogZmlyc3Qgc2VnbWVudCB0aGF0IGlzIGEgY29yZSBtZW1iZXIgd291bGQgaGlkZSBpdCwgc28gYm90aCBhcmUgcmVmdXNlZC5cbiAqL1xuZnVuY3Rpb24gcGxhY2UoXG5cdG1lbWJlcnM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuXHRuYW1lc3BhY2VzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPltdLFxuXHRpZDogc3RyaW5nLFxuXHRtZXRob2Q6IHVua25vd24sXG4pOiB2b2lkIHtcblx0Y29uc3Qgc2VnbWVudHMgPSBpZC5zcGxpdChcIi5cIik7XG5cdGlmIChzZWdtZW50cy5zb21lKChzZWdtZW50KSA9PiBzZWdtZW50ID09PSBcIlwiKSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke2lkfTogYW4gb3BlcmF0aW9uIGlkIG1heSBub3QgaGF2ZSBhbiBlbXB0eSBzZWdtZW50YCxcblx0XHQpO1xuXHR9XG5cdGNvbnN0IGhlYWQgPSBzZWdtZW50c1swXSBhcyBzdHJpbmc7XG5cdGlmIChRR0lTX1NES19NRU1CRVJTLmluY2x1ZGVzKGhlYWQpKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0YCR7aWR9OiBhbiBvcGVyYXRpb24gaWQgbWF5IG5vdCBzdGFydCB3aXRoIGEgUWdpc1NkayBtZW1iZXIgKCR7UUdJU19TREtfTUVNQkVSUy5qb2luKFwiLCBcIil9KWAsXG5cdFx0KTtcblx0fVxuXHRsZXQgbm9kZSA9IG1lbWJlcnM7XG5cdGZvciAoY29uc3QgW2luZGV4LCBzZWdtZW50XSBvZiBzZWdtZW50cy5lbnRyaWVzKCkpIHtcblx0XHRjb25zdCBwcmVmaXggPSBzZWdtZW50cy5zbGljZSgwLCBpbmRleCArIDEpLmpvaW4oXCIuXCIpO1xuXHRcdGNvbnN0IGV4aXN0aW5nID0gbm9kZVtzZWdtZW50XTtcblx0XHRpZiAoaW5kZXggPT09IHNlZ21lbnRzLmxlbmd0aCAtIDEpIHtcblx0XHRcdGlmIChleGlzdGluZyAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdFx0XHR0eXBlb2YgZXhpc3RpbmcgPT09IFwiZnVuY3Rpb25cIlxuXHRcdFx0XHRcdFx0PyBgJHtpZH06IGR1cGxpY2F0ZSBvcGVyYXRpb24gaWRgXG5cdFx0XHRcdFx0XHQ6IGAke2lkfTogYW4gb3BlcmF0aW9uIGlkIG1heSBub3QgYmUgYSBwcmVmaXggb2YgYW5vdGhlciBkZWNsYXJlZCBpZGAsXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0XHRub2RlW3NlZ21lbnRdID0gbWV0aG9kO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRpZiAoZXhpc3RpbmcgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0Y29uc3QgbmFtZXNwYWNlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuXHRcdFx0bmFtZXNwYWNlcy5wdXNoKG5hbWVzcGFjZSk7XG5cdFx0XHRub2RlW3NlZ21lbnRdID0gbmFtZXNwYWNlO1xuXHRcdFx0bm9kZSA9IG5hbWVzcGFjZTtcblx0XHR9IGVsc2UgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRcdGAke2lkfTogJHtwcmVmaXh9IGlzIGFscmVhZHkgYW4gb3BlcmF0aW9uIGlkOyBhbiBpZCBtYXkgbm90IGV4dGVuZCBhbm90aGVyYCxcblx0XHRcdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdG5vZGUgPSBleGlzdGluZyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBUaGUgZW50cnkgcG9pbnQ6IGBRZ2lzU2RrLmZyb21CcmlkZ2VTY2hlbWEoc2NoZW1hKWAuXG4gKlxuICogQSBuYW1lc3BhY2UgcmF0aGVyIHRoYW4gYSBjb25zdGFudCBzbyB0aGUgdmFsdWUgYW5kIHRoZSBpbnN0YW5jZSB0eXBlIHNoYXJlXG4gKiBvbmUgbmFtZSB0aHJvdWdoIGV2ZXJ5IGRlY2xhcmF0aW9uIGJ1bmRsZXIuXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2UgUWdpc1NkayB7XG5cdC8qKlxuXHQgKiBCdWlsZCBhIGBRZ2lzU2RrYCBvbiBhIGdlbmVyYXRlZCBzY2hlbWEuXG5cdCAqXG5cdCAqIFdpdGhvdXQgb3B0aW9ucyBpdCBjb25uZWN0cyB0byB0aGUgcGFnZSdzIFFXZWJDaGFubmVsIG9iamVjdCBuYW1lZFxuXHQgKiBcImJyaWRnZVwiLCB3aGljaCBpcyB3aGF0IHRoZSBQeXRob24gcnVudGltZSByZWdpc3RlcnM7IGEgdGVzdCBwYXNzZXMgdGhlXG5cdCAqIGhhcm5lc3MgZnJvbSBgQGFyY2hvbnQ1NjEvcWdpcy1zZGsvdGVzdGluZ2AgYXMgYHRyYW5zcG9ydGAgaW5zdGVhZC5cblx0ICovXG5cdGV4cG9ydCBmdW5jdGlvbiBmcm9tQnJpZGdlU2NoZW1hPFxuXHRcdE8gZXh0ZW5kcyBSZWNvcmQ8a2V5b2YgTywgT3BlcmF0aW9uU2hhcGU+LFxuXHRcdFMgZXh0ZW5kcyBSZWNvcmQ8a2V5b2YgUywgU3RyZWFtU2hhcGU+LFxuXHQ+KHNjaGVtYTogQnJpZGdlU2NoZW1hPE8sIFM+LCBvcHRpb25zOiBRZ2lzU2RrT3B0aW9ucyA9IHt9KTogUWdpc1NkazxPLCBTPiB7XG5cdFx0cmV0dXJuIGJ1aWxkKHNjaGVtYSwgb3B0aW9ucyk7XG5cdH1cbn1cbiIsCiAgICAiLyoqXG4gKiBUaGUgYnJpZGdlIHNjaGVtYTogYSBwbHVnaW4gZGVzY3JpcHRpb24gdGhhdCBhbHNvIGNhcnJpZXMgaXRzIHR5cGVzLlxuICpcbiAqIGBxZ2lzLXNkayBicmlkZ2UgZ2VuZXJhdGVgIHdyaXRlcyBvbmUgYGJyaWRnZS5zY2hlbWEudHNgIHBlciBwbHVnaW5cbiAqIChkZWNpc2lvbi00NCkuIFRoYXQgbW9kdWxlIGhhcyBubyBjb2RlIG9mIGl0cyBvd246IGl0IGRlY2xhcmVzIHRoZSB2YWx1ZVxuICogaW50ZXJmYWNlcywgdHdvIG1hcHMgLSBgT3BlcmF0aW9uc2AgYW5kIGBTdHJlYW1zYCwga2V5ZWQgYnkgb3BlcmF0aW9uIGlkIC1cbiAqIGFuZCBlbmRzIGluIGBkZWZpbmVCcmlkZ2VTY2hlbWE8T3BlcmF0aW9ucywgU3RyZWFtcz4oeyAuLi5kZXNjcmlwdGlvbiB9KWAuXG4gKiBUaGUgdHdvIHR5cGUgcGFyYW1ldGVycyBuZXZlciBleGlzdCBhdCBydW4gdGltZTsgdGhleSByaWRlIG9uIHRoZSByZXR1cm5lZFxuICogb2JqZWN0IHNvIGBRZ2lzU2RrLmZyb21CcmlkZ2VTY2hlbWEoc2NoZW1hKWAgY2FuIGluZmVyIHRoZW0sIGFuZCB0aGVcbiAqIGRlc2NyaXB0aW9uIGl0c2VsZiBpcyB3aGF0IHRoZSBTREsgdmFsaWRhdGVzIGFnYWluc3QuXG4gKi9cblxuaW1wb3J0IHsgdHlwZSBQbHVnaW5EZXNjcmlwdGlvbiwgcGFyc2VQbHVnaW5EZXNjcmlwdGlvbiB9IGZyb20gXCIuL2RlY2xhcmF0aW9uc1wiO1xuXG4vKiogV2hhdCBvbmUgZGVjbGFyZWQgYWN0aW9uIHByb21pc2VzOiBhbiBvYmplY3QgaW4sIGEgdmFsdWUgb3V0LiAqL1xuZXhwb3J0IGludGVyZmFjZSBPcGVyYXRpb25TaGFwZSB7XG5cdHJlYWRvbmx5IHJlcXVlc3Q6IG9iamVjdDtcblx0cmVhZG9ubHkgcmVzdWx0OiB1bmtub3duO1xufVxuXG4vKiogV2hhdCBvbmUgZGVjbGFyZWQgc3RyZWFtIHByb21pc2VzOiBhbiBvYmplY3QgaW4sIGRpc2NyaW1pbmF0ZWQgZXZlbnRzIG91dC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RyZWFtU2hhcGUge1xuXHRyZWFkb25seSByZXF1ZXN0OiBvYmplY3Q7XG5cdHJlYWRvbmx5IGV2ZW50OiB7IHJlYWRvbmx5IGtpbmQ6IHN0cmluZzsgcmVhZG9ubHkgcGF5bG9hZDogdW5rbm93biB9O1xufVxuXG4vKiogVGhlIGRlZmF1bHQsIHVudHlwZWQgbWFwOiBhbnkgaWQsIGFueSBzaGFwZS4gKi9cbmV4cG9ydCB0eXBlIE9wZXJhdGlvbk1hcCA9IHsgcmVhZG9ubHkgW2lkOiBzdHJpbmddOiBPcGVyYXRpb25TaGFwZSB9O1xuXG4vKiogVGhlIGRlZmF1bHQsIHVudHlwZWQgbWFwOiBhbnkgaWQsIGFueSBzaGFwZS4gKi9cbmV4cG9ydCB0eXBlIFN0cmVhbU1hcCA9IHsgcmVhZG9ubHkgW2lkOiBzdHJpbmddOiBTdHJlYW1TaGFwZSB9O1xuXG4vKipcbiAqIEEgcGFyc2VkIHBsdWdpbiBkZXNjcmlwdGlvbiBjYXJyeWluZyBpdHMgYE9wZXJhdGlvbnNgIGFuZCBgU3RyZWFtc2AgdHlwZXMuXG4gKlxuICogVGhlIGBcIn50eXBlc1wiYCBtZW1iZXIgaXMgY29tcGlsZS10aW1lIG9ubHk6IGl0IGlzIG5ldmVyIHNldCwgYW5kIGEgc2NoZW1hIGlzXG4gKiBhIGZyb3plbiB7QGxpbmsgUGx1Z2luRGVzY3JpcHRpb259IGFuZCBub3RoaW5nIG1vcmUgYXQgcnVuIHRpbWUuIEl0IGlzIGFcbiAqIHN0cmluZyBrZXksIG5vdCBhIHVuaXF1ZSBzeW1ib2wsIHNvIHRoZSB0eXBlIHN0YXlzIHN0cnVjdHVyYWxseSB0aGUgc2FtZVxuICogYWNyb3NzIHRoZSBwYWNrYWdlJ3MgZW50cnkgcG9pbnRzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJyaWRnZVNjaGVtYTxPID0gT3BlcmF0aW9uTWFwLCBTID0gU3RyZWFtTWFwPlxuXHRleHRlbmRzIFBsdWdpbkRlc2NyaXB0aW9uIHtcblx0cmVhZG9ubHkgXCJ+dHlwZXNcIj86IHtcblx0XHRyZWFkb25seSBvcGVyYXRpb25zOiBPO1xuXHRcdHJlYWRvbmx5IHN0cmVhbXM6IFM7XG5cdH07XG59XG5cbi8qKiBUaGUgYE9wZXJhdGlvbnNgIG1hcCBhIHNjaGVtYSBjYXJyaWVzLiAqL1xuZXhwb3J0IHR5cGUgT3BlcmF0aW9uc09mPFNjaGVtYT4gPVxuXHRTY2hlbWEgZXh0ZW5kcyBCcmlkZ2VTY2hlbWE8aW5mZXIgTywgdW5rbm93bj4gPyBPIDogbmV2ZXI7XG5cbi8qKiBUaGUgYFN0cmVhbXNgIG1hcCBhIHNjaGVtYSBjYXJyaWVzLiAqL1xuZXhwb3J0IHR5cGUgU3RyZWFtc09mPFNjaGVtYT4gPVxuXHRTY2hlbWEgZXh0ZW5kcyBCcmlkZ2VTY2hlbWE8dW5rbm93biwgaW5mZXIgUz4gPyBTIDogbmV2ZXI7XG5cbi8qKlxuICogUGFyc2UgYSBkZXNjcmlwdGlvbiBhbmQgdHlwZSBpdDsgdGhlIGdlbmVyYXRlZCBtb2R1bGUgaXMgdGhlIG9ubHkgY2FsbGVyLlxuICpcbiAqIFRoZSBkZXNjcmlwdGlvbiBpcyBjaGVja2VkIHRoZSB3YXkgYW55IGRlc2NyaXB0aW9uIGlzIChgc2NoZW1hX3ZlcnNpb25gLFxuICogaWRzLCBoYW5kbGVycywgZGVjbGFyZWQgc3RyZWFtcyksIHNvIGEgaGFuZC1lZGl0ZWQgb3Igc3RhbGUgbW9kdWxlIGZhaWxzXG4gKiBoZXJlLCBhdCBpbXBvcnQsIHJhdGhlciB0aGFuIG9uIHRoZSBmaXJzdCBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVmaW5lQnJpZGdlU2NoZW1hPFxuXHRPIGV4dGVuZHMgUmVjb3JkPGtleW9mIE8sIE9wZXJhdGlvblNoYXBlPixcblx0UyBleHRlbmRzIFJlY29yZDxrZXlvZiBTLCBTdHJlYW1TaGFwZT4sXG4+KGlucHV0OiBzdHJpbmcgfCBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4pOiBCcmlkZ2VTY2hlbWE8TywgUz4ge1xuXHRyZXR1cm4gcGFyc2VQbHVnaW5EZXNjcmlwdGlvbihpbnB1dCkgYXMgQnJpZGdlU2NoZW1hPE8sIFM+O1xufVxuIgogIF0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBYU8sSUFBTSxtQkFBMkI7QUFDakMsSUFBTSxtQkFBMkI7QUFDakMsSUFBTSxvQ0FBdUM7QUFxRDdDLFNBQVMsaUJBQWlCLENBQUMsT0FBaUM7QUFBQSxFQUNsRSxPQUFPLE9BQU8sVUFBVSxZQUFZLE9BQU8sY0FBYyxLQUFLO0FBQUE7QUFBQTtBQU14RCxNQUFNLGdDQUFnQyxjQUFhO0FBQUEsRUFDbEQsV0FBVyxDQUFDLFNBQWlCO0FBQUEsSUFDbkMsTUFBTSxTQUFTLHFCQUFxQjtBQUFBO0FBRXRDO0FBQUE7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Q3BDLE1BQU0sU0FBUyxZQUFZLE9BQU8sSUFBSSxhQUFhLFFBQVEsTUFBTSxDQUFDO0FBQUEsRUFDbkU7QUFBQSxFQUNBLFdBQVcsYUFBYSxZQUFZO0FBQUEsSUFDbkMsT0FBTyxPQUFPLFNBQVM7QUFBQSxFQUN4QjtBQUFBLEVBQ0EsT0FBTyxPQUFPLE9BQU8sT0FBTztBQUFBO0FBUzdCLFNBQVMsS0FBSyxDQUNiLFNBQ0EsWUFDQSxJQUNBLFFBQ087QUFBQSxFQUNQLE1BQU0sV0FBVyxHQUFHLE1BQU0sR0FBRztBQUFBLEVBQzdCLElBQUksU0FBUyxLQUFLLENBQUMsWUFBWSxZQUFZLEVBQUUsR0FBRztBQUFBLElBQy9DLE1BQU0sSUFBSSx3QkFDVCxHQUFHLG1EQUNKO0FBQUEsRUFDRDtBQUFBLEVBQ0EsTUFBTSxPQUFPLFNBQVM7QUFBQSxFQUN0QixJQUFJLGlCQUFpQixTQUFTLElBQUksR0FBRztBQUFBLElBQ3BDLE1BQU0sSUFBSSx3QkFDVCxHQUFHLDREQUE0RCxpQkFBaUIsS0FBSyxJQUFJLElBQzFGO0FBQUEsRUFDRDtBQUFBLEVBQ0EsSUFBSSxPQUFPO0FBQUEsRUFDWCxZQUFZLE9BQU8sWUFBWSxTQUFTLFFBQVEsR0FBRztBQUFBLElBQ2xELE1BQU0sU0FBUyxTQUFTLE1BQU0sR0FBRyxRQUFRLENBQUMsRUFBRSxLQUFLLEdBQUc7QUFBQSxJQUNwRCxNQUFNLFdBQVcsS0FBSztBQUFBLElBQ3RCLElBQUksVUFBVSxTQUFTLFNBQVMsR0FBRztBQUFBLE1BQ2xDLElBQUksYUFBYSxXQUFXO0FBQUEsUUFDM0IsTUFBTSxJQUFJLHdCQUNULE9BQU8sYUFBYSxhQUNqQixHQUFHLCtCQUNILEdBQUcsZ0VBQ1A7QUFBQSxNQUNEO0FBQUEsTUFDQSxLQUFLLFdBQVc7QUFBQSxNQUNoQjtBQUFBLElBQ0Q7QUFBQSxJQUNBLElBQUksYUFBYSxXQUFXO0FBQUEsTUFDM0IsTUFBTSxZQUFxQyxDQUFDO0FBQUEsTUFDNUMsV0FBVyxLQUFLLFNBQVM7QUFBQSxNQUN6QixLQUFLLFdBQVc7QUFBQSxNQUNoQixPQUFPO0FBQUEsSUFDUixFQUFPLFNBQUksT0FBTyxhQUFhLFlBQVk7QUFBQSxNQUMxQyxNQUFNLElBQUksd0JBQ1QsR0FBRyxPQUFPLGlFQUNYO0FBQUEsSUFDRCxFQUFPO0FBQUEsTUFDTixPQUFPO0FBQUE7QUFBQSxFQUVUO0FBQUE7QUFTTSxJQUFVO0FBQUEsQ0FBVixDQUFVLFlBQVY7QUFBQSxFQVFDLFNBQVMsZ0JBR2YsQ0FBQyxRQUE0QixVQUEwQixDQUFDLEdBQWtCO0FBQUEsSUFDMUUsT0FBTyxNQUFNLFFBQVEsT0FBTztBQUFBO0FBQUEsRUFKdEIsUUFBUztBQUFBLEdBUkE7O0FDbFhWLFNBQVMsa0JBR2YsQ0FBQyxPQUF1RTtBQUFBLEVBQ3hFLE9BQU8sdUJBQXVCLEtBQUs7QUFBQTsiLAogICJkZWJ1Z0lkIjogIjc1NTVDOTNEQTVENTdCMUE2NDc1NkUyMTY0NzU2RTIxIiwKICAibmFtZXMiOiBbXQp9
|