@archont561/qgis-sdk 0.3.0 → 0.5.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/README.md +35 -33
- package/dist/bridge.d.ts +2 -205
- package/dist/bridge.js +3 -4
- package/dist/host.d.ts +2 -157
- package/dist/host.js +72 -430
- package/dist/index.d.ts +62 -95
- package/dist/index.js +399 -12
- package/dist/react.d.ts +61 -161
- package/dist/react.js +70 -139
- package/dist/shared/chunk-2hwva3a3.js +14 -0
- package/dist/shared/chunk-3zscfm3y.d.ts +342 -0
- package/dist/shared/chunk-7tgzmz0m.d.ts +252 -0
- package/dist/shared/chunk-8gawbn19.js +433 -0
- package/dist/shared/chunk-a33y575v.d.ts +155 -0
- package/dist/shared/chunk-pdj2fxjb.d.ts +17 -0
- package/dist/shared/chunk-stre69mw.js +777 -0
- package/dist/shared/chunk-t1vpt5yq.js +895 -0
- package/dist/shared/chunk-wtv4vt4q.d.ts +280 -0
- package/dist/svelte.d.ts +75 -0
- package/dist/svelte.js +70 -0
- package/dist/testing.d.ts +58 -30
- package/dist/testing.js +51 -5
- package/dist/vue.d.ts +106 -0
- package/dist/vue.js +91 -0
- package/package.json +21 -3
- package/dist/shared/chunk-0fknax6w.js +0 -207
- package/dist/shared/chunk-a7bjgeve.js +0 -422
|
@@ -0,0 +1,895 @@
|
|
|
1
|
+
import {
|
|
2
|
+
STREAM_EVENT_KINDS,
|
|
3
|
+
isPlainRecord,
|
|
4
|
+
QgisSdkBridgeAbortedError2
|
|
5
|
+
} from "./chunk-8gawbn19.js";
|
|
6
|
+
import {
|
|
7
|
+
QgisSdkError2
|
|
8
|
+
} from "./chunk-2hwva3a3.js";
|
|
9
|
+
|
|
10
|
+
// src/declarations.ts
|
|
11
|
+
var MAX_SAFE_INTEGER2 = 9007199254740991;
|
|
12
|
+
var MIN_SAFE_INTEGER2 = -9007199254740991;
|
|
13
|
+
var PLUGIN_DESCRIPTION_SCHEMA_VERSION2 = 1;
|
|
14
|
+
function isSafeJsonInteger2(value) {
|
|
15
|
+
return typeof value === "number" && Number.isSafeInteger(value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class QgisSdkDeclarationError2 extends QgisSdkError2 {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message, "invalid_declaration");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
class QgisSdkValidationIssue2 {
|
|
25
|
+
path;
|
|
26
|
+
code;
|
|
27
|
+
constructor(path, code) {
|
|
28
|
+
this.path = Object.freeze([...path]);
|
|
29
|
+
this.code = code;
|
|
30
|
+
}
|
|
31
|
+
toJSON() {
|
|
32
|
+
return {
|
|
33
|
+
path: [...this.path],
|
|
34
|
+
code: this.code
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
class QgisSdkContractValidationError2 extends QgisSdkError2 {
|
|
40
|
+
direction;
|
|
41
|
+
issues;
|
|
42
|
+
constructor(direction, issues) {
|
|
43
|
+
const prefix = direction === "request" ? "Request" : "Result";
|
|
44
|
+
super(`${prefix} contract validation failed`, "contract_validation_failed");
|
|
45
|
+
this.direction = direction;
|
|
46
|
+
this.issues = Object.freeze([...issues]);
|
|
47
|
+
}
|
|
48
|
+
toJSON() {
|
|
49
|
+
return {
|
|
50
|
+
code: this.code,
|
|
51
|
+
direction: this.direction,
|
|
52
|
+
issues: this.issues.map((issue) => issue.toJSON())
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
var DECLARATION_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9_.-]*$/;
|
|
57
|
+
var PYTHON_IDENTIFIER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
58
|
+
function validateDeclarationId(value, label) {
|
|
59
|
+
if (typeof value !== "string" || !DECLARATION_ID_PATTERN.test(value)) {
|
|
60
|
+
throw new QgisSdkDeclarationError2(`Invalid ${label} id: expected [a-zA-Z][a-zA-Z0-9_.-]*`);
|
|
61
|
+
}
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
function validateNonBlankTitle(value, id) {
|
|
65
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
66
|
+
throw new QgisSdkDeclarationError2(`${id}: title must be a nonempty string`);
|
|
67
|
+
}
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
function parseOperationHead(raw, label) {
|
|
71
|
+
if (!isPlainRecord(raw)) {
|
|
72
|
+
throw new QgisSdkDeclarationError2(`${label[0]?.toUpperCase()}${label.slice(1)} description must be an object`);
|
|
73
|
+
}
|
|
74
|
+
const id = validateDeclarationId(raw.id, label);
|
|
75
|
+
const title = validateNonBlankTitle(raw.title, id);
|
|
76
|
+
if (typeof raw.handler !== "string" || !PYTHON_IDENTIFIER_PATTERN.test(raw.handler)) {
|
|
77
|
+
throw new QgisSdkDeclarationError2(`${id}: handler must be a valid Python identifier`);
|
|
78
|
+
}
|
|
79
|
+
if (!isPlainRecord(raw.request)) {
|
|
80
|
+
throw new QgisSdkDeclarationError2(`${id}: request schema must be an object`);
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
raw,
|
|
84
|
+
id,
|
|
85
|
+
title,
|
|
86
|
+
handler: raw.handler,
|
|
87
|
+
request: Object.freeze({ ...raw.request })
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function parseActionDescription(raw) {
|
|
91
|
+
const head = parseOperationHead(raw, "action");
|
|
92
|
+
if (!isPlainRecord(head.raw.result)) {
|
|
93
|
+
throw new QgisSdkDeclarationError2(`${head.id}: result schema must be an object`);
|
|
94
|
+
}
|
|
95
|
+
return Object.freeze({
|
|
96
|
+
id: head.id,
|
|
97
|
+
title: head.title,
|
|
98
|
+
handler: head.handler,
|
|
99
|
+
request: head.request,
|
|
100
|
+
result: Object.freeze({ ...head.raw.result })
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function parseStreamDescription(raw) {
|
|
104
|
+
const head = parseOperationHead(raw, "stream");
|
|
105
|
+
const declared = head.raw.events;
|
|
106
|
+
if (!isPlainRecord(declared) || Object.keys(declared).length === 0) {
|
|
107
|
+
throw new QgisSdkDeclarationError2(`${head.id}: events must map at least one event kind to a schema`);
|
|
108
|
+
}
|
|
109
|
+
const events = {};
|
|
110
|
+
for (const [kind, schema] of Object.entries(declared)) {
|
|
111
|
+
if (!STREAM_EVENT_KINDS.includes(kind)) {
|
|
112
|
+
throw new QgisSdkDeclarationError2(`${head.id}: ${kind} is not a stream event kind`);
|
|
113
|
+
}
|
|
114
|
+
if (!isPlainRecord(schema)) {
|
|
115
|
+
throw new QgisSdkDeclarationError2(`${head.id}: events.${kind} schema must be an object`);
|
|
116
|
+
}
|
|
117
|
+
events[kind] = Object.freeze({ ...schema });
|
|
118
|
+
}
|
|
119
|
+
return Object.freeze({
|
|
120
|
+
id: head.id,
|
|
121
|
+
title: head.title,
|
|
122
|
+
handler: head.handler,
|
|
123
|
+
request: head.request,
|
|
124
|
+
events: Object.freeze(events)
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function parsePluginDescription2(input) {
|
|
128
|
+
let parsed = input;
|
|
129
|
+
if (typeof input === "string") {
|
|
130
|
+
try {
|
|
131
|
+
parsed = JSON.parse(input);
|
|
132
|
+
} catch {
|
|
133
|
+
throw new QgisSdkDeclarationError2("Plugin description is not valid JSON");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (!isPlainRecord(parsed)) {
|
|
137
|
+
throw new QgisSdkDeclarationError2("Plugin description must be an object");
|
|
138
|
+
}
|
|
139
|
+
if (parsed.schema_version !== PLUGIN_DESCRIPTION_SCHEMA_VERSION2) {
|
|
140
|
+
throw new QgisSdkDeclarationError2(`Unsupported plugin description schema_version: ${String(parsed.schema_version)}`);
|
|
141
|
+
}
|
|
142
|
+
const id = validateDeclarationId(parsed.id, "plugin");
|
|
143
|
+
const title = validateNonBlankTitle(parsed.title, id);
|
|
144
|
+
if (!Array.isArray(parsed.actions)) {
|
|
145
|
+
throw new QgisSdkDeclarationError2(`${id}: actions must be an array`);
|
|
146
|
+
}
|
|
147
|
+
const declaredStreams = parsed.streams ?? [];
|
|
148
|
+
if (!Array.isArray(declaredStreams)) {
|
|
149
|
+
throw new QgisSdkDeclarationError2(`${id}: streams must be an array`);
|
|
150
|
+
}
|
|
151
|
+
const seenIds = new Set;
|
|
152
|
+
const claim = (operationId, label) => {
|
|
153
|
+
if (seenIds.has(operationId)) {
|
|
154
|
+
throw new QgisSdkDeclarationError2(`${id}: duplicate ${label} id ${operationId}`);
|
|
155
|
+
}
|
|
156
|
+
seenIds.add(operationId);
|
|
157
|
+
};
|
|
158
|
+
const actions = [];
|
|
159
|
+
for (const item of parsed.actions) {
|
|
160
|
+
const action = parseActionDescription(item);
|
|
161
|
+
claim(action.id, "action");
|
|
162
|
+
actions.push(action);
|
|
163
|
+
}
|
|
164
|
+
const streams = [];
|
|
165
|
+
for (const item of declaredStreams) {
|
|
166
|
+
const stream = parseStreamDescription(item);
|
|
167
|
+
claim(stream.id, "stream");
|
|
168
|
+
streams.push(stream);
|
|
169
|
+
}
|
|
170
|
+
const byId = (left, right) => left.id < right.id ? -1 : 1;
|
|
171
|
+
actions.sort(byId);
|
|
172
|
+
streams.sort(byId);
|
|
173
|
+
return Object.freeze({
|
|
174
|
+
schema_version: PLUGIN_DESCRIPTION_SCHEMA_VERSION2,
|
|
175
|
+
id,
|
|
176
|
+
title,
|
|
177
|
+
actions: Object.freeze(actions),
|
|
178
|
+
streams: Object.freeze(streams)
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// src/validate.ts
|
|
183
|
+
class QgisSdkContractError2 extends QgisSdkError2 {
|
|
184
|
+
operation;
|
|
185
|
+
direction;
|
|
186
|
+
issues;
|
|
187
|
+
constructor(operation, direction, issues) {
|
|
188
|
+
const detail = issues[0] === undefined ? "" : `: ${describe(issues[0])}`;
|
|
189
|
+
super(`${operation}: the ${direction} does not match the declared contract${detail}`, "contract_validation_failed");
|
|
190
|
+
this.operation = operation;
|
|
191
|
+
this.direction = direction;
|
|
192
|
+
this.issues = Object.freeze([...issues]);
|
|
193
|
+
}
|
|
194
|
+
toJSON() {
|
|
195
|
+
return {
|
|
196
|
+
code: this.code,
|
|
197
|
+
operation: this.operation,
|
|
198
|
+
direction: this.direction,
|
|
199
|
+
issues: this.issues.map((issue) => issue.toJSON())
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function describe(issue) {
|
|
204
|
+
const where = issue.path.length === 0 ? "value" : issue.path.join(".");
|
|
205
|
+
return `${where} ${issue.code}`;
|
|
206
|
+
}
|
|
207
|
+
var PRIMITIVES = new Set([
|
|
208
|
+
"string",
|
|
209
|
+
"boolean",
|
|
210
|
+
"integer",
|
|
211
|
+
"number",
|
|
212
|
+
"null",
|
|
213
|
+
"array",
|
|
214
|
+
"object"
|
|
215
|
+
]);
|
|
216
|
+
var KNOWN_KEYWORDS = new Set([
|
|
217
|
+
"type",
|
|
218
|
+
"properties",
|
|
219
|
+
"required",
|
|
220
|
+
"additionalProperties",
|
|
221
|
+
"items",
|
|
222
|
+
"anyOf",
|
|
223
|
+
"enum",
|
|
224
|
+
"minimum",
|
|
225
|
+
"maximum",
|
|
226
|
+
"pattern",
|
|
227
|
+
"title",
|
|
228
|
+
"description",
|
|
229
|
+
"x-qgis-sdk"
|
|
230
|
+
]);
|
|
231
|
+
function validateAgainstSchema2(value, schema, options = {}) {
|
|
232
|
+
const issues = [];
|
|
233
|
+
check(value, schema, options.path ?? [], options.allowUnknown === true, issues);
|
|
234
|
+
return issues;
|
|
235
|
+
}
|
|
236
|
+
function check(value, schema, path, allowUnknown, issues) {
|
|
237
|
+
if (!isPlainRecord(schema)) {
|
|
238
|
+
throw new QgisSdkDeclarationError2(`${where(path)}: a schema must be an object`);
|
|
239
|
+
}
|
|
240
|
+
const unknown = Object.keys(schema).filter((key) => !KNOWN_KEYWORDS.has(key));
|
|
241
|
+
if (unknown.length > 0) {
|
|
242
|
+
throw new QgisSdkDeclarationError2(`${where(path)}: unsupported schema keyword(s) ${unknown.sort().join(", ")}`);
|
|
243
|
+
}
|
|
244
|
+
if ("anyOf" in schema) {
|
|
245
|
+
const branches = schema.anyOf;
|
|
246
|
+
if (!Array.isArray(branches) || branches.length === 0) {
|
|
247
|
+
throw new QgisSdkDeclarationError2(`${where(path)}: anyOf must be a nonempty list`);
|
|
248
|
+
}
|
|
249
|
+
for (const branch of branches) {
|
|
250
|
+
const attempt = [];
|
|
251
|
+
check(value, branch, path, allowUnknown, attempt);
|
|
252
|
+
if (attempt.length === 0) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
issues.push(new QgisSdkValidationIssue2([...path], "any_of"));
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if ("enum" in schema) {
|
|
260
|
+
const choices = schema.enum;
|
|
261
|
+
if (!Array.isArray(choices)) {
|
|
262
|
+
throw new QgisSdkDeclarationError2(`${where(path)}: enum must be a list`);
|
|
263
|
+
}
|
|
264
|
+
if (!choices.some((choice) => sameJson(choice, value))) {
|
|
265
|
+
issues.push(new QgisSdkValidationIssue2([...path], "enum"));
|
|
266
|
+
}
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const declared = schema.type;
|
|
270
|
+
if (declared === undefined) {
|
|
271
|
+
throw new QgisSdkDeclarationError2(`${where(path)}: a schema needs a type, anyOf or enum`);
|
|
272
|
+
}
|
|
273
|
+
if (typeof declared !== "string" || !PRIMITIVES.has(declared)) {
|
|
274
|
+
throw new QgisSdkDeclarationError2(`${where(path)}: unsupported type ${JSON.stringify(declared)}`);
|
|
275
|
+
}
|
|
276
|
+
switch (declared) {
|
|
277
|
+
case "string":
|
|
278
|
+
checkString(value, schema, path, issues);
|
|
279
|
+
return;
|
|
280
|
+
case "boolean":
|
|
281
|
+
if (typeof value !== "boolean") {
|
|
282
|
+
issues.push(new QgisSdkValidationIssue2([...path], "type"));
|
|
283
|
+
}
|
|
284
|
+
return;
|
|
285
|
+
case "integer":
|
|
286
|
+
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
287
|
+
issues.push(new QgisSdkValidationIssue2([...path], "type"));
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
checkBounds(value, schema, path, issues);
|
|
291
|
+
return;
|
|
292
|
+
case "number":
|
|
293
|
+
if (typeof value !== "number") {
|
|
294
|
+
issues.push(new QgisSdkValidationIssue2([...path], "type"));
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (!Number.isFinite(value)) {
|
|
298
|
+
issues.push(new QgisSdkValidationIssue2([...path], "not_finite"));
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
checkBounds(value, schema, path, issues);
|
|
302
|
+
return;
|
|
303
|
+
case "null":
|
|
304
|
+
if (value !== null) {
|
|
305
|
+
issues.push(new QgisSdkValidationIssue2([...path], "type"));
|
|
306
|
+
}
|
|
307
|
+
return;
|
|
308
|
+
case "array":
|
|
309
|
+
checkArray(value, schema, path, allowUnknown, issues);
|
|
310
|
+
return;
|
|
311
|
+
default:
|
|
312
|
+
checkObject(value, schema, path, allowUnknown, issues);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function checkString(value, schema, path, issues) {
|
|
316
|
+
if (typeof value !== "string") {
|
|
317
|
+
issues.push(new QgisSdkValidationIssue2([...path], "type"));
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const pattern = schema.pattern;
|
|
321
|
+
if (pattern === undefined || pattern === null) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (typeof pattern !== "string") {
|
|
325
|
+
throw new QgisSdkDeclarationError2(`${where(path)}: pattern must be a string`);
|
|
326
|
+
}
|
|
327
|
+
let expression;
|
|
328
|
+
try {
|
|
329
|
+
expression = new RegExp(`^(?:${pattern})$`, "u");
|
|
330
|
+
} catch (error) {
|
|
331
|
+
throw new QgisSdkDeclarationError2(`${where(path)}: pattern ${JSON.stringify(pattern)} is unusable: ${String(error)}`);
|
|
332
|
+
}
|
|
333
|
+
if (!expression.test(value)) {
|
|
334
|
+
issues.push(new QgisSdkValidationIssue2([...path], "pattern"));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
function checkBounds(value, schema, path, issues) {
|
|
338
|
+
const minimum = schema.minimum;
|
|
339
|
+
if (typeof minimum === "number" && value < minimum) {
|
|
340
|
+
issues.push(new QgisSdkValidationIssue2([...path], "minimum"));
|
|
341
|
+
}
|
|
342
|
+
const maximum = schema.maximum;
|
|
343
|
+
if (typeof maximum === "number" && value > maximum) {
|
|
344
|
+
issues.push(new QgisSdkValidationIssue2([...path], "maximum"));
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
function checkArray(value, schema, path, allowUnknown, issues) {
|
|
348
|
+
if (!Array.isArray(value)) {
|
|
349
|
+
issues.push(new QgisSdkValidationIssue2([...path], "type"));
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
const items = schema.items;
|
|
353
|
+
if (items === undefined || items === null) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
value.forEach((item, index) => {
|
|
357
|
+
check(item, items, [...path, index], allowUnknown, issues);
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
function checkObject(value, schema, path, allowUnknown, issues) {
|
|
361
|
+
if (!isPlainRecord(value)) {
|
|
362
|
+
issues.push(new QgisSdkValidationIssue2([...path], "type"));
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
const properties = schema.properties ?? {};
|
|
366
|
+
if (!isPlainRecord(properties)) {
|
|
367
|
+
throw new QgisSdkDeclarationError2(`${where(path)}: properties must be an object`);
|
|
368
|
+
}
|
|
369
|
+
const required = schema.required ?? [];
|
|
370
|
+
if (!Array.isArray(required)) {
|
|
371
|
+
throw new QgisSdkDeclarationError2(`${where(path)}: required must be a list`);
|
|
372
|
+
}
|
|
373
|
+
for (const key of required) {
|
|
374
|
+
if (typeof key === "string" && !(key in value)) {
|
|
375
|
+
issues.push(new QgisSdkValidationIssue2([...path, key], "required"));
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
const strict = schema.additionalProperties === false && !allowUnknown;
|
|
379
|
+
for (const [key, item] of Object.entries(value)) {
|
|
380
|
+
if (Object.hasOwn(properties, key)) {
|
|
381
|
+
check(item, properties[key], [...path, key], allowUnknown, issues);
|
|
382
|
+
} else if (strict) {
|
|
383
|
+
issues.push(new QgisSdkValidationIssue2([...path, key], "unknown_property"));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
function sameJson(a, b) {
|
|
388
|
+
if (a === b) {
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
if (typeof a !== typeof b || a === null || b === null) {
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
if (Array.isArray(a)) {
|
|
395
|
+
return Array.isArray(b) && a.length === b.length && a.every((item, index) => sameJson(item, b[index]));
|
|
396
|
+
}
|
|
397
|
+
if (isPlainRecord(a) && isPlainRecord(b)) {
|
|
398
|
+
const keys = Object.keys(a);
|
|
399
|
+
return keys.length === Object.keys(b).length && keys.every((key) => Object.hasOwn(b, key) && sameJson(a[key], b[key]));
|
|
400
|
+
}
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
403
|
+
function where(path) {
|
|
404
|
+
return path.length === 0 ? "value" : path.join(".");
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// src/stores.ts
|
|
408
|
+
class QgisSdkStoreError2 extends QgisSdkError2 {
|
|
409
|
+
constructor(message) {
|
|
410
|
+
super(message, "store_binding");
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
class BaseStore {
|
|
415
|
+
snapshot;
|
|
416
|
+
listeners = new Set;
|
|
417
|
+
constructor(initial) {
|
|
418
|
+
this.snapshot = initial;
|
|
419
|
+
}
|
|
420
|
+
getSnapshot = () => this.snapshot;
|
|
421
|
+
subscribe = (listener) => {
|
|
422
|
+
this.listeners.add(listener);
|
|
423
|
+
listener(this.snapshot);
|
|
424
|
+
return () => {
|
|
425
|
+
this.listeners.delete(listener);
|
|
426
|
+
};
|
|
427
|
+
};
|
|
428
|
+
publish(next) {
|
|
429
|
+
if (Object.is(next, this.snapshot)) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
this.snapshot = next;
|
|
433
|
+
for (const listener of [...this.listeners]) {
|
|
434
|
+
listener(next);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
function asError(error) {
|
|
439
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
440
|
+
}
|
|
441
|
+
var IDLE = Object.freeze({ status: "idle" });
|
|
442
|
+
var PENDING = Object.freeze({ status: "pending" });
|
|
443
|
+
|
|
444
|
+
class OperationStore2 extends BaseStore {
|
|
445
|
+
operation;
|
|
446
|
+
generation = 0;
|
|
447
|
+
controller = null;
|
|
448
|
+
constructor(operation) {
|
|
449
|
+
super(IDLE);
|
|
450
|
+
this.operation = operation;
|
|
451
|
+
}
|
|
452
|
+
abort = () => {
|
|
453
|
+
this.generation += 1;
|
|
454
|
+
this.controller?.abort();
|
|
455
|
+
this.controller = null;
|
|
456
|
+
};
|
|
457
|
+
reset = () => {
|
|
458
|
+
this.abort();
|
|
459
|
+
this.publish(IDLE);
|
|
460
|
+
};
|
|
461
|
+
run = async (input) => {
|
|
462
|
+
this.abort();
|
|
463
|
+
const mine = this.generation;
|
|
464
|
+
const controller = new AbortController;
|
|
465
|
+
this.controller = controller;
|
|
466
|
+
this.publish(PENDING);
|
|
467
|
+
try {
|
|
468
|
+
const value = await this.operation(input, { signal: controller.signal });
|
|
469
|
+
if (this.generation !== mine) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
this.publish({ status: "ok", value });
|
|
473
|
+
return value;
|
|
474
|
+
} catch (error) {
|
|
475
|
+
if (this.generation !== mine || error instanceof QgisSdkBridgeAbortedError2) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
this.publish({ status: "error", error: asError(error) });
|
|
479
|
+
return;
|
|
480
|
+
} finally {
|
|
481
|
+
if (this.controller === controller) {
|
|
482
|
+
this.controller = null;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
var IDLE_STREAM = Object.freeze({
|
|
488
|
+
status: "idle",
|
|
489
|
+
lastEvent: null,
|
|
490
|
+
terminal: null,
|
|
491
|
+
error: null
|
|
492
|
+
});
|
|
493
|
+
function stableKey2(value) {
|
|
494
|
+
return JSON.stringify(value, (_key, item) => isPlainRecord(item) ? Object.fromEntries(Object.entries(item).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) : item);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
class StreamStore2 extends BaseStore {
|
|
498
|
+
open;
|
|
499
|
+
handlers;
|
|
500
|
+
key = null;
|
|
501
|
+
cancel = null;
|
|
502
|
+
constructor(open, handlers = {}) {
|
|
503
|
+
super(IDLE_STREAM);
|
|
504
|
+
this.open = open;
|
|
505
|
+
this.handlers = handlers;
|
|
506
|
+
}
|
|
507
|
+
setHandlers(handlers) {
|
|
508
|
+
this.handlers = handlers;
|
|
509
|
+
}
|
|
510
|
+
setInput = (input) => {
|
|
511
|
+
const key = input === null ? null : stableKey2(input);
|
|
512
|
+
if (key === this.key) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
this.cancel?.();
|
|
516
|
+
this.cancel = null;
|
|
517
|
+
this.key = key;
|
|
518
|
+
if (input === null || key === null) {
|
|
519
|
+
this.publish(IDLE_STREAM);
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
this.cancel = this.start(input);
|
|
523
|
+
};
|
|
524
|
+
close = () => {
|
|
525
|
+
this.setInput(null);
|
|
526
|
+
};
|
|
527
|
+
start(input) {
|
|
528
|
+
let cancelled = false;
|
|
529
|
+
let handle = null;
|
|
530
|
+
const update = (change) => {
|
|
531
|
+
if (!cancelled) {
|
|
532
|
+
this.publish(change(this.getSnapshot()));
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
this.publish({
|
|
536
|
+
status: "opening",
|
|
537
|
+
lastEvent: null,
|
|
538
|
+
terminal: null,
|
|
539
|
+
error: null
|
|
540
|
+
});
|
|
541
|
+
this.open(input, {
|
|
542
|
+
onEvent: (event) => {
|
|
543
|
+
if (cancelled) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
this.handlers.onEvent?.(event);
|
|
547
|
+
update((previous) => ({ ...previous, lastEvent: event }));
|
|
548
|
+
},
|
|
549
|
+
onTerminal: (terminal) => {
|
|
550
|
+
if (cancelled) {
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
this.handlers.onTerminal?.(terminal);
|
|
554
|
+
update((previous) => ({ ...previous, status: "ended", terminal }));
|
|
555
|
+
}
|
|
556
|
+
}).then((opened) => {
|
|
557
|
+
if (cancelled) {
|
|
558
|
+
opened.close();
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
handle = opened;
|
|
562
|
+
update((previous) => previous.status === "ended" ? previous : { ...previous, status: "open" });
|
|
563
|
+
}, (error) => {
|
|
564
|
+
update(() => ({
|
|
565
|
+
status: "failed",
|
|
566
|
+
lastEvent: null,
|
|
567
|
+
terminal: null,
|
|
568
|
+
error: asError(error)
|
|
569
|
+
}));
|
|
570
|
+
});
|
|
571
|
+
return () => {
|
|
572
|
+
cancelled = true;
|
|
573
|
+
handle?.close();
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
var FIELD_KINDS = new Set([
|
|
578
|
+
"text",
|
|
579
|
+
"integer",
|
|
580
|
+
"number",
|
|
581
|
+
"boolean",
|
|
582
|
+
"choice",
|
|
583
|
+
"layer",
|
|
584
|
+
"crs",
|
|
585
|
+
"metres",
|
|
586
|
+
"file",
|
|
587
|
+
"directory",
|
|
588
|
+
"field",
|
|
589
|
+
"range",
|
|
590
|
+
"colour"
|
|
591
|
+
]);
|
|
592
|
+
var PRIMITIVE_KINDS = {
|
|
593
|
+
string: "text",
|
|
594
|
+
integer: "integer",
|
|
595
|
+
number: "number",
|
|
596
|
+
boolean: "boolean"
|
|
597
|
+
};
|
|
598
|
+
var NUMERIC_KINDS = new Set([
|
|
599
|
+
"integer",
|
|
600
|
+
"number",
|
|
601
|
+
"metres",
|
|
602
|
+
"range"
|
|
603
|
+
]);
|
|
604
|
+
var DETAIL_KEYS = ["minimum", "maximum", "step", "of", "filters", "alpha"];
|
|
605
|
+
function labelFor2(name) {
|
|
606
|
+
const spaced = name.replace(/_/g, " ").trim();
|
|
607
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();
|
|
608
|
+
}
|
|
609
|
+
function concrete(schema) {
|
|
610
|
+
const branches = schema.anyOf;
|
|
611
|
+
if (!Array.isArray(branches)) {
|
|
612
|
+
return [schema, false];
|
|
613
|
+
}
|
|
614
|
+
const nonNull = branches.filter((branch) => isPlainRecord(branch) && branch.type !== "null");
|
|
615
|
+
if (nonNull.length === 1 && nonNull.length !== branches.length) {
|
|
616
|
+
return [nonNull[0], true];
|
|
617
|
+
}
|
|
618
|
+
throw new QgisSdkStoreError2("a union field must be one type or that type plus null to be rendered");
|
|
619
|
+
}
|
|
620
|
+
function kindFor(owner, name, schema) {
|
|
621
|
+
const intent = schema["x-qgis-sdk"];
|
|
622
|
+
const marked = isPlainRecord(intent) ? intent.kind : undefined;
|
|
623
|
+
if (typeof marked === "string") {
|
|
624
|
+
if (!FIELD_KINDS.has(marked)) {
|
|
625
|
+
throw new QgisSdkStoreError2(`${owner}: field ${name} has unknown kind ${JSON.stringify(marked)}`);
|
|
626
|
+
}
|
|
627
|
+
return marked;
|
|
628
|
+
}
|
|
629
|
+
if ("enum" in schema) {
|
|
630
|
+
return "choice";
|
|
631
|
+
}
|
|
632
|
+
const kind = PRIMITIVE_KINDS[String(schema.type)];
|
|
633
|
+
if (kind === undefined) {
|
|
634
|
+
throw new QgisSdkStoreError2(`${owner}: field ${name} has no input for its schema; declare a primitive, an enum or a kind`);
|
|
635
|
+
}
|
|
636
|
+
return kind;
|
|
637
|
+
}
|
|
638
|
+
function schemaFields2(schema, owner = "form") {
|
|
639
|
+
const properties = schema.properties;
|
|
640
|
+
if (!isPlainRecord(properties)) {
|
|
641
|
+
return Object.freeze([]);
|
|
642
|
+
}
|
|
643
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
644
|
+
return Object.freeze(Object.entries(properties).map(([name, property]) => {
|
|
645
|
+
if (!isPlainRecord(property)) {
|
|
646
|
+
throw new QgisSdkStoreError2(`${owner}: field ${name} is not a schema`);
|
|
647
|
+
}
|
|
648
|
+
const [shape, nullable] = concrete(property);
|
|
649
|
+
const kind = kindFor(owner, name, shape);
|
|
650
|
+
const intent = isPlainRecord(shape["x-qgis-sdk"]) ? shape["x-qgis-sdk"] : {};
|
|
651
|
+
const merged = { ...shape, ...intent };
|
|
652
|
+
const details = kind === "integer" ? {} : Object.fromEntries(DETAIL_KEYS.filter((key) => (key in merged)).map((key) => [
|
|
653
|
+
key,
|
|
654
|
+
merged[key]
|
|
655
|
+
]));
|
|
656
|
+
return Object.freeze({
|
|
657
|
+
name,
|
|
658
|
+
label: labelFor2(name),
|
|
659
|
+
kind,
|
|
660
|
+
required: required.has(name) && !nullable,
|
|
661
|
+
nullable,
|
|
662
|
+
choices: Object.freeze(kind === "choice" && Array.isArray(shape.enum) ? [...shape.enum] : []),
|
|
663
|
+
details: Object.freeze(details),
|
|
664
|
+
schema: property
|
|
665
|
+
});
|
|
666
|
+
}));
|
|
667
|
+
}
|
|
668
|
+
function operationOf(qgis, id) {
|
|
669
|
+
let node = qgis;
|
|
670
|
+
for (const segment of id.split(".")) {
|
|
671
|
+
node = isPlainRecord(node) || typeof node === "function" ? node[segment] : undefined;
|
|
672
|
+
}
|
|
673
|
+
if (typeof node !== "function") {
|
|
674
|
+
throw new QgisSdkStoreError2(`${id} is not an operation of this QgisSdk`);
|
|
675
|
+
}
|
|
676
|
+
return node;
|
|
677
|
+
}
|
|
678
|
+
function coerce(field, value) {
|
|
679
|
+
if (value === "" && field.kind !== "text") {
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
if (NUMERIC_KINDS.has(field.kind) && typeof value === "string") {
|
|
683
|
+
const trimmed = value.trim();
|
|
684
|
+
if (trimmed !== "" && /^[-+]?(\d+\.?\d*|\.\d+)([eE][-+]?\d+)?$/.test(trimmed)) {
|
|
685
|
+
const number = Number(trimmed);
|
|
686
|
+
if (field.kind !== "integer" || Number.isInteger(number)) {
|
|
687
|
+
return number;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
return value;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
class FormStore2 extends BaseStore {
|
|
695
|
+
id;
|
|
696
|
+
title;
|
|
697
|
+
fields;
|
|
698
|
+
byName;
|
|
699
|
+
request;
|
|
700
|
+
initial;
|
|
701
|
+
operation;
|
|
702
|
+
unsubscribe;
|
|
703
|
+
constructor(qgis, id, options = {}) {
|
|
704
|
+
const action = qgis.schema.actions.find((candidate) => candidate.id === id);
|
|
705
|
+
if (action === undefined) {
|
|
706
|
+
throw new QgisSdkStoreError2(`${id} is not a declared action of this schema`);
|
|
707
|
+
}
|
|
708
|
+
const fields = schemaFields2(action.request, `form ${id}`);
|
|
709
|
+
const initial = FormStore2.defaults(options.initial ?? {});
|
|
710
|
+
super(FormStore2.evaluate(initial, action.request, false, false, IDLE));
|
|
711
|
+
this.id = id;
|
|
712
|
+
this.title = action.title;
|
|
713
|
+
this.fields = fields;
|
|
714
|
+
this.byName = new Map(fields.map((field) => [field.name, field]));
|
|
715
|
+
this.request = action.request;
|
|
716
|
+
this.initial = initial;
|
|
717
|
+
this.operation = new OperationStore2(operationOf(qgis, id));
|
|
718
|
+
let first = true;
|
|
719
|
+
this.unsubscribe = this.operation.subscribe((submission) => {
|
|
720
|
+
if (first) {
|
|
721
|
+
first = false;
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
const current = this.getSnapshot();
|
|
725
|
+
this.publish({ ...current, submission });
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
static describe(qgis, id) {
|
|
729
|
+
return qgis.schema.actions.find((candidate) => candidate.id === id);
|
|
730
|
+
}
|
|
731
|
+
static defaults(initial) {
|
|
732
|
+
return Object.freeze(Object.fromEntries(Object.entries(initial).filter(([, value]) => value !== undefined)));
|
|
733
|
+
}
|
|
734
|
+
static evaluate(values, request, dirty, submitted, submission) {
|
|
735
|
+
const issues = validateAgainstSchema2(values, request);
|
|
736
|
+
const errors = {};
|
|
737
|
+
for (const issue of issues) {
|
|
738
|
+
const [head] = issue.path;
|
|
739
|
+
const name = typeof head === "string" ? head : "";
|
|
740
|
+
if (!(name in errors)) {
|
|
741
|
+
errors[name] = issue.code;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
return Object.freeze({
|
|
745
|
+
values,
|
|
746
|
+
issues: Object.freeze(issues),
|
|
747
|
+
errors: Object.freeze(errors),
|
|
748
|
+
valid: issues.length === 0,
|
|
749
|
+
dirty,
|
|
750
|
+
submitted,
|
|
751
|
+
submission
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
set = (name, value) => {
|
|
755
|
+
this.setValues({ [name]: value });
|
|
756
|
+
};
|
|
757
|
+
setValues = (changes) => {
|
|
758
|
+
const current = this.getSnapshot();
|
|
759
|
+
const values = { ...current.values };
|
|
760
|
+
for (const [name, raw] of Object.entries(changes)) {
|
|
761
|
+
const field = this.byName.get(name);
|
|
762
|
+
if (field === undefined) {
|
|
763
|
+
throw new QgisSdkStoreError2(`${this.id} has no field ${name}`);
|
|
764
|
+
}
|
|
765
|
+
const value = coerce(field, raw);
|
|
766
|
+
if (value === undefined) {
|
|
767
|
+
delete values[name];
|
|
768
|
+
} else {
|
|
769
|
+
values[name] = value;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
this.publish(FormStore2.evaluate(Object.freeze(values), this.request, true, current.submitted, current.submission));
|
|
773
|
+
};
|
|
774
|
+
field(name) {
|
|
775
|
+
const field = this.byName.get(name);
|
|
776
|
+
if (field === undefined) {
|
|
777
|
+
throw new QgisSdkStoreError2(`${this.id} has no field ${name}`);
|
|
778
|
+
}
|
|
779
|
+
return field;
|
|
780
|
+
}
|
|
781
|
+
reset = () => {
|
|
782
|
+
this.operation.reset();
|
|
783
|
+
this.publish(FormStore2.evaluate(this.initial, this.request, false, false, IDLE));
|
|
784
|
+
};
|
|
785
|
+
abort = () => {
|
|
786
|
+
this.operation.abort();
|
|
787
|
+
};
|
|
788
|
+
submit = async () => {
|
|
789
|
+
const current = this.getSnapshot();
|
|
790
|
+
if (!current.valid) {
|
|
791
|
+
this.publish({ ...current, submitted: true });
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
if (!current.submitted) {
|
|
795
|
+
this.publish({ ...current, submitted: true });
|
|
796
|
+
}
|
|
797
|
+
return this.operation.run(current.values);
|
|
798
|
+
};
|
|
799
|
+
dispose() {
|
|
800
|
+
this.operation.abort();
|
|
801
|
+
this.unsubscribe();
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
function formStore2(qgis, id, options) {
|
|
805
|
+
return new FormStore2(qgis, id, options);
|
|
806
|
+
}
|
|
807
|
+
var IDLE_QUERY = Object.freeze({ status: "idle" });
|
|
808
|
+
|
|
809
|
+
class HostQueryStore2 extends BaseStore {
|
|
810
|
+
qgis;
|
|
811
|
+
operation;
|
|
812
|
+
loader;
|
|
813
|
+
generation = 0;
|
|
814
|
+
controller = null;
|
|
815
|
+
constructor(qgis, operation, loader) {
|
|
816
|
+
super(IDLE_QUERY);
|
|
817
|
+
this.qgis = qgis;
|
|
818
|
+
this.operation = operation;
|
|
819
|
+
this.loader = loader;
|
|
820
|
+
}
|
|
821
|
+
abort = () => {
|
|
822
|
+
this.generation += 1;
|
|
823
|
+
this.controller?.abort();
|
|
824
|
+
this.controller = null;
|
|
825
|
+
};
|
|
826
|
+
reset = () => {
|
|
827
|
+
this.abort();
|
|
828
|
+
this.publish(IDLE_QUERY);
|
|
829
|
+
};
|
|
830
|
+
refresh = async () => {
|
|
831
|
+
this.abort();
|
|
832
|
+
const mine = this.generation;
|
|
833
|
+
const controller = new AbortController;
|
|
834
|
+
this.controller = controller;
|
|
835
|
+
this.publish({ status: "loading" });
|
|
836
|
+
try {
|
|
837
|
+
await this.qgis.ready;
|
|
838
|
+
if (this.generation !== mine) {
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
if (!this.qgis.host.granted.includes(this.operation)) {
|
|
842
|
+
this.publish({
|
|
843
|
+
status: "refused",
|
|
844
|
+
operation: this.operation,
|
|
845
|
+
message: `this view was not granted ${this.operation}`
|
|
846
|
+
});
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
const value = await this.loader(this.qgis.host, {
|
|
850
|
+
signal: controller.signal
|
|
851
|
+
});
|
|
852
|
+
if (this.generation !== mine) {
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
this.publish({ status: "ok", value });
|
|
856
|
+
return value;
|
|
857
|
+
} catch (error) {
|
|
858
|
+
if (this.generation !== mine || error instanceof QgisSdkBridgeAbortedError2) {
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
this.publish({ status: "error", error: asError(error) });
|
|
862
|
+
return;
|
|
863
|
+
} finally {
|
|
864
|
+
if (this.controller === controller) {
|
|
865
|
+
this.controller = null;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
function layersQuery2(qgis, options = {}) {
|
|
871
|
+
return new HostQueryStore2(qgis, "layers.list", async (host, { signal }) => {
|
|
872
|
+
const items = [];
|
|
873
|
+
let cursor;
|
|
874
|
+
do {
|
|
875
|
+
const page = await host.layers.list({
|
|
876
|
+
...cursor === undefined ? {} : { cursor },
|
|
877
|
+
...options.pageSize === undefined ? {} : { limit: options.pageSize }
|
|
878
|
+
}, { signal });
|
|
879
|
+
items.push(...page.items);
|
|
880
|
+
cursor = page.next_cursor;
|
|
881
|
+
} while (cursor !== undefined);
|
|
882
|
+
return Object.freeze(items);
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
function layerFieldsQuery2(qgis, layerId) {
|
|
886
|
+
return new HostQueryStore2(qgis, "layers.get", async (host, { signal }) => {
|
|
887
|
+
const layer = await host.layers.get({ layer_id: layerId }, { signal });
|
|
888
|
+
return Object.freeze([...layer.field_names]);
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
export { MAX_SAFE_INTEGER2, MIN_SAFE_INTEGER2, PLUGIN_DESCRIPTION_SCHEMA_VERSION2, isSafeJsonInteger2, QgisSdkDeclarationError2, QgisSdkValidationIssue2, QgisSdkContractValidationError2, parsePluginDescription2, QgisSdkContractError2, validateAgainstSchema2, QgisSdkStoreError2, OperationStore2, stableKey2, StreamStore2, labelFor2, schemaFields2, FormStore2, formStore2, HostQueryStore2, layersQuery2, layerFieldsQuery2 };
|
|
893
|
+
|
|
894
|
+
//# debugId=E60C228E310DFC3564756E2164756E21
|
|
895
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL2RlY2xhcmF0aW9ucy50cyIsICJzcmMvdmFsaWRhdGUudHMiLCAic3JjL3N0b3Jlcy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsKICAgICIvKipcbiAqIFRoZSB2ZXJzaW9uIDEgcGx1Z2luLWRlc2NyaXB0aW9uIGNvbnRyYWN0IGFuZCBpdHMgd2lyZSBsaW1pdHMuXG4gKlxuICogTWlycm9ycyB0aGUgUUdJUy1mcmVlIGBxZ2lzX3Nkay5tb2RlbHNgIGFuZCBgcWdpc19zZGsuZGVjbGFyYXRpb25zYFxuICogKGBzY2hlbWFfdmVyc2lvbiA9IDFgKSBjb250cmFjdHMgd2l0aG91dCBpbXBvcnRpbmcgYnJvd3NlciBvciBRdCBnbG9iYWxzLlxuICogYHBhcnNlUGx1Z2luRGVzY3JpcHRpb25gIGlzIHRoZSBicm93c2VyLXNpZGUgcmVhZGVyIG9mIHdoYXRcbiAqIGBkZXNjcmliZV9wbHVnaW4oY2xzKS50b19qc29uKClgIGVtaXRzOyBgcWdpcy1zZGsgYnJpZGdlIGdlbmVyYXRlYCBpcyB0aGVcbiAqIGJ1aWxkLXRpbWUgb25lLlxuICovXG5cbmltcG9ydCB7IFFnaXNTZGtFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgaXNQbGFpblJlY29yZCwgU1RSRUFNX0VWRU5UX0tJTkRTIH0gZnJvbSBcIi4vaW50ZXJuYWxcIjtcblxuZXhwb3J0IGNvbnN0IE1BWF9TQUZFX0lOVEVHRVI6IG51bWJlciA9IDlfMDA3XzE5OV8yNTRfNzQwXzk5MTtcbmV4cG9ydCBjb25zdCBNSU5fU0FGRV9JTlRFR0VSOiBudW1iZXIgPSAtOV8wMDdfMTk5XzI1NF83NDBfOTkxO1xuZXhwb3J0IGNvbnN0IFBMVUdJTl9ERVNDUklQVElPTl9TQ0hFTUFfVkVSU0lPTjogMSA9IDE7XG5cbmV4cG9ydCB0eXBlIFZhbGlkYXRpb25EaXJlY3Rpb24gPSBcInJlcXVlc3RcIiB8IFwicmVzdWx0XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VyaWFsaXplZFZhbGlkYXRpb25Jc3N1ZSB7XG5cdHJlYWRvbmx5IHBhdGg6IChzdHJpbmcgfCBudW1iZXIpW107XG5cdHJlYWRvbmx5IGNvZGU6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZXJpYWxpemVkQ29udHJhY3RWYWxpZGF0aW9uRXJyb3Ige1xuXHRyZWFkb25seSBjb2RlOiBzdHJpbmc7XG5cdHJlYWRvbmx5IGRpcmVjdGlvbjogVmFsaWRhdGlvbkRpcmVjdGlvbjtcblx0cmVhZG9ubHkgaXNzdWVzOiBTZXJpYWxpemVkVmFsaWRhdGlvbklzc3VlW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWN0aW9uRGVzY3JpcHRpb24ge1xuXHRyZWFkb25seSBpZDogc3RyaW5nO1xuXHRyZWFkb25seSB0aXRsZTogc3RyaW5nO1xuXHRyZWFkb25seSBoYW5kbGVyOiBzdHJpbmc7XG5cdHJlYWRvbmx5IHJlcXVlc3Q6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pjtcblx0cmVhZG9ubHkgcmVzdWx0OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj47XG59XG5cbi8qKiBUaGUgZXZlbnQga2luZHMgYSBzdHJlYW0gbWF5IGRlY2xhcmU7IHRoZSBmcmFtZSBjYXJyaWVzIHRoZSBzYW1lIHRocmVlLiAqL1xuZXhwb3J0IHR5cGUgU3RyZWFtRXZlbnRLaW5kID0gXCJkYXRhXCIgfCBcInByb2dyZXNzXCIgfCBcInN0YXRlXCI7XG5cbi8qKlxuICogQSBkZWNsYXJlZCBzdHJlYW0gKGRlY2lzaW9uLTI4KTogYSByZXF1ZXN0IGluLCBvbmUgcGF5bG9hZCBzY2hlbWEgcGVyXG4gKiBkZWNsYXJlZCBldmVudCBraW5kIG91dC4gVGhlcmUgaXMgbm8gYHJlc3VsdGA6IHRoZSByZXBseSB0byBhIHN1YnNjcmlwdGlvbiBpc1xuICogdGhlIHByb3RvY29sJ3MgYWNrbm93bGVkZ2VtZW50LCBub3Qgc29tZXRoaW5nIGFuIGF1dGhvciBkZWNsYXJlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdHJlYW1EZXNjcmlwdGlvbiB7XG5cdHJlYWRvbmx5IGlkOiBzdHJpbmc7XG5cdHJlYWRvbmx5IHRpdGxlOiBzdHJpbmc7XG5cdHJlYWRvbmx5IGhhbmRsZXI6IHN0cmluZztcblx0cmVhZG9ubHkgcmVxdWVzdDogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+O1xuXHRyZWFkb25seSBldmVudHM6IFJlYWRvbmx5PFxuXHRcdFBhcnRpYWw8UmVjb3JkPFN0cmVhbUV2ZW50S2luZCwgUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+Pj5cblx0Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5EZXNjcmlwdGlvbiB7XG5cdHJlYWRvbmx5IHNjaGVtYV92ZXJzaW9uOiAxO1xuXHRyZWFkb25seSBpZDogc3RyaW5nO1xuXHRyZWFkb25seSB0aXRsZTogc3RyaW5nO1xuXHRyZWFkb25seSBhY3Rpb25zOiByZWFkb25seSBBY3Rpb25EZXNjcmlwdGlvbltdO1xuXHQvKiogRGVjbGFyZWQgc3RyZWFtczsgYSBkZXNjcmlwdGlvbiBmcm9tIGEgaG9zdCB0aGF0IHByZWRhdGVzIHRoZW0gaXMgZW1wdHkuICovXG5cdHJlYWRvbmx5IHN0cmVhbXM6IHJlYWRvbmx5IFN0cmVhbURlc2NyaXB0aW9uW107XG59XG5cbi8qKlxuICogUmV0dXJuIHdoZXRoZXIgYHZhbHVlYCBpcyBhIGZpbml0ZSBpbnRlZ2VyIHdpdGhpbiB0aGUgSmF2YVNjcmlwdC1zYWZlIHdpcmUgcmFuZ2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1NhZmVKc29uSW50ZWdlcih2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIG51bWJlciB7XG5cdHJldHVybiB0eXBlb2YgdmFsdWUgPT09IFwibnVtYmVyXCIgJiYgTnVtYmVyLmlzU2FmZUludGVnZXIodmFsdWUpO1xufVxuXG4vKipcbiAqIEEgZGVjbGFyYXRpb24gY2Fubm90IGJlIHJlcHJlc2VudGVkIG9yIHBhcnNlZCBpbiB0aGUgdmVyc2lvbmVkIGNvbnRyYWN0LlxuICovXG5leHBvcnQgY2xhc3MgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IgZXh0ZW5kcyBRZ2lzU2RrRXJyb3Ige1xuXHRwdWJsaWMgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nKSB7XG5cdFx0c3VwZXIobWVzc2FnZSwgXCJpbnZhbGlkX2RlY2xhcmF0aW9uXCIpO1xuXHR9XG59XG5cbi8qKlxuICogU2FmZSwgc3RydWN0dXJlZCBsb2NhdGlvbiBhbmQgY2F0ZWdvcnkgZm9yIGEgcmVqZWN0ZWQgY29udHJhY3QgdmFsdWUuXG4gKi9cbmV4cG9ydCBjbGFzcyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlIHtcblx0cHVibGljIHJlYWRvbmx5IHBhdGg6IHJlYWRvbmx5IChzdHJpbmcgfCBudW1iZXIpW107XG5cdHB1YmxpYyByZWFkb25seSBjb2RlOiBzdHJpbmc7XG5cblx0cHVibGljIGNvbnN0cnVjdG9yKHBhdGg6IHJlYWRvbmx5IChzdHJpbmcgfCBudW1iZXIpW10sIGNvZGU6IHN0cmluZykge1xuXHRcdHRoaXMucGF0aCA9IE9iamVjdC5mcmVlemUoWy4uLnBhdGhdKTtcblx0XHR0aGlzLmNvZGUgPSBjb2RlO1xuXHR9XG5cblx0cHVibGljIHRvSlNPTigpOiBTZXJpYWxpemVkVmFsaWRhdGlvbklzc3VlIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0cGF0aDogWy4uLnRoaXMucGF0aF0sXG5cdFx0XHRjb2RlOiB0aGlzLmNvZGUsXG5cdFx0fTtcblx0fVxufVxuXG4vKipcbiAqIEEgcmVxdWVzdCBvciByZXN1bHQgZGlkIG5vdCBzYXRpc2Z5IGl0cyBkZWNsYXJlZCB3aXJlIGNvbnRyYWN0LlxuICovXG5leHBvcnQgY2xhc3MgUWdpc1Nka0NvbnRyYWN0VmFsaWRhdGlvbkVycm9yIGV4dGVuZHMgUWdpc1Nka0Vycm9yIHtcblx0cHVibGljIHJlYWRvbmx5IGRpcmVjdGlvbjogVmFsaWRhdGlvbkRpcmVjdGlvbjtcblx0cHVibGljIHJlYWRvbmx5IGlzc3VlczogcmVhZG9ubHkgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZVtdO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3Rvcihcblx0XHRkaXJlY3Rpb246IFZhbGlkYXRpb25EaXJlY3Rpb24sXG5cdFx0aXNzdWVzOiByZWFkb25seSBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlW10sXG5cdCkge1xuXHRcdGNvbnN0IHByZWZpeCA9IGRpcmVjdGlvbiA9PT0gXCJyZXF1ZXN0XCIgPyBcIlJlcXVlc3RcIiA6IFwiUmVzdWx0XCI7XG5cdFx0c3VwZXIoYCR7cHJlZml4fSBjb250cmFjdCB2YWxpZGF0aW9uIGZhaWxlZGAsIFwiY29udHJhY3RfdmFsaWRhdGlvbl9mYWlsZWRcIik7XG5cdFx0dGhpcy5kaXJlY3Rpb24gPSBkaXJlY3Rpb247XG5cdFx0dGhpcy5pc3N1ZXMgPSBPYmplY3QuZnJlZXplKFsuLi5pc3N1ZXNdKTtcblx0fVxuXG5cdHB1YmxpYyB0b0pTT04oKTogU2VyaWFsaXplZENvbnRyYWN0VmFsaWRhdGlvbkVycm9yIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0Y29kZTogdGhpcy5jb2RlLFxuXHRcdFx0ZGlyZWN0aW9uOiB0aGlzLmRpcmVjdGlvbixcblx0XHRcdGlzc3VlczogdGhpcy5pc3N1ZXMubWFwKChpc3N1ZSkgPT4gaXNzdWUudG9KU09OKCkpLFxuXHRcdH07XG5cdH1cbn1cblxuY29uc3QgREVDTEFSQVRJT05fSURfUEFUVEVSTiA9IC9eW2EtekEtWl1bYS16QS1aMC05Xy4tXSokLztcbmNvbnN0IFBZVEhPTl9JREVOVElGSUVSX1BBVFRFUk4gPSAvXlthLXpBLVpfXVthLXpBLVowLTlfXSokLztcblxuZnVuY3Rpb24gdmFsaWRhdGVEZWNsYXJhdGlvbklkKHZhbHVlOiB1bmtub3duLCBsYWJlbDogc3RyaW5nKTogc3RyaW5nIHtcblx0aWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJzdHJpbmdcIiB8fCAhREVDTEFSQVRJT05fSURfUEFUVEVSTi50ZXN0KHZhbHVlKSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGBJbnZhbGlkICR7bGFiZWx9IGlkOiBleHBlY3RlZCBbYS16QS1aXVthLXpBLVowLTlfLi1dKmAsXG5cdFx0KTtcblx0fVxuXHRyZXR1cm4gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlTm9uQmxhbmtUaXRsZSh2YWx1ZTogdW5rbm93biwgaWQ6IHN0cmluZyk6IHN0cmluZyB7XG5cdGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIgfHwgdmFsdWUudHJpbSgpLmxlbmd0aCA9PT0gMCkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihgJHtpZH06IHRpdGxlIG11c3QgYmUgYSBub25lbXB0eSBzdHJpbmdgKTtcblx0fVxuXHRyZXR1cm4gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIHBhcnNlT3BlcmF0aW9uSGVhZChcblx0cmF3OiB1bmtub3duLFxuXHRsYWJlbDogc3RyaW5nLFxuKToge1xuXHRyZWFkb25seSByYXc6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXHRyZWFkb25seSBpZDogc3RyaW5nO1xuXHRyZWFkb25seSB0aXRsZTogc3RyaW5nO1xuXHRyZWFkb25seSBoYW5kbGVyOiBzdHJpbmc7XG5cdHJlYWRvbmx5IHJlcXVlc3Q6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pjtcbn0ge1xuXHRpZiAoIWlzUGxhaW5SZWNvcmQocmF3KSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke2xhYmVsWzBdPy50b1VwcGVyQ2FzZSgpfSR7bGFiZWwuc2xpY2UoMSl9IGRlc2NyaXB0aW9uIG11c3QgYmUgYW4gb2JqZWN0YCxcblx0XHQpO1xuXHR9XG5cdGNvbnN0IGlkID0gdmFsaWRhdGVEZWNsYXJhdGlvbklkKHJhdy5pZCwgbGFiZWwpO1xuXHRjb25zdCB0aXRsZSA9IHZhbGlkYXRlTm9uQmxhbmtUaXRsZShyYXcudGl0bGUsIGlkKTtcblx0aWYgKFxuXHRcdHR5cGVvZiByYXcuaGFuZGxlciAhPT0gXCJzdHJpbmdcIiB8fFxuXHRcdCFQWVRIT05fSURFTlRJRklFUl9QQVRURVJOLnRlc3QocmF3LmhhbmRsZXIpXG5cdCkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke2lkfTogaGFuZGxlciBtdXN0IGJlIGEgdmFsaWQgUHl0aG9uIGlkZW50aWZpZXJgLFxuXHRcdCk7XG5cdH1cblx0aWYgKCFpc1BsYWluUmVjb3JkKHJhdy5yZXF1ZXN0KSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke2lkfTogcmVxdWVzdCBzY2hlbWEgbXVzdCBiZSBhbiBvYmplY3RgLFxuXHRcdCk7XG5cdH1cblx0cmV0dXJuIHtcblx0XHRyYXcsXG5cdFx0aWQsXG5cdFx0dGl0bGUsXG5cdFx0aGFuZGxlcjogcmF3LmhhbmRsZXIsXG5cdFx0cmVxdWVzdDogT2JqZWN0LmZyZWV6ZSh7IC4uLnJhdy5yZXF1ZXN0IH0pLFxuXHR9O1xufVxuXG5mdW5jdGlvbiBwYXJzZUFjdGlvbkRlc2NyaXB0aW9uKHJhdzogdW5rbm93bik6IEFjdGlvbkRlc2NyaXB0aW9uIHtcblx0Y29uc3QgaGVhZCA9IHBhcnNlT3BlcmF0aW9uSGVhZChyYXcsIFwiYWN0aW9uXCIpO1xuXHRpZiAoIWlzUGxhaW5SZWNvcmQoaGVhZC5yYXcucmVzdWx0KSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke2hlYWQuaWR9OiByZXN1bHQgc2NoZW1hIG11c3QgYmUgYW4gb2JqZWN0YCxcblx0XHQpO1xuXHR9XG5cdHJldHVybiBPYmplY3QuZnJlZXplKHtcblx0XHRpZDogaGVhZC5pZCxcblx0XHR0aXRsZTogaGVhZC50aXRsZSxcblx0XHRoYW5kbGVyOiBoZWFkLmhhbmRsZXIsXG5cdFx0cmVxdWVzdDogaGVhZC5yZXF1ZXN0LFxuXHRcdHJlc3VsdDogT2JqZWN0LmZyZWV6ZSh7IC4uLmhlYWQucmF3LnJlc3VsdCB9KSxcblx0fSk7XG59XG5cbmZ1bmN0aW9uIHBhcnNlU3RyZWFtRGVzY3JpcHRpb24ocmF3OiB1bmtub3duKTogU3RyZWFtRGVzY3JpcHRpb24ge1xuXHRjb25zdCBoZWFkID0gcGFyc2VPcGVyYXRpb25IZWFkKHJhdywgXCJzdHJlYW1cIik7XG5cdGNvbnN0IGRlY2xhcmVkID0gaGVhZC5yYXcuZXZlbnRzO1xuXHRpZiAoIWlzUGxhaW5SZWNvcmQoZGVjbGFyZWQpIHx8IE9iamVjdC5rZXlzKGRlY2xhcmVkKS5sZW5ndGggPT09IDApIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRgJHtoZWFkLmlkfTogZXZlbnRzIG11c3QgbWFwIGF0IGxlYXN0IG9uZSBldmVudCBraW5kIHRvIGEgc2NoZW1hYCxcblx0XHQpO1xuXHR9XG5cdGNvbnN0IGV2ZW50czogUGFydGlhbDxcblx0XHRSZWNvcmQ8U3RyZWFtRXZlbnRLaW5kLCBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4+XG5cdD4gPSB7fTtcblx0Zm9yIChjb25zdCBba2luZCwgc2NoZW1hXSBvZiBPYmplY3QuZW50cmllcyhkZWNsYXJlZCkpIHtcblx0XHRpZiAoIVNUUkVBTV9FVkVOVF9LSU5EUy5pbmNsdWRlcyhraW5kIGFzIFN0cmVhbUV2ZW50S2luZCkpIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdFx0YCR7aGVhZC5pZH06ICR7a2luZH0gaXMgbm90IGEgc3RyZWFtIGV2ZW50IGtpbmRgLFxuXHRcdFx0KTtcblx0XHR9XG5cdFx0aWYgKCFpc1BsYWluUmVjb3JkKHNjaGVtYSkpIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdFx0YCR7aGVhZC5pZH06IGV2ZW50cy4ke2tpbmR9IHNjaGVtYSBtdXN0IGJlIGFuIG9iamVjdGAsXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRldmVudHNba2luZCBhcyBTdHJlYW1FdmVudEtpbmRdID0gT2JqZWN0LmZyZWV6ZSh7IC4uLnNjaGVtYSB9KTtcblx0fVxuXHRyZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG5cdFx0aWQ6IGhlYWQuaWQsXG5cdFx0dGl0bGU6IGhlYWQudGl0bGUsXG5cdFx0aGFuZGxlcjogaGVhZC5oYW5kbGVyLFxuXHRcdHJlcXVlc3Q6IGhlYWQucmVxdWVzdCxcblx0XHRldmVudHM6IE9iamVjdC5mcmVlemUoZXZlbnRzKSxcblx0fSk7XG59XG5cbi8qKlxuICogUGFyc2UgYW5kIHZhbGlkYXRlIGEgdmVyc2lvbiAxIGBQbHVnaW5EZXNjcmlwdGlvbmAgZW1pdHRlZCBieSBgZGVzY3JpYmVfcGx1Z2luYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUGx1Z2luRGVzY3JpcHRpb24oXG5cdGlucHV0OiBzdHJpbmcgfCBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4sXG4pOiBQbHVnaW5EZXNjcmlwdGlvbiB7XG5cdGxldCBwYXJzZWQ6IHVua25vd24gPSBpbnB1dDtcblx0aWYgKHR5cGVvZiBpbnB1dCA9PT0gXCJzdHJpbmdcIikge1xuXHRcdHRyeSB7XG5cdFx0XHRwYXJzZWQgPSBKU09OLnBhcnNlKGlucHV0KTtcblx0XHR9IGNhdGNoIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcIlBsdWdpbiBkZXNjcmlwdGlvbiBpcyBub3QgdmFsaWQgSlNPTlwiKTtcblx0XHR9XG5cdH1cblx0aWYgKCFpc1BsYWluUmVjb3JkKHBhcnNlZCkpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXCJQbHVnaW4gZGVzY3JpcHRpb24gbXVzdCBiZSBhbiBvYmplY3RcIik7XG5cdH1cblx0aWYgKHBhcnNlZC5zY2hlbWFfdmVyc2lvbiAhPT0gUExVR0lOX0RFU0NSSVBUSU9OX1NDSEVNQV9WRVJTSU9OKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0YFVuc3VwcG9ydGVkIHBsdWdpbiBkZXNjcmlwdGlvbiBzY2hlbWFfdmVyc2lvbjogJHtTdHJpbmcocGFyc2VkLnNjaGVtYV92ZXJzaW9uKX1gLFxuXHRcdCk7XG5cdH1cblx0Y29uc3QgaWQgPSB2YWxpZGF0ZURlY2xhcmF0aW9uSWQocGFyc2VkLmlkLCBcInBsdWdpblwiKTtcblx0Y29uc3QgdGl0bGUgPSB2YWxpZGF0ZU5vbkJsYW5rVGl0bGUocGFyc2VkLnRpdGxlLCBpZCk7XG5cdGlmICghQXJyYXkuaXNBcnJheShwYXJzZWQuYWN0aW9ucykpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoYCR7aWR9OiBhY3Rpb25zIG11c3QgYmUgYW4gYXJyYXlgKTtcblx0fVxuXHRjb25zdCBkZWNsYXJlZFN0cmVhbXMgPSBwYXJzZWQuc3RyZWFtcyA/PyBbXTtcblx0aWYgKCFBcnJheS5pc0FycmF5KGRlY2xhcmVkU3RyZWFtcykpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoYCR7aWR9OiBzdHJlYW1zIG11c3QgYmUgYW4gYXJyYXlgKTtcblx0fVxuXHQvLyBBY3Rpb25zIGFuZCBzdHJlYW1zIHNoYXJlIG9uZSBpZCBuYW1lc3BhY2UgKGRlY2lzaW9uLTI4KS5cblx0Y29uc3Qgc2VlbklkcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXHRjb25zdCBjbGFpbSA9IChvcGVyYXRpb25JZDogc3RyaW5nLCBsYWJlbDogc3RyaW5nKTogdm9pZCA9PiB7XG5cdFx0aWYgKHNlZW5JZHMuaGFzKG9wZXJhdGlvbklkKSkge1xuXHRcdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0XHRgJHtpZH06IGR1cGxpY2F0ZSAke2xhYmVsfSBpZCAke29wZXJhdGlvbklkfWAsXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRzZWVuSWRzLmFkZChvcGVyYXRpb25JZCk7XG5cdH07XG5cdGNvbnN0IGFjdGlvbnM6IEFjdGlvbkRlc2NyaXB0aW9uW10gPSBbXTtcblx0Zm9yIChjb25zdCBpdGVtIG9mIHBhcnNlZC5hY3Rpb25zKSB7XG5cdFx0Y29uc3QgYWN0aW9uID0gcGFyc2VBY3Rpb25EZXNjcmlwdGlvbihpdGVtKTtcblx0XHRjbGFpbShhY3Rpb24uaWQsIFwiYWN0aW9uXCIpO1xuXHRcdGFjdGlvbnMucHVzaChhY3Rpb24pO1xuXHR9XG5cdGNvbnN0IHN0cmVhbXM6IFN0cmVhbURlc2NyaXB0aW9uW10gPSBbXTtcblx0Zm9yIChjb25zdCBpdGVtIG9mIGRlY2xhcmVkU3RyZWFtcykge1xuXHRcdGNvbnN0IHN0cmVhbSA9IHBhcnNlU3RyZWFtRGVzY3JpcHRpb24oaXRlbSk7XG5cdFx0Y2xhaW0oc3RyZWFtLmlkLCBcInN0cmVhbVwiKTtcblx0XHRzdHJlYW1zLnB1c2goc3RyZWFtKTtcblx0fVxuXHRjb25zdCBieUlkID0gKFxuXHRcdGxlZnQ6IHsgcmVhZG9ubHkgaWQ6IHN0cmluZyB9LFxuXHRcdHJpZ2h0OiB7IHJlYWRvbmx5IGlkOiBzdHJpbmcgfSxcblx0KTogbnVtYmVyID0+IChsZWZ0LmlkIDwgcmlnaHQuaWQgPyAtMSA6IDEpO1xuXHRhY3Rpb25zLnNvcnQoYnlJZCk7XG5cdHN0cmVhbXMuc29ydChieUlkKTtcblx0cmV0dXJuIE9iamVjdC5mcmVlemUoe1xuXHRcdHNjaGVtYV92ZXJzaW9uOiBQTFVHSU5fREVTQ1JJUFRJT05fU0NIRU1BX1ZFUlNJT04sXG5cdFx0aWQsXG5cdFx0dGl0bGUsXG5cdFx0YWN0aW9uczogT2JqZWN0LmZyZWV6ZShhY3Rpb25zKSxcblx0XHRzdHJlYW1zOiBPYmplY3QuZnJlZXplKHN0cmVhbXMpLFxuXHR9KTtcbn1cbiIsCiAgICAiLyoqXG4gKiBWYWxpZGF0ZSBhIHZhbHVlIGFnYWluc3QgdGhlIHNjaGVtYSBzdWJzZXQgYGRlc2NyaWJlX3BsdWdpbmAgZW1pdHMuXG4gKlxuICogVGhpcyBpcyB0aGUgVHlwZVNjcmlwdCBzaWRlIG9mIGBxZ2lzX3Nkay5icmlkZ2Uuc2NoZW1hYDogdGhlIHNhbWUgY2xvc2VkXG4gKiBkaWFsZWN0IChvYmplY3RzIHdpdGggYHByb3BlcnRpZXNgL2ByZXF1aXJlZGAvYGFkZGl0aW9uYWxQcm9wZXJ0aWVzYCwgYXJyYXlzXG4gKiB3aXRoIGBpdGVtc2AsIHRoZSBmaXZlIEpTT04gcHJpbWl0aXZlcywgYGFueU9mYCBhbmQgYGVudW1gLCB0aGUgaW50ZWdlclxuICogYm91bmRzIGFuZCBgcGF0dGVybmApIGNoZWNrZWQgdGhlIHNhbWUgd2F5LCBzbyBgUWdpc1Nka2AgcmVmdXNlcyBvbiB0aGUgcGFnZVxuICogZXhhY3RseSB3aGF0IHRoZSBob3N0IHdvdWxkIHJlZnVzZSBhIG1lc3NhZ2UgbGF0ZXIuIEFueXRoaW5nIG91dHNpZGUgdGhlXG4gKiBkaWFsZWN0IGlzIGEgZGVjbGFyYXRpb24gZmF1bHQgYW5kIHRocm93czsgYSB2YWx1ZSB0aGF0IGRvZXMgbm90IGZpdCBpcyBhblxuICogaXNzdWUgdGhlIGNhbGxlciByZXBvcnRzLlxuICpcbiAqIFRoZSB0d28gYXN5bW1ldHJpZXMgb2YgZGVjaXNpb24tMjIgaG9sZCBoZXJlIHRvbzogYSByZXF1ZXN0IGlzIGNoZWNrZWRcbiAqIHN0cmljdGx5IChhbiB1bmtub3duIHByb3BlcnR5IGlzIGFuIGlzc3VlIHdoZW4gdGhlIHNjaGVtYSBjbG9zZXMgdGhlXG4gKiBvYmplY3QpLCBhIHJlc3VsdCBvciBhbiBldmVudCBsZW5pZW50bHkgKGBhbGxvd1Vua25vd25gKSwgc28gYSBob3N0IG1heSBhZGRcbiAqIGEgZmllbGQgd2l0aG91dCBicmVha2luZyBhbiBvbGRlciBwYWdlIHdoaWxlIGEgbWlzc2luZyBvciBtaXN0eXBlZCBmaWVsZCBpc1xuICogc3RpbGwgY2F1Z2h0LlxuICovXG5cbmltcG9ydCB7XG5cdFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yLFxuXHRRZ2lzU2RrVmFsaWRhdGlvbklzc3VlLFxuXHR0eXBlIFNlcmlhbGl6ZWRWYWxpZGF0aW9uSXNzdWUsXG59IGZyb20gXCIuL2RlY2xhcmF0aW9uc1wiO1xuaW1wb3J0IHsgUWdpc1Nka0Vycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBpc1BsYWluUmVjb3JkIH0gZnJvbSBcIi4vaW50ZXJuYWxcIjtcblxuLyoqIE9uZSBzY2hlbWEgb2YgdGhlIGRlY2xhcmVkIGRpYWxlY3QsIGFzIHRoZSBkZXNjcmlwdGlvbiBjYXJyaWVzIGl0LiAqL1xuZXhwb3J0IHR5cGUgRGVjbGFyZWRTY2hlbWEgPSBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj47XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgdmFsaWRhdGVBZ2FpbnN0U2NoZW1hfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmFsaWRhdGVPcHRpb25zIHtcblx0LyoqIElnbm9yZSBwcm9wZXJ0aWVzIHRoZSBzY2hlbWEgZG9lcyBub3QgbmFtZSAocmVzdWx0cyBhbmQgZXZlbnRzKS4gKi9cblx0cmVhZG9ubHkgYWxsb3dVbmtub3duPzogYm9vbGVhbjtcblx0LyoqIFdoZXJlIHRoZSB2YWx1ZSBzaXRzLCBwcmVmaXhlZCB0byBldmVyeSBpc3N1ZSdzIHBhdGguICovXG5cdHJlYWRvbmx5IHBhdGg/OiByZWFkb25seSAoc3RyaW5nIHwgbnVtYmVyKVtdO1xufVxuXG4vKiogV2hpY2ggc2lkZSBvZiBhIGNhbGwgYSBjb250cmFjdCBpc3N1ZSBiZWxvbmdzIHRvLiAqL1xuZXhwb3J0IHR5cGUgQ29udHJhY3REaXJlY3Rpb24gPSBcInJlcXVlc3RcIiB8IFwicmVzdWx0XCIgfCBcImV2ZW50XCI7XG5cbi8qKiBUaGUgSlNPTiBmb3JtIG9mIHtAbGluayBRZ2lzU2RrQ29udHJhY3RFcnJvcn0uICovXG5leHBvcnQgaW50ZXJmYWNlIFNlcmlhbGl6ZWRDb250cmFjdEVycm9yIHtcblx0cmVhZG9ubHkgY29kZTogc3RyaW5nO1xuXHRyZWFkb25seSBvcGVyYXRpb246IHN0cmluZztcblx0cmVhZG9ubHkgZGlyZWN0aW9uOiBDb250cmFjdERpcmVjdGlvbjtcblx0cmVhZG9ubHkgaXNzdWVzOiBTZXJpYWxpemVkVmFsaWRhdGlvbklzc3VlW107XG59XG5cbi8qKlxuICogQW4gYXJndW1lbnQsIGEgcmVwbHkgb3IgYW4gZXZlbnQgZG9lcyBub3QgbWF0Y2ggdGhlIGRlY2xhcmVkIGNvbnRyYWN0LlxuICpcbiAqIFRoZSBjb2RlIGlzIHRoZSBvbmUgYm90aCBsYW5ndWFnZXMgdXNlIGZvciB0aGlzIGNhdGVnb3J5LCBzbyBhIHBhZ2UgdGhhdFxuICogYWxyZWFkeSBtYXRjaGVzIGBjb250cmFjdF92YWxpZGF0aW9uX2ZhaWxlZGAgbmVlZHMgbm8gc2Vjb25kIGJyYW5jaC5cbiAqL1xuZXhwb3J0IGNsYXNzIFFnaXNTZGtDb250cmFjdEVycm9yIGV4dGVuZHMgUWdpc1Nka0Vycm9yIHtcblx0cHVibGljIHJlYWRvbmx5IG9wZXJhdGlvbjogc3RyaW5nO1xuXHRwdWJsaWMgcmVhZG9ubHkgZGlyZWN0aW9uOiBDb250cmFjdERpcmVjdGlvbjtcblx0cHVibGljIHJlYWRvbmx5IGlzc3VlczogcmVhZG9ubHkgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZVtdO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3Rvcihcblx0XHRvcGVyYXRpb246IHN0cmluZyxcblx0XHRkaXJlY3Rpb246IENvbnRyYWN0RGlyZWN0aW9uLFxuXHRcdGlzc3VlczogcmVhZG9ubHkgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZVtdLFxuXHQpIHtcblx0XHRjb25zdCBkZXRhaWwgPSBpc3N1ZXNbMF0gPT09IHVuZGVmaW5lZCA/IFwiXCIgOiBgOiAke2Rlc2NyaWJlKGlzc3Vlc1swXSl9YDtcblx0XHRzdXBlcihcblx0XHRcdGAke29wZXJhdGlvbn06IHRoZSAke2RpcmVjdGlvbn0gZG9lcyBub3QgbWF0Y2ggdGhlIGRlY2xhcmVkIGNvbnRyYWN0JHtkZXRhaWx9YCxcblx0XHRcdFwiY29udHJhY3RfdmFsaWRhdGlvbl9mYWlsZWRcIixcblx0XHQpO1xuXHRcdHRoaXMub3BlcmF0aW9uID0gb3BlcmF0aW9uO1xuXHRcdHRoaXMuZGlyZWN0aW9uID0gZGlyZWN0aW9uO1xuXHRcdHRoaXMuaXNzdWVzID0gT2JqZWN0LmZyZWV6ZShbLi4uaXNzdWVzXSk7XG5cdH1cblxuXHRwdWJsaWMgdG9KU09OKCk6IFNlcmlhbGl6ZWRDb250cmFjdEVycm9yIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0Y29kZTogdGhpcy5jb2RlLFxuXHRcdFx0b3BlcmF0aW9uOiB0aGlzLm9wZXJhdGlvbixcblx0XHRcdGRpcmVjdGlvbjogdGhpcy5kaXJlY3Rpb24sXG5cdFx0XHRpc3N1ZXM6IHRoaXMuaXNzdWVzLm1hcCgoaXNzdWUpID0+IGlzc3VlLnRvSlNPTigpKSxcblx0XHR9O1xuXHR9XG59XG5cbmZ1bmN0aW9uIGRlc2NyaWJlKGlzc3VlOiBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKTogc3RyaW5nIHtcblx0Y29uc3Qgd2hlcmUgPSBpc3N1ZS5wYXRoLmxlbmd0aCA9PT0gMCA/IFwidmFsdWVcIiA6IGlzc3VlLnBhdGguam9pbihcIi5cIik7XG5cdHJldHVybiBgJHt3aGVyZX0gJHtpc3N1ZS5jb2RlfWA7XG59XG5cbmNvbnN0IFBSSU1JVElWRVM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KFtcblx0XCJzdHJpbmdcIixcblx0XCJib29sZWFuXCIsXG5cdFwiaW50ZWdlclwiLFxuXHRcIm51bWJlclwiLFxuXHRcIm51bGxcIixcblx0XCJhcnJheVwiLFxuXHRcIm9iamVjdFwiLFxuXSk7XG5cbmNvbnN0IEtOT1dOX0tFWVdPUkRTOiBSZWFkb25seVNldDxzdHJpbmc+ID0gbmV3IFNldChbXG5cdFwidHlwZVwiLFxuXHRcInByb3BlcnRpZXNcIixcblx0XCJyZXF1aXJlZFwiLFxuXHRcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCIsXG5cdFwiaXRlbXNcIixcblx0XCJhbnlPZlwiLFxuXHRcImVudW1cIixcblx0XCJtaW5pbXVtXCIsXG5cdFwibWF4aW11bVwiLFxuXHRcInBhdHRlcm5cIixcblx0XCJ0aXRsZVwiLFxuXHRcImRlc2NyaXB0aW9uXCIsXG5cdC8vIFRoZSBpbnB1dCBraW5kIGEgZGVzY3JpYmVyIGFubm90YXRlZCAoYHsga2luZDogXCJsYXllclwiIH1gKTsgZm9ybXMgYW5kXG5cdC8vIHBhZ2VzIHJlYWQgaXQsIHZhbGlkYXRpb24gcmVhZHMgcGFzdCBpdC5cblx0XCJ4LXFnaXMtc2RrXCIsXG5dKTtcblxudHlwZSBQYXRoID0gcmVhZG9ubHkgKHN0cmluZyB8IG51bWJlcilbXTtcblxuLyoqXG4gKiBSZXR1cm4gZXZlcnkgaXNzdWUgYHZhbHVlYCBoYXMgYWdhaW5zdCBgc2NoZW1hYDsgYW4gZW1wdHkgYXJyYXkgaXMgYSBtYXRjaC5cbiAqXG4gKiBUaHJvd3Mge0BsaW5rIFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yfSB3aGVuIGBzY2hlbWFgIGxlYXZlcyB0aGUgZGVjbGFyZWRcbiAqIGRpYWxlY3QsIGJlY2F1c2UgdGhhdCBpcyBhIGZhdWx0IGluIHRoZSBkZWNsYXJhdGlvbiwgbmV2ZXIgaW4gdGhlIHZhbHVlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVBZ2FpbnN0U2NoZW1hKFxuXHR2YWx1ZTogdW5rbm93bixcblx0c2NoZW1hOiBEZWNsYXJlZFNjaGVtYSxcblx0b3B0aW9uczogVmFsaWRhdGVPcHRpb25zID0ge30sXG4pOiBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlW10ge1xuXHRjb25zdCBpc3N1ZXM6IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWVbXSA9IFtdO1xuXHRjaGVjayhcblx0XHR2YWx1ZSxcblx0XHRzY2hlbWEsXG5cdFx0b3B0aW9ucy5wYXRoID8/IFtdLFxuXHRcdG9wdGlvbnMuYWxsb3dVbmtub3duID09PSB0cnVlLFxuXHRcdGlzc3Vlcyxcblx0KTtcblx0cmV0dXJuIGlzc3Vlcztcbn1cblxuZnVuY3Rpb24gY2hlY2soXG5cdHZhbHVlOiB1bmtub3duLFxuXHRzY2hlbWE6IHVua25vd24sXG5cdHBhdGg6IFBhdGgsXG5cdGFsbG93VW5rbm93bjogYm9vbGVhbixcblx0aXNzdWVzOiBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlW10sXG4pOiB2b2lkIHtcblx0aWYgKCFpc1BsYWluUmVjb3JkKHNjaGVtYSkpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRgJHt3aGVyZShwYXRoKX06IGEgc2NoZW1hIG11c3QgYmUgYW4gb2JqZWN0YCxcblx0XHQpO1xuXHR9XG5cdGNvbnN0IHVua25vd24gPSBPYmplY3Qua2V5cyhzY2hlbWEpLmZpbHRlcigoa2V5KSA9PiAhS05PV05fS0VZV09SRFMuaGFzKGtleSkpO1xuXHRpZiAodW5rbm93bi5sZW5ndGggPiAwKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0YCR7d2hlcmUocGF0aCl9OiB1bnN1cHBvcnRlZCBzY2hlbWEga2V5d29yZChzKSAke3Vua25vd24uc29ydCgpLmpvaW4oXCIsIFwiKX1gLFxuXHRcdCk7XG5cdH1cblx0aWYgKFwiYW55T2ZcIiBpbiBzY2hlbWEpIHtcblx0XHRjb25zdCBicmFuY2hlcyA9IHNjaGVtYS5hbnlPZjtcblx0XHRpZiAoIUFycmF5LmlzQXJyYXkoYnJhbmNoZXMpIHx8IGJyYW5jaGVzLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0XHRgJHt3aGVyZShwYXRoKX06IGFueU9mIG11c3QgYmUgYSBub25lbXB0eSBsaXN0YCxcblx0XHRcdCk7XG5cdFx0fVxuXHRcdGZvciAoY29uc3QgYnJhbmNoIG9mIGJyYW5jaGVzKSB7XG5cdFx0XHRjb25zdCBhdHRlbXB0OiBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlW10gPSBbXTtcblx0XHRcdGNoZWNrKHZhbHVlLCBicmFuY2gsIHBhdGgsIGFsbG93VW5rbm93biwgYXR0ZW1wdCk7XG5cdFx0XHRpZiAoYXR0ZW1wdC5sZW5ndGggPT09IDApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpc3N1ZXMucHVzaChuZXcgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZShbLi4ucGF0aF0sIFwiYW55X29mXCIpKTtcblx0XHRyZXR1cm47XG5cdH1cblx0aWYgKFwiZW51bVwiIGluIHNjaGVtYSkge1xuXHRcdGNvbnN0IGNob2ljZXMgPSBzY2hlbWEuZW51bTtcblx0XHRpZiAoIUFycmF5LmlzQXJyYXkoY2hvaWNlcykpIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihgJHt3aGVyZShwYXRoKX06IGVudW0gbXVzdCBiZSBhIGxpc3RgKTtcblx0XHR9XG5cdFx0aWYgKCFjaG9pY2VzLnNvbWUoKGNob2ljZSkgPT4gc2FtZUpzb24oY2hvaWNlLCB2YWx1ZSkpKSB7XG5cdFx0XHRpc3N1ZXMucHVzaChuZXcgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZShbLi4ucGF0aF0sIFwiZW51bVwiKSk7XG5cdFx0fVxuXHRcdHJldHVybjtcblx0fVxuXHRjb25zdCBkZWNsYXJlZCA9IHNjaGVtYS50eXBlO1xuXHRpZiAoZGVjbGFyZWQgPT09IHVuZGVmaW5lZCkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke3doZXJlKHBhdGgpfTogYSBzY2hlbWEgbmVlZHMgYSB0eXBlLCBhbnlPZiBvciBlbnVtYCxcblx0XHQpO1xuXHR9XG5cdGlmICh0eXBlb2YgZGVjbGFyZWQgIT09IFwic3RyaW5nXCIgfHwgIVBSSU1JVElWRVMuaGFzKGRlY2xhcmVkKSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke3doZXJlKHBhdGgpfTogdW5zdXBwb3J0ZWQgdHlwZSAke0pTT04uc3RyaW5naWZ5KGRlY2xhcmVkKX1gLFxuXHRcdCk7XG5cdH1cblx0c3dpdGNoIChkZWNsYXJlZCkge1xuXHRcdGNhc2UgXCJzdHJpbmdcIjpcblx0XHRcdGNoZWNrU3RyaW5nKHZhbHVlLCBzY2hlbWEsIHBhdGgsIGlzc3Vlcyk7XG5cdFx0XHRyZXR1cm47XG5cdFx0Y2FzZSBcImJvb2xlYW5cIjpcblx0XHRcdGlmICh0eXBlb2YgdmFsdWUgIT09IFwiYm9vbGVhblwiKSB7XG5cdFx0XHRcdGlzc3Vlcy5wdXNoKG5ldyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKFsuLi5wYXRoXSwgXCJ0eXBlXCIpKTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHRjYXNlIFwiaW50ZWdlclwiOlxuXHRcdFx0aWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJudW1iZXJcIiB8fCAhTnVtYmVyLmlzSW50ZWdlcih2YWx1ZSkpIHtcblx0XHRcdFx0aXNzdWVzLnB1c2gobmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGhdLCBcInR5cGVcIikpO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHRjaGVja0JvdW5kcyh2YWx1ZSwgc2NoZW1hLCBwYXRoLCBpc3N1ZXMpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdGNhc2UgXCJudW1iZXJcIjpcblx0XHRcdGlmICh0eXBlb2YgdmFsdWUgIT09IFwibnVtYmVyXCIpIHtcblx0XHRcdFx0aXNzdWVzLnB1c2gobmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGhdLCBcInR5cGVcIikpO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHRpZiAoIU51bWJlci5pc0Zpbml0ZSh2YWx1ZSkpIHtcblx0XHRcdFx0aXNzdWVzLnB1c2gobmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGhdLCBcIm5vdF9maW5pdGVcIikpO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHRjaGVja0JvdW5kcyh2YWx1ZSwgc2NoZW1hLCBwYXRoLCBpc3N1ZXMpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdGNhc2UgXCJudWxsXCI6XG5cdFx0XHRpZiAodmFsdWUgIT09IG51bGwpIHtcblx0XHRcdFx0aXNzdWVzLnB1c2gobmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGhdLCBcInR5cGVcIikpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuO1xuXHRcdGNhc2UgXCJhcnJheVwiOlxuXHRcdFx0Y2hlY2tBcnJheSh2YWx1ZSwgc2NoZW1hLCBwYXRoLCBhbGxvd1Vua25vd24sIGlzc3Vlcyk7XG5cdFx0XHRyZXR1cm47XG5cdFx0ZGVmYXVsdDpcblx0XHRcdGNoZWNrT2JqZWN0KHZhbHVlLCBzY2hlbWEsIHBhdGgsIGFsbG93VW5rbm93biwgaXNzdWVzKTtcblx0fVxufVxuXG5mdW5jdGlvbiBjaGVja1N0cmluZyhcblx0dmFsdWU6IHVua25vd24sXG5cdHNjaGVtYTogRGVjbGFyZWRTY2hlbWEsXG5cdHBhdGg6IFBhdGgsXG5cdGlzc3VlczogUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZVtdLFxuKTogdm9pZCB7XG5cdGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIpIHtcblx0XHRpc3N1ZXMucHVzaChuZXcgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZShbLi4ucGF0aF0sIFwidHlwZVwiKSk7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGNvbnN0IHBhdHRlcm4gPSBzY2hlbWEucGF0dGVybjtcblx0aWYgKHBhdHRlcm4gPT09IHVuZGVmaW5lZCB8fCBwYXR0ZXJuID09PSBudWxsKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGlmICh0eXBlb2YgcGF0dGVybiAhPT0gXCJzdHJpbmdcIikge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke3doZXJlKHBhdGgpfTogcGF0dGVybiBtdXN0IGJlIGEgc3RyaW5nYCxcblx0XHQpO1xuXHR9XG5cdGxldCBleHByZXNzaW9uOiBSZWdFeHA7XG5cdHRyeSB7XG5cdFx0Ly8gUHl0aG9uJ3MgcmUuZnVsbG1hdGNoOiB0aGUgd2hvbGUgc3RyaW5nLCB3aXRoIHRoZSB1bmljb2RlIGZsYWcgdGhlXG5cdFx0Ly8gZGVjbGFyYXRpb24gc2lkZSBhbHJlYWR5IGFzc3VtZXMuXG5cdFx0ZXhwcmVzc2lvbiA9IG5ldyBSZWdFeHAoYF4oPzoke3BhdHRlcm59KSRgLCBcInVcIik7XG5cdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0YCR7d2hlcmUocGF0aCl9OiBwYXR0ZXJuICR7SlNPTi5zdHJpbmdpZnkocGF0dGVybil9IGlzIHVudXNhYmxlOiAke1N0cmluZyhlcnJvcil9YCxcblx0XHQpO1xuXHR9XG5cdGlmICghZXhwcmVzc2lvbi50ZXN0KHZhbHVlKSkge1xuXHRcdGlzc3Vlcy5wdXNoKG5ldyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKFsuLi5wYXRoXSwgXCJwYXR0ZXJuXCIpKTtcblx0fVxufVxuXG5mdW5jdGlvbiBjaGVja0JvdW5kcyhcblx0dmFsdWU6IG51bWJlcixcblx0c2NoZW1hOiBEZWNsYXJlZFNjaGVtYSxcblx0cGF0aDogUGF0aCxcblx0aXNzdWVzOiBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlW10sXG4pOiB2b2lkIHtcblx0Y29uc3QgbWluaW11bSA9IHNjaGVtYS5taW5pbXVtO1xuXHRpZiAodHlwZW9mIG1pbmltdW0gPT09IFwibnVtYmVyXCIgJiYgdmFsdWUgPCBtaW5pbXVtKSB7XG5cdFx0aXNzdWVzLnB1c2gobmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGhdLCBcIm1pbmltdW1cIikpO1xuXHR9XG5cdGNvbnN0IG1heGltdW0gPSBzY2hlbWEubWF4aW11bTtcblx0aWYgKHR5cGVvZiBtYXhpbXVtID09PSBcIm51bWJlclwiICYmIHZhbHVlID4gbWF4aW11bSkge1xuXHRcdGlzc3Vlcy5wdXNoKG5ldyBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlKFsuLi5wYXRoXSwgXCJtYXhpbXVtXCIpKTtcblx0fVxufVxuXG5mdW5jdGlvbiBjaGVja0FycmF5KFxuXHR2YWx1ZTogdW5rbm93bixcblx0c2NoZW1hOiBEZWNsYXJlZFNjaGVtYSxcblx0cGF0aDogUGF0aCxcblx0YWxsb3dVbmtub3duOiBib29sZWFuLFxuXHRpc3N1ZXM6IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWVbXSxcbik6IHZvaWQge1xuXHRpZiAoIUFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG5cdFx0aXNzdWVzLnB1c2gobmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGhdLCBcInR5cGVcIikpO1xuXHRcdHJldHVybjtcblx0fVxuXHRjb25zdCBpdGVtcyA9IHNjaGVtYS5pdGVtcztcblx0aWYgKGl0ZW1zID09PSB1bmRlZmluZWQgfHwgaXRlbXMgPT09IG51bGwpIHtcblx0XHRyZXR1cm47XG5cdH1cblx0dmFsdWUuZm9yRWFjaCgoaXRlbSwgaW5kZXgpID0+IHtcblx0XHRjaGVjayhpdGVtLCBpdGVtcywgWy4uLnBhdGgsIGluZGV4XSwgYWxsb3dVbmtub3duLCBpc3N1ZXMpO1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gY2hlY2tPYmplY3QoXG5cdHZhbHVlOiB1bmtub3duLFxuXHRzY2hlbWE6IERlY2xhcmVkU2NoZW1hLFxuXHRwYXRoOiBQYXRoLFxuXHRhbGxvd1Vua25vd246IGJvb2xlYW4sXG5cdGlzc3VlczogUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZVtdLFxuKTogdm9pZCB7XG5cdGlmICghaXNQbGFpblJlY29yZCh2YWx1ZSkpIHtcblx0XHRpc3N1ZXMucHVzaChuZXcgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZShbLi4ucGF0aF0sIFwidHlwZVwiKSk7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGNvbnN0IHByb3BlcnRpZXMgPSBzY2hlbWEucHJvcGVydGllcyA/PyB7fTtcblx0aWYgKCFpc1BsYWluUmVjb3JkKHByb3BlcnRpZXMpKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0YCR7d2hlcmUocGF0aCl9OiBwcm9wZXJ0aWVzIG11c3QgYmUgYW4gb2JqZWN0YCxcblx0XHQpO1xuXHR9XG5cdGNvbnN0IHJlcXVpcmVkID0gc2NoZW1hLnJlcXVpcmVkID8/IFtdO1xuXHRpZiAoIUFycmF5LmlzQXJyYXkocmVxdWlyZWQpKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0YCR7d2hlcmUocGF0aCl9OiByZXF1aXJlZCBtdXN0IGJlIGEgbGlzdGAsXG5cdFx0KTtcblx0fVxuXHRmb3IgKGNvbnN0IGtleSBvZiByZXF1aXJlZCkge1xuXHRcdGlmICh0eXBlb2Yga2V5ID09PSBcInN0cmluZ1wiICYmICEoa2V5IGluIHZhbHVlKSkge1xuXHRcdFx0aXNzdWVzLnB1c2gobmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGgsIGtleV0sIFwicmVxdWlyZWRcIikpO1xuXHRcdH1cblx0fVxuXHRjb25zdCBzdHJpY3QgPSBzY2hlbWEuYWRkaXRpb25hbFByb3BlcnRpZXMgPT09IGZhbHNlICYmICFhbGxvd1Vua25vd247XG5cdGZvciAoY29uc3QgW2tleSwgaXRlbV0gb2YgT2JqZWN0LmVudHJpZXModmFsdWUpKSB7XG5cdFx0aWYgKE9iamVjdC5oYXNPd24ocHJvcGVydGllcywga2V5KSkge1xuXHRcdFx0Y2hlY2soaXRlbSwgcHJvcGVydGllc1trZXldLCBbLi4ucGF0aCwga2V5XSwgYWxsb3dVbmtub3duLCBpc3N1ZXMpO1xuXHRcdH0gZWxzZSBpZiAoc3RyaWN0KSB7XG5cdFx0XHRpc3N1ZXMucHVzaChcblx0XHRcdFx0bmV3IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWUoWy4uLnBhdGgsIGtleV0sIFwidW5rbm93bl9wcm9wZXJ0eVwiKSxcblx0XHRcdCk7XG5cdFx0fVxuXHR9XG59XG5cbi8qKiBKU09OIGVxdWFsaXR5OiBgdHJ1ZWAgaXMgbm90IGAxYCwgYW5kIGAxYCBpcyBgMS4wYC4gKi9cbmZ1bmN0aW9uIHNhbWVKc29uKGE6IHVua25vd24sIGI6IHVua25vd24pOiBib29sZWFuIHtcblx0aWYgKGEgPT09IGIpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXHRpZiAodHlwZW9mIGEgIT09IHR5cGVvZiBiIHx8IGEgPT09IG51bGwgfHwgYiA9PT0gbnVsbCkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRpZiAoQXJyYXkuaXNBcnJheShhKSkge1xuXHRcdHJldHVybiAoXG5cdFx0XHRBcnJheS5pc0FycmF5KGIpICYmXG5cdFx0XHRhLmxlbmd0aCA9PT0gYi5sZW5ndGggJiZcblx0XHRcdGEuZXZlcnkoKGl0ZW0sIGluZGV4KSA9PiBzYW1lSnNvbihpdGVtLCBiW2luZGV4XSkpXG5cdFx0KTtcblx0fVxuXHRpZiAoaXNQbGFpblJlY29yZChhKSAmJiBpc1BsYWluUmVjb3JkKGIpKSB7XG5cdFx0Y29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGEpO1xuXHRcdHJldHVybiAoXG5cdFx0XHRrZXlzLmxlbmd0aCA9PT0gT2JqZWN0LmtleXMoYikubGVuZ3RoICYmXG5cdFx0XHRrZXlzLmV2ZXJ5KChrZXkpID0+IE9iamVjdC5oYXNPd24oYiwga2V5KSAmJiBzYW1lSnNvbihhW2tleV0sIGJba2V5XSkpXG5cdFx0KTtcblx0fVxuXHRyZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHdoZXJlKHBhdGg6IFBhdGgpOiBzdHJpbmcge1xuXHRyZXR1cm4gcGF0aC5sZW5ndGggPT09IDAgPyBcInZhbHVlXCIgOiBwYXRoLmpvaW4oXCIuXCIpO1xufVxuIiwKICAgICIvKipcbiAqIFRoZSBmcmFtZXdvcmstZnJlZSBzdG9yZSBjb3JlIChkZWNpc2lvbi00NykuXG4gKlxuICogRXZlcnkgYWRhcHRlciAtIGAuL3JlYWN0YCwgYC4vdnVlYCwgYC4vc3ZlbHRlYCwgb3IgYSB2YW5pbGxhIHBhZ2Ugd2l0aCBub1xuICogYWRhcHRlciBhdCBhbGwgLSBkcml2ZXMgdGhlIHNhbWUgZm91ciBzdG9yZXMuIEEgc3RvcmUgaXMgYSB2YWx1ZSBwbHVzIHRoZVxuICogU3ZlbHRlIHN0b3JlIGNvbnRyYWN0OiBgc3Vic2NyaWJlKGxpc3RlbmVyKWAgY2FsbHMgdGhlIGxpc3RlbmVyIGF0IG9uY2Ugd2l0aFxuICogdGhlIGN1cnJlbnQgc25hcHNob3QgYW5kIGFnYWluIGFmdGVyIGV2ZXJ5IGNoYW5nZSwgYW5kIHJldHVybnMgdGhlXG4gKiB1bnN1YnNjcmliZSBmdW5jdGlvbjsgYGdldFNuYXBzaG90KClgIGlzIHRoZSBzYW1lIHZhbHVlIHdpdGhvdXQgYVxuICogc3Vic2NyaXB0aW9uLCBrZXB0IHJlZmVyZW50aWFsbHkgc3RhYmxlIGJldHdlZW4gY2hhbmdlcyBzbyBSZWFjdCdzXG4gKiBgdXNlU3luY0V4dGVybmFsU3RvcmVgIGNhbiBjb21wYXJlIGl0LiBOb3RoaW5nIGluIHRoaXMgbW9kdWxlIGltcG9ydHMgYVxuICogZnJhbWV3b3JrLCB0b3VjaGVzIHRoZSBET00gb3IgcnVucyBhdCBpbXBvcnQgdGltZS5cbiAqXG4gKiAtIHtAbGluayBPcGVyYXRpb25TdG9yZX0gcnVucyBvbmUgZ2VuZXJhdGVkIG9wZXJhdGlvbjogdGhlIGxhdGVzdCBydW4gd2lucyxcbiAqICAgYW4gYWJvcnRlZCBjYWxsIGlzIHN3YWxsb3dlZCwgYW5kIGBydW5gIG5ldmVyIHJlamVjdHMgaW50byBhIGhhbmRsZXIuXG4gKiAtIHtAbGluayBTdHJlYW1TdG9yZX0gaG9sZHMgb25lIGdlbmVyYXRlZCBzdHJlYW0gb3BlbiB3aGlsZSBpdHMgaW5wdXQgaXNcbiAqICAgbm9uLW51bGwsIHJlb3BlbmluZyBvbmx5IHdoZW4gdGhlIGlucHV0J3MgKmNvbnRlbnQqIGNoYW5nZXMuXG4gKiAtIHtAbGluayBGb3JtU3RvcmV9IGJpbmRzIHRoZSB2YWx1ZXMgb2Ygb25lIGRlY2xhcmVkIGFjdGlvbidzIHJlcXVlc3QgdG8gaXRzXG4gKiAgIHNjaGVtYTogZmllbGRzIGZyb20gdGhlIGRlY2xhcmF0aW9uLCBpc3N1ZXMgZnJvbSB0aGUgdmFsaWRhdG9yLCBzdWJtaXNzaW9uXG4gKiAgIHRocm91Z2ggYW4gb3BlcmF0aW9uIHN0b3JlLlxuICogLSB7QGxpbmsgSG9zdFF1ZXJ5U3RvcmV9IHJlYWRzIHRoZSBjdXJhdGVkIGhvc3Qgc3VyZmFjZSBhbmQgc2F5cyBgcmVmdXNlZGBcbiAqICAgLSBiZWZvcmUgYW55IGNhbGwgbGVhdmVzIHRoZSBwYWdlIC0gd2hlbiB0aGUgdmlldyB3YXMgbm90IGdyYW50ZWQgdGhlXG4gKiAgIG9wZXJhdGlvbiBpdCBuZWVkcy5cbiAqL1xuXG5pbXBvcnQgeyBRZ2lzU2RrQnJpZGdlQWJvcnRlZEVycm9yIH0gZnJvbSBcIi4vYnJpZGdlXCI7XG5pbXBvcnQgdHlwZSB7IEFjdGlvbkRlc2NyaXB0aW9uLCBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlIH0gZnJvbSBcIi4vZGVjbGFyYXRpb25zXCI7XG5pbXBvcnQgeyBRZ2lzU2RrRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHtcblx0SG9zdE9wZXJhdGlvbklkLFxuXHRMYXllclBhZ2UsXG5cdFZlY3RvckxheWVySW5mbyxcbn0gZnJvbSBcIi4vZ2VuZXJhdGVkL2hvc3RcIjtcbmltcG9ydCB7IGlzUGxhaW5SZWNvcmQgfSBmcm9tIFwiLi9pbnRlcm5hbFwiO1xuaW1wb3J0IHR5cGUgeyBRZ2lzU2RrQ29yZSwgUWdpc1Nka0hvc3QgfSBmcm9tIFwiLi9xZ2lzLXNka1wiO1xuaW1wb3J0IHR5cGUgeyBPcGVyYXRpb25TaGFwZSB9IGZyb20gXCIuL3NjaGVtYVwiO1xuaW1wb3J0IHsgdHlwZSBEZWNsYXJlZFNjaGVtYSwgdmFsaWRhdGVBZ2FpbnN0U2NoZW1hIH0gZnJvbSBcIi4vdmFsaWRhdGVcIjtcblxuLyoqIEEgc3RvcmUgd2FzIGJ1aWx0IG9yIGRyaXZlbiBvdXRzaWRlIHRoZSBzaGFwZSBpdCBuZWVkcy4gKi9cbmV4cG9ydCBjbGFzcyBRZ2lzU2RrU3RvcmVFcnJvciBleHRlbmRzIFFnaXNTZGtFcnJvciB7XG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcblx0XHRzdXBlcihtZXNzYWdlLCBcInN0b3JlX2JpbmRpbmdcIik7XG5cdH1cbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBUaGUgY29udHJhY3Rcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogV2hhdCBhIGxpc3RlbmVyIHJlY2VpdmVzOiB0aGUgd2hvbGUgc25hcHNob3QsIG5ldmVyIGEgZGlmZi4gKi9cbmV4cG9ydCB0eXBlIFN0b3JlTGlzdGVuZXI8VD4gPSAoc25hcHNob3Q6IFQpID0+IHZvaWQ7XG5cbi8qKlxuICogVGhlIGNvbnRyYWN0IGV2ZXJ5IHN0b3JlIGhvbm91cnMsIGFuZCB0aGUgb25lIGB1c2VTeW5jRXh0ZXJuYWxTdG9yZWAsXG4gKiBWdWUncyBgc2hhbGxvd1JlZmAgd2lyaW5nIGFuZCBTdmVsdGUncyBgJHN0b3JlYCBhbGwgcmVhZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdG9yZTxUPiB7XG5cdC8qKiBUaGUgY3VycmVudCB2YWx1ZTsgdGhlIHNhbWUgb2JqZWN0IHVudGlsIHRoZSBuZXh0IGNoYW5nZS4gQm91bmQuICovXG5cdHJlYWRvbmx5IGdldFNuYXBzaG90OiAoKSA9PiBUO1xuXHQvKipcblx0ICogQ2FsbCBgbGlzdGVuZXJgIG5vdyBhbmQgYWZ0ZXIgZXZlcnkgY2hhbmdlOyB0aGUgcmV0dXJuZWQgZnVuY3Rpb25cblx0ICogc3RvcHMgdGhlIGNhbGxzLiBCb3VuZC4gU3ZlbHRlIHBhc3NlcyBhIHNlY29uZCBgaW52YWxpZGF0ZWAgYXJndW1lbnQsXG5cdCAqIHdoaWNoIGlzIGlnbm9yZWQuXG5cdCAqL1xuXHRyZWFkb25seSBzdWJzY3JpYmU6IChsaXN0ZW5lcjogU3RvcmVMaXN0ZW5lcjxUPikgPT4gKCkgPT4gdm9pZDtcbn1cblxuYWJzdHJhY3QgY2xhc3MgQmFzZVN0b3JlPFQ+IGltcGxlbWVudHMgU3RvcmU8VD4ge1xuXHRwcml2YXRlIHNuYXBzaG90OiBUO1xuXHRwcml2YXRlIHJlYWRvbmx5IGxpc3RlbmVycyA9IG5ldyBTZXQ8U3RvcmVMaXN0ZW5lcjxUPj4oKTtcblxuXHRwcm90ZWN0ZWQgY29uc3RydWN0b3IoaW5pdGlhbDogVCkge1xuXHRcdHRoaXMuc25hcHNob3QgPSBpbml0aWFsO1xuXHR9XG5cblx0Ly8gQm91bmQsIHNvIGB1c2VTeW5jRXh0ZXJuYWxTdG9yZShzdG9yZS5zdWJzY3JpYmUsIHN0b3JlLmdldFNuYXBzaG90KWBcblx0Ly8gbmVlZHMgbm8gd3JhcHBlci5cblx0cHVibGljIHJlYWRvbmx5IGdldFNuYXBzaG90ID0gKCk6IFQgPT4gdGhpcy5zbmFwc2hvdDtcblxuXHRwdWJsaWMgcmVhZG9ubHkgc3Vic2NyaWJlID0gKGxpc3RlbmVyOiBTdG9yZUxpc3RlbmVyPFQ+KTogKCgpID0+IHZvaWQpID0+IHtcblx0XHR0aGlzLmxpc3RlbmVycy5hZGQobGlzdGVuZXIpO1xuXHRcdGxpc3RlbmVyKHRoaXMuc25hcHNob3QpO1xuXHRcdHJldHVybiAoKSA9PiB7XG5cdFx0XHR0aGlzLmxpc3RlbmVycy5kZWxldGUobGlzdGVuZXIpO1xuXHRcdH07XG5cdH07XG5cblx0cHJvdGVjdGVkIHB1Ymxpc2gobmV4dDogVCk6IHZvaWQge1xuXHRcdGlmIChPYmplY3QuaXMobmV4dCwgdGhpcy5zbmFwc2hvdCkpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy5zbmFwc2hvdCA9IG5leHQ7XG5cdFx0Zm9yIChjb25zdCBsaXN0ZW5lciBvZiBbLi4udGhpcy5saXN0ZW5lcnNdKSB7XG5cdFx0XHRsaXN0ZW5lcihuZXh0KTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gYXNFcnJvcihlcnJvcjogdW5rbm93bik6IEVycm9yIHtcblx0cmV0dXJuIGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBPcGVyYXRpb25TdG9yZVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKiBXaGVyZSBvbmUgaW52b2NhdGlvbiBzdGFuZHMuICovXG5leHBvcnQgdHlwZSBPcGVyYXRpb25TdGF0ZTxSPiA9XG5cdHwgeyByZWFkb25seSBzdGF0dXM6IFwiaWRsZVwiIH1cblx0fCB7IHJlYWRvbmx5IHN0YXR1czogXCJwZW5kaW5nXCIgfVxuXHR8IHsgcmVhZG9ubHkgc3RhdHVzOiBcIm9rXCI7IHJlYWRvbmx5IHZhbHVlOiBSIH1cblx0fCB7IHJlYWRvbmx5IHN0YXR1czogXCJlcnJvclwiOyByZWFkb25seSBlcnJvcjogRXJyb3IgfTtcblxuLyoqIEFuIG9wZXJhdGlvbiBtZW1iZXIgb2YgYSBnZW5lcmF0ZWQgbWFwOiBpbnB1dCwgb3B0aW9uYWwgc2lnbmFsLCBwcm9taXNlLiAqL1xuZXhwb3J0IHR5cGUgT3BlcmF0aW9uPEksIFI+ID0gKFxuXHRpbnB1dDogSSxcblx0b3B0aW9ucz86IHsgcmVhZG9ubHkgc2lnbmFsPzogQWJvcnRTaWduYWwgfSxcbikgPT4gUHJvbWlzZTxSPjtcblxuY29uc3QgSURMRTogT3BlcmF0aW9uU3RhdGU8bmV2ZXI+ID0gT2JqZWN0LmZyZWV6ZSh7IHN0YXR1czogXCJpZGxlXCIgfSk7XG5jb25zdCBQRU5ESU5HOiBPcGVyYXRpb25TdGF0ZTxuZXZlcj4gPSBPYmplY3QuZnJlZXplKHsgc3RhdHVzOiBcInBlbmRpbmdcIiB9KTtcblxuLyoqXG4gKiBSdW4gb25lIGdlbmVyYXRlZCBvcGVyYXRpb24uXG4gKlxuICogYHJ1bmAgcmVzb2x2ZXMgd2l0aCB0aGUgdmFsdWUsIG9yIHdpdGggYHVuZGVmaW5lZGAgd2hlbiB0aGUgY2FsbCBmYWlsZWQsXG4gKiB3YXMgYWJvcnRlZCBvciB3YXMgc3VwZXJzZWRlZCBieSBhIGxhdGVyIHJ1biAtIHRoZSBzdGF0ZSBjYXJyaWVzIHRoZSBlcnJvcixcbiAqIHNvIHRoZSBwcm9taXNlIG5ldmVyIHJlamVjdHMgaW50byBhbiBldmVudCBoYW5kbGVyLiBPbmx5IHRoZSBsYXRlc3QgcnVuIGNhblxuICogY2hhbmdlIHRoZSBzdGF0ZS4gYGFib3J0YCBlbmRzIHRoZSBpbi1mbGlnaHQgY2FsbCBsb2NhbGx5ICh0aGUgaG9zdCBtYXlcbiAqIHN0aWxsIHJ1biBpdCk7IGByZXNldGAgYWJvcnRzIGFuZCByZXR1cm5zIHRvIGBpZGxlYC4gVGhlIG1ldGhvZHMgYXJlIGJvdW5kLFxuICogc28gdGhleSBjYW4gYmUgcGFzc2VkIGFyb3VuZCB3aXRob3V0IHRoZSBzdG9yZS5cbiAqL1xuZXhwb3J0IGNsYXNzIE9wZXJhdGlvblN0b3JlPEksIFI+IGV4dGVuZHMgQmFzZVN0b3JlPE9wZXJhdGlvblN0YXRlPFI+PiB7XG5cdHByaXZhdGUgZ2VuZXJhdGlvbiA9IDA7XG5cdHByaXZhdGUgY29udHJvbGxlcjogQWJvcnRDb250cm9sbGVyIHwgbnVsbCA9IG51bGw7XG5cblx0cHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgb3BlcmF0aW9uOiBPcGVyYXRpb248SSwgUj4pIHtcblx0XHRzdXBlcihJRExFKTtcblx0fVxuXG5cdHB1YmxpYyByZWFkb25seSBhYm9ydCA9ICgpOiB2b2lkID0+IHtcblx0XHR0aGlzLmdlbmVyYXRpb24gKz0gMTtcblx0XHR0aGlzLmNvbnRyb2xsZXI/LmFib3J0KCk7XG5cdFx0dGhpcy5jb250cm9sbGVyID0gbnVsbDtcblx0fTtcblxuXHRwdWJsaWMgcmVhZG9ubHkgcmVzZXQgPSAoKTogdm9pZCA9PiB7XG5cdFx0dGhpcy5hYm9ydCgpO1xuXHRcdHRoaXMucHVibGlzaChJRExFKTtcblx0fTtcblxuXHRwdWJsaWMgcmVhZG9ubHkgcnVuID0gYXN5bmMgKGlucHV0OiBJKTogUHJvbWlzZTxSIHwgdW5kZWZpbmVkPiA9PiB7XG5cdFx0dGhpcy5hYm9ydCgpO1xuXHRcdGNvbnN0IG1pbmUgPSB0aGlzLmdlbmVyYXRpb247XG5cdFx0Y29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblx0XHR0aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuXHRcdHRoaXMucHVibGlzaChQRU5ESU5HKTtcblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgdmFsdWUgPSBhd2FpdCB0aGlzLm9wZXJhdGlvbihpbnB1dCwgeyBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsIH0pO1xuXHRcdFx0aWYgKHRoaXMuZ2VuZXJhdGlvbiAhPT0gbWluZSkge1xuXHRcdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5wdWJsaXNoKHsgc3RhdHVzOiBcIm9rXCIsIHZhbHVlIH0pO1xuXHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRpZiAoXG5cdFx0XHRcdHRoaXMuZ2VuZXJhdGlvbiAhPT0gbWluZSB8fFxuXHRcdFx0XHRlcnJvciBpbnN0YW5jZW9mIFFnaXNTZGtCcmlkZ2VBYm9ydGVkRXJyb3Jcblx0XHRcdCkge1xuXHRcdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5wdWJsaXNoKHsgc3RhdHVzOiBcImVycm9yXCIsIGVycm9yOiBhc0Vycm9yKGVycm9yKSB9KTtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fSBmaW5hbGx5IHtcblx0XHRcdGlmICh0aGlzLmNvbnRyb2xsZXIgPT09IGNvbnRyb2xsZXIpIHtcblx0XHRcdFx0dGhpcy5jb250cm9sbGVyID0gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cdH07XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gU3RyZWFtU3RvcmVcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogSG93IGEgc3RyZWFtIGVuZGVkLCBhcyB0aGUgZ2VuZXJhdGVkIG1vZHVsZSByZXBvcnRzIGl0LiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdHJlYW1UZXJtaW5hbExpa2Uge1xuXHRyZWFkb25seSBraW5kOiBzdHJpbmc7XG5cdHJlYWRvbmx5IG1lc3NhZ2U/OiBzdHJpbmc7XG5cdHJlYWRvbmx5IGRyb3BwZWQ/OiBudW1iZXI7XG59XG5cbi8qKiBUaGUgaGFuZGxlIGEgZ2VuZXJhdGVkIHN0cmVhbSBtZW1iZXIgcmVzb2x2ZXMgd2l0aC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RyZWFtSGFuZGxlTGlrZSB7XG5cdHJlYWRvbmx5IGlkOiBzdHJpbmc7XG5cdHJlYWRvbmx5IGNsb3NlZDogYm9vbGVhbjtcblx0Y2xvc2UoKTogdm9pZDtcbn1cblxuLyoqIEhhbmRsZXJzIGZvciBhIHN0cmVhbSwgYXMgYSBnZW5lcmF0ZWQgbW9kdWxlIHR5cGVzIHRoZW0uICovXG5leHBvcnQgaW50ZXJmYWNlIFN0cmVhbUhhbmRsZXJzTGlrZTxFPiB7XG5cdHJlYWRvbmx5IG9uRXZlbnQ/OiAoZXZlbnQ6IEUpID0+IHZvaWQ7XG5cdHJlYWRvbmx5IG9uVGVybWluYWw/OiAodGVybWluYWw6IFN0cmVhbVRlcm1pbmFsTGlrZSkgPT4gdm9pZDtcbn1cblxuLyoqIEEgc3RyZWFtIG1lbWJlciBvZiBhIGdlbmVyYXRlZCBtYXAuICovXG5leHBvcnQgdHlwZSBTdHJlYW08SSwgRT4gPSAoXG5cdGlucHV0OiBJLFxuXHRoYW5kbGVyczogU3RyZWFtSGFuZGxlcnNMaWtlPEU+LFxuXHRvcHRpb25zPzogeyByZWFkb25seSBzaWduYWw/OiBBYm9ydFNpZ25hbCB9LFxuKSA9PiBQcm9taXNlPFN0cmVhbUhhbmRsZUxpa2U+O1xuXG4vKiogV2hlcmUgb25lIHN1YnNjcmlwdGlvbiBzdGFuZHMuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0cmVhbVN0YXRlPEU+IHtcblx0LyoqIGBpZGxlYCB3aXRoIGEgbnVsbCBpbnB1dCwgYGZhaWxlZGAgd2hlbiB0aGUgaG9zdCByZWZ1c2VkIHRvIG9wZW4gaXQuICovXG5cdHJlYWRvbmx5IHN0YXR1czogXCJpZGxlXCIgfCBcIm9wZW5pbmdcIiB8IFwib3BlblwiIHwgXCJlbmRlZFwiIHwgXCJmYWlsZWRcIjtcblx0cmVhZG9ubHkgbGFzdEV2ZW50OiBFIHwgbnVsbDtcblx0cmVhZG9ubHkgdGVybWluYWw6IFN0cmVhbVRlcm1pbmFsTGlrZSB8IG51bGw7XG5cdHJlYWRvbmx5IGVycm9yOiBFcnJvciB8IG51bGw7XG59XG5cbmNvbnN0IElETEVfU1RSRUFNOiBTdHJlYW1TdGF0ZTxuZXZlcj4gPSBPYmplY3QuZnJlZXplKHtcblx0c3RhdHVzOiBcImlkbGVcIixcblx0bGFzdEV2ZW50OiBudWxsLFxuXHR0ZXJtaW5hbDogbnVsbCxcblx0ZXJyb3I6IG51bGwsXG59KTtcblxuLyoqXG4gKiBSZXR1cm4gYSBrZXkgdGhhdCBpcyBlcXVhbCBmb3IgdHdvIGlucHV0cyB3aXRoIHRoZSBzYW1lIGNvbnRlbnQsIHdoYXRldmVyXG4gKiB0aGUgb3JkZXIgdGhlaXIgZmllbGRzIHdlcmUgd3JpdHRlbiBpbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0YWJsZUtleSh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB7XG5cdHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZSwgKF9rZXksIGl0ZW06IHVua25vd24pID0+XG5cdFx0aXNQbGFpblJlY29yZChpdGVtKVxuXHRcdFx0PyBPYmplY3QuZnJvbUVudHJpZXMoXG5cdFx0XHRcdFx0T2JqZWN0LmVudHJpZXMoaXRlbSkuc29ydCgoW2FdLCBbYl0pID0+IChhIDwgYiA/IC0xIDogYSA+IGIgPyAxIDogMCkpLFxuXHRcdFx0XHQpXG5cdFx0XHQ6IGl0ZW0sXG5cdCk7XG59XG5cbi8qKlxuICogSG9sZCBvbmUgZ2VuZXJhdGVkIHN0cmVhbSBvcGVuIHdoaWxlIGl0cyBpbnB1dCBpcyBub24tbnVsbC5cbiAqXG4gKiBgc2V0SW5wdXRgIGZvbGxvd3MgdGhlICpjb250ZW50KiBvZiB0aGUgaW5wdXQ6IGEgbmV3IG9iamVjdCB3aXRoIHRoZSBzYW1lXG4gKiBmaWVsZHMgY2hhbmdlcyBub3RoaW5nLCBhIGRpZmZlcmVudCBvbmUgY2xvc2VzIHRoZSBvbGQgc3RyZWFtIGFuZCBvcGVucyBhXG4gKiBuZXcgb25lLCBgbnVsbGAgY2xvc2VzIGl0LiBIYW5kbGVycyBhcmUgcmVhZCBmcmVzaCBvbiBldmVyeSBmcmFtZSwgc29cbiAqIGBzZXRIYW5kbGVyc2Agd2l0aCBhIG5ldyBjbG9zdXJlIHJlb3BlbnMgbm90aGluZy4gYGNsb3NlYCBpcyBzYWZlIGJlZm9yZSB0aGVcbiAqIGhvc3QgaGFzIGFja25vd2xlZGdlZCB0aGUgc3RyZWFtOiB0aGUgaGFuZGxlIGlzIGNsb3NlZCB0aGUgbW9tZW50IGl0XG4gKiBhcnJpdmVzLlxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtU3RvcmU8SSwgRT4gZXh0ZW5kcyBCYXNlU3RvcmU8U3RyZWFtU3RhdGU8RT4+IHtcblx0cHJpdmF0ZSBrZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXHRwcml2YXRlIGNhbmNlbDogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG5cblx0cHVibGljIGNvbnN0cnVjdG9yKFxuXHRcdHByaXZhdGUgcmVhZG9ubHkgb3BlbjogU3RyZWFtPEksIEU+LFxuXHRcdHByaXZhdGUgaGFuZGxlcnM6IFN0cmVhbUhhbmRsZXJzTGlrZTxFPiA9IHt9LFxuXHQpIHtcblx0XHRzdXBlcihJRExFX1NUUkVBTSk7XG5cdH1cblxuXHQvKiogUmVwbGFjZSB0aGUgaGFuZGxlcnMgdGhlIG5leHQgZnJhbWVzIHJlYWNoOyBub3RoaW5nIHJlb3BlbnMuICovXG5cdHB1YmxpYyBzZXRIYW5kbGVycyhoYW5kbGVyczogU3RyZWFtSGFuZGxlcnNMaWtlPEU+KTogdm9pZCB7XG5cdFx0dGhpcy5oYW5kbGVycyA9IGhhbmRsZXJzO1xuXHR9XG5cblx0cHVibGljIHJlYWRvbmx5IHNldElucHV0ID0gKGlucHV0OiBJIHwgbnVsbCk6IHZvaWQgPT4ge1xuXHRcdGNvbnN0IGtleSA9IGlucHV0ID09PSBudWxsID8gbnVsbCA6IHN0YWJsZUtleShpbnB1dCk7XG5cdFx0aWYgKGtleSA9PT0gdGhpcy5rZXkpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy5jYW5jZWw/LigpO1xuXHRcdHRoaXMuY2FuY2VsID0gbnVsbDtcblx0XHR0aGlzLmtleSA9IGtleTtcblx0XHRpZiAoaW5wdXQgPT09IG51bGwgfHwga2V5ID09PSBudWxsKSB7XG5cdFx0XHR0aGlzLnB1Ymxpc2goSURMRV9TVFJFQU0pO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLmNhbmNlbCA9IHRoaXMuc3RhcnQoaW5wdXQpO1xuXHR9O1xuXG5cdHB1YmxpYyByZWFkb25seSBjbG9zZSA9ICgpOiB2b2lkID0+IHtcblx0XHR0aGlzLnNldElucHV0KG51bGwpO1xuXHR9O1xuXG5cdHByaXZhdGUgc3RhcnQoaW5wdXQ6IEkpOiAoKSA9PiB2b2lkIHtcblx0XHRsZXQgY2FuY2VsbGVkID0gZmFsc2U7XG5cdFx0bGV0IGhhbmRsZTogU3RyZWFtSGFuZGxlTGlrZSB8IG51bGwgPSBudWxsO1xuXHRcdGNvbnN0IHVwZGF0ZSA9IChjaGFuZ2U6IChwcmV2aW91czogU3RyZWFtU3RhdGU8RT4pID0+IFN0cmVhbVN0YXRlPEU+KSA9PiB7XG5cdFx0XHRpZiAoIWNhbmNlbGxlZCkge1xuXHRcdFx0XHR0aGlzLnB1Ymxpc2goY2hhbmdlKHRoaXMuZ2V0U25hcHNob3QoKSkpO1xuXHRcdFx0fVxuXHRcdH07XG5cdFx0dGhpcy5wdWJsaXNoKHtcblx0XHRcdHN0YXR1czogXCJvcGVuaW5nXCIsXG5cdFx0XHRsYXN0RXZlbnQ6IG51bGwsXG5cdFx0XHR0ZXJtaW5hbDogbnVsbCxcblx0XHRcdGVycm9yOiBudWxsLFxuXHRcdH0pO1xuXHRcdHRoaXMub3BlbihpbnB1dCwge1xuXHRcdFx0b25FdmVudDogKGV2ZW50KSA9PiB7XG5cdFx0XHRcdGlmIChjYW5jZWxsZWQpIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5oYW5kbGVycy5vbkV2ZW50Py4oZXZlbnQpO1xuXHRcdFx0XHR1cGRhdGUoKHByZXZpb3VzKSA9PiAoeyAuLi5wcmV2aW91cywgbGFzdEV2ZW50OiBldmVudCB9KSk7XG5cdFx0XHR9LFxuXHRcdFx0b25UZXJtaW5hbDogKHRlcm1pbmFsKSA9PiB7XG5cdFx0XHRcdGlmIChjYW5jZWxsZWQpIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5oYW5kbGVycy5vblRlcm1pbmFsPy4odGVybWluYWwpO1xuXHRcdFx0XHR1cGRhdGUoKHByZXZpb3VzKSA9PiAoeyAuLi5wcmV2aW91cywgc3RhdHVzOiBcImVuZGVkXCIsIHRlcm1pbmFsIH0pKTtcblx0XHRcdH0sXG5cdFx0fSkudGhlbihcblx0XHRcdChvcGVuZWQpID0+IHtcblx0XHRcdFx0aWYgKGNhbmNlbGxlZCkge1xuXHRcdFx0XHRcdG9wZW5lZC5jbG9zZSgpO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0XHRoYW5kbGUgPSBvcGVuZWQ7XG5cdFx0XHRcdHVwZGF0ZSgocHJldmlvdXMpID0+XG5cdFx0XHRcdFx0cHJldmlvdXMuc3RhdHVzID09PSBcImVuZGVkXCJcblx0XHRcdFx0XHRcdD8gcHJldmlvdXNcblx0XHRcdFx0XHRcdDogeyAuLi5wcmV2aW91cywgc3RhdHVzOiBcIm9wZW5cIiB9LFxuXHRcdFx0XHQpO1xuXHRcdFx0fSxcblx0XHRcdChlcnJvcjogdW5rbm93bikgPT4ge1xuXHRcdFx0XHR1cGRhdGUoKCkgPT4gKHtcblx0XHRcdFx0XHRzdGF0dXM6IFwiZmFpbGVkXCIsXG5cdFx0XHRcdFx0bGFzdEV2ZW50OiBudWxsLFxuXHRcdFx0XHRcdHRlcm1pbmFsOiBudWxsLFxuXHRcdFx0XHRcdGVycm9yOiBhc0Vycm9yKGVycm9yKSxcblx0XHRcdFx0fSkpO1xuXHRcdFx0fSxcblx0XHQpO1xuXHRcdHJldHVybiAoKSA9PiB7XG5cdFx0XHRjYW5jZWxsZWQgPSB0cnVlO1xuXHRcdFx0aGFuZGxlPy5jbG9zZSgpO1xuXHRcdH07XG5cdH1cbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBGb3JtU3RvcmVcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIFRoZSBpbnB1dCBmYW1pbGllcyBhIGRlY2xhcmVkIHJlcXVlc3QgY2FuIGFzayBmb3I6IHRoZSBzYW1lIG5hbWVzIHRoZVxuICogUHl0aG9uIGBxZ2lzX3Nkay51aWAgY2F0YWxvZ3VlIGRyYXdzLCBzbyBhIGZvcm0gb24gZWl0aGVyIHNpZGUgb2YgdGhlXG4gKiBicmlkZ2UgcmVuZGVycyBvbmUgZGVjbGFyYXRpb24gdGhlIHNhbWUgd2F5LlxuICovXG5leHBvcnQgdHlwZSBGb3JtRmllbGRLaW5kID1cblx0fCBcInRleHRcIlxuXHR8IFwiaW50ZWdlclwiXG5cdHwgXCJudW1iZXJcIlxuXHR8IFwiYm9vbGVhblwiXG5cdHwgXCJjaG9pY2VcIlxuXHR8IFwibGF5ZXJcIlxuXHR8IFwiY3JzXCJcblx0fCBcIm1ldHJlc1wiXG5cdHwgXCJmaWxlXCJcblx0fCBcImRpcmVjdG9yeVwiXG5cdHwgXCJmaWVsZFwiXG5cdHwgXCJyYW5nZVwiXG5cdHwgXCJjb2xvdXJcIjtcblxuY29uc3QgRklFTERfS0lORFM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0PEZvcm1GaWVsZEtpbmQ+KFtcblx0XCJ0ZXh0XCIsXG5cdFwiaW50ZWdlclwiLFxuXHRcIm51bWJlclwiLFxuXHRcImJvb2xlYW5cIixcblx0XCJjaG9pY2VcIixcblx0XCJsYXllclwiLFxuXHRcImNyc1wiLFxuXHRcIm1ldHJlc1wiLFxuXHRcImZpbGVcIixcblx0XCJkaXJlY3RvcnlcIixcblx0XCJmaWVsZFwiLFxuXHRcInJhbmdlXCIsXG5cdFwiY29sb3VyXCIsXG5dKTtcbmNvbnN0IFBSSU1JVElWRV9LSU5EUzogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgRm9ybUZpZWxkS2luZD4+ID0ge1xuXHRzdHJpbmc6IFwidGV4dFwiLFxuXHRpbnRlZ2VyOiBcImludGVnZXJcIixcblx0bnVtYmVyOiBcIm51bWJlclwiLFxuXHRib29sZWFuOiBcImJvb2xlYW5cIixcbn07XG5jb25zdCBOVU1FUklDX0tJTkRTOiBSZWFkb25seVNldDxGb3JtRmllbGRLaW5kPiA9IG5ldyBTZXQ8Rm9ybUZpZWxkS2luZD4oW1xuXHRcImludGVnZXJcIixcblx0XCJudW1iZXJcIixcblx0XCJtZXRyZXNcIixcblx0XCJyYW5nZVwiLFxuXSk7XG5jb25zdCBERVRBSUxfS0VZUyA9IFtcIm1pbmltdW1cIiwgXCJtYXhpbXVtXCIsIFwic3RlcFwiLCBcIm9mXCIsIFwiZmlsdGVyc1wiLCBcImFscGhhXCJdO1xuXG4vKiogT25lIGlucHV0IG9mIGEgZGVjbGFyZWQgYWN0aW9uLCBhcyBhIHBhZ2Ugc2hvdWxkIHJlbmRlciBpdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRm9ybUZpZWxkIHtcblx0cmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXHQvKiogYGJ1ZmZlcl9kaXN0YW5jZWAgLT4gYEJ1ZmZlciBkaXN0YW5jZWAuICovXG5cdHJlYWRvbmx5IGxhYmVsOiBzdHJpbmc7XG5cdHJlYWRvbmx5IGtpbmQ6IEZvcm1GaWVsZEtpbmQ7XG5cdHJlYWRvbmx5IHJlcXVpcmVkOiBib29sZWFuO1xuXHRyZWFkb25seSBudWxsYWJsZTogYm9vbGVhbjtcblx0LyoqIFRoZSBgZW51bWAgb2YgYSBgY2hvaWNlYCBmaWVsZDsgZW1wdHkgb3RoZXJ3aXNlLiAqL1xuXHRyZWFkb25seSBjaG9pY2VzOiByZWFkb25seSB1bmtub3duW107XG5cdC8qKiBCb3VuZHMsIGEgcGFyZW50IGlucHV0LCBwaWNrZXIgZmlsdGVyczogd2hhdCB0aGUga2luZCBuZWVkcyBiZXlvbmQgYSBuYW1lLiAqL1xuXHRyZWFkb25seSBkZXRhaWxzOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj47XG5cdC8qKiBUaGUgcHJvcGVydHkgc2NoZW1hIHRoZSB2YWx1ZSBpcyB2YWxpZGF0ZWQgYWdhaW5zdC4gKi9cblx0cmVhZG9ubHkgc2NoZW1hOiBEZWNsYXJlZFNjaGVtYTtcbn1cblxuLyoqIFJlbmRlciBhIGZpZWxkIG5hbWUgYXMgYSBsYWJlbC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsYWJlbEZvcihuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuXHRjb25zdCBzcGFjZWQgPSBuYW1lLnJlcGxhY2UoL18vZywgXCIgXCIpLnRyaW0oKTtcblx0cmV0dXJuIHNwYWNlZC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHNwYWNlZC5zbGljZSgxKS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBjb25jcmV0ZShzY2hlbWE6IERlY2xhcmVkU2NoZW1hKTogW0RlY2xhcmVkU2NoZW1hLCBib29sZWFuXSB7XG5cdGNvbnN0IGJyYW5jaGVzID0gc2NoZW1hLmFueU9mO1xuXHRpZiAoIUFycmF5LmlzQXJyYXkoYnJhbmNoZXMpKSB7XG5cdFx0cmV0dXJuIFtzY2hlbWEsIGZhbHNlXTtcblx0fVxuXHRjb25zdCBub25OdWxsID0gYnJhbmNoZXMuZmlsdGVyKFxuXHRcdChicmFuY2gpOiBicmFuY2ggaXMgRGVjbGFyZWRTY2hlbWEgPT5cblx0XHRcdGlzUGxhaW5SZWNvcmQoYnJhbmNoKSAmJiBicmFuY2gudHlwZSAhPT0gXCJudWxsXCIsXG5cdCk7XG5cdGlmIChub25OdWxsLmxlbmd0aCA9PT0gMSAmJiBub25OdWxsLmxlbmd0aCAhPT0gYnJhbmNoZXMubGVuZ3RoKSB7XG5cdFx0cmV0dXJuIFtub25OdWxsWzBdIGFzIERlY2xhcmVkU2NoZW1hLCB0cnVlXTtcblx0fVxuXHR0aHJvdyBuZXcgUWdpc1Nka1N0b3JlRXJyb3IoXG5cdFx0XCJhIHVuaW9uIGZpZWxkIG11c3QgYmUgb25lIHR5cGUgb3IgdGhhdCB0eXBlIHBsdXMgbnVsbCB0byBiZSByZW5kZXJlZFwiLFxuXHQpO1xufVxuXG5mdW5jdGlvbiBraW5kRm9yKFxuXHRvd25lcjogc3RyaW5nLFxuXHRuYW1lOiBzdHJpbmcsXG5cdHNjaGVtYTogRGVjbGFyZWRTY2hlbWEsXG4pOiBGb3JtRmllbGRLaW5kIHtcblx0Y29uc3QgaW50ZW50ID0gc2NoZW1hW1wieC1xZ2lzLXNka1wiXTtcblx0Y29uc3QgbWFya2VkID0gaXNQbGFpblJlY29yZChpbnRlbnQpID8gaW50ZW50LmtpbmQgOiB1bmRlZmluZWQ7XG5cdGlmICh0eXBlb2YgbWFya2VkID09PSBcInN0cmluZ1wiKSB7XG5cdFx0aWYgKCFGSUVMRF9LSU5EUy5oYXMobWFya2VkKSkge1xuXHRcdFx0dGhyb3cgbmV3IFFnaXNTZGtTdG9yZUVycm9yKFxuXHRcdFx0XHRgJHtvd25lcn06IGZpZWxkICR7bmFtZX0gaGFzIHVua25vd24ga2luZCAke0pTT04uc3RyaW5naWZ5KG1hcmtlZCl9YCxcblx0XHRcdCk7XG5cdFx0fVxuXHRcdHJldHVybiBtYXJrZWQgYXMgRm9ybUZpZWxkS2luZDtcblx0fVxuXHRpZiAoXCJlbnVtXCIgaW4gc2NoZW1hKSB7XG5cdFx0cmV0dXJuIFwiY2hvaWNlXCI7XG5cdH1cblx0Y29uc3Qga2luZCA9IFBSSU1JVElWRV9LSU5EU1tTdHJpbmcoc2NoZW1hLnR5cGUpXTtcblx0aWYgKGtpbmQgPT09IHVuZGVmaW5lZCkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrU3RvcmVFcnJvcihcblx0XHRcdGAke293bmVyfTogZmllbGQgJHtuYW1lfSBoYXMgbm8gaW5wdXQgZm9yIGl0cyBzY2hlbWE7IGRlY2xhcmUgYSBwcmltaXRpdmUsIGFuIGVudW0gb3IgYSBraW5kYCxcblx0XHQpO1xuXHR9XG5cdHJldHVybiBraW5kO1xufVxuXG4vKipcbiAqIFRoZSBmaWVsZHMgb2YgYSBkZWNsYXJlZCByZXF1ZXN0IHNjaGVtYSwgaW4gZGVjbGFyYXRpb24gb3JkZXI6IHRoZVxuICogVHlwZVNjcmlwdCB0d2luIG9mIGBxZ2lzX3Nkay51aS5zY2hlbWFfZmllbGRzYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjaGVtYUZpZWxkcyhcblx0c2NoZW1hOiBEZWNsYXJlZFNjaGVtYSxcblx0b3duZXIgPSBcImZvcm1cIixcbik6IHJlYWRvbmx5IEZvcm1GaWVsZFtdIHtcblx0Y29uc3QgcHJvcGVydGllcyA9IHNjaGVtYS5wcm9wZXJ0aWVzO1xuXHRpZiAoIWlzUGxhaW5SZWNvcmQocHJvcGVydGllcykpIHtcblx0XHRyZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG5cdH1cblx0Y29uc3QgcmVxdWlyZWQgPSBuZXcgU2V0KFxuXHRcdEFycmF5LmlzQXJyYXkoc2NoZW1hLnJlcXVpcmVkKSA/IChzY2hlbWEucmVxdWlyZWQgYXMgc3RyaW5nW10pIDogW10sXG5cdCk7XG5cdHJldHVybiBPYmplY3QuZnJlZXplKFxuXHRcdE9iamVjdC5lbnRyaWVzKHByb3BlcnRpZXMpLm1hcCgoW25hbWUsIHByb3BlcnR5XSkgPT4ge1xuXHRcdFx0aWYgKCFpc1BsYWluUmVjb3JkKHByb3BlcnR5KSkge1xuXHRcdFx0XHR0aHJvdyBuZXcgUWdpc1Nka1N0b3JlRXJyb3IoYCR7b3duZXJ9OiBmaWVsZCAke25hbWV9IGlzIG5vdCBhIHNjaGVtYWApO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgW3NoYXBlLCBudWxsYWJsZV0gPSBjb25jcmV0ZShwcm9wZXJ0eSk7XG5cdFx0XHRjb25zdCBraW5kID0ga2luZEZvcihvd25lciwgbmFtZSwgc2hhcGUpO1xuXHRcdFx0Y29uc3QgaW50ZW50ID0gaXNQbGFpblJlY29yZChzaGFwZVtcIngtcWdpcy1zZGtcIl0pXG5cdFx0XHRcdD8gc2hhcGVbXCJ4LXFnaXMtc2RrXCJdXG5cdFx0XHRcdDoge307XG5cdFx0XHRjb25zdCBtZXJnZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0geyAuLi5zaGFwZSwgLi4uaW50ZW50IH07XG5cdFx0XHRjb25zdCBkZXRhaWxzID1cblx0XHRcdFx0a2luZCA9PT0gXCJpbnRlZ2VyXCJcblx0XHRcdFx0XHQ/IHt9XG5cdFx0XHRcdFx0OiBPYmplY3QuZnJvbUVudHJpZXMoXG5cdFx0XHRcdFx0XHRcdERFVEFJTF9LRVlTLmZpbHRlcigoa2V5KSA9PiBrZXkgaW4gbWVyZ2VkKS5tYXAoKGtleSkgPT4gW1xuXHRcdFx0XHRcdFx0XHRcdGtleSxcblx0XHRcdFx0XHRcdFx0XHRtZXJnZWRba2V5XSxcblx0XHRcdFx0XHRcdFx0XSksXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0cmV0dXJuIE9iamVjdC5mcmVlemUoe1xuXHRcdFx0XHRuYW1lLFxuXHRcdFx0XHRsYWJlbDogbGFiZWxGb3IobmFtZSksXG5cdFx0XHRcdGtpbmQsXG5cdFx0XHRcdHJlcXVpcmVkOiByZXF1aXJlZC5oYXMobmFtZSkgJiYgIW51bGxhYmxlLFxuXHRcdFx0XHRudWxsYWJsZSxcblx0XHRcdFx0Y2hvaWNlczogT2JqZWN0LmZyZWV6ZShcblx0XHRcdFx0XHRraW5kID09PSBcImNob2ljZVwiICYmIEFycmF5LmlzQXJyYXkoc2hhcGUuZW51bSkgPyBbLi4uc2hhcGUuZW51bV0gOiBbXSxcblx0XHRcdFx0KSxcblx0XHRcdFx0ZGV0YWlsczogT2JqZWN0LmZyZWV6ZShkZXRhaWxzKSxcblx0XHRcdFx0c2NoZW1hOiBwcm9wZXJ0eSxcblx0XHRcdH0pO1xuXHRcdH0pLFxuXHQpO1xufVxuXG4vKiogVGhlIHZhbHVlcyBhIGZvcm0gaG9sZHM6IG9uZSBlbnRyeSBwZXIgZmllbGQgdGhlIHVzZXIgb3IgdGhlIHNjaGVtYSBzZXQuICovXG5leHBvcnQgdHlwZSBGb3JtVmFsdWVzID0gUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+O1xuXG4vKiogV2hlcmUgb25lIGZvcm0gc3RhbmRzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBGb3JtU3RhdGU8Uj4ge1xuXHRyZWFkb25seSB2YWx1ZXM6IEZvcm1WYWx1ZXM7XG5cdC8qKiBFdmVyeSBpc3N1ZSB0aGUgY3VycmVudCB2YWx1ZXMgaGF2ZSBhZ2FpbnN0IHRoZSByZXF1ZXN0IHNjaGVtYS4gKi9cblx0cmVhZG9ubHkgaXNzdWVzOiByZWFkb25seSBRZ2lzU2RrVmFsaWRhdGlvbklzc3VlW107XG5cdC8qKiBUaGUgZmlyc3QgaXNzdWUgY29kZSBwZXIgZmllbGQgbmFtZSwgZm9yIGEgbGFiZWwgdG8gc2hvdy4gKi9cblx0cmVhZG9ubHkgZXJyb3JzOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+Pjtcblx0cmVhZG9ubHkgdmFsaWQ6IGJvb2xlYW47XG5cdC8qKiBBIHZhbHVlIGNoYW5nZWQgc2luY2UgY29uc3RydWN0aW9uIG9yIHRoZSBsYXN0IGByZXNldGAuICovXG5cdHJlYWRvbmx5IGRpcnR5OiBib29sZWFuO1xuXHQvKiogYHN1Ym1pdGAgd2FzIGF0dGVtcHRlZCBzaW5jZSBjb25zdHJ1Y3Rpb24gb3IgdGhlIGxhc3QgYHJlc2V0YC4gKi9cblx0cmVhZG9ubHkgc3VibWl0dGVkOiBib29sZWFuO1xuXHQvKiogVGhlIGxhdGVzdCBzdWJtaXNzaW9uLCBhcyBhbiBvcGVyYXRpb24gc3RvcmUgcmVwb3J0cyBpdC4gKi9cblx0cmVhZG9ubHkgc3VibWlzc2lvbjogT3BlcmF0aW9uU3RhdGU8Uj47XG59XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgRm9ybVN0b3JlfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRm9ybU9wdGlvbnMge1xuXHQvKiogVmFsdWVzIHRvIHN0YXJ0IGZyb207IHRoZSBkZWNsYXJlZCBkaWFsZWN0IGhhcyBubyBkZWZhdWx0cyBvZiBpdHMgb3duLiAqL1xuXHRyZWFkb25seSBpbml0aWFsPzogRm9ybVZhbHVlcztcbn1cblxudHlwZSBSZXF1ZXN0T2Y8TywgSyBleHRlbmRzIGtleW9mIE8+ID0gT1tLXSBleHRlbmRzIE9wZXJhdGlvblNoYXBlXG5cdD8gT1tLXVtcInJlcXVlc3RcIl1cblx0OiBuZXZlcjtcbnR5cGUgUmVzdWx0T2Y8TywgSyBleHRlbmRzIGtleW9mIE8+ID0gT1tLXSBleHRlbmRzIE9wZXJhdGlvblNoYXBlXG5cdD8gT1tLXVtcInJlc3VsdFwiXVxuXHQ6IG5ldmVyO1xuXG4vKipcbiAqIFdhbGsgYHFnaXNgIGJ5IHRoZSBkb3R0ZWQgaWQgdG8gdGhlIG1ldGhvZCBhIGRlY2xhcmVkIGFjdGlvbiBiZWNhbWUuXG4gKi9cbmZ1bmN0aW9uIG9wZXJhdGlvbk9mPEksIFI+KFxuXHRxZ2lzOiBRZ2lzU2RrQ29yZTx1bmtub3duLCB1bmtub3duPixcblx0aWQ6IHN0cmluZyxcbik6IE9wZXJhdGlvbjxJLCBSPiB7XG5cdGxldCBub2RlOiB1bmtub3duID0gcWdpcztcblx0Zm9yIChjb25zdCBzZWdtZW50IG9mIGlkLnNwbGl0KFwiLlwiKSkge1xuXHRcdG5vZGUgPVxuXHRcdFx0aXNQbGFpblJlY29yZChub2RlKSB8fCB0eXBlb2Ygbm9kZSA9PT0gXCJmdW5jdGlvblwiXG5cdFx0XHRcdD8gKG5vZGUgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW3NlZ21lbnRdXG5cdFx0XHRcdDogdW5kZWZpbmVkO1xuXHR9XG5cdGlmICh0eXBlb2Ygbm9kZSAhPT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtTdG9yZUVycm9yKGAke2lkfSBpcyBub3QgYW4gb3BlcmF0aW9uIG9mIHRoaXMgUWdpc1Nka2ApO1xuXHR9XG5cdHJldHVybiBub2RlIGFzIE9wZXJhdGlvbjxJLCBSPjtcbn1cblxuZnVuY3Rpb24gY29lcmNlKGZpZWxkOiBGb3JtRmllbGQsIHZhbHVlOiB1bmtub3duKTogdW5rbm93biB7XG5cdGlmICh2YWx1ZSA9PT0gXCJcIiAmJiBmaWVsZC5raW5kICE9PSBcInRleHRcIikge1xuXHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdH1cblx0aWYgKE5VTUVSSUNfS0lORFMuaGFzKGZpZWxkLmtpbmQpICYmIHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuXHRcdGNvbnN0IHRyaW1tZWQgPSB2YWx1ZS50cmltKCk7XG5cdFx0aWYgKFxuXHRcdFx0dHJpbW1lZCAhPT0gXCJcIiAmJlxuXHRcdFx0L15bLStdPyhcXGQrXFwuP1xcZCp8XFwuXFxkKykoW2VFXVstK10/XFxkKyk/JC8udGVzdCh0cmltbWVkKVxuXHRcdCkge1xuXHRcdFx0Y29uc3QgbnVtYmVyID0gTnVtYmVyKHRyaW1tZWQpO1xuXHRcdFx0aWYgKGZpZWxkLmtpbmQgIT09IFwiaW50ZWdlclwiIHx8IE51bWJlci5pc0ludGVnZXIobnVtYmVyKSkge1xuXHRcdFx0XHRyZXR1cm4gbnVtYmVyO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXHRyZXR1cm4gdmFsdWU7XG59XG5cbi8qKlxuICogQmluZCB0aGUgcmVxdWVzdCBvZiBvbmUgZGVjbGFyZWQgYWN0aW9uIHRvIGl0cyBzY2hlbWEuXG4gKlxuICogVGhlIGZpZWxkcyBjb21lIGZyb20gdGhlIGRlY2xhcmF0aW9uLCBzbyBhIHBhZ2UgcmVuZGVycyBgZm9ybS5maWVsZHNgXG4gKiBpbnN0ZWFkIG9mIGd1ZXNzaW5nOyBgc2V0YCBjb2VyY2VzIHdoYXQgYW4gYDxpbnB1dD5gIHlpZWxkcyAoYFwiM1wiYCBmb3IgYVxuICogbnVtZXJpYyBmaWVsZCwgYFwiXCJgIGZvciBhbiB1bnNldCBvbmUpIGFuZCByZS12YWxpZGF0ZXM7IGBzdWJtaXRgIHJlZnVzZXNcbiAqIGludmFsaWQgdmFsdWVzIHdpdGhvdXQgYSBjYWxsIGFuZCBvdGhlcndpc2UgcnVucyB0aGUgb3BlcmF0aW9uIHRocm91Z2ggYW5cbiAqIHtAbGluayBPcGVyYXRpb25TdG9yZX0sIHdob3NlIHN0YXRlIGlzIGBzdWJtaXNzaW9uYC5cbiAqL1xuZXhwb3J0IGNsYXNzIEZvcm1TdG9yZTxSZXEgZXh0ZW5kcyBvYmplY3QsIFI+IGV4dGVuZHMgQmFzZVN0b3JlPEZvcm1TdGF0ZTxSPj4ge1xuXHRwdWJsaWMgcmVhZG9ubHkgaWQ6IHN0cmluZztcblx0cHVibGljIHJlYWRvbmx5IHRpdGxlOiBzdHJpbmc7XG5cdHB1YmxpYyByZWFkb25seSBmaWVsZHM6IHJlYWRvbmx5IEZvcm1GaWVsZFtdO1xuXHRwcml2YXRlIHJlYWRvbmx5IGJ5TmFtZTogUmVhZG9ubHlNYXA8c3RyaW5nLCBGb3JtRmllbGQ+O1xuXHRwcml2YXRlIHJlYWRvbmx5IHJlcXVlc3Q6IERlY2xhcmVkU2NoZW1hO1xuXHRwcml2YXRlIHJlYWRvbmx5IGluaXRpYWw6IEZvcm1WYWx1ZXM7XG5cdHByaXZhdGUgcmVhZG9ubHkgb3BlcmF0aW9uOiBPcGVyYXRpb25TdG9yZTxSZXEsIFI+O1xuXHRwcml2YXRlIHJlYWRvbmx5IHVuc3Vic2NyaWJlOiAoKSA9PiB2b2lkO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3Rvcihcblx0XHRxZ2lzOiBRZ2lzU2RrQ29yZTx1bmtub3duLCB1bmtub3duPixcblx0XHRpZDogc3RyaW5nLFxuXHRcdG9wdGlvbnM6IEZvcm1PcHRpb25zID0ge30sXG5cdCkge1xuXHRcdGNvbnN0IGFjdGlvbiA9IHFnaXMuc2NoZW1hLmFjdGlvbnMuZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUuaWQgPT09IGlkKTtcblx0XHRpZiAoYWN0aW9uID09PSB1bmRlZmluZWQpIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrU3RvcmVFcnJvcihcblx0XHRcdFx0YCR7aWR9IGlzIG5vdCBhIGRlY2xhcmVkIGFjdGlvbiBvZiB0aGlzIHNjaGVtYWAsXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRjb25zdCBmaWVsZHMgPSBzY2hlbWFGaWVsZHMoYWN0aW9uLnJlcXVlc3QsIGBmb3JtICR7aWR9YCk7XG5cdFx0Y29uc3QgaW5pdGlhbCA9IEZvcm1TdG9yZS5kZWZhdWx0cyhvcHRpb25zLmluaXRpYWwgPz8ge30pO1xuXHRcdHN1cGVyKEZvcm1TdG9yZS5ldmFsdWF0ZShpbml0aWFsLCBhY3Rpb24ucmVxdWVzdCwgZmFsc2UsIGZhbHNlLCBJRExFKSk7XG5cdFx0dGhpcy5pZCA9IGlkO1xuXHRcdHRoaXMudGl0bGUgPSBhY3Rpb24udGl0bGU7XG5cdFx0dGhpcy5maWVsZHMgPSBmaWVsZHM7XG5cdFx0dGhpcy5ieU5hbWUgPSBuZXcgTWFwKGZpZWxkcy5tYXAoKGZpZWxkKSA9PiBbZmllbGQubmFtZSwgZmllbGRdKSk7XG5cdFx0dGhpcy5yZXF1ZXN0ID0gYWN0aW9uLnJlcXVlc3Q7XG5cdFx0dGhpcy5pbml0aWFsID0gaW5pdGlhbDtcblx0XHR0aGlzLm9wZXJhdGlvbiA9IG5ldyBPcGVyYXRpb25TdG9yZShvcGVyYXRpb25PZjxSZXEsIFI+KHFnaXMsIGlkKSk7XG5cdFx0bGV0IGZpcnN0ID0gdHJ1ZTtcblx0XHR0aGlzLnVuc3Vic2NyaWJlID0gdGhpcy5vcGVyYXRpb24uc3Vic2NyaWJlKChzdWJtaXNzaW9uKSA9PiB7XG5cdFx0XHRpZiAoZmlyc3QpIHtcblx0XHRcdFx0Zmlyc3QgPSBmYWxzZTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgY3VycmVudCA9IHRoaXMuZ2V0U25hcHNob3QoKTtcblx0XHRcdHRoaXMucHVibGlzaCh7IC4uLmN1cnJlbnQsIHN1Ym1pc3Npb24gfSk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKiogVGhlIGRlY2xhcmF0aW9uIHRoZSBmb3JtIHdhcyBidWlsdCBmcm9tLCBmb3IgYSBwYWdlIHRoYXQgcmVuZGVycyBtb3JlLiAqL1xuXHRwdWJsaWMgc3RhdGljIGRlc2NyaWJlKFxuXHRcdHFnaXM6IFFnaXNTZGtDb3JlPHVua25vd24sIHVua25vd24+LFxuXHRcdGlkOiBzdHJpbmcsXG5cdCk6IEFjdGlvbkRlc2NyaXB0aW9uIHwgdW5kZWZpbmVkIHtcblx0XHRyZXR1cm4gcWdpcy5zY2hlbWEuYWN0aW9ucy5maW5kKChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZS5pZCA9PT0gaWQpO1xuXHR9XG5cblx0cHJpdmF0ZSBzdGF0aWMgZGVmYXVsdHMoaW5pdGlhbDogRm9ybVZhbHVlcyk6IEZvcm1WYWx1ZXMge1xuXHRcdC8vIFRoZSBkZWNsYXJlZCBkaWFsZWN0IGNhcnJpZXMgbm8gYGRlZmF1bHRgIGtleXdvcmQ6IHdoYXQgYSBmb3JtIHN0YXJ0c1xuXHRcdC8vIGZyb20gaXMgdGhlIHBhZ2UncyBjaG9pY2UsIGFuZCBhbiB1bnNldCByZXF1aXJlZCBmaWVsZCBpcyBhbiBpc3N1ZVxuXHRcdC8vIHRoZSBwYWdlIHNob3dzIG9uY2UgYHN1Ym1pdHRlZGAgaXMgdHJ1ZS5cblx0XHRyZXR1cm4gT2JqZWN0LmZyZWV6ZShcblx0XHRcdE9iamVjdC5mcm9tRW50cmllcyhcblx0XHRcdFx0T2JqZWN0LmVudHJpZXMoaW5pdGlhbCkuZmlsdGVyKChbLCB2YWx1ZV0pID0+IHZhbHVlICE9PSB1bmRlZmluZWQpLFxuXHRcdFx0KSxcblx0XHQpO1xuXHR9XG5cblx0cHJpdmF0ZSBzdGF0aWMgZXZhbHVhdGU8Uj4oXG5cdFx0dmFsdWVzOiBGb3JtVmFsdWVzLFxuXHRcdHJlcXVlc3Q6IERlY2xhcmVkU2NoZW1hLFxuXHRcdGRpcnR5OiBib29sZWFuLFxuXHRcdHN1Ym1pdHRlZDogYm9vbGVhbixcblx0XHRzdWJtaXNzaW9uOiBPcGVyYXRpb25TdGF0ZTxSPixcblx0KTogRm9ybVN0YXRlPFI+IHtcblx0XHRjb25zdCBpc3N1ZXMgPSB2YWxpZGF0ZUFnYWluc3RTY2hlbWEodmFsdWVzLCByZXF1ZXN0KTtcblx0XHRjb25zdCBlcnJvcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblx0XHRmb3IgKGNvbnN0IGlzc3VlIG9mIGlzc3Vlcykge1xuXHRcdFx0Y29uc3QgW2hlYWRdID0gaXNzdWUucGF0aDtcblx0XHRcdGNvbnN0IG5hbWUgPSB0eXBlb2YgaGVhZCA9PT0gXCJzdHJpbmdcIiA/IGhlYWQgOiBcIlwiO1xuXHRcdFx0aWYgKCEobmFtZSBpbiBlcnJvcnMpKSB7XG5cdFx0XHRcdGVycm9yc1tuYW1lXSA9IGlzc3VlLmNvZGU7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBPYmplY3QuZnJlZXplKHtcblx0XHRcdHZhbHVlcyxcblx0XHRcdGlzc3VlczogT2JqZWN0LmZyZWV6ZShpc3N1ZXMpLFxuXHRcdFx0ZXJyb3JzOiBPYmplY3QuZnJlZXplKGVycm9ycyksXG5cdFx0XHR2YWxpZDogaXNzdWVzLmxlbmd0aCA9PT0gMCxcblx0XHRcdGRpcnR5LFxuXHRcdFx0c3VibWl0dGVkLFxuXHRcdFx0c3VibWlzc2lvbixcblx0XHR9KTtcblx0fVxuXG5cdC8qKiBTZXQgb25lIGZpZWxkOyBgdW5kZWZpbmVkYCB1bnNldHMgaXQuICovXG5cdHB1YmxpYyByZWFkb25seSBzZXQgPSAobmFtZTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bik6IHZvaWQgPT4ge1xuXHRcdHRoaXMuc2V0VmFsdWVzKHsgW25hbWVdOiB2YWx1ZSB9KTtcblx0fTtcblxuXHQvKiogU2V0IHNldmVyYWwgZmllbGRzIGF0IG9uY2UuICovXG5cdHB1YmxpYyByZWFkb25seSBzZXRWYWx1ZXMgPSAoY2hhbmdlczogRm9ybVZhbHVlcyk6IHZvaWQgPT4ge1xuXHRcdGNvbnN0IGN1cnJlbnQgPSB0aGlzLmdldFNuYXBzaG90KCk7XG5cdFx0Y29uc3QgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHsgLi4uY3VycmVudC52YWx1ZXMgfTtcblx0XHRmb3IgKGNvbnN0IFtuYW1lLCByYXddIG9mIE9iamVjdC5lbnRyaWVzKGNoYW5nZXMpKSB7XG5cdFx0XHRjb25zdCBmaWVsZCA9IHRoaXMuYnlOYW1lLmdldChuYW1lKTtcblx0XHRcdGlmIChmaWVsZCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdHRocm93IG5ldyBRZ2lzU2RrU3RvcmVFcnJvcihgJHt0aGlzLmlkfSBoYXMgbm8gZmllbGQgJHtuYW1lfWApO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgdmFsdWUgPSBjb2VyY2UoZmllbGQsIHJhdyk7XG5cdFx0XHRpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRkZWxldGUgdmFsdWVzW25hbWVdO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFsdWVzW25hbWVdID0gdmFsdWU7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHRoaXMucHVibGlzaChcblx0XHRcdEZvcm1TdG9yZS5ldmFsdWF0ZShcblx0XHRcdFx0T2JqZWN0LmZyZWV6ZSh2YWx1ZXMpLFxuXHRcdFx0XHR0aGlzLnJlcXVlc3QsXG5cdFx0XHRcdHRydWUsXG5cdFx0XHRcdGN1cnJlbnQuc3VibWl0dGVkLFxuXHRcdFx0XHRjdXJyZW50LnN1Ym1pc3Npb24sXG5cdFx0XHQpLFxuXHRcdCk7XG5cdH07XG5cblx0LyoqIFRoZSBkZWNsYXJlZCBmaWVsZCwgZm9yIGEgcmVuZGVyZXIgd29ya2luZyBmcm9tIGEgbmFtZS4gKi9cblx0cHVibGljIGZpZWxkKG5hbWU6IHN0cmluZyk6IEZvcm1GaWVsZCB7XG5cdFx0Y29uc3QgZmllbGQgPSB0aGlzLmJ5TmFtZS5nZXQobmFtZSk7XG5cdFx0aWYgKGZpZWxkID09PSB1bmRlZmluZWQpIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrU3RvcmVFcnJvcihgJHt0aGlzLmlkfSBoYXMgbm8gZmllbGQgJHtuYW1lfWApO1xuXHRcdH1cblx0XHRyZXR1cm4gZmllbGQ7XG5cdH1cblxuXHQvKiogQmFjayB0byB0aGUgaW5pdGlhbCB2YWx1ZXMgYW5kIGFuIGlkbGUgc3VibWlzc2lvbjsgYWJvcnRzIGEgY2FsbCBpbiBmbGlnaHQuICovXG5cdHB1YmxpYyByZWFkb25seSByZXNldCA9ICgpOiB2b2lkID0+IHtcblx0XHR0aGlzLm9wZXJhdGlvbi5yZXNldCgpO1xuXHRcdHRoaXMucHVibGlzaChcblx0XHRcdEZvcm1TdG9yZS5ldmFsdWF0ZSh0aGlzLmluaXRpYWwsIHRoaXMucmVxdWVzdCwgZmFsc2UsIGZhbHNlLCBJRExFKSxcblx0XHQpO1xuXHR9O1xuXG5cdC8qKiBBYm9ydCBhIHN1Ym1pc3Npb24gaW4gZmxpZ2h0OyB0aGUgdmFsdWVzIHN0YXkuICovXG5cdHB1YmxpYyByZWFkb25seSBhYm9ydCA9ICgpOiB2b2lkID0+IHtcblx0XHR0aGlzLm9wZXJhdGlvbi5hYm9ydCgpO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBWYWxpZGF0ZSwgdGhlbiBydW4gdGhlIGFjdGlvbiB3aXRoIHRoZSBjdXJyZW50IHZhbHVlcy4gUmVzb2x2ZXMgd2l0aCB0aGVcblx0ICogcmVzdWx0LCBvciBgdW5kZWZpbmVkYCB3aGVuIHRoZSB2YWx1ZXMgYXJlIGludmFsaWQgKG5vIGNhbGwgaXMgbWFkZSkgb3Jcblx0ICogdGhlIGNhbGwgZmFpbGVkLCB3YXMgYWJvcnRlZCBvciBzdXBlcnNlZGVkIC0gYHN1Ym1pc3Npb25gIHNheXMgd2hpY2guXG5cdCAqL1xuXHRwdWJsaWMgcmVhZG9ubHkgc3VibWl0ID0gYXN5bmMgKCk6IFByb21pc2U8UiB8IHVuZGVmaW5lZD4gPT4ge1xuXHRcdGNvbnN0IGN1cnJlbnQgPSB0aGlzLmdldFNuYXBzaG90KCk7XG5cdFx0aWYgKCFjdXJyZW50LnZhbGlkKSB7XG5cdFx0XHR0aGlzLnB1Ymxpc2goeyAuLi5jdXJyZW50LCBzdWJtaXR0ZWQ6IHRydWUgfSk7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHRpZiAoIWN1cnJlbnQuc3VibWl0dGVkKSB7XG5cdFx0XHR0aGlzLnB1Ymxpc2goeyAuLi5jdXJyZW50LCBzdWJtaXR0ZWQ6IHRydWUgfSk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLm9wZXJhdGlvbi5ydW4oY3VycmVudC52YWx1ZXMgYXMgUmVxKTtcblx0fTtcblxuXHQvKiogU3RvcCBmb2xsb3dpbmcgdGhlIHN1Ym1pc3Npb247IGZvciBhbiBhZGFwdGVyIHRlYXJpbmcgdGhlIGZvcm0gZG93bi4gKi9cblx0cHVibGljIGRpc3Bvc2UoKTogdm9pZCB7XG5cdFx0dGhpcy5vcGVyYXRpb24uYWJvcnQoKTtcblx0XHR0aGlzLnVuc3Vic2NyaWJlKCk7XG5cdH1cbn1cblxuLyoqXG4gKiBUaGUgZm9ybSBmb3IgYHFnaXMuPGlkPmAsIHR5cGVkIGZyb20gdGhlIHNjaGVtYTogdGhlIHJlcXVlc3QgbmFtZXMgdGhlXG4gKiBmaWVsZHMsIHRoZSByZXN1bHQgdHlwZXMgdGhlIHN1Ym1pc3Npb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtU3RvcmU8TywgSyBleHRlbmRzIGtleW9mIE8gJiBzdHJpbmc+KFxuXHRxZ2lzOiBRZ2lzU2RrQ29yZTxPLCB1bmtub3duPixcblx0aWQ6IEssXG5cdG9wdGlvbnM/OiBGb3JtT3B0aW9ucyxcbik6IEZvcm1TdG9yZTxSZXF1ZXN0T2Y8TywgSz4gJiBvYmplY3QsIFJlc3VsdE9mPE8sIEs+PiB7XG5cdHJldHVybiBuZXcgRm9ybVN0b3JlKHFnaXMgYXMgUWdpc1Nka0NvcmU8dW5rbm93biwgdW5rbm93bj4sIGlkLCBvcHRpb25zKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBIb3N0UXVlcnlTdG9yZVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKiBXaGVyZSBvbmUgaG9zdCBxdWVyeSBzdGFuZHMuICovXG5leHBvcnQgdHlwZSBIb3N0UXVlcnlTdGF0ZTxUPiA9XG5cdHwgeyByZWFkb25seSBzdGF0dXM6IFwiaWRsZVwiIH1cblx0fCB7IHJlYWRvbmx5IHN0YXR1czogXCJsb2FkaW5nXCIgfVxuXHR8IHsgcmVhZG9ubHkgc3RhdHVzOiBcIm9rXCI7IHJlYWRvbmx5IHZhbHVlOiBUIH1cblx0fCB7IHJlYWRvbmx5IHN0YXR1czogXCJlcnJvclwiOyByZWFkb25seSBlcnJvcjogRXJyb3IgfVxuXHR8IHtcblx0XHRcdC8qKiBUaGUgaGFuZHNoYWtlIGRpZCBub3QgZ3JhbnQgYG9wZXJhdGlvbmA7IG5vIGNhbGwgd2FzIG1hZGUuICovXG5cdFx0XHRyZWFkb25seSBzdGF0dXM6IFwicmVmdXNlZFwiO1xuXHRcdFx0cmVhZG9ubHkgb3BlcmF0aW9uOiBIb3N0T3BlcmF0aW9uSWQ7XG5cdFx0XHRyZWFkb25seSBtZXNzYWdlOiBzdHJpbmc7XG5cdCAgfTtcblxuY29uc3QgSURMRV9RVUVSWTogSG9zdFF1ZXJ5U3RhdGU8bmV2ZXI+ID0gT2JqZWN0LmZyZWV6ZSh7IHN0YXR1czogXCJpZGxlXCIgfSk7XG5cbi8qKiBXaGF0IGEgaG9zdCBxdWVyeSBydW5zIG9uY2UgdGhlIGdyYW50IGlzIGNvbmZpcm1lZC4gKi9cbmV4cG9ydCB0eXBlIEhvc3RRdWVyeUxvYWRlcjxUPiA9IChcblx0aG9zdDogUWdpc1Nka0hvc3QsXG5cdG9wdGlvbnM6IHsgcmVhZG9ubHkgc2lnbmFsOiBBYm9ydFNpZ25hbCB9LFxuKSA9PiBQcm9taXNlPFQ+O1xuXG4vKipcbiAqIFJlYWQgdGhlIGN1cmF0ZWQgaG9zdCBzdXJmYWNlLCBncmFudCBmaXJzdC5cbiAqXG4gKiBgcmVmcmVzaGAgd2FpdHMgZm9yIHRoZSBoYW5kc2hha2UsIHRoZW4gLSB3aGVuIGBxZ2lzLmhvc3QuZ3JhbnRlZGAgbGFja3NcbiAqIHRoZSBvcGVyYXRpb24gdGhlIHF1ZXJ5IG5lZWRzIC0gc2V0dGxlcyBvbiBgcmVmdXNlZGAgd2l0aG91dCBhIGNhbGwsIHNvIGFcbiAqIHBhZ2UgY2FuIHNob3cgXCJhc2sgdGhlIHBsdWdpbiBhdXRob3IgZm9yIGBsYXllcnMucmVhZGBcIiBpbnN0ZWFkIG9mIGFcbiAqIGBub3RfYXV0aG9yaXplZGAgZmF1bHQuIE90aGVyd2lzZSB0aGUgbG9hZGVyIHJ1bnMgd2l0aCBsYXRlc3Qtd2luc1xuICogc2VtYW50aWNzIGxpa2UgYW4gb3BlcmF0aW9uIHN0b3JlLlxuICovXG5leHBvcnQgY2xhc3MgSG9zdFF1ZXJ5U3RvcmU8VD4gZXh0ZW5kcyBCYXNlU3RvcmU8SG9zdFF1ZXJ5U3RhdGU8VD4+IHtcblx0cHJpdmF0ZSBnZW5lcmF0aW9uID0gMDtcblx0cHJpdmF0ZSBjb250cm9sbGVyOiBBYm9ydENvbnRyb2xsZXIgfCBudWxsID0gbnVsbDtcblxuXHRwdWJsaWMgY29uc3RydWN0b3IoXG5cdFx0cHJpdmF0ZSByZWFkb25seSBxZ2lzOiBRZ2lzU2RrQ29yZTx1bmtub3duLCB1bmtub3duPixcblx0XHRwdWJsaWMgcmVhZG9ubHkgb3BlcmF0aW9uOiBIb3N0T3BlcmF0aW9uSWQsXG5cdFx0cHJpdmF0ZSByZWFkb25seSBsb2FkZXI6IEhvc3RRdWVyeUxvYWRlcjxUPixcblx0KSB7XG5cdFx0c3VwZXIoSURMRV9RVUVSWSk7XG5cdH1cblxuXHRwdWJsaWMgcmVhZG9ubHkgYWJvcnQgPSAoKTogdm9pZCA9PiB7XG5cdFx0dGhpcy5nZW5lcmF0aW9uICs9IDE7XG5cdFx0dGhpcy5jb250cm9sbGVyPy5hYm9ydCgpO1xuXHRcdHRoaXMuY29udHJvbGxlciA9IG51bGw7XG5cdH07XG5cblx0cHVibGljIHJlYWRvbmx5IHJlc2V0ID0gKCk6IHZvaWQgPT4ge1xuXHRcdHRoaXMuYWJvcnQoKTtcblx0XHR0aGlzLnB1Ymxpc2goSURMRV9RVUVSWSk7XG5cdH07XG5cblx0cHVibGljIHJlYWRvbmx5IHJlZnJlc2ggPSBhc3luYyAoKTogUHJvbWlzZTxUIHwgdW5kZWZpbmVkPiA9PiB7XG5cdFx0dGhpcy5hYm9ydCgpO1xuXHRcdGNvbnN0IG1pbmUgPSB0aGlzLmdlbmVyYXRpb247XG5cdFx0Y29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblx0XHR0aGlzLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuXHRcdHRoaXMucHVibGlzaCh7IHN0YXR1czogXCJsb2FkaW5nXCIgfSk7XG5cdFx0dHJ5IHtcblx0XHRcdGF3YWl0IHRoaXMucWdpcy5yZWFkeTtcblx0XHRcdGlmICh0aGlzLmdlbmVyYXRpb24gIT09IG1pbmUpIHtcblx0XHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHRcdH1cblx0XHRcdGlmICghdGhpcy5xZ2lzLmhvc3QuZ3JhbnRlZC5pbmNsdWRlcyh0aGlzLm9wZXJhdGlvbikpIHtcblx0XHRcdFx0dGhpcy5wdWJsaXNoKHtcblx0XHRcdFx0XHRzdGF0dXM6IFwicmVmdXNlZFwiLFxuXHRcdFx0XHRcdG9wZXJhdGlvbjogdGhpcy5vcGVyYXRpb24sXG5cdFx0XHRcdFx0bWVzc2FnZTogYHRoaXMgdmlldyB3YXMgbm90IGdyYW50ZWQgJHt0aGlzLm9wZXJhdGlvbn1gLFxuXHRcdFx0XHR9KTtcblx0XHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHRcdH1cblx0XHRcdGNvbnN0IHZhbHVlID0gYXdhaXQgdGhpcy5sb2FkZXIodGhpcy5xZ2lzLmhvc3QsIHtcblx0XHRcdFx0c2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCxcblx0XHRcdH0pO1xuXHRcdFx0aWYgKHRoaXMuZ2VuZXJhdGlvbiAhPT0gbWluZSkge1xuXHRcdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5wdWJsaXNoKHsgc3RhdHVzOiBcIm9rXCIsIHZhbHVlIH0pO1xuXHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRpZiAoXG5cdFx0XHRcdHRoaXMuZ2VuZXJhdGlvbiAhPT0gbWluZSB8fFxuXHRcdFx0XHRlcnJvciBpbnN0YW5jZW9mIFFnaXNTZGtCcmlkZ2VBYm9ydGVkRXJyb3Jcblx0XHRcdCkge1xuXHRcdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5wdWJsaXNoKHsgc3RhdHVzOiBcImVycm9yXCIsIGVycm9yOiBhc0Vycm9yKGVycm9yKSB9KTtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fSBmaW5hbGx5IHtcblx0XHRcdGlmICh0aGlzLmNvbnRyb2xsZXIgPT09IGNvbnRyb2xsZXIpIHtcblx0XHRcdFx0dGhpcy5jb250cm9sbGVyID0gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cdH07XG59XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgbGF5ZXJzUXVlcnl9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBMYXllcnNRdWVyeU9wdGlvbnMge1xuXHQvKiogSXRlbXMgcGVyIHBhZ2Ugd2hpbGUgZm9sbG93aW5nIGBuZXh0X2N1cnNvcmA7IHRoZSBob3N0J3MgZGVmYXVsdCBvdGhlcndpc2UuICovXG5cdHJlYWRvbmx5IHBhZ2VTaXplPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIEV2ZXJ5IHZlY3RvciBsYXllciBvZiB0aGUgcHJvamVjdCwgZm9sbG93aW5nIGBsYXllcnMubGlzdGAgcGFnZXMgdG8gdGhlXG4gKiBlbmQ6IHdoYXQgYSBsYXllciBwaWNrZXIgYmluZHMgdG8uIE5lZWRzIHRoZSBgbGF5ZXJzLnJlYWRgIGdyYW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gbGF5ZXJzUXVlcnkoXG5cdHFnaXM6IFFnaXNTZGtDb3JlPHVua25vd24sIHVua25vd24+LFxuXHRvcHRpb25zOiBMYXllcnNRdWVyeU9wdGlvbnMgPSB7fSxcbik6IEhvc3RRdWVyeVN0b3JlPHJlYWRvbmx5IFZlY3RvckxheWVySW5mb1tdPiB7XG5cdHJldHVybiBuZXcgSG9zdFF1ZXJ5U3RvcmUocWdpcywgXCJsYXllcnMubGlzdFwiLCBhc3luYyAoaG9zdCwgeyBzaWduYWwgfSkgPT4ge1xuXHRcdGNvbnN0IGl0ZW1zOiBWZWN0b3JMYXllckluZm9bXSA9IFtdO1xuXHRcdGxldCBjdXJzb3I6IHN0cmluZyB8IHVuZGVmaW5lZDtcblx0XHRkbyB7XG5cdFx0XHRjb25zdCBwYWdlOiBMYXllclBhZ2UgPSBhd2FpdCBob3N0LmxheWVycy5saXN0KFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0Li4uKGN1cnNvciA9PT0gdW5kZWZpbmVkID8ge30gOiB7IGN1cnNvciB9KSxcblx0XHRcdFx0XHQuLi4ob3B0aW9ucy5wYWdlU2l6ZSA9PT0gdW5kZWZpbmVkXG5cdFx0XHRcdFx0XHQ/IHt9XG5cdFx0XHRcdFx0XHQ6IHsgbGltaXQ6IG9wdGlvbnMucGFnZVNpemUgfSksXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHsgc2lnbmFsIH0sXG5cdFx0XHQpO1xuXHRcdFx0aXRlbXMucHVzaCguLi5wYWdlLml0ZW1zKTtcblx0XHRcdGN1cnNvciA9IHBhZ2UubmV4dF9jdXJzb3I7XG5cdFx0fSB3aGlsZSAoY3Vyc29yICE9PSB1bmRlZmluZWQpO1xuXHRcdHJldHVybiBPYmplY3QuZnJlZXplKGl0ZW1zKTtcblx0fSk7XG59XG5cbi8qKlxuICogVGhlIGZpZWxkIG5hbWVzIG9mIG9uZSB2ZWN0b3IgbGF5ZXIsIGZvciBhIGBmaWVsZGAgaW5wdXQgd2hvc2UgYG9mYCBuYW1lc1xuICogYSBsYXllciBpbnB1dDogYGxheWVycy5nZXRgIHVuZGVyIHRoZSBgbGF5ZXJzLnJlYWRgIGdyYW50LiBBIGxheWVyJ3MgQ1JTIGlzXG4gKiBvbiB0aGUgc2FtZSByZXBseTsgYSBwcm9qZWN0IENSUyBxdWVyeSBpcyBub3Qgb24gdGhlIHdpcmUgeWV0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gbGF5ZXJGaWVsZHNRdWVyeShcblx0cWdpczogUWdpc1Nka0NvcmU8dW5rbm93biwgdW5rbm93bj4sXG5cdGxheWVySWQ6IHN0cmluZyxcbik6IEhvc3RRdWVyeVN0b3JlPHJlYWRvbmx5IHN0cmluZ1tdPiB7XG5cdHJldHVybiBuZXcgSG9zdFF1ZXJ5U3RvcmUocWdpcywgXCJsYXllcnMuZ2V0XCIsIGFzeW5jIChob3N0LCB7IHNpZ25hbCB9KSA9PiB7XG5cdFx0Y29uc3QgbGF5ZXIgPSBhd2FpdCBob3N0LmxheWVycy5nZXQoeyBsYXllcl9pZDogbGF5ZXJJZCB9LCB7IHNpZ25hbCB9KTtcblx0XHRyZXR1cm4gT2JqZWN0LmZyZWV6ZShbLi4ubGF5ZXIuZmllbGRfbmFtZXNdKTtcblx0fSk7XG59XG4iCiAgXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7O0FBYU8sSUFBTSxvQkFBMkI7QUFDakMsSUFBTSxvQkFBMkI7QUFDakMsSUFBTSxxQ0FBdUM7QUFxRDdDLFNBQVMsa0JBQWlCLENBQUMsT0FBaUM7QUFBQSxFQUNsRSxPQUFPLE9BQU8sVUFBVSxZQUFZLE9BQU8sY0FBYyxLQUFLO0FBQUE7QUFBQTtBQU14RCxNQUFNLGlDQUFnQyxjQUFhO0FBQUEsRUFDbEQsV0FBVyxDQUFDLFNBQWlCO0FBQUEsSUFDbkMsTUFBTSxTQUFTLHFC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
|