@blinkk/root-cms 2.0.0-rc.0 → 2.0.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/dist/app.js +226 -20
- package/dist/cli.js +217 -164
- package/dist/{client-dBGLkauA.d.ts → client-fqtWzfpQ.d.ts} +349 -113
- package/dist/client.d.ts +1 -1
- package/dist/client.js +699 -316
- package/dist/core.d.ts +5 -80
- package/dist/core.js +705 -515
- package/dist/functions.js +695 -306
- package/dist/plugin.d.ts +1 -1
- package/dist/plugin.js +961 -524
- package/dist/project.d.ts +1 -1
- package/dist/project.js +2 -2
- package/dist/richtext.js +0 -1
- package/dist/{schema-ix967Ud0.d.ts → schema-KpQGOA1Z.d.ts} +65 -8
- package/dist/ui/signin.css +0 -1
- package/dist/ui/signin.js +0 -1
- package/dist/ui/ui.css +1 -2
- package/dist/ui/ui.js +142 -103
- package/package.json +20 -16
package/dist/core.js
CHANGED
|
@@ -5,60 +5,359 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// core/client.ts
|
|
8
|
-
import
|
|
8
|
+
import crypto from "node:crypto";
|
|
9
9
|
import {
|
|
10
|
-
FieldValue,
|
|
11
|
-
Timestamp as
|
|
10
|
+
FieldValue as FieldValue2,
|
|
11
|
+
Timestamp as Timestamp2
|
|
12
12
|
} from "firebase-admin/firestore";
|
|
13
13
|
|
|
14
|
-
// core/
|
|
15
|
-
import { promises as fs } from "node:fs";
|
|
16
|
-
import path2 from "node:path";
|
|
17
|
-
import { fileURLToPath } from "node:url";
|
|
18
|
-
import bodyParser from "body-parser";
|
|
14
|
+
// core/translations-manager.ts
|
|
19
15
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} from "firebase-admin/app";
|
|
24
|
-
import { getAuth } from "firebase-admin/auth";
|
|
25
|
-
import { getFirestore } from "firebase-admin/firestore";
|
|
26
|
-
import * as jsonwebtoken from "jsonwebtoken";
|
|
27
|
-
import sirv from "sirv";
|
|
28
|
-
|
|
29
|
-
// core/api.ts
|
|
30
|
-
import { multipartMiddleware } from "@blinkk/root/middleware";
|
|
31
|
-
|
|
32
|
-
// core/ai.ts
|
|
33
|
-
import crypto from "node:crypto";
|
|
34
|
-
import { generate } from "@genkit-ai/ai";
|
|
35
|
-
import { configureGenkit } from "@genkit-ai/core";
|
|
36
|
-
import { vertexAI } from "@genkit-ai/vertexai";
|
|
37
|
-
import { gemini15ProPreview, gemini15FlashPreview } from "@genkit-ai/vertexai";
|
|
38
|
-
import { Timestamp } from "firebase-admin/firestore";
|
|
39
|
-
|
|
40
|
-
// core/versions.ts
|
|
41
|
-
import path from "node:path";
|
|
42
|
-
import { Timestamp as Timestamp2 } from "firebase-admin/firestore";
|
|
43
|
-
import glob from "tiny-glob";
|
|
44
|
-
var DOCUMENT_SAVE_OFFSET = 5 * 60 * 1e3;
|
|
45
|
-
|
|
46
|
-
// core/csv.ts
|
|
47
|
-
import { parse as csvParse } from "csv-parse/sync";
|
|
48
|
-
import { stringify as csvStringify } from "csv-stringify/sync";
|
|
16
|
+
FieldValue,
|
|
17
|
+
Timestamp
|
|
18
|
+
} from "firebase-admin/firestore";
|
|
49
19
|
|
|
50
|
-
//
|
|
51
|
-
import
|
|
20
|
+
// shared/strings.ts
|
|
21
|
+
import fnv from "fnv-plus";
|
|
22
|
+
function normalizeStr(str) {
|
|
23
|
+
const lines = str.trim().split("\n").map((line) => removeTrailingWhitespace(line));
|
|
24
|
+
return lines.join("\n");
|
|
25
|
+
}
|
|
26
|
+
function removeTrailingWhitespace(str) {
|
|
27
|
+
return str.trimEnd().replace(/ $/, "");
|
|
28
|
+
}
|
|
29
|
+
function hashStr(str) {
|
|
30
|
+
if (!str || typeof str !== "string") {
|
|
31
|
+
throw new Error("input string is invalid");
|
|
32
|
+
}
|
|
33
|
+
return fnv.fast1a52hex(normalizeStr(str));
|
|
34
|
+
}
|
|
52
35
|
|
|
53
|
-
// core/
|
|
54
|
-
var
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
throw new Error("could not find root-cms plugin config in root.config.ts");
|
|
36
|
+
// core/translations-manager.ts
|
|
37
|
+
var TRANSLATIONS_DB_PATH_FORMAT = "/Projects/{project}/TranslationsManager/{mode}/Translations";
|
|
38
|
+
var TRANSLATIONS_LOCALE_DOC_DB_PATH_FORMAT = `${TRANSLATIONS_DB_PATH_FORMAT}/{id}:{locale}`;
|
|
39
|
+
var TranslationsManager = class {
|
|
40
|
+
constructor(cmsClient) {
|
|
41
|
+
this.cmsClient = cmsClient;
|
|
60
42
|
}
|
|
61
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Saves draft translations for a translations doc id.
|
|
45
|
+
*
|
|
46
|
+
* Example:
|
|
47
|
+
* ```
|
|
48
|
+
* const strings = {
|
|
49
|
+
* 'one': {es: 'uno', fr: 'un'},
|
|
50
|
+
* 'two': {es: 'dos', fr: 'deux'},
|
|
51
|
+
* };
|
|
52
|
+
* await tm.saveTranslations('Pages/index', strings);
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
async saveTranslations(id, strings, options) {
|
|
56
|
+
const mode = "draft";
|
|
57
|
+
const localesSet = /* @__PURE__ */ new Set();
|
|
58
|
+
Object.values(strings).forEach((entry) => {
|
|
59
|
+
Object.keys(entry).forEach((locale) => {
|
|
60
|
+
if (locale !== "source") {
|
|
61
|
+
localesSet.add(locale);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
const batch = this.cmsClient.db.batch();
|
|
66
|
+
const locales = Array.from(localesSet);
|
|
67
|
+
locales.forEach((locale) => {
|
|
68
|
+
const updates = {
|
|
69
|
+
id,
|
|
70
|
+
locale,
|
|
71
|
+
sys: {
|
|
72
|
+
modifiedAt: Timestamp.now(),
|
|
73
|
+
modifiedBy: (options == null ? void 0 : options.modifiedBy) || "root-cms-client"
|
|
74
|
+
},
|
|
75
|
+
strings: {}
|
|
76
|
+
};
|
|
77
|
+
if ((options == null ? void 0 : options.tags) && options.tags.length > 0) {
|
|
78
|
+
updates.tags = FieldValue.arrayUnion(...options.tags);
|
|
79
|
+
}
|
|
80
|
+
let numUpdates = 0;
|
|
81
|
+
const hashMap = this.toLocaleDocHashMap(strings, locale);
|
|
82
|
+
Object.entries(hashMap).forEach(([hash, translations]) => {
|
|
83
|
+
Object.entries(translations).forEach(([locale2, translation]) => {
|
|
84
|
+
if (translation) {
|
|
85
|
+
updates.strings[hash] ??= {};
|
|
86
|
+
updates.strings[hash][locale2] = translation;
|
|
87
|
+
numUpdates += 1;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
if (numUpdates > 0) {
|
|
92
|
+
const localeDocPath = buildTranslationsLocaleDocDbPath({
|
|
93
|
+
project: this.cmsClient.projectId,
|
|
94
|
+
mode,
|
|
95
|
+
id,
|
|
96
|
+
locale
|
|
97
|
+
});
|
|
98
|
+
const localeDocRef = this.cmsClient.db.doc(localeDocPath);
|
|
99
|
+
batch.set(localeDocRef, updates, { merge: true });
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
await batch.commit();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Publishes a translations doc.
|
|
106
|
+
*/
|
|
107
|
+
async publishTranslations(id, options) {
|
|
108
|
+
const db = this.cmsClient.db;
|
|
109
|
+
const project = this.cmsClient.projectId;
|
|
110
|
+
const draftPath = buildTranslationsDbPath({ project, mode: "draft" });
|
|
111
|
+
const query = db.collection(draftPath).where("id", "==", id);
|
|
112
|
+
const res = await query.get();
|
|
113
|
+
if (res.size === 0) {
|
|
114
|
+
console.warn(`no translations to publish for ${id}`);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const batch = (options == null ? void 0 : options.batch) || db.batch();
|
|
118
|
+
res.docs.forEach((doc) => {
|
|
119
|
+
const translationsLocaleDoc = doc.data();
|
|
120
|
+
const sys = {
|
|
121
|
+
...translationsLocaleDoc.sys,
|
|
122
|
+
publishedAt: Timestamp.now(),
|
|
123
|
+
publishedBy: (options == null ? void 0 : options.publishedBy) || "root-cms-client"
|
|
124
|
+
};
|
|
125
|
+
batch.update(doc.ref, { sys });
|
|
126
|
+
const publishedDocPath = buildTranslationsLocaleDocDbPath({
|
|
127
|
+
project,
|
|
128
|
+
mode: "published",
|
|
129
|
+
id: translationsLocaleDoc.id,
|
|
130
|
+
locale: translationsLocaleDoc.locale
|
|
131
|
+
});
|
|
132
|
+
const publishedDocRef = db.doc(publishedDocPath);
|
|
133
|
+
batch.set(publishedDocRef, { ...translationsLocaleDoc, sys });
|
|
134
|
+
});
|
|
135
|
+
const shouldCommitBatch = !(options == null ? void 0 : options.batch);
|
|
136
|
+
if (shouldCommitBatch) {
|
|
137
|
+
await batch.commit();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Fetches translations from one or more translations docs in the translations
|
|
142
|
+
* manager.
|
|
143
|
+
*
|
|
144
|
+
* Example:
|
|
145
|
+
* ```
|
|
146
|
+
* await tm.loadTranslations();
|
|
147
|
+
* // =>
|
|
148
|
+
* // {
|
|
149
|
+
* // "one": {"es": "uno", "fr": "un"},
|
|
150
|
+
* // "two": {"es": "dos", "fr": "deux"}
|
|
151
|
+
* // }
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* To load a specific set of translations docs by id:
|
|
155
|
+
* ```
|
|
156
|
+
* const translationsToLoad = ['Global/strings', 'Global/header', 'Global/footer', 'Pages/index'];
|
|
157
|
+
* await tm.loadTranslations({ids: translationsToLoad});
|
|
158
|
+
* // =>
|
|
159
|
+
* // {
|
|
160
|
+
* // "one": {"es": "uno", "fr": "un"},
|
|
161
|
+
* // "two": {"es": "dos", "fr": "deux"}
|
|
162
|
+
* // }
|
|
163
|
+
* ```
|
|
164
|
+
*
|
|
165
|
+
* To load a subset of locales (more performant):
|
|
166
|
+
* ```
|
|
167
|
+
* await tm.loadTranslations({locales: ['es']});
|
|
168
|
+
* // =>
|
|
169
|
+
* // {
|
|
170
|
+
* // "one": {"es": "uno"},
|
|
171
|
+
* // "two": {"es": "dos"}
|
|
172
|
+
* // }
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
async loadTranslations(options) {
|
|
176
|
+
const mode = (options == null ? void 0 : options.mode) || "published";
|
|
177
|
+
const dbPath = buildTranslationsDbPath({
|
|
178
|
+
project: this.cmsClient.projectId,
|
|
179
|
+
mode
|
|
180
|
+
});
|
|
181
|
+
let query = this.cmsClient.db.collection(dbPath);
|
|
182
|
+
if ((options == null ? void 0 : options.ids) && options.ids.length > 0) {
|
|
183
|
+
query = query.where("id", "in", options.ids);
|
|
184
|
+
}
|
|
185
|
+
if ((options == null ? void 0 : options.tags) && options.tags.length > 0) {
|
|
186
|
+
query = query.where("tags", "array-contains", options.tags);
|
|
187
|
+
}
|
|
188
|
+
if ((options == null ? void 0 : options.locales) && options.locales.length > 0) {
|
|
189
|
+
query = query.where("locale", "in", options.locales);
|
|
190
|
+
}
|
|
191
|
+
const results = await query.get();
|
|
192
|
+
const strings = {};
|
|
193
|
+
results.forEach((result) => {
|
|
194
|
+
const localeDoc = result.data();
|
|
195
|
+
Object.values(localeDoc.strings || {}).forEach((item) => {
|
|
196
|
+
strings[item.source] ??= { source: item.source };
|
|
197
|
+
strings[item.source][localeDoc.locale] = item.translation;
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
return strings;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Fetches translations for a given locale, with optional fallbacks.
|
|
204
|
+
* The return value is a map of source string to translated string.
|
|
205
|
+
*
|
|
206
|
+
* Example:
|
|
207
|
+
* ```
|
|
208
|
+
* await translationsDoc.loadTranslationsForLocale('es');
|
|
209
|
+
* // =>
|
|
210
|
+
* // {
|
|
211
|
+
* // "one": "uno",
|
|
212
|
+
* // "two": "dos",
|
|
213
|
+
* // }
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
216
|
+
async loadTranslationsForLocale(locale, options) {
|
|
217
|
+
const localeSet = /* @__PURE__ */ new Set([
|
|
218
|
+
locale,
|
|
219
|
+
...(options == null ? void 0 : options.fallbackLocales) || []
|
|
220
|
+
]);
|
|
221
|
+
const fallbackLocales = Array.from(localeSet);
|
|
222
|
+
const multiLocaleStrings = await this.loadTranslations({
|
|
223
|
+
mode: options == null ? void 0 : options.mode,
|
|
224
|
+
locales: fallbackLocales
|
|
225
|
+
});
|
|
226
|
+
return this.toSingleLocaleMap(multiLocaleStrings, fallbackLocales);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Converts a multi-locale translations map to a flat single-locale map,
|
|
230
|
+
* with optional support for fallback locales.
|
|
231
|
+
*
|
|
232
|
+
* ```
|
|
233
|
+
* const multiLocaleStrings = {
|
|
234
|
+
* 'one': {es: 'uno', fr: 'un'},
|
|
235
|
+
* 'two': {es: 'dos', fr: 'deux'}
|
|
236
|
+
* };
|
|
237
|
+
* translationsDoc.toSingleLocaleMap(multiLocaleStrings, ['es']);
|
|
238
|
+
* // =>
|
|
239
|
+
* // {
|
|
240
|
+
* // "one": "uno",
|
|
241
|
+
* // "two": "dos",
|
|
242
|
+
* // }
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
toSingleLocaleMap(multiLocaleStrings, fallbackLocales) {
|
|
246
|
+
const singleLocaleStrings = {};
|
|
247
|
+
Object.entries(multiLocaleStrings).forEach(([source, translations]) => {
|
|
248
|
+
let translation = source;
|
|
249
|
+
for (const locale of fallbackLocales) {
|
|
250
|
+
if (translations[locale]) {
|
|
251
|
+
translation = translations[locale];
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
singleLocaleStrings[source] = translation;
|
|
256
|
+
});
|
|
257
|
+
return singleLocaleStrings;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Converts a multi-locale translations map to a single-locale hashed version,
|
|
261
|
+
* used for storage in in the DB.
|
|
262
|
+
*
|
|
263
|
+
* ```
|
|
264
|
+
* const multiLocaleStrings = {
|
|
265
|
+
* 'one': {es: 'uno', fr: 'un'},
|
|
266
|
+
* 'two': {es: 'dos', fr: 'deux'}
|
|
267
|
+
* };
|
|
268
|
+
* translationsDoc.toLocaleDocHashMap(multiLocaleStrings, 'es');
|
|
269
|
+
* // =>
|
|
270
|
+
* // {
|
|
271
|
+
* // "<hash1>": {"source": "one", "translation": "uno"},
|
|
272
|
+
* // "<hash2>": {"source": "two", "translation": "dos"},
|
|
273
|
+
* // }
|
|
274
|
+
* ```
|
|
275
|
+
*
|
|
276
|
+
* One reason for using hashes is because the DB has limits on the number of
|
|
277
|
+
* chars that can be used as the "key" in a object map.
|
|
278
|
+
*/
|
|
279
|
+
toLocaleDocHashMap(multiLocaleStrings, locale) {
|
|
280
|
+
const hashMap = {};
|
|
281
|
+
Object.entries(multiLocaleStrings).forEach(([source, translations]) => {
|
|
282
|
+
const translation = translations[locale];
|
|
283
|
+
if (translation) {
|
|
284
|
+
const hash = hashStr(source);
|
|
285
|
+
hashMap[hash] = { source, translation };
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
return hashMap;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Import translations from the v1 system to the TranslationsManager.
|
|
292
|
+
*/
|
|
293
|
+
async importTranslationsFromV1() {
|
|
294
|
+
var _a;
|
|
295
|
+
const projectId = this.cmsClient.projectId;
|
|
296
|
+
const db = this.cmsClient.db;
|
|
297
|
+
const dbPath = `Projects/${projectId}/Translations`;
|
|
298
|
+
const query = db.collection(dbPath);
|
|
299
|
+
const querySnapshot = await query.get();
|
|
300
|
+
if (querySnapshot.size === 0) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
console.log(
|
|
304
|
+
"[root cms] importing v1 Translations to v2 TranslationsManager"
|
|
305
|
+
);
|
|
306
|
+
const translationsDocs = {};
|
|
307
|
+
querySnapshot.forEach((doc) => {
|
|
308
|
+
const translation = doc.data();
|
|
309
|
+
const source = this.cmsClient.normalizeString(translation.source);
|
|
310
|
+
delete translation.source;
|
|
311
|
+
const tags = translation.tags || [];
|
|
312
|
+
delete translation.tags;
|
|
313
|
+
for (const tag of tags) {
|
|
314
|
+
if (tag.includes("/")) {
|
|
315
|
+
const translationsId = tag;
|
|
316
|
+
translationsDocs[translationsId] ??= {
|
|
317
|
+
id: translationsId,
|
|
318
|
+
tags,
|
|
319
|
+
strings: {}
|
|
320
|
+
};
|
|
321
|
+
translationsDocs[translationsId].strings[source] = translation;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
if (Object.keys(translationsDocs).length === 0) {
|
|
326
|
+
console.log("[root cms] no v1 translations to save");
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
for (const docId in translationsDocs) {
|
|
330
|
+
const [collection2, slug] = docId.split("/");
|
|
331
|
+
if (collection2 && slug) {
|
|
332
|
+
const doc = await this.cmsClient.getDoc(collection2, slug, {
|
|
333
|
+
mode: "draft"
|
|
334
|
+
});
|
|
335
|
+
const linkedSheet = (_a = doc == null ? void 0 : doc.sys) == null ? void 0 : _a.l10nSheet;
|
|
336
|
+
if (linkedSheet) {
|
|
337
|
+
translationsDocs[docId].sys.linkedSheet = linkedSheet;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
Object.entries(translationsDocs).forEach(([translationsId, data]) => {
|
|
342
|
+
const len = Object.keys(data.strings).length;
|
|
343
|
+
console.log(`[root cms] saving ${len} string(s) to ${translationsId}...`);
|
|
344
|
+
this.saveTranslations(translationsId, data.strings, {
|
|
345
|
+
tags: data.tags || [translationsId]
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
function buildTranslationsDbPath(options) {
|
|
351
|
+
return TRANSLATIONS_DB_PATH_FORMAT.replace(
|
|
352
|
+
"{project}",
|
|
353
|
+
options.project
|
|
354
|
+
).replace("{mode}", options.mode);
|
|
355
|
+
}
|
|
356
|
+
function buildTranslationsLocaleDocDbPath(options) {
|
|
357
|
+
return TRANSLATIONS_LOCALE_DOC_DB_PATH_FORMAT.replace(
|
|
358
|
+
"{project}",
|
|
359
|
+
options.project
|
|
360
|
+
).replace("{mode}", options.mode).replace("{id}", options.id.replaceAll("/", "--")).replace("{locale}", options.locale);
|
|
62
361
|
}
|
|
63
362
|
|
|
64
363
|
// core/client.ts
|
|
@@ -87,13 +386,19 @@ var RootCMSClient = class {
|
|
|
87
386
|
*/
|
|
88
387
|
async getRawDoc(collectionId, slug, options) {
|
|
89
388
|
const mode = options.mode;
|
|
90
|
-
const
|
|
389
|
+
const modeCollection = mode === "draft" ? "Drafts" : "Published";
|
|
390
|
+
slug = slug.replaceAll("/", "--");
|
|
391
|
+
const dbPath = `Projects/${this.projectId}/Collections/${collectionId}/${modeCollection}/${slug}`;
|
|
392
|
+
const docRef = this.db.doc(dbPath);
|
|
91
393
|
const doc = await docRef.get();
|
|
92
394
|
if (doc.exists) {
|
|
93
395
|
return doc.data();
|
|
94
396
|
}
|
|
95
397
|
return null;
|
|
96
398
|
}
|
|
399
|
+
/**
|
|
400
|
+
* Firestore path for a collection.
|
|
401
|
+
*/
|
|
97
402
|
dbCollectionDocsPath(collectionId, options) {
|
|
98
403
|
let modeCollection = "";
|
|
99
404
|
if (options.mode === "draft") {
|
|
@@ -105,11 +410,17 @@ var RootCMSClient = class {
|
|
|
105
410
|
}
|
|
106
411
|
return `Projects/${this.projectId}/Collections/${collectionId}/${modeCollection}`;
|
|
107
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* Firestore path for a content doc.
|
|
415
|
+
*/
|
|
108
416
|
dbDocPath(collectionId, slug, options) {
|
|
109
417
|
const collectionDocsPath = this.dbCollectionDocsPath(collectionId, options);
|
|
110
418
|
const normalizedSlug = slug.replaceAll("/", "--");
|
|
111
419
|
return `${collectionDocsPath}/${normalizedSlug}`;
|
|
112
420
|
}
|
|
421
|
+
/**
|
|
422
|
+
* Firestore doc ref for a content doc.
|
|
423
|
+
*/
|
|
113
424
|
dbDocRef(collectionId, slug, options) {
|
|
114
425
|
const docPath = this.dbDocPath(collectionId, slug, options);
|
|
115
426
|
return this.db.doc(docPath);
|
|
@@ -132,9 +443,9 @@ var RootCMSClient = class {
|
|
|
132
443
|
slug,
|
|
133
444
|
sys: {
|
|
134
445
|
...draftSys,
|
|
135
|
-
createdAt: draftSys.createdAt ??
|
|
446
|
+
createdAt: draftSys.createdAt ?? Timestamp2.now(),
|
|
136
447
|
createdBy: draftSys.createdBy ?? modifiedBy,
|
|
137
|
-
modifiedAt:
|
|
448
|
+
modifiedAt: Timestamp2.now(),
|
|
138
449
|
modifiedBy,
|
|
139
450
|
locales: (options == null ? void 0 : options.locales) ?? draftSys.locales ?? ["en"]
|
|
140
451
|
},
|
|
@@ -230,6 +541,10 @@ var RootCMSClient = class {
|
|
|
230
541
|
}
|
|
231
542
|
let batchCount = 0;
|
|
232
543
|
const batch = (options == null ? void 0 : options.batch) || this.db.batch();
|
|
544
|
+
const versionTags = ["published"];
|
|
545
|
+
if (options == null ? void 0 : options.releaseId) {
|
|
546
|
+
versionTags.push(`release:${options.releaseId}`);
|
|
547
|
+
}
|
|
233
548
|
const publishedDocs = [];
|
|
234
549
|
for (const doc of docs) {
|
|
235
550
|
const { id, collection: collection2, slug, sys, fields } = doc;
|
|
@@ -242,7 +557,7 @@ var RootCMSClient = class {
|
|
|
242
557
|
const publishedRef = this.db.doc(
|
|
243
558
|
`${projectCollectionsPath}/${collection2}/Published/${slug}`
|
|
244
559
|
);
|
|
245
|
-
const firstPublishedAt = sys.firstPublishedAt ??
|
|
560
|
+
const firstPublishedAt = sys.firstPublishedAt ?? FieldValue2.serverTimestamp();
|
|
246
561
|
const firstPublishedBy = sys.firstPublishedBy ?? publishedBy;
|
|
247
562
|
batch.set(publishedRef, {
|
|
248
563
|
id,
|
|
@@ -253,24 +568,43 @@ var RootCMSClient = class {
|
|
|
253
568
|
...sys,
|
|
254
569
|
firstPublishedAt,
|
|
255
570
|
firstPublishedBy,
|
|
256
|
-
publishedAt:
|
|
571
|
+
publishedAt: FieldValue2.serverTimestamp(),
|
|
257
572
|
publishedBy
|
|
258
573
|
}
|
|
259
574
|
});
|
|
260
575
|
batchCount += 1;
|
|
576
|
+
const versionRef = this.db.doc(
|
|
577
|
+
`${projectCollectionsPath}/${collection2}/Drafts/${slug}/Versions/${Date.now()}`
|
|
578
|
+
);
|
|
579
|
+
const versionData = {
|
|
580
|
+
id,
|
|
581
|
+
collection: collection2,
|
|
582
|
+
slug,
|
|
583
|
+
fields: fields || {},
|
|
584
|
+
sys: {
|
|
585
|
+
...sys,
|
|
586
|
+
firstPublishedAt,
|
|
587
|
+
firstPublishedBy,
|
|
588
|
+
publishedAt: FieldValue2.serverTimestamp(),
|
|
589
|
+
publishedBy
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
if (versionTags.length) {
|
|
593
|
+
versionData.tags = versionTags;
|
|
594
|
+
}
|
|
595
|
+
batch.set(versionRef, versionData);
|
|
596
|
+
batchCount += 1;
|
|
261
597
|
batch.delete(scheduledRef);
|
|
262
598
|
batchCount += 1;
|
|
263
599
|
batch.update(draftRef, {
|
|
264
|
-
"sys.scheduledAt":
|
|
265
|
-
"sys.scheduledBy":
|
|
600
|
+
"sys.scheduledAt": FieldValue2.delete(),
|
|
601
|
+
"sys.scheduledBy": FieldValue2.delete(),
|
|
266
602
|
"sys.firstPublishedAt": firstPublishedAt,
|
|
267
603
|
"sys.firstPublishedBy": firstPublishedBy,
|
|
268
|
-
"sys.publishedAt":
|
|
604
|
+
"sys.publishedAt": FieldValue2.serverTimestamp(),
|
|
269
605
|
"sys.publishedBy": publishedBy
|
|
270
606
|
});
|
|
271
607
|
batchCount += 1;
|
|
272
|
-
this.publishTranslationsDoc(doc.id, { batch });
|
|
273
|
-
batchCount += 2;
|
|
274
608
|
publishedDocs.push(doc);
|
|
275
609
|
if (batchCount >= 400) {
|
|
276
610
|
await batch.commit();
|
|
@@ -317,6 +651,7 @@ var RootCMSClient = class {
|
|
|
317
651
|
}
|
|
318
652
|
let batchCount = 0;
|
|
319
653
|
const batch = this.db.batch();
|
|
654
|
+
const versionTags = ["published"];
|
|
320
655
|
const publishedDocs = [];
|
|
321
656
|
for (const doc of docs) {
|
|
322
657
|
const { id, collection: collection2, slug, data } = doc;
|
|
@@ -341,24 +676,41 @@ var RootCMSClient = class {
|
|
|
341
676
|
...sys,
|
|
342
677
|
firstPublishedAt,
|
|
343
678
|
firstPublishedBy,
|
|
344
|
-
publishedAt:
|
|
679
|
+
publishedAt: FieldValue2.serverTimestamp(),
|
|
345
680
|
publishedBy: scheduledBy || ""
|
|
346
681
|
}
|
|
347
682
|
});
|
|
348
683
|
batchCount += 1;
|
|
684
|
+
const versionRef = this.db.doc(
|
|
685
|
+
`${projectCollectionsPath}/${collection2}/Drafts/${slug}/Versions/${Date.now()}`
|
|
686
|
+
);
|
|
687
|
+
const versionData = {
|
|
688
|
+
id,
|
|
689
|
+
collection: collection2,
|
|
690
|
+
slug,
|
|
691
|
+
fields: data.fields || {},
|
|
692
|
+
sys: {
|
|
693
|
+
...sys,
|
|
694
|
+
firstPublishedAt,
|
|
695
|
+
firstPublishedBy,
|
|
696
|
+
publishedAt: FieldValue2.serverTimestamp(),
|
|
697
|
+
publishedBy: scheduledBy || ""
|
|
698
|
+
},
|
|
699
|
+
tags: versionTags
|
|
700
|
+
};
|
|
701
|
+
batch.set(versionRef, versionData);
|
|
702
|
+
batchCount += 1;
|
|
349
703
|
batch.delete(scheduledRef);
|
|
350
704
|
batchCount += 1;
|
|
351
705
|
batch.update(draftRef, {
|
|
352
|
-
"sys.scheduledAt":
|
|
353
|
-
"sys.scheduledBy":
|
|
706
|
+
"sys.scheduledAt": FieldValue2.delete(),
|
|
707
|
+
"sys.scheduledBy": FieldValue2.delete(),
|
|
354
708
|
"sys.firstPublishedAt": firstPublishedAt,
|
|
355
709
|
"sys.firstPublishedBy": firstPublishedBy,
|
|
356
|
-
"sys.publishedAt":
|
|
710
|
+
"sys.publishedAt": FieldValue2.serverTimestamp(),
|
|
357
711
|
"sys.publishedBy": scheduledBy || "root-cms-client"
|
|
358
712
|
});
|
|
359
713
|
batchCount += 1;
|
|
360
|
-
this.publishTranslationsDoc(doc.id, { batch });
|
|
361
|
-
batchCount += 2;
|
|
362
714
|
publishedDocs.push(doc);
|
|
363
715
|
if (batchCount >= 400) {
|
|
364
716
|
await batch.commit();
|
|
@@ -378,50 +730,31 @@ var RootCMSClient = class {
|
|
|
378
730
|
async publishScheduledReleases() {
|
|
379
731
|
const releasesPath = `Projects/${this.projectId}/Releases`;
|
|
380
732
|
const now = Math.ceil((/* @__PURE__ */ new Date()).getTime());
|
|
381
|
-
const query = this.db.collection(releasesPath).where("scheduledAt", "<=",
|
|
733
|
+
const query = this.db.collection(releasesPath).where("scheduledAt", "<=", Timestamp2.fromMillis(now));
|
|
382
734
|
const querySnapshot = await query.get();
|
|
383
735
|
for (const snapshot of querySnapshot.docs) {
|
|
384
736
|
const release = snapshot.data();
|
|
385
737
|
const batch = this.db.batch();
|
|
386
738
|
const publishedBy = release.scheduledBy || "root-cms-client";
|
|
387
739
|
batch.update(snapshot.ref, {
|
|
388
|
-
publishedAt:
|
|
740
|
+
publishedAt: Timestamp2.now(),
|
|
389
741
|
publishedBy,
|
|
390
|
-
scheduledAt:
|
|
391
|
-
scheduledBy:
|
|
742
|
+
scheduledAt: FieldValue2.delete(),
|
|
743
|
+
scheduledBy: FieldValue2.delete()
|
|
744
|
+
});
|
|
745
|
+
const dataSourceIds = release.dataSourceIds || [];
|
|
746
|
+
if (dataSourceIds.length > 0) {
|
|
747
|
+
await this.publishDataSources(dataSourceIds, {
|
|
748
|
+
publishedBy,
|
|
749
|
+
batch,
|
|
750
|
+
commitBatch: false
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
await this.publishDocs(release.docIds || [], {
|
|
754
|
+
publishedBy,
|
|
755
|
+
batch,
|
|
756
|
+
releaseId: release.id
|
|
392
757
|
});
|
|
393
|
-
await this.publishDocs(release.docIds || [], { publishedBy, batch });
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
async publishTranslationsDoc(translationsId, options) {
|
|
397
|
-
const docSlug = translationsId.replaceAll("/", "--");
|
|
398
|
-
const draftRef = this.db.doc(
|
|
399
|
-
`Projects/${this.projectId}/TranslationsManager/draft/Translations/${docSlug}`
|
|
400
|
-
);
|
|
401
|
-
const snapshot = await draftRef.get();
|
|
402
|
-
if (!snapshot.exists) {
|
|
403
|
-
console.warn(`translations ${translationsId} does not exist`);
|
|
404
|
-
return;
|
|
405
|
-
}
|
|
406
|
-
const commitBatch = !(options == null ? void 0 : options.batch);
|
|
407
|
-
const batch = (options == null ? void 0 : options.batch) || this.db.batch();
|
|
408
|
-
batch.update(draftRef, {
|
|
409
|
-
"sys.publishedAt": Timestamp4.now(),
|
|
410
|
-
"sys.publishedBy": (options == null ? void 0 : options.publishedBy) || "root-cms-client"
|
|
411
|
-
});
|
|
412
|
-
const publishedRef = this.db.doc(
|
|
413
|
-
`Projects/${this.projectId}/TranslationsManager/published/Translations/${docSlug}`
|
|
414
|
-
);
|
|
415
|
-
const data = { ...snapshot.data() };
|
|
416
|
-
if (!data.sys) {
|
|
417
|
-
data.sys = {};
|
|
418
|
-
}
|
|
419
|
-
data.sys.publishedAt = Timestamp4.now();
|
|
420
|
-
data.sys.publishedBy = (options == null ? void 0 : options.publishedBy) || "root-cms-client";
|
|
421
|
-
batch.set(publishedRef, data);
|
|
422
|
-
if (commitBatch) {
|
|
423
|
-
await batch.commit();
|
|
424
|
-
this.logAction("translations.publish", { metadata: { translationsId } });
|
|
425
758
|
}
|
|
426
759
|
}
|
|
427
760
|
/**
|
|
@@ -431,7 +764,7 @@ var RootCMSClient = class {
|
|
|
431
764
|
var _a;
|
|
432
765
|
if ((_a = doc.sys) == null ? void 0 : _a.publishingLocked) {
|
|
433
766
|
if (doc.sys.publishingLocked.until) {
|
|
434
|
-
const now =
|
|
767
|
+
const now = Timestamp2.now().toMillis();
|
|
435
768
|
const until = doc.sys.publishingLocked.until.toMillis();
|
|
436
769
|
return now < until;
|
|
437
770
|
}
|
|
@@ -440,36 +773,51 @@ var RootCMSClient = class {
|
|
|
440
773
|
return false;
|
|
441
774
|
}
|
|
442
775
|
/**
|
|
443
|
-
*
|
|
776
|
+
* Returns a `TranslationsManager` object for managing translations.
|
|
777
|
+
*
|
|
778
|
+
* To get translations:
|
|
779
|
+
* ```
|
|
780
|
+
* await tm.loadTranslations({
|
|
781
|
+
* ids: ['Global/strings', 'Pages/index'],
|
|
782
|
+
* locales: ['es'],
|
|
783
|
+
* });
|
|
784
|
+
* ```
|
|
785
|
+
*
|
|
786
|
+
* NOTE: The `TranslationsManager` is a v2 feature that will eventually
|
|
787
|
+
* replace the v1 translations system.
|
|
788
|
+
*/
|
|
789
|
+
getTranslationsManager() {
|
|
790
|
+
var _a;
|
|
791
|
+
const cmsPluginOptions = this.cmsPlugin.getConfig();
|
|
792
|
+
if ((_a = cmsPluginOptions.experiments) == null ? void 0 : _a.v2TranslationsManager) {
|
|
793
|
+
throw new Error(
|
|
794
|
+
"`v2TranslationsManager` is not enabled. update root.config.ts and add: `{experiments: {v2TranslationsManager: true}}`"
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
return new TranslationsManager(this);
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Loads translations saved in the translations collection, optionally
|
|
801
|
+
* filtered by tag.
|
|
444
802
|
*
|
|
803
|
+
* Returns a map like:
|
|
445
804
|
* ```
|
|
446
805
|
* {
|
|
447
806
|
* "<hash>": {"source": "Hello", "es": "Hola", "fr": "Bonjour"},
|
|
448
807
|
* }
|
|
449
808
|
* ```
|
|
450
|
-
*
|
|
451
|
-
* @deprecated Use `createBatchRequest()` to fetch draft/published translations.
|
|
452
809
|
*/
|
|
453
810
|
async loadTranslations(options) {
|
|
454
|
-
const dbPath = `Projects/${this.projectId}/
|
|
455
|
-
const translationsMap = {};
|
|
456
|
-
const addTranslations = (hash, translations) => {
|
|
457
|
-
translationsMap[hash] = Object.assign(
|
|
458
|
-
translationsMap[hash] || {},
|
|
459
|
-
translations
|
|
460
|
-
);
|
|
461
|
-
};
|
|
811
|
+
const dbPath = `Projects/${this.projectId}/Translations`;
|
|
462
812
|
let query = this.db.collection(dbPath);
|
|
463
|
-
if (
|
|
464
|
-
query = query.where("
|
|
465
|
-
}
|
|
466
|
-
const
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
addTranslations(hash, translations);
|
|
472
|
-
});
|
|
813
|
+
if (options == null ? void 0 : options.tags) {
|
|
814
|
+
query = query.where("tags", "array-contains-any", options.tags);
|
|
815
|
+
}
|
|
816
|
+
const querySnapshot = await query.get();
|
|
817
|
+
const translationsMap = {};
|
|
818
|
+
querySnapshot.forEach((doc) => {
|
|
819
|
+
const hash = doc.id;
|
|
820
|
+
translationsMap[hash] = doc.data();
|
|
473
821
|
});
|
|
474
822
|
return translationsMap;
|
|
475
823
|
}
|
|
@@ -480,9 +828,6 @@ var RootCMSClient = class {
|
|
|
480
828
|
* "Hello": {"es": "Hola", "fr": "Bonjour"},
|
|
481
829
|
* });
|
|
482
830
|
* ```
|
|
483
|
-
*
|
|
484
|
-
* @deprecated Use `saveDraftTranslations()` and `publishTranslations()`
|
|
485
|
-
* instead.
|
|
486
831
|
*/
|
|
487
832
|
async saveTranslations(translations, tags) {
|
|
488
833
|
const translationsPath = `Projects/${this.projectId}/Translations`;
|
|
@@ -496,7 +841,7 @@ var RootCMSClient = class {
|
|
|
496
841
|
source: this.normalizeString(source)
|
|
497
842
|
};
|
|
498
843
|
if (tags) {
|
|
499
|
-
data.tags = tags;
|
|
844
|
+
data.tags = FieldValue2.arrayUnion(...tags);
|
|
500
845
|
}
|
|
501
846
|
batch.set(translationRef, data, { merge: true });
|
|
502
847
|
batchCount += 1;
|
|
@@ -506,34 +851,12 @@ var RootCMSClient = class {
|
|
|
506
851
|
}
|
|
507
852
|
await batch.commit();
|
|
508
853
|
}
|
|
509
|
-
async saveDraftTranslations(translationsId, translations, options) {
|
|
510
|
-
const docSlug = translationsId.replaceAll("/", "--");
|
|
511
|
-
const docPath = `Projects/${this.projectId}/TranslationsManager/draft/${docSlug}`;
|
|
512
|
-
const docRef = this.db.doc(docPath);
|
|
513
|
-
const snapshot = await docRef.get();
|
|
514
|
-
const data = snapshot.data() || {
|
|
515
|
-
id: translationsId.replaceAll("--", "/"),
|
|
516
|
-
sys: {},
|
|
517
|
-
strings: {}
|
|
518
|
-
};
|
|
519
|
-
data.sys.modifiedAt = Timestamp4.now();
|
|
520
|
-
data.sys.modifiedBy = (options == null ? void 0 : options.modifiedby) || "root-cms-client";
|
|
521
|
-
const strings = data.strings || {};
|
|
522
|
-
Object.entries(translations).forEach(([source, row]) => {
|
|
523
|
-
const normalizedSource = this.normalizeString(source);
|
|
524
|
-
const hash = this.getTranslationKey(normalizedSource);
|
|
525
|
-
strings[hash] = { ...strings[hash], ...row, source: normalizedSource };
|
|
526
|
-
});
|
|
527
|
-
data.strings = strings;
|
|
528
|
-
await docRef.set(data);
|
|
529
|
-
this.logAction("translations.save", { metadata: { translationsId } });
|
|
530
|
-
}
|
|
531
854
|
/**
|
|
532
855
|
* Returns the "key" used for a translation as stored in the db. Translations
|
|
533
856
|
* are stored under `Projects/<project id>/Translations/<sha1 hash>`.
|
|
534
857
|
*/
|
|
535
858
|
getTranslationKey(source) {
|
|
536
|
-
const sha1 =
|
|
859
|
+
const sha1 = crypto.createHash("sha1").update(this.normalizeString(source)).digest("hex");
|
|
537
860
|
return sha1;
|
|
538
861
|
}
|
|
539
862
|
/**
|
|
@@ -559,6 +882,25 @@ var RootCMSClient = class {
|
|
|
559
882
|
const translationsMap = await this.loadTranslations(options);
|
|
560
883
|
return translationsForLocale(translationsMap, locale);
|
|
561
884
|
}
|
|
885
|
+
/**
|
|
886
|
+
* Firestore path for a translations file.
|
|
887
|
+
*/
|
|
888
|
+
dbTranslationsPath(translationsId, options) {
|
|
889
|
+
const mode = options.mode;
|
|
890
|
+
if (!(mode === "draft" || mode === "published")) {
|
|
891
|
+
throw new Error(`invalid mode: ${mode}`);
|
|
892
|
+
}
|
|
893
|
+
const slug = translationsId.replaceAll("/", "--");
|
|
894
|
+
const dbPath = `Projects/${this.projectId}/TranslationsManager/${mode}/Translations/${slug}`;
|
|
895
|
+
return dbPath;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Firestore doc ref for a translations file.
|
|
899
|
+
*/
|
|
900
|
+
dbTranslationsRef(translationsId, options) {
|
|
901
|
+
const dbPath = this.dbTranslationsPath(translationsId, options);
|
|
902
|
+
return this.db.doc(dbPath);
|
|
903
|
+
}
|
|
562
904
|
/**
|
|
563
905
|
* Returns a data source configuration object.
|
|
564
906
|
*/
|
|
@@ -589,7 +931,7 @@ var RootCMSClient = class {
|
|
|
589
931
|
const syncedBy = (options == null ? void 0 : options.syncedBy) || "root-cms-client";
|
|
590
932
|
const updatedDataSource = {
|
|
591
933
|
...dataSource,
|
|
592
|
-
syncedAt:
|
|
934
|
+
syncedAt: Timestamp2.now(),
|
|
593
935
|
syncedBy
|
|
594
936
|
};
|
|
595
937
|
const batch = this.db.batch();
|
|
@@ -598,7 +940,7 @@ var RootCMSClient = class {
|
|
|
598
940
|
data
|
|
599
941
|
});
|
|
600
942
|
batch.update(dataSourceDocRef, {
|
|
601
|
-
syncedAt:
|
|
943
|
+
syncedAt: Timestamp2.now(),
|
|
602
944
|
syncedBy
|
|
603
945
|
});
|
|
604
946
|
await batch.commit();
|
|
@@ -623,25 +965,64 @@ var RootCMSClient = class {
|
|
|
623
965
|
const publishedBy = (options == null ? void 0 : options.publishedBy) || "root-cms-client";
|
|
624
966
|
const updatedDataSource = {
|
|
625
967
|
...dataSource,
|
|
626
|
-
publishedAt:
|
|
968
|
+
publishedAt: Timestamp2.now(),
|
|
627
969
|
publishedBy
|
|
628
970
|
};
|
|
629
971
|
const batch = this.db.batch();
|
|
630
972
|
batch.set(dataDocRefPublished, {
|
|
631
973
|
dataSource: updatedDataSource,
|
|
632
|
-
data: (dataRes == null ? void 0 : dataRes.data) || null
|
|
974
|
+
data: (dataRes == null ? void 0 : dataRes.data) || null,
|
|
975
|
+
...(dataRes == null ? void 0 : dataRes.headers) ? { headers: dataRes.headers } : {}
|
|
633
976
|
});
|
|
634
977
|
batch.update(dataDocRefDraft, {
|
|
635
978
|
dataSource: updatedDataSource
|
|
636
979
|
});
|
|
637
980
|
batch.update(dataSourceDocRef, {
|
|
638
|
-
publishedAt:
|
|
981
|
+
publishedAt: Timestamp2.now(),
|
|
639
982
|
publishedBy
|
|
640
983
|
});
|
|
641
984
|
await batch.commit();
|
|
642
985
|
console.log(`published data ${dataSourceId}`);
|
|
643
986
|
console.log(`published by: ${publishedBy}`);
|
|
644
987
|
}
|
|
988
|
+
async publishDataSources(dataSourceIds, options) {
|
|
989
|
+
const publishedBy = (options == null ? void 0 : options.publishedBy) || "root-cms-client";
|
|
990
|
+
const batch = (options == null ? void 0 : options.batch) || this.db.batch();
|
|
991
|
+
for (const id of dataSourceIds) {
|
|
992
|
+
const dataSource = await this.getDataSource(id);
|
|
993
|
+
if (!dataSource) {
|
|
994
|
+
throw new Error(`data source not found: ${id}`);
|
|
995
|
+
}
|
|
996
|
+
const dataSourceDocRef = this.db.doc(
|
|
997
|
+
`Projects/${this.projectId}/DataSources/${id}`
|
|
998
|
+
);
|
|
999
|
+
const dataDocRefDraft = this.db.doc(
|
|
1000
|
+
`Projects/${this.projectId}/DataSources/${id}/draft`
|
|
1001
|
+
);
|
|
1002
|
+
const dataDocRefPublished = this.db.doc(
|
|
1003
|
+
`Projects/${this.projectId}/DataSources/${id}/published`
|
|
1004
|
+
);
|
|
1005
|
+
const dataRes = await this.getFromDataSource(id, { mode: "draft" });
|
|
1006
|
+
const updatedDataSource = {
|
|
1007
|
+
...dataSource,
|
|
1008
|
+
publishedAt: FieldValue2.serverTimestamp(),
|
|
1009
|
+
publishedBy
|
|
1010
|
+
};
|
|
1011
|
+
batch.set(dataDocRefPublished, {
|
|
1012
|
+
dataSource: updatedDataSource,
|
|
1013
|
+
data: (dataRes == null ? void 0 : dataRes.data) || null,
|
|
1014
|
+
...(dataRes == null ? void 0 : dataRes.headers) ? { headers: dataRes.headers } : {}
|
|
1015
|
+
});
|
|
1016
|
+
batch.update(dataDocRefDraft, { dataSource: updatedDataSource });
|
|
1017
|
+
batch.update(dataSourceDocRef, {
|
|
1018
|
+
publishedAt: FieldValue2.serverTimestamp(),
|
|
1019
|
+
publishedBy
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
if (!(options == null ? void 0 : options.batch) || (options == null ? void 0 : options.commitBatch)) {
|
|
1023
|
+
await batch.commit();
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
645
1026
|
async fetchData(dataSource) {
|
|
646
1027
|
if (dataSource.type === "http") {
|
|
647
1028
|
return await this.fetchHttpData(dataSource);
|
|
@@ -674,6 +1055,12 @@ var RootCMSClient = class {
|
|
|
674
1055
|
*/
|
|
675
1056
|
async getFromDataSource(dataSourceId, options) {
|
|
676
1057
|
const mode = (options == null ? void 0 : options.mode) || "published";
|
|
1058
|
+
if (!(mode === "draft" || mode === "published")) {
|
|
1059
|
+
throw new Error(`invalid mode: ${mode}`);
|
|
1060
|
+
}
|
|
1061
|
+
if (!dataSourceId || dataSourceId.includes("/")) {
|
|
1062
|
+
throw new Error(`invalid data source id: ${dataSourceId}`);
|
|
1063
|
+
}
|
|
677
1064
|
const docRef = this.dbDataSourceDataRef(dataSourceId, { mode });
|
|
678
1065
|
const doc = await docRef.get();
|
|
679
1066
|
if (doc.exists) {
|
|
@@ -681,6 +1068,9 @@ var RootCMSClient = class {
|
|
|
681
1068
|
}
|
|
682
1069
|
return null;
|
|
683
1070
|
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Firestore path for a datasource data.
|
|
1073
|
+
*/
|
|
684
1074
|
dbDataSourceDataPath(dataSourceId, options) {
|
|
685
1075
|
if (!dataSourceId || dataSourceId.includes("/")) {
|
|
686
1076
|
throw new Error(`invalid data source id: ${dataSourceId}`);
|
|
@@ -692,23 +1082,13 @@ var RootCMSClient = class {
|
|
|
692
1082
|
const dbPath = `Projects/${this.projectId}/DataSources/${dataSourceId}/Data/${mode}`;
|
|
693
1083
|
return dbPath;
|
|
694
1084
|
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Firestore doc ref for a datasource data.
|
|
1087
|
+
*/
|
|
695
1088
|
dbDataSourceDataRef(dataSourceId, options) {
|
|
696
1089
|
const dbPath = this.dbDataSourceDataPath(dataSourceId, options);
|
|
697
1090
|
return this.db.doc(dbPath);
|
|
698
1091
|
}
|
|
699
|
-
dbTranslationsPath(translationsId, options) {
|
|
700
|
-
const mode = options.mode;
|
|
701
|
-
if (!(mode === "draft" || mode === "published")) {
|
|
702
|
-
throw new Error(`invalid mode: ${mode}`);
|
|
703
|
-
}
|
|
704
|
-
const slug = translationsId.replaceAll("/", "--");
|
|
705
|
-
const dbPath = `Projects/${this.projectId}/TranslationsManager/${mode}/Translations/${slug}`;
|
|
706
|
-
return dbPath;
|
|
707
|
-
}
|
|
708
|
-
dbTranslationsRef(translationsId, options) {
|
|
709
|
-
const dbPath = this.dbTranslationsPath(translationsId, options);
|
|
710
|
-
return this.db.doc(dbPath);
|
|
711
|
-
}
|
|
712
1092
|
/**
|
|
713
1093
|
* Gets the user's role from the project's ACL.
|
|
714
1094
|
*/
|
|
@@ -763,7 +1143,7 @@ var RootCMSClient = class {
|
|
|
763
1143
|
}
|
|
764
1144
|
const data = {
|
|
765
1145
|
action,
|
|
766
|
-
timestamp:
|
|
1146
|
+
timestamp: Timestamp2.now(),
|
|
767
1147
|
by: (options == null ? void 0 : options.by) || "system",
|
|
768
1148
|
metadata: (options == null ? void 0 : options.metadata) || {}
|
|
769
1149
|
};
|
|
@@ -780,10 +1160,158 @@ var RootCMSClient = class {
|
|
|
780
1160
|
}
|
|
781
1161
|
}
|
|
782
1162
|
}
|
|
1163
|
+
/**
|
|
1164
|
+
* Creates a batch request that is capable of fetching one or more docs,
|
|
1165
|
+
* corresponding translations, and dataSources.
|
|
1166
|
+
*/
|
|
783
1167
|
createBatchRequest(options) {
|
|
784
1168
|
return new BatchRequest(this, options);
|
|
785
1169
|
}
|
|
786
1170
|
};
|
|
1171
|
+
function isRichTextData(data) {
|
|
1172
|
+
return Boolean(
|
|
1173
|
+
isObject(data) && Array.isArray(data.blocks) && data.time && data.version
|
|
1174
|
+
);
|
|
1175
|
+
}
|
|
1176
|
+
function getCmsPlugin(rootConfig) {
|
|
1177
|
+
const plugins = rootConfig.plugins || [];
|
|
1178
|
+
const plugin = plugins.find((plugin2) => plugin2.name === "root-cms");
|
|
1179
|
+
if (!plugin) {
|
|
1180
|
+
throw new Error("could not find root-cms plugin config in root.config.ts");
|
|
1181
|
+
}
|
|
1182
|
+
return plugin;
|
|
1183
|
+
}
|
|
1184
|
+
function marshalData(data) {
|
|
1185
|
+
if (isRichTextData(data)) {
|
|
1186
|
+
return data;
|
|
1187
|
+
}
|
|
1188
|
+
const result = {};
|
|
1189
|
+
for (const key in data) {
|
|
1190
|
+
const val = data[key];
|
|
1191
|
+
if (isObject(val)) {
|
|
1192
|
+
result[key] = marshalData(val);
|
|
1193
|
+
} else if (Array.isArray(val)) {
|
|
1194
|
+
if (val.length > 0 && val.some((item) => isObject(item))) {
|
|
1195
|
+
const items = val.map((item) => {
|
|
1196
|
+
if (isObject(item)) {
|
|
1197
|
+
return marshalData(item);
|
|
1198
|
+
}
|
|
1199
|
+
return item;
|
|
1200
|
+
});
|
|
1201
|
+
result[key] = toArrayObject(items);
|
|
1202
|
+
} else {
|
|
1203
|
+
result[key] = val;
|
|
1204
|
+
}
|
|
1205
|
+
} else {
|
|
1206
|
+
result[key] = val;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
return result;
|
|
1210
|
+
}
|
|
1211
|
+
function unmarshalData(data) {
|
|
1212
|
+
const result = {};
|
|
1213
|
+
for (const key in data) {
|
|
1214
|
+
const val = data[key];
|
|
1215
|
+
if (isObject(val)) {
|
|
1216
|
+
if (val.toMillis) {
|
|
1217
|
+
result[key] = val.toMillis();
|
|
1218
|
+
} else if (Object.hasOwn(val, "_array") && Array.isArray(val._array)) {
|
|
1219
|
+
const arr = val._array.map((arrayKey) => {
|
|
1220
|
+
return {
|
|
1221
|
+
...unmarshalData(val[arrayKey] || {}),
|
|
1222
|
+
_arrayKey: arrayKey
|
|
1223
|
+
};
|
|
1224
|
+
});
|
|
1225
|
+
result[key] = arr;
|
|
1226
|
+
} else {
|
|
1227
|
+
result[key] = unmarshalData(val);
|
|
1228
|
+
}
|
|
1229
|
+
} else {
|
|
1230
|
+
result[key] = val;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
return result;
|
|
1234
|
+
}
|
|
1235
|
+
function normalizeData(data) {
|
|
1236
|
+
return unmarshalData(data);
|
|
1237
|
+
}
|
|
1238
|
+
function toArrayObject(arr) {
|
|
1239
|
+
if (!Array.isArray(arr)) {
|
|
1240
|
+
return arr;
|
|
1241
|
+
}
|
|
1242
|
+
const arrObject = { _array: [] };
|
|
1243
|
+
for (const item of arr) {
|
|
1244
|
+
const key = randString(6);
|
|
1245
|
+
arrObject[key] = item;
|
|
1246
|
+
arrObject._array.push(key);
|
|
1247
|
+
}
|
|
1248
|
+
return arrObject;
|
|
1249
|
+
}
|
|
1250
|
+
var marshalArray = toArrayObject;
|
|
1251
|
+
function unmarshalArray(arrObject) {
|
|
1252
|
+
if (!Array.isArray(arrObject == null ? void 0 : arrObject._array)) {
|
|
1253
|
+
return [];
|
|
1254
|
+
}
|
|
1255
|
+
const arr = arrObject._array.map((k) => arrObject[k]);
|
|
1256
|
+
return arr;
|
|
1257
|
+
}
|
|
1258
|
+
function isObject(data) {
|
|
1259
|
+
return typeof data === "object" && !Array.isArray(data) && data !== null;
|
|
1260
|
+
}
|
|
1261
|
+
function randString(len) {
|
|
1262
|
+
const result = [];
|
|
1263
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
1264
|
+
for (let i = 0; i < len; i++) {
|
|
1265
|
+
const rand = Math.floor(Math.random() * chars.length);
|
|
1266
|
+
result.push(chars.charAt(rand));
|
|
1267
|
+
}
|
|
1268
|
+
return result.join("");
|
|
1269
|
+
}
|
|
1270
|
+
function translationsForLocale(translationsMap, locale) {
|
|
1271
|
+
const localeTranslations = {};
|
|
1272
|
+
Object.values(translationsMap).forEach((string2) => {
|
|
1273
|
+
const source = string2.source;
|
|
1274
|
+
const translation = string2[locale] || string2.en || string2.source;
|
|
1275
|
+
localeTranslations[source] = translation;
|
|
1276
|
+
});
|
|
1277
|
+
return localeTranslations;
|
|
1278
|
+
}
|
|
1279
|
+
function stringifyObj(obj) {
|
|
1280
|
+
function format(obj2) {
|
|
1281
|
+
if (obj2 === null) {
|
|
1282
|
+
return "null";
|
|
1283
|
+
}
|
|
1284
|
+
if (typeof obj2 === "undefined") {
|
|
1285
|
+
return "undefined";
|
|
1286
|
+
}
|
|
1287
|
+
if (typeof obj2 === "string") {
|
|
1288
|
+
return `"${obj2.replaceAll('"', '\\"')}"`;
|
|
1289
|
+
}
|
|
1290
|
+
if (typeof obj2 !== "object") {
|
|
1291
|
+
return String(obj2);
|
|
1292
|
+
}
|
|
1293
|
+
if (Array.isArray(obj2)) {
|
|
1294
|
+
return `[${obj2.map(format).join(", ")}]`;
|
|
1295
|
+
}
|
|
1296
|
+
const entries = Object.entries(obj2).map(([key, value]) => {
|
|
1297
|
+
return `${key}: ${format(value)}`;
|
|
1298
|
+
});
|
|
1299
|
+
return `{${entries.join(", ")}}`;
|
|
1300
|
+
}
|
|
1301
|
+
return format(obj);
|
|
1302
|
+
}
|
|
1303
|
+
function parseDocId(docId) {
|
|
1304
|
+
const sepIndex = docId.indexOf("/");
|
|
1305
|
+
if (sepIndex <= 0) {
|
|
1306
|
+
throw new Error(`invalid doc id: ${docId}`);
|
|
1307
|
+
}
|
|
1308
|
+
const collection2 = docId.slice(0, sepIndex);
|
|
1309
|
+
const slug = docId.slice(sepIndex + 1).replaceAll("/", "--");
|
|
1310
|
+
if (!collection2 || !slug) {
|
|
1311
|
+
throw new Error(`invalid doc id: ${docId}`);
|
|
1312
|
+
}
|
|
1313
|
+
return { collection: collection2, slug };
|
|
1314
|
+
}
|
|
787
1315
|
var BatchRequest = class {
|
|
788
1316
|
constructor(cmsClient, options) {
|
|
789
1317
|
this.docIds = [];
|
|
@@ -953,6 +1481,8 @@ var BatchResponse = class {
|
|
|
953
1481
|
* The input is either a single locale (e.g. "de") or an array of locales
|
|
954
1482
|
* representing the fallback tree, e.g. ["en-CA", "en-GB", "en"].
|
|
955
1483
|
*
|
|
1484
|
+
* TODO(stevenle): support the locale fallback tree.
|
|
1485
|
+
*
|
|
956
1486
|
* The returned value is a flat map of source string to translated string,
|
|
957
1487
|
* e.g.:
|
|
958
1488
|
* {"<source>": "<translation>"}
|
|
@@ -986,348 +1516,9 @@ var BatchResponse = class {
|
|
|
986
1516
|
return translationsMap;
|
|
987
1517
|
}
|
|
988
1518
|
};
|
|
989
|
-
function isRichTextData(data) {
|
|
990
|
-
return Boolean(
|
|
991
|
-
isObject(data) && Array.isArray(data.blocks) && data.time && data.version
|
|
992
|
-
);
|
|
993
|
-
}
|
|
994
|
-
function marshalData(data) {
|
|
995
|
-
if (isRichTextData(data)) {
|
|
996
|
-
return data;
|
|
997
|
-
}
|
|
998
|
-
const result = {};
|
|
999
|
-
for (const key in data) {
|
|
1000
|
-
const val = data[key];
|
|
1001
|
-
if (isObject(val)) {
|
|
1002
|
-
result[key] = marshalData(val);
|
|
1003
|
-
} else if (Array.isArray(val)) {
|
|
1004
|
-
if (val.length > 0 && val.some((item) => isObject(item))) {
|
|
1005
|
-
const items = val.map((item) => {
|
|
1006
|
-
if (isObject(item)) {
|
|
1007
|
-
return marshalData(item);
|
|
1008
|
-
}
|
|
1009
|
-
return item;
|
|
1010
|
-
});
|
|
1011
|
-
result[key] = toArrayObject(items);
|
|
1012
|
-
} else {
|
|
1013
|
-
result[key] = val;
|
|
1014
|
-
}
|
|
1015
|
-
} else {
|
|
1016
|
-
result[key] = val;
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
return result;
|
|
1020
|
-
}
|
|
1021
|
-
function unmarshalData(data) {
|
|
1022
|
-
const result = {};
|
|
1023
|
-
for (const key in data) {
|
|
1024
|
-
const val = data[key];
|
|
1025
|
-
if (isObject(val)) {
|
|
1026
|
-
if (val.toMillis) {
|
|
1027
|
-
result[key] = val.toMillis();
|
|
1028
|
-
} else if (Object.hasOwn(val, "_array") && Array.isArray(val._array)) {
|
|
1029
|
-
const arr = val._array.map((arrayKey) => {
|
|
1030
|
-
return {
|
|
1031
|
-
...unmarshalData(val[arrayKey] || {}),
|
|
1032
|
-
_arrayKey: arrayKey
|
|
1033
|
-
};
|
|
1034
|
-
});
|
|
1035
|
-
result[key] = arr;
|
|
1036
|
-
} else {
|
|
1037
|
-
result[key] = unmarshalData(val);
|
|
1038
|
-
}
|
|
1039
|
-
} else {
|
|
1040
|
-
result[key] = val;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
return result;
|
|
1044
|
-
}
|
|
1045
|
-
function normalizeData(data) {
|
|
1046
|
-
return unmarshalData(data);
|
|
1047
|
-
}
|
|
1048
|
-
function toArrayObject(arr) {
|
|
1049
|
-
if (!Array.isArray(arr)) {
|
|
1050
|
-
return arr;
|
|
1051
|
-
}
|
|
1052
|
-
const arrObject = { _array: [] };
|
|
1053
|
-
for (const item of arr) {
|
|
1054
|
-
const key = randString(6);
|
|
1055
|
-
arrObject[key] = item;
|
|
1056
|
-
arrObject._array.push(key);
|
|
1057
|
-
}
|
|
1058
|
-
return arrObject;
|
|
1059
|
-
}
|
|
1060
|
-
var marshalArray = toArrayObject;
|
|
1061
|
-
function unmarshalArray(arrObject) {
|
|
1062
|
-
if (!Array.isArray(arrObject == null ? void 0 : arrObject._array)) {
|
|
1063
|
-
return [];
|
|
1064
|
-
}
|
|
1065
|
-
const arr = arrObject._array.map((k) => arrObject[k]);
|
|
1066
|
-
return arr;
|
|
1067
|
-
}
|
|
1068
|
-
function isObject(data) {
|
|
1069
|
-
return typeof data === "object" && !Array.isArray(data) && data !== null;
|
|
1070
|
-
}
|
|
1071
|
-
function randString(len) {
|
|
1072
|
-
const result = [];
|
|
1073
|
-
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
1074
|
-
for (let i = 0; i < len; i++) {
|
|
1075
|
-
const rand = Math.floor(Math.random() * chars.length);
|
|
1076
|
-
result.push(chars.charAt(rand));
|
|
1077
|
-
}
|
|
1078
|
-
return result.join("");
|
|
1079
|
-
}
|
|
1080
|
-
function translationsForLocale(translationsMap, locale) {
|
|
1081
|
-
const localeTranslations = {};
|
|
1082
|
-
const fallbackLocales = Array.isArray(locale) ? locale : [locale];
|
|
1083
|
-
if (!fallbackLocales.includes("en")) {
|
|
1084
|
-
fallbackLocales.push("en");
|
|
1085
|
-
}
|
|
1086
|
-
Object.values(translationsMap).forEach((string2) => {
|
|
1087
|
-
const source = string2.source;
|
|
1088
|
-
let translation = source;
|
|
1089
|
-
for (const fallbackLocale of fallbackLocales) {
|
|
1090
|
-
if (string2[fallbackLocale]) {
|
|
1091
|
-
translation = string2[fallbackLocale];
|
|
1092
|
-
break;
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
localeTranslations[source] = translation;
|
|
1096
|
-
});
|
|
1097
|
-
return localeTranslations;
|
|
1098
|
-
}
|
|
1099
|
-
function stringifyObj(obj) {
|
|
1100
|
-
function format(obj2) {
|
|
1101
|
-
if (obj2 === null) {
|
|
1102
|
-
return "null";
|
|
1103
|
-
}
|
|
1104
|
-
if (typeof obj2 === "undefined") {
|
|
1105
|
-
return "undefined";
|
|
1106
|
-
}
|
|
1107
|
-
if (typeof obj2 === "string") {
|
|
1108
|
-
return `"${obj2.replaceAll('"', '\\"')}"`;
|
|
1109
|
-
}
|
|
1110
|
-
if (typeof obj2 !== "object") {
|
|
1111
|
-
return String(obj2);
|
|
1112
|
-
}
|
|
1113
|
-
if (Array.isArray(obj2)) {
|
|
1114
|
-
return `[${obj2.map(format).join(", ")}]`;
|
|
1115
|
-
}
|
|
1116
|
-
const entries = Object.entries(obj2).map(([key, value]) => {
|
|
1117
|
-
return `${key}: ${format(value)}`;
|
|
1118
|
-
});
|
|
1119
|
-
return `{${entries.join(", ")}}`;
|
|
1120
|
-
}
|
|
1121
|
-
return format(obj);
|
|
1122
|
-
}
|
|
1123
|
-
function parseDocId(docId) {
|
|
1124
|
-
const sepIndex = docId.indexOf("/");
|
|
1125
|
-
if (sepIndex <= 0) {
|
|
1126
|
-
throw new Error(`invalid doc id: ${docId}`);
|
|
1127
|
-
}
|
|
1128
|
-
const collection2 = docId.slice(0, sepIndex);
|
|
1129
|
-
const slug = docId.slice(sepIndex + 1).replaceAll("/", "--");
|
|
1130
|
-
if (!collection2 || !slug) {
|
|
1131
|
-
throw new Error(`invalid doc id: ${docId}`);
|
|
1132
|
-
}
|
|
1133
|
-
return { collection: collection2, slug };
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
// core/cms-route.ts
|
|
1137
|
-
function cmsRoute(options) {
|
|
1138
|
-
let cmsClient = null;
|
|
1139
|
-
function getSlug(params) {
|
|
1140
|
-
if (options.slug) {
|
|
1141
|
-
return options.slug;
|
|
1142
|
-
}
|
|
1143
|
-
const slugParam = options.slugParam || "slug";
|
|
1144
|
-
return (params[slugParam] || "index").replaceAll("/", "--");
|
|
1145
|
-
}
|
|
1146
|
-
async function fetchData(fetchOptions) {
|
|
1147
|
-
if (!options.fetchData) {
|
|
1148
|
-
return {};
|
|
1149
|
-
}
|
|
1150
|
-
const promisesMap = options.fetchData(fetchOptions);
|
|
1151
|
-
return resolvePromisesMap(promisesMap);
|
|
1152
|
-
}
|
|
1153
|
-
async function generateProps(routeContext, preferredLocale) {
|
|
1154
|
-
var _a, _b;
|
|
1155
|
-
const { slug, mode } = routeContext;
|
|
1156
|
-
const primaryDocId = `${options.collection}/${slug}`;
|
|
1157
|
-
let batchRequest = routeContext.cmsClient.createBatchRequest({
|
|
1158
|
-
mode,
|
|
1159
|
-
translate: true
|
|
1160
|
-
});
|
|
1161
|
-
batchRequest.addDoc(primaryDocId);
|
|
1162
|
-
if (options.preRequestHook) {
|
|
1163
|
-
const overridedBatchRequest = options.preRequestHook(
|
|
1164
|
-
batchRequest,
|
|
1165
|
-
routeContext
|
|
1166
|
-
);
|
|
1167
|
-
if (overridedBatchRequest) {
|
|
1168
|
-
batchRequest = overridedBatchRequest;
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
const [batchRes, data] = await Promise.all([
|
|
1172
|
-
batchRequest.fetch(),
|
|
1173
|
-
fetchData(routeContext)
|
|
1174
|
-
]);
|
|
1175
|
-
const doc = batchRes.docs[primaryDocId];
|
|
1176
|
-
if (!doc) {
|
|
1177
|
-
return { notFound: true };
|
|
1178
|
-
}
|
|
1179
|
-
let locale;
|
|
1180
|
-
if (typeof preferredLocale === "string") {
|
|
1181
|
-
locale = preferredLocale;
|
|
1182
|
-
} else {
|
|
1183
|
-
locale = preferredLocale(doc);
|
|
1184
|
-
}
|
|
1185
|
-
const docLocales = ((_a = doc.sys) == null ? void 0 : _a.locales) || ["en"];
|
|
1186
|
-
if (!locale || !docLocales.includes(locale)) {
|
|
1187
|
-
return { notFound: true };
|
|
1188
|
-
}
|
|
1189
|
-
const i18nFallbacks = ((_b = routeContext.cmsClient.rootConfig.i18n) == null ? void 0 : _b.fallbacks) || {};
|
|
1190
|
-
const translationFallbackLocales = i18nFallbacks[locale] || [locale];
|
|
1191
|
-
const translations = batchRes.getTranslations(translationFallbackLocales);
|
|
1192
|
-
let props = { ...data, locale, mode, slug, doc };
|
|
1193
|
-
if (routeContext.req) {
|
|
1194
|
-
const country = getFirstQueryParam(routeContext.req, "gl") || routeContext.req.get("x-country-code") || routeContext.req.get("x-appengine-country") || null;
|
|
1195
|
-
props.country = country;
|
|
1196
|
-
}
|
|
1197
|
-
if (options.preRenderHook) {
|
|
1198
|
-
props = await options.preRenderHook(props, routeContext);
|
|
1199
|
-
}
|
|
1200
|
-
return { props, locale, translations };
|
|
1201
|
-
}
|
|
1202
|
-
let getStaticPaths = null;
|
|
1203
|
-
let getStaticProps = null;
|
|
1204
|
-
if (options.enableSSG) {
|
|
1205
|
-
getStaticPaths = async (ctx) => {
|
|
1206
|
-
if (!options.slugParam) {
|
|
1207
|
-
return { paths: [] };
|
|
1208
|
-
}
|
|
1209
|
-
if (!cmsClient) {
|
|
1210
|
-
cmsClient = new RootCMSClient(ctx.rootConfig);
|
|
1211
|
-
}
|
|
1212
|
-
const mode = "published";
|
|
1213
|
-
const res = await cmsClient.listDocs(options.collection, { mode });
|
|
1214
|
-
const ssgPaths = [];
|
|
1215
|
-
res.docs.forEach((doc) => {
|
|
1216
|
-
const params = {};
|
|
1217
|
-
params[options.slugParam] = doc.slug;
|
|
1218
|
-
ssgPaths.push({ params });
|
|
1219
|
-
});
|
|
1220
|
-
return { paths: ssgPaths };
|
|
1221
|
-
};
|
|
1222
|
-
getStaticProps = async (ctx) => {
|
|
1223
|
-
if (!cmsClient) {
|
|
1224
|
-
cmsClient = new RootCMSClient(ctx.rootConfig);
|
|
1225
|
-
}
|
|
1226
|
-
const slug = getSlug(ctx.params);
|
|
1227
|
-
const mode = "published";
|
|
1228
|
-
const routeContext = { slug, mode, cmsClient };
|
|
1229
|
-
return generateProps(routeContext, ctx.params.$locale);
|
|
1230
|
-
};
|
|
1231
|
-
}
|
|
1232
|
-
return {
|
|
1233
|
-
// SSG handlers (only enabled with `{enableSSG: true}`).
|
|
1234
|
-
getStaticPaths,
|
|
1235
|
-
getStaticProps,
|
|
1236
|
-
// SSR handler.
|
|
1237
|
-
handle: async (req, res) => {
|
|
1238
|
-
if (!cmsClient) {
|
|
1239
|
-
cmsClient = new RootCMSClient(req.rootConfig);
|
|
1240
|
-
}
|
|
1241
|
-
req.cmsClient = cmsClient;
|
|
1242
|
-
const ctx = req.handlerContext;
|
|
1243
|
-
const slug = getSlug(ctx.params);
|
|
1244
|
-
if (slug.includes(".")) {
|
|
1245
|
-
res.setHeader("cache-control", "private");
|
|
1246
|
-
return ctx.render404();
|
|
1247
|
-
}
|
|
1248
|
-
const mode = String(req.query.preview) === "true" ? "draft" : "published";
|
|
1249
|
-
const routeContext = { req, slug, mode, cmsClient };
|
|
1250
|
-
function getLocale(doc) {
|
|
1251
|
-
var _a;
|
|
1252
|
-
const docLocales = ((_a = doc.sys) == null ? void 0 : _a.locales) || ["en"];
|
|
1253
|
-
let locale2 = ctx.route.locale;
|
|
1254
|
-
if (ctx.route.isDefaultLocale) {
|
|
1255
|
-
locale2 = ctx.getPreferredLocale(docLocales);
|
|
1256
|
-
if (docLocales.length > 0 && !docLocales.includes(locale2)) {
|
|
1257
|
-
locale2 = docLocales[0];
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
return locale2;
|
|
1261
|
-
}
|
|
1262
|
-
const resData = await generateProps(routeContext, getLocale);
|
|
1263
|
-
if (resData.notFound) {
|
|
1264
|
-
res.setHeader("cache-control", "private");
|
|
1265
|
-
return ctx.render404();
|
|
1266
|
-
}
|
|
1267
|
-
const { props, locale, translations } = resData;
|
|
1268
|
-
if (props.$redirect) {
|
|
1269
|
-
const redirectCode = props.$redirectCode || 302;
|
|
1270
|
-
console.log(`redirecting to: ${props.$redirect} (${redirectCode})`);
|
|
1271
|
-
redirectWithQuery(req, res, redirectCode, props.$redirect);
|
|
1272
|
-
return;
|
|
1273
|
-
}
|
|
1274
|
-
if (options.disableCacheControl) {
|
|
1275
|
-
res.setHeader("cache-control", "private");
|
|
1276
|
-
} else if (mode === "published") {
|
|
1277
|
-
res.setHeader("cache-control", "public, max-age=15, s-maxage=30");
|
|
1278
|
-
if (ctx.route.isDefaultLocale) {
|
|
1279
|
-
res.setHeader("vary", "accept-language, x-country-code");
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
if (options.setResponseHeaders) {
|
|
1283
|
-
options.setResponseHeaders(req, res);
|
|
1284
|
-
}
|
|
1285
|
-
return ctx.render(props, { locale, translations });
|
|
1286
|
-
}
|
|
1287
|
-
};
|
|
1288
|
-
}
|
|
1289
|
-
async function resolvePromisesMap(promisesMap) {
|
|
1290
|
-
const keys = Object.keys(promisesMap);
|
|
1291
|
-
const promises = Object.values(promisesMap);
|
|
1292
|
-
const results = await Promise.all(promises);
|
|
1293
|
-
const resultMap = {};
|
|
1294
|
-
keys.forEach((key, index) => {
|
|
1295
|
-
resultMap[key] = results[index];
|
|
1296
|
-
});
|
|
1297
|
-
return resultMap;
|
|
1298
|
-
}
|
|
1299
|
-
function getFirstQueryParam(req, key) {
|
|
1300
|
-
const val = req.query[key];
|
|
1301
|
-
if (val === null || val === void 0) {
|
|
1302
|
-
return null;
|
|
1303
|
-
}
|
|
1304
|
-
if (Array.isArray(val)) {
|
|
1305
|
-
if (val.length === 0) {
|
|
1306
|
-
return null;
|
|
1307
|
-
}
|
|
1308
|
-
return String(val[0]);
|
|
1309
|
-
}
|
|
1310
|
-
return String(val);
|
|
1311
|
-
}
|
|
1312
|
-
function redirectWithQuery(req, res, redirectCode, redirectPath) {
|
|
1313
|
-
if (!redirectPath.startsWith("/")) {
|
|
1314
|
-
res.redirect(redirectCode, redirectPath);
|
|
1315
|
-
return;
|
|
1316
|
-
}
|
|
1317
|
-
const queryStr = getQueryStr(req);
|
|
1318
|
-
const redirectUrl = queryStr ? `${redirectPath}?${queryStr}` : redirectPath;
|
|
1319
|
-
res.redirect(redirectCode, redirectUrl);
|
|
1320
|
-
}
|
|
1321
|
-
function getQueryStr(req) {
|
|
1322
|
-
const qIndex = req.originalUrl.indexOf("?");
|
|
1323
|
-
if (qIndex === -1) {
|
|
1324
|
-
return "";
|
|
1325
|
-
}
|
|
1326
|
-
return req.originalUrl.slice(qIndex + 1);
|
|
1327
|
-
}
|
|
1328
1519
|
|
|
1329
1520
|
// core/runtime.ts
|
|
1330
|
-
import { FieldValue as
|
|
1521
|
+
import { FieldValue as FieldValue3 } from "firebase-admin/firestore";
|
|
1331
1522
|
async function getDoc(rootConfig, collectionId, slug, options) {
|
|
1332
1523
|
const cmsPlugin = getCmsPlugin(rootConfig);
|
|
1333
1524
|
const cmsPluginOptions = cmsPlugin.getConfig();
|
|
@@ -1449,7 +1640,7 @@ async function publishScheduledDocs(rootConfig) {
|
|
|
1449
1640
|
...sys,
|
|
1450
1641
|
firstPublishedAt,
|
|
1451
1642
|
firstPublishedBy,
|
|
1452
|
-
publishedAt:
|
|
1643
|
+
publishedAt: FieldValue3.serverTimestamp(),
|
|
1453
1644
|
publishedBy: scheduledBy || ""
|
|
1454
1645
|
}
|
|
1455
1646
|
});
|
|
@@ -1457,11 +1648,11 @@ async function publishScheduledDocs(rootConfig) {
|
|
|
1457
1648
|
batch.delete(scheduledRef);
|
|
1458
1649
|
batchCount += 1;
|
|
1459
1650
|
batch.update(draftRef, {
|
|
1460
|
-
"sys.scheduledAt":
|
|
1461
|
-
"sys.scheduledBy":
|
|
1651
|
+
"sys.scheduledAt": FieldValue3.delete(),
|
|
1652
|
+
"sys.scheduledBy": FieldValue3.delete(),
|
|
1462
1653
|
"sys.firstPublishedAt": firstPublishedAt,
|
|
1463
1654
|
"sys.firstPublishedBy": firstPublishedBy,
|
|
1464
|
-
"sys.publishedAt":
|
|
1655
|
+
"sys.publishedAt": FieldValue3.serverTimestamp(),
|
|
1465
1656
|
"sys.publishedBy": scheduledBy || ""
|
|
1466
1657
|
});
|
|
1467
1658
|
batchCount += 1;
|
|
@@ -1573,7 +1764,9 @@ export {
|
|
|
1573
1764
|
BatchRequest,
|
|
1574
1765
|
BatchResponse,
|
|
1575
1766
|
RootCMSClient,
|
|
1576
|
-
|
|
1767
|
+
TranslationsManager,
|
|
1768
|
+
buildTranslationsDbPath,
|
|
1769
|
+
buildTranslationsLocaleDocDbPath,
|
|
1577
1770
|
getCmsPlugin,
|
|
1578
1771
|
getDoc,
|
|
1579
1772
|
isRichTextData,
|
|
@@ -1586,12 +1779,9 @@ export {
|
|
|
1586
1779
|
numDocs,
|
|
1587
1780
|
parseDocId,
|
|
1588
1781
|
publishScheduledDocs,
|
|
1589
|
-
redirectWithQuery,
|
|
1590
|
-
resolvePromisesMap,
|
|
1591
1782
|
schema_exports as schema,
|
|
1592
1783
|
toArrayObject,
|
|
1593
1784
|
translationsForLocale,
|
|
1594
1785
|
unmarshalArray,
|
|
1595
1786
|
unmarshalData
|
|
1596
1787
|
};
|
|
1597
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vY29yZS9jbGllbnQudHMiLCAiLi4vY29yZS9wbHVnaW4udHMiLCAiLi4vY29yZS9hcGkudHMiLCAiLi4vY29yZS9haS50cyIsICIuLi9jb3JlL3ZlcnNpb25zLnRzIiwgIi4uL2NvcmUvY3N2LnRzIiwgIi4uL2NvcmUvY29tcGF0aWJpbGl0eS50cyIsICIuLi9jb3JlL2Ntcy1yb3V0ZS50cyIsICIuLi9jb3JlL3J1bnRpbWUudHMiLCAiLi4vY29yZS9zY2hlbWEudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCBjcnlwdG8gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0IHR5cGUge1Jvb3RDb25maWd9IGZyb20gJ0BibGlua2svcm9vdCc7XG5pbXBvcnQge0FwcH0gZnJvbSAnZmlyZWJhc2UtYWRtaW4vYXBwJztcbmltcG9ydCB7XG4gIEZpZWxkVmFsdWUsXG4gIEZpcmVzdG9yZSxcbiAgUXVlcnksXG4gIFRpbWVzdGFtcCxcbiAgV3JpdGVCYXRjaCxcbn0gZnJvbSAnZmlyZWJhc2UtYWRtaW4vZmlyZXN0b3JlJztcbmltcG9ydCB7Q01TUGx1Z2luLCBnZXRDbXNQbHVnaW59IGZyb20gJy4vcGx1Z2luLmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBEb2M8RmllbGRzID0gYW55PiB7XG4gIC8qKiBUaGUgaWQgb2YgdGhlIGRvYywgZS5nLiBcIlBhZ2VzL2Zvby1iYXJcIi4gKi9cbiAgaWQ6IHN0cmluZztcbiAgLyoqIFRoZSBjb2xsZWN0aW9uIGlkIG9mIHRoZSBkb2MsIGUuZy4gXCJQYWdlc1wiLiAqL1xuICBjb2xsZWN0aW9uOiBzdHJpbmc7XG4gIC8qKiBUaGUgc2x1ZyBvZiB0aGUgZG9jLCBlLmcuIFwiZm9vLWJhclwiLiAqL1xuICBzbHVnOiBzdHJpbmc7XG4gIHN5czoge1xuICAgIGNyZWF0ZWRBdDogbnVtYmVyO1xuICAgIGNyZWF0ZWRCeTogc3RyaW5nO1xuICAgIG1vZGlmaWVkQXQ6IG51bWJlcjtcbiAgICBtb2RpZmllZEJ5OiBzdHJpbmc7XG4gICAgZmlyc3RQdWJsaXNoZWRBdD86IG51bWJlcjtcbiAgICBmaXJzdFB1Ymxpc2hlZEJ5Pzogc3RyaW5nO1xuICAgIHB1Ymxpc2hlZEF0PzogbnVtYmVyO1xuICAgIHB1Ymxpc2hlZEJ5Pzogc3RyaW5nO1xuICAgIHB1Ymxpc2hpbmdMb2NrZWQ6IHtcbiAgICAgIGxvY2tlZEF0OiBzdHJpbmc7XG4gICAgICBsb2NrZWRCeTogc3RyaW5nO1xuICAgICAgcmVhc29uOiBzdHJpbmc7XG4gICAgICB1bnRpbD86IFRpbWVzdGFtcDtcbiAgICB9O1xuICAgIGxvY2FsZXM/OiBzdHJpbmdbXTtcbiAgfTtcbiAgZmllbGRzOiBGaWVsZHM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNsYXRpb25zRG9jIHtcbiAgaWQ6IHN0cmluZztcbiAgc3lzOiB7XG4gICAgbW9kaWZpZWRBdDogVGltZXN0YW1wO1xuICAgIG1vZGlmaWVkQnk6IHN0cmluZztcbiAgICBwdWJsaXNoZWRBdD86IFRpbWVzdGFtcDtcbiAgICBwdWJsaXNoZWRCeT86IHN0cmluZztcbiAgICBsaW5rZWRTaGVldD86IHtcbiAgICAgIHNwcmVhZHNoZWV0SWQ6IHN0cmluZztcbiAgICAgIGdpZDogbnVtYmVyO1xuICAgICAgbGlua2VkQXQ6IFRpbWVzdGFtcDtcbiAgICAgIGxpbmtlZEJ5OiBzdHJpbmc7XG4gICAgfTtcbiAgICB0YWdzPzogc3RyaW5nW107XG4gIH07XG4gIHN0cmluZ3M6IFRyYW5zbGF0aW9uc01hcDtcbn1cblxuZXhwb3J0IHR5cGUgRG9jTW9kZSA9ICdkcmFmdCcgfCAncHVibGlzaGVkJztcblxuZXhwb3J0IHR5cGUgVXNlclJvbGUgPSAnQURNSU4nIHwgJ0VESVRPUicgfCAnVklFV0VSJztcblxuZXhwb3J0IHR5cGUgSHR0cE1ldGhvZCA9ICdHRVQnIHwgJ1BPU1QnO1xuXG5leHBvcnQgaW50ZXJmYWNlIERhdGFTb3VyY2Uge1xuICBpZDogc3RyaW5nO1xuICBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgdHlwZTogJ2h0dHAnIHwgJ2dzaGVldCc7XG4gIHVybDogc3RyaW5nO1xuICAvKipcbiAgICogQ3VycmVudGx5IG9ubHkgdXNlZCBieSBnc2hlZXQuIGBhcnJheWAgcmV0dXJucyB0aGUgc2hlZXQgYXMgYW4gYXJyYXkgb2ZcbiAgICogYXJyYXlzLCBgbWFwYCByZXR1cm5zIHRoZSBzaGVldCBhcyBhbiBhcnJheSBvZiBvYmplY3RzLlxuICAgKi9cbiAgZGF0YUZvcm1hdD86ICdhcnJheScgfCAnbWFwJztcbiAgLyoqXG4gICAqIE9wdGlvbnMgZm9yIEhUVFAgcmVxdWVzdHMuXG4gICAqL1xuICBodHRwT3B0aW9ucz86IHtcbiAgICBtZXRob2Q6IEh0dHBNZXRob2Q7XG4gICAgaGVhZGVycz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gICAgYm9keT86IHN0cmluZztcbiAgfTtcbiAgY3JlYXRlZEF0OiBUaW1lc3RhbXA7XG4gIGNyZWF0ZWRCeTogc3RyaW5nO1xuICBzeW5jZWRBdD86IFRpbWVzdGFtcDtcbiAgc3luY2VkQnk/OiBzdHJpbmc7XG4gIHB1Ymxpc2hlZEF0PzogVGltZXN0YW1wO1xuICBwdWJsaXNoZWRCeT86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEYXRhU291cmNlRGF0YTxUID0gYW55PiB7XG4gIGRhdGFTb3VyY2U6IERhdGFTb3VyY2U7XG4gIGRhdGE6IFQ7XG59XG5cbmV4cG9ydCB0eXBlIERhdGFTb3VyY2VNb2RlID0gJ2RyYWZ0JyB8ICdwdWJsaXNoZWQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdldERvY09wdGlvbnMge1xuICAvKiogTW9kZSwgZWl0aGVyIFwiZHJhZnRcIiBvciBcInB1Ymxpc2hlZFwiLiAqL1xuICBtb2RlOiBEb2NNb2RlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNldERvY09wdGlvbnMge1xuICAvKiogTW9kZSwgZWl0aGVyIFwiZHJhZnRcIiBvciBcInB1Ymxpc2hlZFwiLiAqL1xuICBtb2RlOiBEb2NNb2RlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNhdmVEcmFmdE9wdGlvbnMge1xuICAvKipcbiAgICogTG9jYWxlcyB0byBlbmFibGUuXG4gICAqL1xuICBsb2NhbGVzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEVtYWlsIG9mIHVzZXIgbW9kaWZ5aW5nIHRoZSBkb2MuIElmIGJsYW5rLCBkZWZhdWx0cyB0byBgcm9vdC1jbXMtY2xpZW50YC5cbiAgICovXG4gIG1vZGlmaWVkQnk/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGlzdERvY3NPcHRpb25zIHtcbiAgbW9kZTogRG9jTW9kZTtcbiAgb2Zmc2V0PzogbnVtYmVyO1xuICBsaW1pdD86IG51bWJlcjtcbiAgb3JkZXJCeT86IHN0cmluZztcbiAgb3JkZXJCeURpcmVjdGlvbj86ICdhc2MnIHwgJ2Rlc2MnO1xuICBxdWVyeT86IChxdWVyeTogUXVlcnkpID0+IFF1ZXJ5O1xuICAvKipcbiAgICogV2hldGhlciB0byBmZXRjaCB0aGUgXCJyYXdcIiB2ZXJzaW9uIG9mIHRoZSBkb2MgKGZvciB1c2UgaW4gY29uanVuY3Rpb24gd2l0aFxuICAgKiBgc2V0UmF3RG9jKClgKS5cbiAgICovXG4gIHJhdz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0Q291bnRPcHRpb25zIHtcbiAgbW9kZTogRG9jTW9kZTtcbiAgcXVlcnk/OiAocXVlcnk6IFF1ZXJ5KSA9PiBRdWVyeTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmFuc2xhdGlvbiB7XG4gIFtsb2NhbGU6IHN0cmluZ106IHN0cmluZztcbiAgc291cmNlOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNsYXRpb25zTWFwIHtcbiAgW2hhc2g6IHN0cmluZ106IFRyYW5zbGF0aW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExvY2FsZVRyYW5zbGF0aW9ucyB7XG4gIFtzb3VyY2U6IHN0cmluZ106IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBMb2FkVHJhbnNsYXRpb25zT3B0aW9ucyB7XG4gIHRhZ3M/OiBzdHJpbmdbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWxlYXNlIHtcbiAgaWQ6IHN0cmluZztcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIGRvY0lkcz86IHN0cmluZ1tdO1xuICBjcmVhdGVkQXQ/OiBUaW1lc3RhbXA7XG4gIGNyZWF0ZWRCeT86IHN0cmluZztcbiAgc2NoZWR1bGVkQXQ/OiBUaW1lc3RhbXA7XG4gIHNjaGVkdWxlZEJ5Pzogc3RyaW5nO1xuICBwdWJsaXNoZWRBdD86IFRpbWVzdGFtcDtcbiAgcHVibGlzaGVkQnk/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWN0aW9uPFQgPSBhbnk+IHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBhY3Rpb24uXG4gICAqL1xuICBhY3Rpb246IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSB1c2VyJ3MgZW1haWwgdGhhdCBwZXJmb3JtZWQgdGhlIGFjdGlvbiAob3IgXCJzeXN0ZW1cIikuXG4gICAqL1xuICBieT86IHN0cmluZztcbiAgLyoqXG4gICAqIFRpbWVzdGFtcCB3aGVuIHRoZSBhY3Rpb24gb2NjdXJyZWQuXG4gICAqL1xuICB0aW1lc3RhbXA6IFRpbWVzdGFtcDtcbiAgLyoqXG4gICAqIE1ldGFkYXRhIGZvciB0aGUgYWN0aW9uLlxuICAgKi9cbiAgbWV0YWRhdGE/OiBUO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExpc3RBY3Rpb25zT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBGaWx0ZXIgYnkgYSBzcGVjaWZpYyBhY3Rpb24uIERlZmF1bHRzIHRvIGFsbCBhY3Rpb25zLlxuICAgKi9cbiAgYWN0aW9uPzogc3RyaW5nO1xuICAvKipcbiAgICogRmlsdGVyIGJ5IGEgc3BlY2lmaWMgdXNlci4gRGVmYXVsdHMgdG8gYWxsIHVzZXJzLlxuICAgKi9cbiAgYnk/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBNYXggbnVtYmVyIG9mIGFjdGlvbnMgdG8gcmV0dXJuLiBEZWZhdWx0cyB0byAxMDAuXG4gICAqL1xuICBsaW1pdD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIFJvb3RDTVNDbGllbnQge1xuICByZWFkb25seSByb290Q29uZmlnOiBSb290Q29uZmlnO1xuICByZWFkb25seSBjbXNQbHVnaW46IENNU1BsdWdpbjtcbiAgcmVhZG9ubHkgcHJvamVjdElkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGFwcDogQXBwO1xuICByZWFkb25seSBkYjogRmlyZXN0b3JlO1xuXG4gIGNvbnN0cnVjdG9yKHJvb3RDb25maWc6IFJvb3RDb25maWcpIHtcbiAgICB0aGlzLnJvb3RDb25maWcgPSByb290Q29uZmlnO1xuICAgIHRoaXMuY21zUGx1Z2luID0gZ2V0Q21zUGx1Z2luKHRoaXMucm9vdENvbmZpZyk7XG5cbiAgICBjb25zdCBjbXNQbHVnaW5PcHRpb25zID0gdGhpcy5jbXNQbHVnaW4uZ2V0Q29uZmlnKCk7XG4gICAgdGhpcy5wcm9qZWN0SWQgPSBjbXNQbHVnaW5PcHRpb25zLmlkIHx8ICdkZWZhdWx0JztcbiAgICB0aGlzLmFwcCA9IHRoaXMuY21zUGx1Z2luLmdldEZpcmViYXNlQXBwKCk7XG4gICAgdGhpcy5kYiA9IHRoaXMuY21zUGx1Z2luLmdldEZpcmVzdG9yZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyBkb2MgZGF0YSBmcm9tIFJvb3QuanMgQ01TLlxuICAgKi9cbiAgYXN5bmMgZ2V0RG9jPEZpZWxkcyA9IGFueT4oXG4gICAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gICAgc2x1Zzogc3RyaW5nLFxuICAgIG9wdGlvbnM6IEdldERvY09wdGlvbnNcbiAgKTogUHJvbWlzZTxEb2M8RmllbGRzPiB8IG51bGw+IHtcbiAgICBjb25zdCByYXdEYXRhID0gYXdhaXQgdGhpcy5nZXRSYXdEb2MoY29sbGVjdGlvbklkLCBzbHVnLCBvcHRpb25zKTtcbiAgICBpZiAocmF3RGF0YSkge1xuICAgICAgcmV0dXJuIHVubWFyc2hhbERhdGEocmF3RGF0YSkgYXMgRG9jPEZpZWxkcz47XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyByYXcgZG9jIGRhdGEgYXMgc3RvcmVkIGluIHRoZSBkYXRhYmFzZS4gT25seSB1c2UgdGhpcyBpZiB5b3Uga25vd1xuICAgKiB3aGF0IHlvdSBhcmUgZG9pbmcuXG4gICAqL1xuICBhc3luYyBnZXRSYXdEb2MoXG4gICAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gICAgc2x1Zzogc3RyaW5nLFxuICAgIG9wdGlvbnM6IEdldERvY09wdGlvbnNcbiAgKTogUHJvbWlzZTxhbnkgfCBudWxsPiB7XG4gICAgY29uc3QgbW9kZSA9IG9wdGlvbnMubW9kZTtcbiAgICBjb25zdCBkb2NSZWYgPSB0aGlzLmRiRG9jUmVmKGNvbGxlY3Rpb25JZCwgc2x1Zywge21vZGV9KTtcbiAgICBjb25zdCBkb2MgPSBhd2FpdCBkb2NSZWYuZ2V0KCk7XG4gICAgaWYgKGRvYy5leGlzdHMpIHtcbiAgICAgIHJldHVybiBkb2MuZGF0YSgpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGRiQ29sbGVjdGlvbkRvY3NQYXRoKFxuICAgIGNvbGxlY3Rpb25JZDogc3RyaW5nLFxuICAgIG9wdGlvbnM6IHttb2RlOiAnZHJhZnQnIHwgJ3B1Ymxpc2hlZCd9XG4gICkge1xuICAgIGxldCBtb2RlQ29sbGVjdGlvbiA9ICcnO1xuICAgIGlmIChvcHRpb25zLm1vZGUgPT09ICdkcmFmdCcpIHtcbiAgICAgIG1vZGVDb2xsZWN0aW9uID0gJ0RyYWZ0cyc7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLm1vZGUgPT09ICdwdWJsaXNoZWQnKSB7XG4gICAgICBtb2RlQ29sbGVjdGlvbiA9ICdQdWJsaXNoZWQnO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gbW9kZTogJHtvcHRpb25zLm1vZGV9YCk7XG4gICAgfVxuICAgIHJldHVybiBgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH0vQ29sbGVjdGlvbnMvJHtjb2xsZWN0aW9uSWR9LyR7bW9kZUNvbGxlY3Rpb259YDtcbiAgfVxuXG4gIGRiRG9jUGF0aChcbiAgICBjb2xsZWN0aW9uSWQ6IHN0cmluZyxcbiAgICBzbHVnOiBzdHJpbmcsXG4gICAgb3B0aW9uczoge21vZGU6ICdkcmFmdCcgfCAncHVibGlzaGVkJ31cbiAgKSB7XG4gICAgY29uc3QgY29sbGVjdGlvbkRvY3NQYXRoID0gdGhpcy5kYkNvbGxlY3Rpb25Eb2NzUGF0aChjb2xsZWN0aW9uSWQsIG9wdGlvbnMpO1xuICAgIC8vIFNsdWdzIHdpdGggc2xhc2hlcyBhcmUgZW5jb2RlZCBhcyBgLS1gIGluIHRoZSBEQi5cbiAgICBjb25zdCBub3JtYWxpemVkU2x1ZyA9IHNsdWcucmVwbGFjZUFsbCgnLycsICctLScpO1xuICAgIHJldHVybiBgJHtjb2xsZWN0aW9uRG9jc1BhdGh9LyR7bm9ybWFsaXplZFNsdWd9YDtcbiAgfVxuXG4gIGRiRG9jUmVmKFxuICAgIGNvbGxlY3Rpb25JZDogc3RyaW5nLFxuICAgIHNsdWc6IHN0cmluZyxcbiAgICBvcHRpb25zOiB7bW9kZTogJ2RyYWZ0JyB8ICdwdWJsaXNoZWQnfVxuICApIHtcbiAgICBjb25zdCBkb2NQYXRoID0gdGhpcy5kYkRvY1BhdGgoY29sbGVjdGlvbklkLCBzbHVnLCBvcHRpb25zKTtcbiAgICByZXR1cm4gdGhpcy5kYi5kb2MoZG9jUGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogU2F2ZXMgZHJhZnQgZGF0YSB0byBhIGRvYy5cbiAgICpcbiAgICogTm90ZTogdGhpcyBzYXZlcyBkYXRhIHRvIHRoZSBcImZpZWxkc1wiIGF0dHIgb2YgdGhlIGRyYWZ0IGRvYy4gSWYgeW91IG5lZWQgdG9cbiAgICogbW9kaWZ5IHRoZSBzeXMtbGV2ZWwgYXR0cmlidXRlcyBvZiB0aGUgZG9jLCB1c2UgYHNldFJhd0RvYygpYC5cbiAgICovXG4gIGFzeW5jIHNhdmVEcmFmdERhdGEoXG4gICAgZG9jSWQ6IHN0cmluZyxcbiAgICBmaWVsZHNEYXRhOiBhbnksXG4gICAgb3B0aW9ucz86IFNhdmVEcmFmdE9wdGlvbnNcbiAgKSB7XG4gICAgY29uc3Qge2NvbGxlY3Rpb24sIHNsdWd9ID0gcGFyc2VEb2NJZChkb2NJZCk7XG4gICAgY29uc3QgZHJhZnREb2MgPVxuICAgICAgKGF3YWl0IHRoaXMuZ2V0UmF3RG9jKGNvbGxlY3Rpb24sIHNsdWcsIHttb2RlOiAnZHJhZnQnfSkpIHx8IHt9O1xuICAgIGNvbnN0IGRyYWZ0U3lzID0gZHJhZnREb2Muc3lzIHx8IHt9O1xuICAgIGNvbnN0IG1vZGlmaWVkQnkgPSBvcHRpb25zPy5tb2RpZmllZEJ5IHx8ICdyb290LWNtcy1jbGllbnQnO1xuICAgIGNvbnN0IGZpZWxkcyA9IG1hcnNoYWxEYXRhKGZpZWxkc0RhdGEgfHwge30pO1xuICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICBpZDogZG9jSWQsXG4gICAgICBjb2xsZWN0aW9uLFxuICAgICAgc2x1ZyxcbiAgICAgIHN5czoge1xuICAgICAgICAuLi5kcmFmdFN5cyxcbiAgICAgICAgY3JlYXRlZEF0OiBkcmFmdFN5cy5jcmVhdGVkQXQgPz8gVGltZXN0YW1wLm5vdygpLFxuICAgICAgICBjcmVhdGVkQnk6IGRyYWZ0U3lzLmNyZWF0ZWRCeSA/PyBtb2RpZmllZEJ5LFxuICAgICAgICBtb2RpZmllZEF0OiBUaW1lc3RhbXAubm93KCksXG4gICAgICAgIG1vZGlmaWVkQnksXG4gICAgICAgIGxvY2FsZXM6IG9wdGlvbnM/LmxvY2FsZXMgPz8gZHJhZnRTeXMubG9jYWxlcyA/PyBbJ2VuJ10sXG4gICAgICB9LFxuICAgICAgZmllbGRzLFxuICAgIH07XG4gICAgYXdhaXQgdGhpcy5zZXRSYXdEb2MoY29sbGVjdGlvbiwgc2x1ZywgZGF0YSwge21vZGU6ICdkcmFmdCd9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVmZXIgYHNhdmVEcmFmdERhdGEoJ1BhZ2VzL2ZvbycsIGRhdGEpYC4gT25seSB1c2UgdGhpcyBpZiB5b3Uga25vdyB3aGF0XG4gICAqIHlvdSdyZSBkb2luZy5cbiAgICovXG4gIGFzeW5jIHNldFJhd0RvYyhcbiAgICBjb2xsZWN0aW9uSWQ6IHN0cmluZyxcbiAgICBzbHVnOiBzdHJpbmcsXG4gICAgZGF0YTogYW55LFxuICAgIG9wdGlvbnM6IFNldERvY09wdGlvbnNcbiAgKSB7XG4gICAgY29uc3QgbW9kZSA9IG9wdGlvbnMubW9kZTtcbiAgICBjb25zdCBtb2RlQ29sbGVjdGlvbiA9IG1vZGUgPT09ICdkcmFmdCcgPyAnRHJhZnRzJyA6ICdQdWJsaXNoZWQnO1xuICAgIGNvbnN0IGRiUGF0aCA9IGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9Db2xsZWN0aW9ucy8ke2NvbGxlY3Rpb25JZH0vJHttb2RlQ29sbGVjdGlvbn0vJHtzbHVnfWA7XG4gICAgY29uc3QgZG9jUmVmID0gdGhpcy5kYi5kb2MoZGJQYXRoKTtcbiAgICBhd2FpdCBkb2NSZWYuc2V0KGRhdGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3RzIGRvY3MgZnJvbSBhIFJvb3QuanMgQ01TIGNvbGxlY3Rpb24uXG4gICAqL1xuICBhc3luYyBsaXN0RG9jczxUPihcbiAgICBjb2xsZWN0aW9uSWQ6IHN0cmluZyxcbiAgICBvcHRpb25zOiBMaXN0RG9jc09wdGlvbnNcbiAgKTogUHJvbWlzZTx7ZG9jczogVFtdfT4ge1xuICAgIGNvbnN0IG1vZGUgPSBvcHRpb25zLm1vZGU7XG4gICAgY29uc3QgbW9kZUNvbGxlY3Rpb24gPSBtb2RlID09PSAnZHJhZnQnID8gJ0RyYWZ0cycgOiAnUHVibGlzaGVkJztcbiAgICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH0vQ29sbGVjdGlvbnMvJHtjb2xsZWN0aW9uSWR9LyR7bW9kZUNvbGxlY3Rpb259YDtcbiAgICBsZXQgcXVlcnk6IFF1ZXJ5ID0gdGhpcy5kYi5jb2xsZWN0aW9uKGRiUGF0aCk7XG4gICAgaWYgKG9wdGlvbnMubGltaXQpIHtcbiAgICAgIHF1ZXJ5ID0gcXVlcnkubGltaXQob3B0aW9ucy5saW1pdCk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLm9mZnNldCkge1xuICAgICAgcXVlcnkgPSBxdWVyeS5vZmZzZXQob3B0aW9ucy5vZmZzZXQpO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5vcmRlckJ5KSB7XG4gICAgICBxdWVyeSA9IHF1ZXJ5Lm9yZGVyQnkob3B0aW9ucy5vcmRlckJ5LCBvcHRpb25zLm9yZGVyQnlEaXJlY3Rpb24pO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5xdWVyeSkge1xuICAgICAgcXVlcnkgPSBvcHRpb25zLnF1ZXJ5KHF1ZXJ5KTtcbiAgICB9XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHF1ZXJ5LmdldCgpO1xuICAgIGNvbnN0IGRvY3M6IFRbXSA9IFtdO1xuICAgIHJlc3VsdHMuZm9yRWFjaCgocmVzdWx0KSA9PiB7XG4gICAgICBpZiAob3B0aW9ucy5yYXcpIHtcbiAgICAgICAgLy8gRm9yIGNhbGxlcnMgdGhhdCB3aXNoIHRvIG1vZGlmeSB0aGUgcmF3IGRvYyB2aWEgYHNldFJhd0RvYygpYCxcbiAgICAgICAgLy8gcmV0dXJuIHRoZSB1bm1vZGlmaWVkIGRvYyBhcyByZXR1cm5lZCBmcm9tIGZpcmVzdG9yZS5cbiAgICAgICAgY29uc3QgcmF3RG9jID0gcmVzdWx0LmRhdGEoKSBhcyBUO1xuICAgICAgICBkb2NzLnB1c2gocmF3RG9jKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGRvYyA9IHVubWFyc2hhbERhdGEocmVzdWx0LmRhdGEoKSkgYXMgVDtcbiAgICAgICAgZG9jcy5wdXNoKGRvYyk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHtkb2NzfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZG9jcyBpbiBhIFJvb3QuanMgQ01TIGNvbGxlY3Rpb24uXG4gICAqL1xuICBhc3luYyBnZXREb2NzQ291bnQoY29sbGVjdGlvbklkOiBzdHJpbmcsIG9wdGlvbnM6IEdldENvdW50T3B0aW9ucykge1xuICAgIGNvbnN0IG1vZGUgPSBvcHRpb25zLm1vZGU7XG4gICAgY29uc3QgbW9kZUNvbGxlY3Rpb24gPSBtb2RlID09PSAnZHJhZnQnID8gJ0RyYWZ0cycgOiAnUHVibGlzaGVkJztcbiAgICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH0vQ29sbGVjdGlvbnMvJHtjb2xsZWN0aW9uSWR9LyR7bW9kZUNvbGxlY3Rpb259YDtcbiAgICBsZXQgcXVlcnk6IFF1ZXJ5ID0gdGhpcy5kYi5jb2xsZWN0aW9uKGRiUGF0aCk7XG4gICAgaWYgKG9wdGlvbnMucXVlcnkpIHtcbiAgICAgIHF1ZXJ5ID0gb3B0aW9ucy5xdWVyeShxdWVyeSk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBxdWVyeS5jb3VudCgpLmdldCgpO1xuICAgIGNvbnN0IGNvdW50ID0gcmVzdWx0cy5kYXRhKCkuY291bnQ7XG4gICAgcmV0dXJuIGNvdW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEJhdGNoIHB1Ymxpc2hlcyBhIHNldCBvZiBkb2NzIGJ5IGlkLlxuICAgKi9cbiAgYXN5bmMgcHVibGlzaERvY3MoXG4gICAgZG9jSWRzOiBzdHJpbmdbXSxcbiAgICBvcHRpb25zPzoge3B1Ymxpc2hlZEJ5OiBzdHJpbmc7IGJhdGNoPzogV3JpdGVCYXRjaH1cbiAgKSB7XG4gICAgY29uc3QgcHJvamVjdENvbGxlY3Rpb25zUGF0aCA9IGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9Db2xsZWN0aW9uc2A7XG4gICAgY29uc3QgcHVibGlzaGVkQnkgPSBvcHRpb25zPy5wdWJsaXNoZWRCeSB8fCAncm9vdC1jbXMtY2xpZW50JztcblxuICAgIC8vIEZldGNoIHRoZSBjdXJyZW50IGRyYWZ0IGRhdGEgZm9yIGVhY2ggZG9jLlxuICAgIGNvbnN0IGRvY1JlZnMgPSBkb2NJZHMubWFwKChkb2NJZCkgPT4ge1xuICAgICAgY29uc3QgW2NvbGxlY3Rpb24sIHNsdWddID0gZG9jSWQuc3BsaXQoJy8nKTtcbiAgICAgIGlmICghY29sbGVjdGlvbiB8fCAhc2x1Zykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgZG9jIGlkOiAke2RvY0lkfWApO1xuICAgICAgfVxuICAgICAgY29uc3QgZG9jUmVmID0gdGhpcy5kYi5kb2MoXG4gICAgICAgIGAke3Byb2plY3RDb2xsZWN0aW9uc1BhdGh9LyR7Y29sbGVjdGlvbn0vRHJhZnRzLyR7c2x1Z31gXG4gICAgICApO1xuICAgICAgcmV0dXJuIGRvY1JlZjtcbiAgICB9KTtcbiAgICBjb25zdCBkb2NTbmFwc2hvdHMgPSBhd2FpdCB0aGlzLmRiLmdldEFsbCguLi5kb2NSZWZzKTtcbiAgICBjb25zdCBkb2NzID0gZG9jU25hcHNob3RzXG4gICAgICAvLyBSZXRyaWV2ZSBzbmFwc2hvdCBkYXRhIGZvciBlYWNoIGRvYy5cbiAgICAgIC5tYXAoKHNuYXBzaG90KSA9PiBzbmFwc2hvdC5kYXRhKCkgYXMgRG9jKVxuICAgICAgLy8gUmVtb3ZlIGRvY3MgdGhhdCBkb24ndCBleGlzdC5cbiAgICAgIC5maWx0ZXIoKGQpID0+ICEhZCk7XG5cbiAgICBpZiAoZG9jcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGNvbnNvbGUubG9nKCdubyBkb2NzIHRvIHB1Ymxpc2gnKTtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG5cbiAgICAvLyBWZXJpZnkgdGhlcmUgYXJlIG5vIHB1Ymxpc2hpbmcgbG9ja3Mgb24gYW55IGRvY3MuXG4gICAgZm9yIChjb25zdCBkb2Mgb2YgZG9jcykge1xuICAgICAgaWYgKHRoaXMudGVzdFB1Ymxpc2hpbmdMb2NrZWQoZG9jKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHB1Ymxpc2hpbmcgaXMgbG9ja2VkIGZvciBkb2M6ICR7ZG9jLmlkfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIC8vIEVhY2ggdHJhbnNhY3Rpb24gb3IgYmF0Y2ggY2FuIHdyaXRlIGEgbWF4IG9mIDUwMCBvcHMuXG4gICAgLy8gLy8gaHR0cHM6Ly9maXJlYmFzZS5nb29nbGUuY29tL2RvY3MvZmlyZXN0b3JlL21hbmFnZS1kYXRhL3RyYW5zYWN0aW9uc1xuICAgIGxldCBiYXRjaENvdW50ID0gMDtcbiAgICBjb25zdCBiYXRjaCA9IG9wdGlvbnM/LmJhdGNoIHx8IHRoaXMuZGIuYmF0Y2goKTtcbiAgICBjb25zdCBwdWJsaXNoZWREb2NzOiBhbnlbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgZG9jIG9mIGRvY3MpIHtcbiAgICAgIGNvbnN0IHtpZCwgY29sbGVjdGlvbiwgc2x1Zywgc3lzLCBmaWVsZHN9ID0gZG9jO1xuICAgICAgY29uc3QgZHJhZnRSZWYgPSB0aGlzLmRiLmRvYyhcbiAgICAgICAgYCR7cHJvamVjdENvbGxlY3Rpb25zUGF0aH0vJHtjb2xsZWN0aW9ufS9EcmFmdHMvJHtzbHVnfWBcbiAgICAgICk7XG4gICAgICBjb25zdCBzY2hlZHVsZWRSZWYgPSB0aGlzLmRiLmRvYyhcbiAgICAgICAgYCR7cHJvamVjdENvbGxlY3Rpb25zUGF0aH0vJHtjb2xsZWN0aW9ufS9TY2hlZHVsZWQvJHtzbHVnfWBcbiAgICAgICk7XG4gICAgICBjb25zdCBwdWJsaXNoZWRSZWYgPSB0aGlzLmRiLmRvYyhcbiAgICAgICAgYCR7cHJvamVjdENvbGxlY3Rpb25zUGF0aH0vJHtjb2xsZWN0aW9ufS9QdWJsaXNoZWQvJHtzbHVnfWBcbiAgICAgICk7XG5cbiAgICAgIC8vIE9ubHkgdXBkYXRlIGBmaXJzdFB1Ymxpc2hlZGAgaWYgaXQgZG9lc24ndCBhbHJlYWR5IGV4aXN0LlxuICAgICAgY29uc3QgZmlyc3RQdWJsaXNoZWRBdCA9XG4gICAgICAgIHN5cy5maXJzdFB1Ymxpc2hlZEF0ID8/IEZpZWxkVmFsdWUuc2VydmVyVGltZXN0YW1wKCk7XG4gICAgICBjb25zdCBmaXJzdFB1Ymxpc2hlZEJ5ID0gc3lzLmZpcnN0UHVibGlzaGVkQnkgPz8gcHVibGlzaGVkQnk7XG5cbiAgICAgIC8vIFNhdmUgcHVibGlzaGVkIGRvYy5cbiAgICAgIGJhdGNoLnNldChwdWJsaXNoZWRSZWYsIHtcbiAgICAgICAgaWQsXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIHNsdWcsXG4gICAgICAgIGZpZWxkczogZmllbGRzIHx8IHt9LFxuICAgICAgICBzeXM6IHtcbiAgICAgICAgICAuLi5zeXMsXG4gICAgICAgICAgZmlyc3RQdWJsaXNoZWRBdDogZmlyc3RQdWJsaXNoZWRBdCxcbiAgICAgICAgICBmaXJzdFB1Ymxpc2hlZEJ5OiBmaXJzdFB1Ymxpc2hlZEJ5LFxuICAgICAgICAgIHB1Ymxpc2hlZEF0OiBGaWVsZFZhbHVlLnNlcnZlclRpbWVzdGFtcCgpLFxuICAgICAgICAgIHB1Ymxpc2hlZEJ5OiBwdWJsaXNoZWRCeSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgYmF0Y2hDb3VudCArPSAxO1xuXG4gICAgICAvLyBSZW1vdmUgc2NoZWR1bGVkIGRvYywgaWYgYW55LlxuICAgICAgYmF0Y2guZGVsZXRlKHNjaGVkdWxlZFJlZik7XG4gICAgICBiYXRjaENvdW50ICs9IDE7XG5cbiAgICAgIC8vIFVwZGF0ZSB0aGUgZHJhZnQgZG9jIHRvIHJlbW92ZSBgc2NoZWR1bGVkQXRgIGFuZCBgc2NoZWR1bGVkQnlgIGZpZWxkc1xuICAgICAgLy8gYW5kIHVwZGF0ZSB0aGUgYHB1Ymxpc2hlZEF0YCBhbmQgYHB1Ymxpc2hlZEJ5YCBmaWVsZHMuXG4gICAgICBiYXRjaC51cGRhdGUoZHJhZnRSZWYsIHtcbiAgICAgICAgJ3N5cy5zY2hlZHVsZWRBdCc6IEZpZWxkVmFsdWUuZGVsZXRlKCksXG4gICAgICAgICdzeXMuc2NoZWR1bGVkQnknOiBGaWVsZFZhbHVlLmRlbGV0ZSgpLFxuICAgICAgICAnc3lzLmZpcnN0UHVibGlzaGVkQXQnOiBmaXJzdFB1Ymxpc2hlZEF0LFxuICAgICAgICAnc3lzLmZpcnN0UHVibGlzaGVkQnknOiBmaXJzdFB1Ymxpc2hlZEJ5LFxuICAgICAgICAnc3lzLnB1Ymxpc2hlZEF0JzogRmllbGRWYWx1ZS5zZXJ2ZXJUaW1lc3RhbXAoKSxcbiAgICAgICAgJ3N5cy5wdWJsaXNoZWRCeSc6IHB1Ymxpc2hlZEJ5LFxuICAgICAgfSk7XG4gICAgICBiYXRjaENvdW50ICs9IDE7XG5cbiAgICAgIHRoaXMucHVibGlzaFRyYW5zbGF0aW9uc0RvYyhkb2MuaWQsIHtiYXRjaH0pO1xuICAgICAgYmF0Y2hDb3VudCArPSAyO1xuXG4gICAgICBwdWJsaXNoZWREb2NzLnB1c2goZG9jKTtcblxuICAgICAgaWYgKGJhdGNoQ291bnQgPj0gNDAwKSB7XG4gICAgICAgIGF3YWl0IGJhdGNoLmNvbW1pdCgpO1xuICAgICAgICBiYXRjaENvdW50ID0gMDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoYmF0Y2hDb3VudCA+IDApIHtcbiAgICAgIGF3YWl0IGJhdGNoLmNvbW1pdCgpO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhgcHVibGlzaGVkICR7cHVibGlzaGVkRG9jcy5sZW5ndGh9IGRvY3MhYCk7XG4gICAgcmV0dXJuIHB1Ymxpc2hlZERvY3M7XG4gIH1cblxuICAvKipcbiAgICogUHVibGlzaGVzIHNjaGVkdWxlZCBkb2NzLlxuICAgKi9cbiAgYXN5bmMgcHVibGlzaFNjaGVkdWxlZERvY3MoKSB7XG4gICAgY29uc3QgcHJvamVjdENvbGxlY3Rpb25zUGF0aCA9IGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9Db2xsZWN0aW9uc2A7XG4gICAgY29uc3Qgbm93ID0gTWF0aC5jZWlsKG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcblxuICAgIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgdGhpcy5kYi5jb2xsZWN0aW9uR3JvdXAoJ1NjaGVkdWxlZCcpLmdldCgpO1xuICAgIGNvbnN0IGRvY3MgPSBzbmFwc2hvdC5kb2NzXG4gICAgICAuZmlsdGVyKChkKSA9PiB7XG4gICAgICAgIC8vIEZpbHRlciBkb2NzIGJ5IHByb2plY3QuXG4gICAgICAgIGlmICghZC5yZWYucGF0aC5zdGFydHNXaXRoKHByb2plY3RDb2xsZWN0aW9uc1BhdGgpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZpbHRlciBkb2NzIHdoZXJlIHNjaGVkdWxlZEF0IGlzIGluIHRoZSBwYXN0LlxuICAgICAgICAvLyBOT1RFKHN0ZXZlbmxlKTogdGhlIGZpbHRlcmluZyBpcyBkb25lIG1hbnVhbGx5IGluc3RlYWQgb2YgdXNpbmcgYSBxdWVyeVxuICAgICAgICAvLyB0byBhdm9pZCBoYXZpbmcgdG8gY3JlYXRlIGFuIGluZGV4IGluIGZpcmVzdG9yZS5cbiAgICAgICAgY29uc3QgZGF0YSA9IGQuZGF0YSgpIHx8IHt9O1xuICAgICAgICBjb25zdCBzY2hlZHVsZWRBdDogVGltZXN0YW1wIHwgdW5kZWZpbmVkID0gZGF0YS5zeXM/LnNjaGVkdWxlZEF0O1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIHNjaGVkdWxlZEF0ICYmIHNjaGVkdWxlZEF0LnRvTWlsbGlzICYmIHNjaGVkdWxlZEF0LnRvTWlsbGlzKCkgPD0gbm93XG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICAgLm1hcCgoZCkgPT4ge1xuICAgICAgICBjb25zdCBkYlBhdGggPSBkLnJlZi5wYXRoO1xuICAgICAgICBjb25zdCBzZWdtZW50cyA9IGRiUGF0aC5zcGxpdCgnLycpO1xuICAgICAgICBjb25zdCBzbHVnID0gc2VnbWVudHMuYXQoLTEpO1xuICAgICAgICBjb25zdCBjb2xsZWN0aW9uID0gc2VnbWVudHMuYXQoLTMpO1xuICAgICAgICBjb25zdCBpZCA9IGAke2NvbGxlY3Rpb259LyR7c2x1Z31gO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGRhdGE6IGQuZGF0YSgpLFxuICAgICAgICAgIGlkLFxuICAgICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgICAgc2x1ZyxcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuXG4gICAgaWYgKGRvY3MubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zb2xlLmxvZygnbm8gZG9jcyB0byBzY2hlZHVsZScpO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIC8vIEVhY2ggdHJhbnNhY3Rpb24gb3IgYmF0Y2ggY2FuIHdyaXRlIGEgbWF4IG9mIDUwMCBvcHMuXG4gICAgLy8gaHR0cHM6Ly9maXJlYmFzZS5nb29nbGUuY29tL2RvY3MvZmlyZXN0b3JlL21hbmFnZS1kYXRhL3RyYW5zYWN0aW9uc1xuICAgIGxldCBiYXRjaENvdW50ID0gMDtcbiAgICBjb25zdCBiYXRjaCA9IHRoaXMuZGIuYmF0Y2goKTtcbiAgICBjb25zdCBwdWJsaXNoZWREb2NzOiBhbnlbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgZG9jIG9mIGRvY3MpIHtcbiAgICAgIGNvbnN0IHtpZCwgY29sbGVjdGlvbiwgc2x1ZywgZGF0YX0gPSBkb2M7XG4gICAgICBjb25zdCBkcmFmdFJlZiA9IHRoaXMuZGIuZG9jKFxuICAgICAgICBgJHtwcm9qZWN0Q29sbGVjdGlvbnNQYXRofS8ke2NvbGxlY3Rpb259L0RyYWZ0cy8ke3NsdWd9YFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHNjaGVkdWxlZFJlZiA9IHRoaXMuZGIuZG9jKFxuICAgICAgICBgJHtwcm9qZWN0Q29sbGVjdGlvbnNQYXRofS8ke2NvbGxlY3Rpb259L1NjaGVkdWxlZC8ke3NsdWd9YFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHB1Ymxpc2hlZFJlZiA9IHRoaXMuZGIuZG9jKFxuICAgICAgICBgJHtwcm9qZWN0Q29sbGVjdGlvbnNQYXRofS8ke2NvbGxlY3Rpb259L1B1Ymxpc2hlZC8ke3NsdWd9YFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHtzY2hlZHVsZWRBdCwgc2NoZWR1bGVkQnksIC4uLnN5c30gPSBkYXRhLnN5cyB8fCB7fTtcblxuICAgICAgLy8gT25seSB1cGRhdGUgYGZpcnN0UHVibGlzaGVkYCBpZiBpdCBkb2Vzbid0IGFscmVhZHkgZXhpc3QuXG4gICAgICBjb25zdCBmaXJzdFB1Ymxpc2hlZEF0ID0gc3lzLmZpcnN0UHVibGlzaGVkQXQgPz8gc2NoZWR1bGVkQXQ7XG4gICAgICBjb25zdCBmaXJzdFB1Ymxpc2hlZEJ5ID1cbiAgICAgICAgc3lzLmZpcnN0UHVibGlzaGVkQnkgPz8gKHNjaGVkdWxlZEJ5IHx8ICdyb290LWNtcy1jbGllbnQnKTtcblxuICAgICAgLy8gU2F2ZSBwdWJsaXNoZWQgZG9jLlxuICAgICAgYmF0Y2guc2V0KHB1Ymxpc2hlZFJlZiwge1xuICAgICAgICBpZCxcbiAgICAgICAgY29sbGVjdGlvbixcbiAgICAgICAgc2x1ZyxcbiAgICAgICAgZmllbGRzOiBkYXRhLmZpZWxkcyB8fCB7fSxcbiAgICAgICAgc3lzOiB7XG4gICAgICAgICAgLi4uc3lzLFxuICAgICAgICAgIGZpcnN0UHVibGlzaGVkQXQ6IGZpcnN0UHVibGlzaGVkQXQsXG4gICAgICAgICAgZmlyc3RQdWJsaXNoZWRCeTogZmlyc3RQdWJsaXNoZWRCeSxcbiAgICAgICAgICBwdWJsaXNoZWRBdDogRmllbGRWYWx1ZS5zZXJ2ZXJUaW1lc3RhbXAoKSxcbiAgICAgICAgICBwdWJsaXNoZWRCeTogc2NoZWR1bGVkQnkgfHwgJycsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIGJhdGNoQ291bnQgKz0gMTtcblxuICAgICAgLy8gUmVtb3ZlIHB1Ymxpc2hlZCBkb2MuXG4gICAgICBiYXRjaC5kZWxldGUoc2NoZWR1bGVkUmVmKTtcbiAgICAgIGJhdGNoQ291bnQgKz0gMTtcblxuICAgICAgLy8gVXBkYXRlIHRoZSBkcmFmdCBkb2MgdG8gcmVtb3ZlIGBzY2hlZHVsZWRBdGAgYW5kIGBzY2hlZHVsZWRCeWAgZmllbGRzXG4gICAgICAvLyBhbmQgdXBkYXRlIHRoZSBgcHVibGlzaGVkQXRgIGFuZCBgcHVibGlzaGVkQnlgIGZpZWxkcy5cbiAgICAgIGJhdGNoLnVwZGF0ZShkcmFmdFJlZiwge1xuICAgICAgICAnc3lzLnNjaGVkdWxlZEF0JzogRmllbGRWYWx1ZS5kZWxldGUoKSxcbiAgICAgICAgJ3N5cy5zY2hlZHVsZWRCeSc6IEZpZWxkVmFsdWUuZGVsZXRlKCksXG4gICAgICAgICdzeXMuZmlyc3RQdWJsaXNoZWRBdCc6IGZpcnN0UHVibGlzaGVkQXQsXG4gICAgICAgICdzeXMuZmlyc3RQdWJsaXNoZWRCeSc6IGZpcnN0UHVibGlzaGVkQnksXG4gICAgICAgICdzeXMucHVibGlzaGVkQXQnOiBGaWVsZFZhbHVlLnNlcnZlclRpbWVzdGFtcCgpLFxuICAgICAgICAnc3lzLnB1Ymxpc2hlZEJ5Jzogc2NoZWR1bGVkQnkgfHwgJ3Jvb3QtY21zLWNsaWVudCcsXG4gICAgICB9KTtcbiAgICAgIGJhdGNoQ291bnQgKz0gMTtcblxuICAgICAgdGhpcy5wdWJsaXNoVHJhbnNsYXRpb25zRG9jKGRvYy5pZCwge2JhdGNofSk7XG4gICAgICBiYXRjaENvdW50ICs9IDI7XG5cbiAgICAgIHB1Ymxpc2hlZERvY3MucHVzaChkb2MpO1xuXG4gICAgICBpZiAoYmF0Y2hDb3VudCA+PSA0MDApIHtcbiAgICAgICAgYXdhaXQgYmF0Y2guY29tbWl0KCk7XG4gICAgICAgIGJhdGNoQ291bnQgPSAwO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoYmF0Y2hDb3VudCA+IDApIHtcbiAgICAgIGF3YWl0IGJhdGNoLmNvbW1pdCgpO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhgcHVibGlzaGVkICR7cHVibGlzaGVkRG9jcy5sZW5ndGh9IGRvY3MhYCk7XG4gICAgcmV0dXJuIHB1Ymxpc2hlZERvY3M7XG4gIH1cblxuICAvKipcbiAgICogUHVibGlzaGVzIGRvY3MgaW4gc2NoZWR1bGVkIHJlbGVhc2VzLlxuICAgKi9cbiAgYXN5bmMgcHVibGlzaFNjaGVkdWxlZFJlbGVhc2VzKCkge1xuICAgIGNvbnN0IHJlbGVhc2VzUGF0aCA9IGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9SZWxlYXNlc2A7XG4gICAgY29uc3Qgbm93ID0gTWF0aC5jZWlsKG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcbiAgICBjb25zdCBxdWVyeTogUXVlcnkgPSB0aGlzLmRiXG4gICAgICAuY29sbGVjdGlvbihyZWxlYXNlc1BhdGgpXG4gICAgICAud2hlcmUoJ3NjaGVkdWxlZEF0JywgJzw9JywgVGltZXN0YW1wLmZyb21NaWxsaXMobm93KSk7XG4gICAgY29uc3QgcXVlcnlTbmFwc2hvdCA9IGF3YWl0IHF1ZXJ5LmdldCgpO1xuXG4gICAgZm9yIChjb25zdCBzbmFwc2hvdCBvZiBxdWVyeVNuYXBzaG90LmRvY3MpIHtcbiAgICAgIGNvbnN0IHJlbGVhc2UgPSBzbmFwc2hvdC5kYXRhKCkgYXMgUmVsZWFzZTtcbiAgICAgIGNvbnN0IGJhdGNoID0gdGhpcy5kYi5iYXRjaCgpO1xuICAgICAgY29uc3QgcHVibGlzaGVkQnkgPSByZWxlYXNlLnNjaGVkdWxlZEJ5IHx8ICdyb290LWNtcy1jbGllbnQnO1xuICAgICAgYmF0Y2gudXBkYXRlKHNuYXBzaG90LnJlZiwge1xuICAgICAgICBwdWJsaXNoZWRBdDogVGltZXN0YW1wLm5vdygpLFxuICAgICAgICBwdWJsaXNoZWRCeTogcHVibGlzaGVkQnksXG4gICAgICAgIHNjaGVkdWxlZEF0OiBGaWVsZFZhbHVlLmRlbGV0ZSgpLFxuICAgICAgICBzY2hlZHVsZWRCeTogRmllbGRWYWx1ZS5kZWxldGUoKSxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhpcy5wdWJsaXNoRG9jcyhyZWxlYXNlLmRvY0lkcyB8fCBbXSwge3B1Ymxpc2hlZEJ5LCBiYXRjaH0pO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHB1Ymxpc2hUcmFuc2xhdGlvbnNEb2MoXG4gICAgdHJhbnNsYXRpb25zSWQ6IHN0cmluZyxcbiAgICBvcHRpb25zPzoge2JhdGNoPzogV3JpdGVCYXRjaDsgcHVibGlzaGVkQnk/OiBzdHJpbmd9XG4gICkge1xuICAgIGNvbnN0IGRvY1NsdWcgPSB0cmFuc2xhdGlvbnNJZC5yZXBsYWNlQWxsKCcvJywgJy0tJyk7XG4gICAgY29uc3QgZHJhZnRSZWYgPSB0aGlzLmRiLmRvYyhcbiAgICAgIGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9UcmFuc2xhdGlvbnNNYW5hZ2VyL2RyYWZ0L1RyYW5zbGF0aW9ucy8ke2RvY1NsdWd9YFxuICAgICk7XG4gICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCBkcmFmdFJlZi5nZXQoKTtcblxuICAgIGlmICghc25hcHNob3QuZXhpc3RzKSB7XG4gICAgICAvLyBJZ25vcmUgbWlzc2luZyB0cmFuc2xhdGlvbnMuXG4gICAgICBjb25zb2xlLndhcm4oYHRyYW5zbGF0aW9ucyAke3RyYW5zbGF0aW9uc0lkfSBkb2VzIG5vdCBleGlzdGApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIElmIHRoZSB0cmFuc2xhdGlvbnMgcHVibGlzaGluZyBpcyB0aWVkIHRvIGFub3RoZXIgYmF0Y2ggcmVxdWVzdCAoZS5nLiBkb2NcbiAgICAvLyBwdWJsaXNoaW5nKSwgdGhlIGJhdGNoIHJlcXVlc3Qgd2lsbCBiZSBjb21taXR0ZWQgdXBzdHJlYW0uXG4gICAgY29uc3QgY29tbWl0QmF0Y2ggPSAhb3B0aW9ucz8uYmF0Y2g7XG5cbiAgICBjb25zdCBiYXRjaCA9IG9wdGlvbnM/LmJhdGNoIHx8IHRoaXMuZGIuYmF0Y2goKTtcbiAgICBiYXRjaC51cGRhdGUoZHJhZnRSZWYsIHtcbiAgICAgICdzeXMucHVibGlzaGVkQXQnOiBUaW1lc3RhbXAubm93KCksXG4gICAgICAnc3lzLnB1Ymxpc2hlZEJ5Jzogb3B0aW9ucz8ucHVibGlzaGVkQnkgfHwgJ3Jvb3QtY21zLWNsaWVudCcsXG4gICAgfSk7XG5cbiAgICBjb25zdCBwdWJsaXNoZWRSZWYgPSB0aGlzLmRiLmRvYyhcbiAgICAgIGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9UcmFuc2xhdGlvbnNNYW5hZ2VyL3B1Ymxpc2hlZC9UcmFuc2xhdGlvbnMvJHtkb2NTbHVnfWBcbiAgICApO1xuICAgIGNvbnN0IGRhdGEgPSB7Li4uc25hcHNob3QuZGF0YSgpfTtcbiAgICBpZiAoIWRhdGEuc3lzKSB7XG4gICAgICBkYXRhLnN5cyA9IHt9O1xuICAgIH1cbiAgICBkYXRhLnN5cy5wdWJsaXNoZWRBdCA9IFRpbWVzdGFtcC5ub3coKTtcbiAgICBkYXRhLnN5cy5wdWJsaXNoZWRCeSA9IG9wdGlvbnM/LnB1Ymxpc2hlZEJ5IHx8ICdyb290LWNtcy1jbGllbnQnO1xuICAgIGJhdGNoLnNldChwdWJsaXNoZWRSZWYsIGRhdGEpO1xuICAgIGlmIChjb21taXRCYXRjaCkge1xuICAgICAgYXdhaXQgYmF0Y2guY29tbWl0KCk7XG4gICAgICB0aGlzLmxvZ0FjdGlvbigndHJhbnNsYXRpb25zLnB1Ymxpc2gnLCB7bWV0YWRhdGE6IHt0cmFuc2xhdGlvbnNJZH19KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgZG9jIGlzIGN1cnJlbnRseSBcImxvY2tlZFwiIGZvciBwdWJsaXNoaW5nLlxuICAgKi9cbiAgdGVzdFB1Ymxpc2hpbmdMb2NrZWQoZG9jOiBEb2MpIHtcbiAgICBpZiAoZG9jLnN5cz8ucHVibGlzaGluZ0xvY2tlZCkge1xuICAgICAgaWYgKGRvYy5zeXMucHVibGlzaGluZ0xvY2tlZC51bnRpbCkge1xuICAgICAgICBjb25zdCBub3cgPSBUaW1lc3RhbXAubm93KCkudG9NaWxsaXMoKTtcbiAgICAgICAgY29uc3QgdW50aWwgPSBkb2Muc3lzLnB1Ymxpc2hpbmdMb2NrZWQudW50aWwudG9NaWxsaXMoKTtcbiAgICAgICAgcmV0dXJuIG5vdyA8IHVudGlsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyBhbGwgcHVibGlzaGVkIHN0cmluZ3MgaW4gdGhlIGRiLlxuICAgKlxuICAgKiBgYGBcbiAgICoge1xuICAgKiAgIFwiPGhhc2g+XCI6IHtcInNvdXJjZVwiOiBcIkhlbGxvXCIsIFwiZXNcIjogXCJIb2xhXCIsIFwiZnJcIjogXCJCb25qb3VyXCJ9LFxuICAgKiB9XG4gICAqIGBgYFxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBVc2UgYGNyZWF0ZUJhdGNoUmVxdWVzdCgpYCB0byBmZXRjaCBkcmFmdC9wdWJsaXNoZWQgdHJhbnNsYXRpb25zLlxuICAgKi9cbiAgYXN5bmMgbG9hZFRyYW5zbGF0aW9ucyhcbiAgICBvcHRpb25zPzogTG9hZFRyYW5zbGF0aW9uc09wdGlvbnNcbiAgKTogUHJvbWlzZTxUcmFuc2xhdGlvbnNNYXA+IHtcbiAgICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH0vVHJhbnNsYXRpb25zTWFuYWdlci9wdWJsaXNoZWQvVHJhbnNsYXRpb25zYDtcbiAgICBjb25zdCB0cmFuc2xhdGlvbnNNYXA6IFRyYW5zbGF0aW9uc01hcCA9IHt9O1xuXG4gICAgY29uc3QgYWRkVHJhbnNsYXRpb25zID0gKGhhc2g6IHN0cmluZywgdHJhbnNsYXRpb25zOiBUcmFuc2xhdGlvbikgPT4ge1xuICAgICAgdHJhbnNsYXRpb25zTWFwW2hhc2hdID0gT2JqZWN0LmFzc2lnbihcbiAgICAgICAgdHJhbnNsYXRpb25zTWFwW2hhc2hdIHx8IHt9LFxuICAgICAgICB0cmFuc2xhdGlvbnNcbiAgICAgICk7XG4gICAgfTtcblxuICAgIGxldCBxdWVyeTogUXVlcnkgPSB0aGlzLmRiLmNvbGxlY3Rpb24oZGJQYXRoKTtcbiAgICBpZiAob3B0aW9ucz8udGFncyAmJiBvcHRpb25zLnRhZ3MubGVuZ3RoID4gMCkge1xuICAgICAgcXVlcnkgPSBxdWVyeS53aGVyZSgnc3lzLnRhZ3MnLCAnYXJyYXktY29udGFpbnMtYW55Jywgb3B0aW9ucy50YWdzKTtcbiAgICB9XG4gICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCBxdWVyeS5nZXQoKTtcbiAgICBzbmFwc2hvdC5mb3JFYWNoKChkb2MpID0+IHtcbiAgICAgIGNvbnN0IGRhdGEgPSBkb2MuZGF0YSgpO1xuICAgICAgY29uc3Qgc3RyaW5ncyA9IChkYXRhLnN0cmluZ3MgfHwge30pIGFzIFJlY29yZDxzdHJpbmcsIFRyYW5zbGF0aW9uPjtcbiAgICAgIE9iamVjdC5lbnRyaWVzKHN0cmluZ3MpLmZvckVhY2goKFtoYXNoLCB0cmFuc2xhdGlvbnNdKSA9PiB7XG4gICAgICAgIGFkZFRyYW5zbGF0aW9ucyhoYXNoLCB0cmFuc2xhdGlvbnMpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdHJhbnNsYXRpb25zTWFwO1xuICB9XG5cbiAgLyoqXG4gICAqIFNhdmVzIGEgbWFwIG9mIHRyYW5zbGF0aW9ucywgZS5nLjpcbiAgICogYGBgXG4gICAqIGF3YWl0IGNsaWVudC5zYXZlVHJhbnNsYXRpb25zKHtcbiAgICogICBcIkhlbGxvXCI6IHtcImVzXCI6IFwiSG9sYVwiLCBcImZyXCI6IFwiQm9uam91clwifSxcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBVc2UgYHNhdmVEcmFmdFRyYW5zbGF0aW9ucygpYCBhbmQgYHB1Ymxpc2hUcmFuc2xhdGlvbnMoKWBcbiAgICogaW5zdGVhZC5cbiAgICovXG4gIGFzeW5jIHNhdmVUcmFuc2xhdGlvbnMoXG4gICAgdHJhbnNsYXRpb25zOiB7XG4gICAgICBbc291cmNlOiBzdHJpbmddOiB7W2xvY2FsZTogc3RyaW5nXTogc3RyaW5nfTtcbiAgICB9LFxuICAgIHRhZ3M/OiBzdHJpbmdbXVxuICApIHtcbiAgICBjb25zdCB0cmFuc2xhdGlvbnNQYXRoID0gYFByb2plY3RzLyR7dGhpcy5wcm9qZWN0SWR9L1RyYW5zbGF0aW9uc2A7XG4gICAgY29uc3QgYmF0Y2ggPSB0aGlzLmRiLmJhdGNoKCk7XG4gICAgbGV0IGJhdGNoQ291bnQgPSAwO1xuICAgIE9iamVjdC5lbnRyaWVzKHRyYW5zbGF0aW9ucykuZm9yRWFjaCgoW3NvdXJjZSwgc291cmNlVHJhbnNsYXRpb25zXSkgPT4ge1xuICAgICAgY29uc3QgaGFzaCA9IHRoaXMuZ2V0VHJhbnNsYXRpb25LZXkoc291cmNlKTtcbiAgICAgIGNvbnN0IHRyYW5zbGF0aW9uUmVmID0gdGhpcy5kYi5kb2MoYCR7dHJhbnNsYXRpb25zUGF0aH0vJHtoYXNofWApO1xuICAgICAgY29uc3QgZGF0YTogYW55ID0ge1xuICAgICAgICAuLi5zb3VyY2VUcmFuc2xhdGlvbnMsXG4gICAgICAgIHNvdXJjZTogdGhpcy5ub3JtYWxpemVTdHJpbmcoc291cmNlKSxcbiAgICAgIH07XG4gICAgICBpZiAodGFncykge1xuICAgICAgICBkYXRhLnRhZ3MgPSB0YWdzO1xuICAgICAgfVxuICAgICAgYmF0Y2guc2V0KHRyYW5zbGF0aW9uUmVmLCBkYXRhLCB7bWVyZ2U6IHRydWV9KTtcbiAgICAgIGJhdGNoQ291bnQgKz0gMTtcbiAgICB9KTtcbiAgICBpZiAoYmF0Y2hDb3VudCA+IDUwMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd1cCB0byA1MDAgdHJhbnNsYXRpb25zIGNhbiBiZSBzYXZlZCBhdCBhIHRpbWUuJyk7XG4gICAgfVxuICAgIGF3YWl0IGJhdGNoLmNvbW1pdCgpO1xuICB9XG5cbiAgYXN5bmMgc2F2ZURyYWZ0VHJhbnNsYXRpb25zKFxuICAgIHRyYW5zbGF0aW9uc0lkOiBzdHJpbmcsXG4gICAgdHJhbnNsYXRpb25zOiB7W3NvdXJjZTogc3RyaW5nXToge1tsb2NhbGU6IHN0cmluZ106IHN0cmluZ319LFxuICAgIG9wdGlvbnM/OiB7bW9kaWZpZWRieT86IHN0cmluZ31cbiAgKSB7XG4gICAgY29uc3QgZG9jU2x1ZyA9IHRyYW5zbGF0aW9uc0lkLnJlcGxhY2VBbGwoJy8nLCAnLS0nKTtcbiAgICBjb25zdCBkb2NQYXRoID0gYFByb2plY3RzLyR7dGhpcy5wcm9qZWN0SWR9L1RyYW5zbGF0aW9uc01hbmFnZXIvZHJhZnQvJHtkb2NTbHVnfWA7XG4gICAgY29uc3QgZG9jUmVmID0gdGhpcy5kYi5kb2MoZG9jUGF0aCk7XG5cbiAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IGRvY1JlZi5nZXQoKTtcbiAgICBjb25zdCBkYXRhID0gc25hcHNob3QuZGF0YSgpIHx8IHtcbiAgICAgIGlkOiB0cmFuc2xhdGlvbnNJZC5yZXBsYWNlQWxsKCctLScsICcvJyksXG4gICAgICBzeXM6IHt9LFxuICAgICAgc3RyaW5nczoge30sXG4gICAgfTtcbiAgICBkYXRhLnN5cy5tb2RpZmllZEF0ID0gVGltZXN0YW1wLm5vdygpO1xuICAgIGRhdGEuc3lzLm1vZGlmaWVkQnkgPSBvcHRpb25zPy5tb2RpZmllZGJ5IHx8ICdyb290LWNtcy1jbGllbnQnO1xuXG4gICAgY29uc3Qgc3RyaW5ncyA9IGRhdGEuc3RyaW5ncyB8fCB7fTtcbiAgICBPYmplY3QuZW50cmllcyh0cmFuc2xhdGlvbnMpLmZvckVhY2goKFtzb3VyY2UsIHJvd10pID0+IHtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRTb3VyY2UgPSB0aGlzLm5vcm1hbGl6ZVN0cmluZyhzb3VyY2UpO1xuICAgICAgY29uc3QgaGFzaCA9IHRoaXMuZ2V0VHJhbnNsYXRpb25LZXkobm9ybWFsaXplZFNvdXJjZSk7XG4gICAgICBzdHJpbmdzW2hhc2hdID0gey4uLnN0cmluZ3NbaGFzaF0sIC4uLnJvdywgc291cmNlOiBub3JtYWxpemVkU291cmNlfTtcbiAgICB9KTtcbiAgICBkYXRhLnN0cmluZ3MgPSBzdHJpbmdzO1xuICAgIGF3YWl0IGRvY1JlZi5zZXQoZGF0YSk7XG4gICAgdGhpcy5sb2dBY3Rpb24oJ3RyYW5zbGF0aW9ucy5zYXZlJywge21ldGFkYXRhOiB7dHJhbnNsYXRpb25zSWR9fSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgXCJrZXlcIiB1c2VkIGZvciBhIHRyYW5zbGF0aW9uIGFzIHN0b3JlZCBpbiB0aGUgZGIuIFRyYW5zbGF0aW9uc1xuICAgKiBhcmUgc3RvcmVkIHVuZGVyIGBQcm9qZWN0cy88cHJvamVjdCBpZD4vVHJhbnNsYXRpb25zLzxzaGExIGhhc2g+YC5cbiAgICovXG4gIGdldFRyYW5zbGF0aW9uS2V5KHNvdXJjZTogc3RyaW5nKSB7XG4gICAgY29uc3Qgc2hhMSA9IGNyeXB0b1xuICAgICAgLmNyZWF0ZUhhc2goJ3NoYTEnKVxuICAgICAgLnVwZGF0ZSh0aGlzLm5vcm1hbGl6ZVN0cmluZyhzb3VyY2UpKVxuICAgICAgLmRpZ2VzdCgnaGV4Jyk7XG4gICAgcmV0dXJuIHNoYTE7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYW5zIGEgc3RyaW5nIHRoYXQncyB1c2VkIGZvciB0cmFuc2xhdGlvbnMuIFBlcmZvcm1zIHRoZSBmb2xsb3dpbmc6XG4gICAqIC0gUmVtb3ZlcyBhbnkgbGVhZGluZy90cmFpbGluZyB3aGl0ZXNwYWNlXG4gICAqIC0gUmVtb3ZlcyBzcGFjZXMgYXQgdGhlIGVuZCBvZiBhbnkgbGluZVxuICAgKi9cbiAgbm9ybWFsaXplU3RyaW5nKHN0cjogc3RyaW5nKSB7XG4gICAgY29uc3QgbGluZXMgPSBTdHJpbmcoc3RyKVxuICAgICAgLnRyaW0oKVxuICAgICAgLnNwbGl0KCdcXG4nKVxuICAgICAgLm1hcCgobGluZSkgPT4gbGluZS50cmltRW5kKCkpO1xuICAgIHJldHVybiBsaW5lcy5qb2luKCdcXG4nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyB0cmFuc2xhdGlvbnMgZm9yIGEgcGFydGljdWxhciBsb2NhbGUuXG4gICAqXG4gICAqIFJldHVybnMgYSBtYXAgbGlrZTpcbiAgICogYGBgXG4gICAqIHtcbiAgICogICBcIkhlbGxvXCI6IFwiQm9uam91clwiLFxuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgbG9hZFRyYW5zbGF0aW9uc0ZvckxvY2FsZShcbiAgICBsb2NhbGU6IHN0cmluZyxcbiAgICBvcHRpb25zPzogTG9hZFRyYW5zbGF0aW9uc09wdGlvbnNcbiAgKTogUHJvbWlzZTxMb2NhbGVUcmFuc2xhdGlvbnM+IHtcbiAgICBjb25zdCB0cmFuc2xhdGlvbnNNYXAgPSBhd2FpdCB0aGlzLmxvYWRUcmFuc2xhdGlvbnMob3B0aW9ucyk7XG4gICAgcmV0dXJuIHRyYW5zbGF0aW9uc0ZvckxvY2FsZSh0cmFuc2xhdGlvbnNNYXAsIGxvY2FsZSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGRhdGEgc291cmNlIGNvbmZpZ3VyYXRpb24gb2JqZWN0LlxuICAgKi9cbiAgYXN5bmMgZ2V0RGF0YVNvdXJjZShkYXRhU291cmNlSWQ6IHN0cmluZykge1xuICAgIGNvbnN0IGRiUGF0aCA9IGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9EYXRhU291cmNlcy8ke2RhdGFTb3VyY2VJZH1gO1xuICAgIGNvbnN0IGRvY1JlZiA9IHRoaXMuZGIuZG9jKGRiUGF0aCk7XG4gICAgY29uc3QgZG9jID0gYXdhaXQgZG9jUmVmLmdldCgpO1xuICAgIGlmIChkb2MuZXhpc3RzKSB7XG4gICAgICByZXR1cm4gZG9jLmRhdGEoKSBhcyBEYXRhU291cmNlO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTeW5jcyBhIGRhdGEgc291cmNlIHRvIGRyYWZ0IHN0YXRlLlxuICAgKi9cbiAgYXN5bmMgc3luY0RhdGFTb3VyY2UoZGF0YVNvdXJjZUlkOiBzdHJpbmcsIG9wdGlvbnM/OiB7c3luY2VkQnk/OiBzdHJpbmd9KSB7XG4gICAgY29uc3QgZGF0YVNvdXJjZSA9IGF3YWl0IHRoaXMuZ2V0RGF0YVNvdXJjZShkYXRhU291cmNlSWQpO1xuICAgIGlmICghZGF0YVNvdXJjZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBkYXRhIHNvdXJjZSBub3QgZm91bmQ6ICR7ZGF0YVNvdXJjZUlkfWApO1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLmZldGNoRGF0YShkYXRhU291cmNlKTtcblxuICAgIGNvbnN0IGRhdGFTb3VyY2VEb2NSZWYgPSB0aGlzLmRiLmRvYyhcbiAgICAgIGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9EYXRhU291cmNlcy8ke2RhdGFTb3VyY2VJZH1gXG4gICAgKTtcbiAgICBjb25zdCBkYXRhRG9jUmVmID0gdGhpcy5kYi5kb2MoXG4gICAgICBgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH0vRGF0YVNvdXJjZXMvJHtkYXRhU291cmNlSWR9L0RhdGEvZHJhZnRgXG4gICAgKTtcbiAgICBjb25zdCBzeW5jZWRCeSA9IG9wdGlvbnM/LnN5bmNlZEJ5IHx8ICdyb290LWNtcy1jbGllbnQnO1xuXG4gICAgY29uc3QgdXBkYXRlZERhdGFTb3VyY2U6IERhdGFTb3VyY2UgPSB7XG4gICAgICAuLi5kYXRhU291cmNlLFxuICAgICAgc3luY2VkQXQ6IFRpbWVzdGFtcC5ub3coKSxcbiAgICAgIHN5bmNlZEJ5OiBzeW5jZWRCeSxcbiAgICB9O1xuXG4gICAgY29uc3QgYmF0Y2ggPSB0aGlzLmRiLmJhdGNoKCk7XG4gICAgYmF0Y2guc2V0KGRhdGFEb2NSZWYsIHtcbiAgICAgIGRhdGFTb3VyY2U6IHVwZGF0ZWREYXRhU291cmNlLFxuICAgICAgZGF0YTogZGF0YSxcbiAgICB9KTtcbiAgICBiYXRjaC51cGRhdGUoZGF0YVNvdXJjZURvY1JlZiwge1xuICAgICAgc3luY2VkQXQ6IFRpbWVzdGFtcC5ub3coKSxcbiAgICAgIHN5bmNlZEJ5OiBzeW5jZWRCeSxcbiAgICB9KTtcbiAgICBhd2FpdCBiYXRjaC5jb21taXQoKTtcblxuICAgIGNvbnNvbGUubG9nKGBzeW5jZWQgZGF0YSBzb3VyY2U6ICR7ZGF0YVNvdXJjZUlkfWApO1xuICAgIGNvbnNvbGUubG9nKGBzeW5jZWQgYnk6ICR7c3luY2VkQnl9YCk7XG4gIH1cblxuICBhc3luYyBwdWJsaXNoRGF0YVNvdXJjZShcbiAgICBkYXRhU291cmNlSWQ6IHN0cmluZyxcbiAgICBvcHRpb25zPzoge3B1Ymxpc2hlZEJ5Pzogc3RyaW5nfVxuICApIHtcbiAgICBjb25zdCBkYXRhU291cmNlID0gYXdhaXQgdGhpcy5nZXREYXRhU291cmNlKGRhdGFTb3VyY2VJZCk7XG4gICAgaWYgKCFkYXRhU291cmNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGRhdGEgc291cmNlIG5vdCBmb3VuZDogJHtkYXRhU291cmNlSWR9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgZGF0YVNvdXJjZURvY1JlZiA9IHRoaXMuZGIuZG9jKFxuICAgICAgYFByb2plY3RzLyR7dGhpcy5wcm9qZWN0SWR9L0RhdGFTb3VyY2VzLyR7ZGF0YVNvdXJjZUlkfWBcbiAgICApO1xuICAgIGNvbnN0IGRhdGFEb2NSZWZEcmFmdCA9IHRoaXMuZGIuZG9jKFxuICAgICAgYFByb2plY3RzLyR7dGhpcy5wcm9qZWN0SWR9L0RhdGFTb3VyY2VzLyR7ZGF0YVNvdXJjZUlkfS9kcmFmdGBcbiAgICApO1xuICAgIGNvbnN0IGRhdGFEb2NSZWZQdWJsaXNoZWQgPSB0aGlzLmRiLmRvYyhcbiAgICAgIGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9EYXRhU291cmNlcy8ke2RhdGFTb3VyY2VJZH0vcHVibGlzaGVkYFxuICAgICk7XG5cbiAgICBjb25zdCBkYXRhUmVzID0gYXdhaXQgdGhpcy5nZXRGcm9tRGF0YVNvdXJjZShkYXRhU291cmNlSWQsIHttb2RlOiAnZHJhZnQnfSk7XG5cbiAgICBjb25zdCBwdWJsaXNoZWRCeSA9IG9wdGlvbnM/LnB1Ymxpc2hlZEJ5IHx8ICdyb290LWNtcy1jbGllbnQnO1xuXG4gICAgY29uc3QgdXBkYXRlZERhdGFTb3VyY2U6IERhdGFTb3VyY2UgPSB7XG4gICAgICAuLi5kYXRhU291cmNlLFxuICAgICAgcHVibGlzaGVkQXQ6IFRpbWVzdGFtcC5ub3coKSxcbiAgICAgIHB1Ymxpc2hlZEJ5OiBwdWJsaXNoZWRCeSxcbiAgICB9O1xuXG4gICAgY29uc3QgYmF0Y2ggPSB0aGlzLmRiLmJhdGNoKCk7XG4gICAgYmF0Y2guc2V0KGRhdGFEb2NSZWZQdWJsaXNoZWQsIHtcbiAgICAgIGRhdGFTb3VyY2U6IHVwZGF0ZWREYXRhU291cmNlLFxuICAgICAgZGF0YTogZGF0YVJlcz8uZGF0YSB8fCBudWxsLFxuICAgIH0pO1xuICAgIGJhdGNoLnVwZGF0ZShkYXRhRG9jUmVmRHJhZnQsIHtcbiAgICAgIGRhdGFTb3VyY2U6IHVwZGF0ZWREYXRhU291cmNlLFxuICAgIH0pO1xuICAgIGJhdGNoLnVwZGF0ZShkYXRhU291cmNlRG9jUmVmLCB7XG4gICAgICBwdWJsaXNoZWRBdDogVGltZXN0YW1wLm5vdygpLFxuICAgICAgcHVibGlzaGVkQnk6IHB1Ymxpc2hlZEJ5LFxuICAgIH0pO1xuICAgIGF3YWl0IGJhdGNoLmNvbW1pdCgpO1xuXG4gICAgY29uc29sZS5sb2coYHB1Ymxpc2hlZCBkYXRhICR7ZGF0YVNvdXJjZUlkfWApO1xuICAgIGNvbnNvbGUubG9nKGBwdWJsaXNoZWQgYnk6ICR7cHVibGlzaGVkQnl9YCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoRGF0YShkYXRhU291cmNlOiBEYXRhU291cmNlKSB7XG4gICAgaWYgKGRhdGFTb3VyY2UudHlwZSA9PT0gJ2h0dHAnKSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5mZXRjaEh0dHBEYXRhKGRhdGFTb3VyY2UpO1xuICAgIH1cbiAgICAvLyBUT0RPKHN0ZXZlbmxlKTogaW1wbC5cbiAgICAvLyBpZiAoZGF0YVNvdXJjZS50eXBlID09PSAnZ3NoZWV0Jykge1xuICAgIC8vICAgcmV0dXJuIGF3YWl0IGZldGNoR3NoZWV0RGF0YShkYXRhU291cmNlKTtcbiAgICAvLyB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHNvdXJjZTogJHtkYXRhU291cmNlLnR5cGV9YCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoSHR0cERhdGEoZGF0YVNvdXJjZTogRGF0YVNvdXJjZSkge1xuICAgIGNvbnN0IHVybCA9IGRhdGFTb3VyY2UudXJsIHx8ICcnO1xuICAgIGlmICghdXJsLnN0YXJ0c1dpdGgoJ2h0dHBzOi8vJykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdXJsIG5vdCBzdXBwb3J0ZWQ6ICR7dXJsfWApO1xuICAgIH1cblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKHVybCwge1xuICAgICAgbWV0aG9kOiBkYXRhU291cmNlLmh0dHBPcHRpb25zPy5tZXRob2QgfHwgJ0dFVCcsXG4gICAgICBoZWFkZXJzOiBkYXRhU291cmNlLmh0dHBPcHRpb25zPy5oZWFkZXJzIHx8IFtdLFxuICAgICAgYm9keTogZGF0YVNvdXJjZS5odHRwT3B0aW9ucz8uYm9keSB8fCB1bmRlZmluZWQsXG4gICAgfSk7XG5cbiAgICBpZiAocmVzLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICBjb25zdCBlcnIgPSBhd2FpdCByZXMudGV4dCgpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGByZXEgZmFpbGVkOiAke2Vycn1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb250ZW50VHlwZSA9IFN0cmluZyhyZXMuaGVhZGVycy5nZXQoJ2NvbnRlbnQtdHlwZScpKTtcbiAgICBpZiAoY29udGVudFR5cGUuaW5jbHVkZXMoJ2FwcGxpY2F0aW9uL2pzb24nKSkge1xuICAgICAgcmV0dXJuIGF3YWl0IHJlcy5qc29uKCk7XG4gICAgfVxuICAgIHJldHVybiByZXMudGV4dCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZldGNoZXMgZGF0YSBmcm9tIGEgZGF0YSBzb3VyY2UuXG4gICAqL1xuICBhc3luYyBnZXRGcm9tRGF0YVNvdXJjZTxUID0gYW55PihcbiAgICBkYXRhU291cmNlSWQ6IHN0cmluZyxcbiAgICBvcHRpb25zPzoge21vZGU/OiAnZHJhZnQnIHwgJ3B1Ymxpc2hlZCd9XG4gICk6IFByb21pc2U8RGF0YVNvdXJjZURhdGE8VD4gfCBudWxsPiB7XG4gICAgY29uc3QgbW9kZSA9IG9wdGlvbnM/Lm1vZGUgfHwgJ3B1Ymxpc2hlZCc7XG5cbiAgICBjb25zdCBkb2NSZWYgPSB0aGlzLmRiRGF0YVNvdXJjZURhdGFSZWYoZGF0YVNvdXJjZUlkLCB7bW9kZX0pO1xuICAgIGNvbnN0IGRvYyA9IGF3YWl0IGRvY1JlZi5nZXQoKTtcbiAgICBpZiAoZG9jLmV4aXN0cykge1xuICAgICAgcmV0dXJuIGRvYy5kYXRhKCkgYXMgRGF0YVNvdXJjZURhdGE8VD47XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgZGJEYXRhU291cmNlRGF0YVBhdGgoXG4gICAgZGF0YVNvdXJjZUlkOiBzdHJpbmcsXG4gICAgb3B0aW9uczoge21vZGU6ICdkcmFmdCcgfCAncHVibGlzaGVkJ31cbiAgKSB7XG4gICAgaWYgKCFkYXRhU291cmNlSWQgfHwgZGF0YVNvdXJjZUlkLmluY2x1ZGVzKCcvJykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkYXRhIHNvdXJjZSBpZDogJHtkYXRhU291cmNlSWR9YCk7XG4gICAgfVxuICAgIGNvbnN0IG1vZGUgPSBvcHRpb25zLm1vZGU7XG4gICAgaWYgKCEobW9kZSA9PT0gJ2RyYWZ0JyB8fCBtb2RlID09PSAncHVibGlzaGVkJykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBtb2RlOiAke21vZGV9YCk7XG4gICAgfVxuICAgIGNvbnN0IGRiUGF0aCA9IGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9EYXRhU291cmNlcy8ke2RhdGFTb3VyY2VJZH0vRGF0YS8ke21vZGV9YDtcbiAgICByZXR1cm4gZGJQYXRoO1xuICB9XG5cbiAgZGJEYXRhU291cmNlRGF0YVJlZihcbiAgICBkYXRhU291cmNlSWQ6IHN0cmluZyxcbiAgICBvcHRpb25zOiB7bW9kZTogJ2RyYWZ0JyB8ICdwdWJsaXNoZWQnfVxuICApIHtcbiAgICBjb25zdCBkYlBhdGggPSB0aGlzLmRiRGF0YVNvdXJjZURhdGFQYXRoKGRhdGFTb3VyY2VJZCwgb3B0aW9ucyk7XG4gICAgcmV0dXJuIHRoaXMuZGIuZG9jKGRiUGF0aCk7XG4gIH1cblxuICBkYlRyYW5zbGF0aW9uc1BhdGgoXG4gICAgdHJhbnNsYXRpb25zSWQ6IHN0cmluZyxcbiAgICBvcHRpb25zOiB7bW9kZTogJ2RyYWZ0JyB8ICdwdWJsaXNoZWQnfVxuICApIHtcbiAgICBjb25zdCBtb2RlID0gb3B0aW9ucy5tb2RlO1xuICAgIGlmICghKG1vZGUgPT09ICdkcmFmdCcgfHwgbW9kZSA9PT0gJ3B1Ymxpc2hlZCcpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgbW9kZTogJHttb2RlfWApO1xuICAgIH1cbiAgICBjb25zdCBzbHVnID0gdHJhbnNsYXRpb25zSWQucmVwbGFjZUFsbCgnLycsICctLScpO1xuICAgIGNvbnN0IGRiUGF0aCA9IGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9UcmFuc2xhdGlvbnNNYW5hZ2VyLyR7bW9kZX0vVHJhbnNsYXRpb25zLyR7c2x1Z31gO1xuICAgIHJldHVybiBkYlBhdGg7XG4gIH1cblxuICBkYlRyYW5zbGF0aW9uc1JlZihcbiAgICB0cmFuc2xhdGlvbnNJZDogc3RyaW5nLFxuICAgIG9wdGlvbnM6IHttb2RlOiAnZHJhZnQnIHwgJ3B1Ymxpc2hlZCd9XG4gICkge1xuICAgIGNvbnN0IGRiUGF0aCA9IHRoaXMuZGJUcmFuc2xhdGlvbnNQYXRoKHRyYW5zbGF0aW9uc0lkLCBvcHRpb25zKTtcbiAgICByZXR1cm4gdGhpcy5kYi5kb2MoZGJQYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSB1c2VyJ3Mgcm9sZSBmcm9tIHRoZSBwcm9qZWN0J3MgQUNMLlxuICAgKi9cbiAgYXN5bmMgZ2V0VXNlclJvbGUoZW1haWw6IHN0cmluZyk6IFByb21pc2U8VXNlclJvbGUgfCBudWxsPiB7XG4gICAgaWYgKCFlbWFpbCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IGRvY1JlZiA9IHRoaXMuZGIuZG9jKGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfWApO1xuICAgIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgZG9jUmVmLmdldCgpO1xuICAgIGNvbnN0IGRhdGEgPSBzbmFwc2hvdC5kYXRhKCkgfHwge307XG4gICAgY29uc3QgYWNsID0gZGF0YS5yb2xlcyB8fCB7fTtcblxuICAgIGlmIChlbWFpbCBpbiBhY2wpIHtcbiAgICAgIHJldHVybiBhY2xbZW1haWxdO1xuICAgIH1cblxuICAgIC8vIENoZWNrIHdpbGRjYXJkIGRvbWFpbnMsIGUuZy4gYCpAZXhhbXBsZS5jb21gLlxuICAgIGlmICghZW1haWwuaW5jbHVkZXMoJ0AnKSkge1xuICAgICAgY29uc29sZS53YXJuKGBpbnZhbGlkIGVtYWlsOiAke2VtYWlsfWApO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IGRvbWFpbiA9IGVtYWlsLnNwbGl0KCdAJykuYXQoLTEpO1xuICAgIGlmIChkb21haW4gJiYgYCpAJHtkb21haW59YCBpbiBhY2wpIHtcbiAgICAgIHJldHVybiBhY2xbYCpAJHtkb21haW59YF07XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWVzIHVzZXIgZXhpc3RzIGluIHRoZSBBQ0wgbGlzdC5cbiAgICovXG4gIGFzeW5jIHVzZXJFeGlzdHNJbkFjbChlbWFpbDogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKCFlbWFpbCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCBkb2NSZWYgPSB0aGlzLmRiLmRvYyhgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH1gKTtcbiAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IGRvY1JlZi5nZXQoKTtcbiAgICBjb25zdCBkYXRhID0gc25hcHNob3QuZGF0YSgpIHx8IHt9O1xuICAgIGNvbnN0IGFjbCA9IGRhdGEucm9sZXMgfHwge307XG4gICAgaWYgKGVtYWlsIGluIGFjbCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgd2lsZGNhcmQgZG9tYWlucywgZS5nLiBgKkBleGFtcGxlLmNvbWAuXG4gICAgaWYgKCFlbWFpbC5pbmNsdWRlcygnQCcpKSB7XG4gICAgICBjb25zb2xlLndhcm4oYGludmFsaWQgZW1haWw6ICR7ZW1haWx9YCk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IGRvbWFpbiA9IGVtYWlsLnNwbGl0KCdAJykuYXQoLTEpO1xuICAgIGlmIChkb21haW4gJiYgYCpAJHtkb21haW59YCBpbiBhY2wpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBhc3luYyBsb2dBY3Rpb24oYWN0aW9uOiBzdHJpbmcsIG9wdGlvbnM/OiB7Ynk/OiBzdHJpbmc7IG1ldGFkYXRhPzogYW55fSkge1xuICAgIGlmICghYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgcmVxdWlyZWQ6IFwiYWN0aW9uXCInKTtcbiAgICB9XG4gICAgY29uc3QgZGF0YSA9IHtcbiAgICAgIGFjdGlvbjogYWN0aW9uLFxuICAgICAgdGltZXN0YW1wOiBUaW1lc3RhbXAubm93KCksXG4gICAgICBieTogb3B0aW9ucz8uYnkgfHwgJ3N5c3RlbScsXG4gICAgICBtZXRhZGF0YTogb3B0aW9ucz8ubWV0YWRhdGEgfHwge30sXG4gICAgfTtcbiAgICBjb25zdCBjb2xSZWYgPSB0aGlzLmRiLmNvbGxlY3Rpb24oYFByb2plY3RzLyR7dGhpcy5wcm9qZWN0SWR9L0FjdGlvbkxvZ3NgKTtcbiAgICBhd2FpdCBjb2xSZWYuYWRkKGRhdGEpO1xuXG4gICAgY29uc3QgbWV0YVN0ciA9IG9wdGlvbnM/Lm1ldGFkYXRhID8gc3RyaW5naWZ5T2JqKG9wdGlvbnMubWV0YWRhdGEpIDogJyc7XG4gICAgY29uc29sZS5sb2coYFske2RhdGEudGltZXN0YW1wLnRvTWlsbGlzKCl9XSBhY3Rpb246ICR7YWN0aW9ufSAke21ldGFTdHJ9YCk7XG5cbiAgICAvLyBDYWxsIHRoZSBgb25BY3Rpb24oKWAgY2FsbGJhY2sgZnJvbSBjbXNQbHVnaW4oKS5cbiAgICBjb25zdCBjbXNQbHVnaW5Db25maWcgPSB0aGlzLmNtc1BsdWdpbi5nZXRDb25maWcoKTtcbiAgICBpZiAoY21zUGx1Z2luQ29uZmlnLm9uQWN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjbXNQbHVnaW5Db25maWcub25BY3Rpb24oZGF0YSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNyZWF0ZUJhdGNoUmVxdWVzdChvcHRpb25zOiBCYXRjaFJlcXVlc3RPcHRpb25zKTogQmF0Y2hSZXF1ZXN0IHtcbiAgICByZXR1cm4gbmV3IEJhdGNoUmVxdWVzdCh0aGlzLCBvcHRpb25zKTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJhdGNoUmVxdWVzdE9wdGlvbnMge1xuICBtb2RlOiAnZHJhZnQnIHwgJ3B1Ymxpc2hlZCc7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGF1dG9tYXRpY2FsbHkgZmV0Y2ggdHJhbnNsYXRpb25zIGZvciB0aGUgZG9jcyByZXRyaWV2ZWQgaW4gdGhlXG4gICAqIHJlcXVlc3QuXG4gICAqL1xuICB0cmFuc2xhdGU/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJhdGNoUmVxdWVzdFF1ZXJ5IHtcbiAgcXVlcnlJZDogc3RyaW5nO1xuICBjb2xsZWN0aW9uSWQ6IHN0cmluZztcbiAgcXVlcnlPcHRpb25zPzogQmF0Y2hSZXF1ZXN0UXVlcnlPcHRpb25zO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJhdGNoUmVxdWVzdFF1ZXJ5T3B0aW9ucyB7XG4gIG9mZnNldD86IG51bWJlcjtcbiAgbGltaXQ/OiBudW1iZXI7XG4gIG9yZGVyQnk/OiBzdHJpbmc7XG4gIG9yZGVyQnlEaXJlY3Rpb24/OiAnYXNjJyB8ICdkZXNjJztcbiAgcXVlcnk/OiAocXVlcnk6IFF1ZXJ5KSA9PiBRdWVyeTtcbn1cblxuZXhwb3J0IGNsYXNzIEJhdGNoUmVxdWVzdCB7XG4gIGNtc0NsaWVudDogUm9vdENNU0NsaWVudDtcbiAgcHJpdmF0ZSBvcHRpb25zOiBCYXRjaFJlcXVlc3RPcHRpb25zO1xuICBwcml2YXRlIGRiOiBGaXJlc3RvcmU7XG4gIHByaXZhdGUgZG9jSWRzOiBzdHJpbmdbXSA9IFtdO1xuICBwcml2YXRlIGRhdGFTb3VyY2VJZHM6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgcXVlcmllczogQmF0Y2hSZXF1ZXN0UXVlcnlbXSA9IFtdO1xuICBwcml2YXRlIHRyYW5zbGF0aW9uc0lkczogc3RyaW5nW10gPSBbXTtcblxuICBjb25zdHJ1Y3RvcihjbXNDbGllbnQ6IFJvb3RDTVNDbGllbnQsIG9wdGlvbnM6IEJhdGNoUmVxdWVzdE9wdGlvbnMpIHtcbiAgICB0aGlzLmNtc0NsaWVudCA9IGNtc0NsaWVudDtcbiAgICB0aGlzLmRiID0gY21zQ2xpZW50LmRiO1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIGRvYyB0byB0aGUgYmF0Y2ggcmVxdWVzdC5cbiAgICovXG4gIGFkZERvYyhkb2NJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5kb2NJZHMucHVzaChkb2NJZCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIGRhdGEgc291cmNlIHRvIHRoZSBiYXRjaCByZXF1ZXN0LlxuICAgKi9cbiAgYWRkRGF0YVNvdXJjZShkYXRhU291cmNlSWQ6IHN0cmluZykge1xuICAgIHRoaXMuZGF0YVNvdXJjZUlkcy5wdXNoKGRhdGFTb3VyY2VJZCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIGNvbGxlY3Rpb24tYmFzZWQgcXVlcnkgdG8gdGhlIGJhdGNoIHJlcXVlc3QuXG4gICAqL1xuICBhZGRRdWVyeShcbiAgICBxdWVyeUlkOiBzdHJpbmcsXG4gICAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gICAgcXVlcnlPcHRpb25zPzogQmF0Y2hSZXF1ZXN0UXVlcnlPcHRpb25zXG4gICkge1xuICAgIHRoaXMucXVlcmllcy5wdXNoKHtcbiAgICAgIHF1ZXJ5SWQ6IHF1ZXJ5SWQsXG4gICAgICBjb2xsZWN0aW9uSWQ6IGNvbGxlY3Rpb25JZCxcbiAgICAgIHF1ZXJ5T3B0aW9uczogcXVlcnlPcHRpb25zLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSB0cmFuc2xhdGlvbiBmaWxlIHRvIHRoZSByZXF1ZXN0LlxuICAgKi9cbiAgYWRkVHJhbnNsYXRpb25zKHRyYW5zbGF0aW9uc0lkOiBzdHJpbmcpIHtcbiAgICB0aGlzLnRyYW5zbGF0aW9uc0lkcy5wdXNoKHRyYW5zbGF0aW9uc0lkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGZXRjaGVzIGRhdGEgZnJvbSB0aGUgREIuXG4gICAqL1xuICBhc3luYyBmZXRjaCgpOiBQcm9taXNlPEJhdGNoUmVzcG9uc2U+IHtcbiAgICBjb25zdCByZXMgPSBuZXcgQmF0Y2hSZXNwb25zZSgpO1xuXG4gICAgY29uc3QgcHJvbWlzZXMgPSBbXG4gICAgICB0aGlzLmZldGNoRG9jcyhyZXMpLFxuICAgICAgdGhpcy5mZXRjaFF1ZXJpZXMocmVzKSxcbiAgICAgIHRoaXMuZmV0Y2hEYXRhU291cmNlcyhyZXMpLFxuICAgIF07XG4gICAgLy8gSWYgYG9wdGlvbnMudHJhbnNsYXRlYCBpcyBkaXNhYmxlZCBhbmQgdHJhbnNsYXRpb25zIGFyZSByZXF1ZXN0ZWQsXG4gICAgLy8gZmV0Y2ggdGhlIHRyYW5zbGF0aW9ucyBpbiBwYXJhbGxlbCB3aXRoIHRoZSBvdGhlciBkb2NzLlxuICAgIGlmICghdGhpcy5vcHRpb25zLnRyYW5zbGF0ZSAmJiB0aGlzLnRyYW5zbGF0aW9uc0lkcy5sZW5ndGggPiAwKSB7XG4gICAgICBwcm9taXNlcy5wdXNoKHRoaXMuZmV0Y2hUcmFuc2xhdGlvbnMocmVzKSk7XG4gICAgfVxuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuXG4gICAgLy8gSWYgYG9wdGlvbnMudHJhbnNsYXRlYCBpcyBlbmFibGVkLCB0aGUgZmV0Y2hYKCkgbWV0aG9kcyB3aWxsXG4gICAgLy8gYXV0b21hdGljYWxseSBhZGQgZWFjaCBkb2MncyB0cmFuc2xhdGlvbnMgaWQgdG8gdGhlIHJlcXVlc3QsIHNvXG4gICAgLy8gdHJhbnNsYXRpb25zIHNob3VsZCBiZSBmZXRjaGVkIGFmdGVyIGFsbCB0aGUgb3RoZXIgZG9jcyBhcmUgZmV0Y2hlZC5cbiAgICBpZiAodGhpcy50cmFuc2xhdGlvbnNJZHMubGVuZ3RoID4gMCkge1xuICAgICAgYXdhaXQgdGhpcy5mZXRjaFRyYW5zbGF0aW9ucyhyZXMpO1xuICAgIH1cblxuICAgIHJldHVybiByZXM7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoRG9jcyhyZXM6IEJhdGNoUmVzcG9uc2UpIHtcbiAgICBpZiAodGhpcy5kb2NJZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGRvY1JlZnMgPSB0aGlzLmRvY0lkcy5tYXAoKGRvY0lkKSA9PiB7XG4gICAgICBjb25zdCBbY29sbGVjdGlvbklkLCBzbHVnXSA9IGRvY0lkLnNwbGl0KCcvJyk7XG4gICAgICByZXR1cm4gdGhpcy5jbXNDbGllbnQuZGJEb2NSZWYoY29sbGVjdGlvbklkLCBzbHVnLCB7XG4gICAgICAgIG1vZGU6IHRoaXMub3B0aW9ucy5tb2RlLFxuICAgICAgfSk7XG4gICAgfSk7XG4gICAgY29uc3QgZG9jcyA9IGF3YWl0IHRoaXMuZGIuZ2V0QWxsKC4uLmRvY1JlZnMpO1xuICAgIHRoaXMuZG9jSWRzLmZvckVhY2goKGRvY0lkLCBpKSA9PiB7XG4gICAgICBjb25zdCBkb2MgPSBkb2NzW2ldO1xuICAgICAgaWYgKCFkb2MuZXhpc3RzKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihgZG9jIFwiJHtkb2NJZH1cIiBkb2VzIG5vdCBleGlzdGApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCBkb2NEYXRhID0gdW5tYXJzaGFsRGF0YShkb2MuZGF0YSgpKSBhcyBEb2M7XG4gICAgICByZXMuZG9jc1tkb2NJZF0gPSBkb2NEYXRhO1xuXG4gICAgICBpZiAodGhpcy5vcHRpb25zLnRyYW5zbGF0ZSkge1xuICAgICAgICB0aGlzLmFkZFRyYW5zbGF0aW9ucyhkb2NJZCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoUXVlcmllcyhyZXM6IEJhdGNoUmVzcG9uc2UpIHtcbiAgICBpZiAodGhpcy5xdWVyaWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBtb2RlID0gdGhpcy5vcHRpb25zLm1vZGU7XG5cbiAgICBjb25zdCBoYW5kbGVRdWVyeSA9IGFzeW5jIChxdWVyeUl0ZW06IEJhdGNoUmVxdWVzdFF1ZXJ5KSA9PiB7XG4gICAgICBjb25zdCBkb2NzUGF0aCA9IHRoaXMuY21zQ2xpZW50LmRiQ29sbGVjdGlvbkRvY3NQYXRoKFxuICAgICAgICBxdWVyeUl0ZW0uY29sbGVjdGlvbklkLFxuICAgICAgICB7bW9kZX1cbiAgICAgICk7XG4gICAgICBjb25zdCBxdWVyeU9wdGlvbnMgPSBxdWVyeUl0ZW0ucXVlcnlPcHRpb25zIHx8IHt9O1xuICAgICAgbGV0IHF1ZXJ5OiBRdWVyeSA9IHRoaXMuZGIuY29sbGVjdGlvbihkb2NzUGF0aCk7XG4gICAgICBpZiAocXVlcnlPcHRpb25zLmxpbWl0KSB7XG4gICAgICAgIHF1ZXJ5ID0gcXVlcnkubGltaXQocXVlcnlPcHRpb25zLmxpbWl0KTtcbiAgICAgIH1cbiAgICAgIGlmIChxdWVyeU9wdGlvbnMub2Zmc2V0KSB7XG4gICAgICAgIHF1ZXJ5ID0gcXVlcnkub2Zmc2V0KHF1ZXJ5T3B0aW9ucy5vZmZzZXQpO1xuICAgICAgfVxuICAgICAgaWYgKHF1ZXJ5T3B0aW9ucy5vcmRlckJ5KSB7XG4gICAgICAgIHF1ZXJ5ID0gcXVlcnkub3JkZXJCeShcbiAgICAgICAgICBxdWVyeU9wdGlvbnMub3JkZXJCeSxcbiAgICAgICAgICBxdWVyeU9wdGlvbnMub3JkZXJCeURpcmVjdGlvblxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKHF1ZXJ5T3B0aW9ucy5xdWVyeSkge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5T3B0aW9ucy5xdWVyeShxdWVyeSk7XG4gICAgICB9XG4gICAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgcXVlcnkuZ2V0KCk7XG4gICAgICBjb25zdCBkb2NzOiBEb2NbXSA9IFtdO1xuICAgICAgcmVzdWx0cy5mb3JFYWNoKChyZXN1bHQpID0+IHtcbiAgICAgICAgY29uc3QgZG9jID0gdW5tYXJzaGFsRGF0YShyZXN1bHQuZGF0YSgpKSBhcyBEb2M7XG4gICAgICAgIGRvY3MucHVzaChkb2MpO1xuICAgICAgfSk7XG4gICAgICByZXMucXVlcmllc1txdWVyeUl0ZW0ucXVlcnlJZF0gPSBkb2NzO1xuICAgIH07XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbCh0aGlzLnF1ZXJpZXMubWFwKChxdWVyeUl0ZW0pID0+IGhhbmRsZVF1ZXJ5KHF1ZXJ5SXRlbSkpKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hEYXRhU291cmNlcyhyZXM6IEJhdGNoUmVzcG9uc2UpIHtcbiAgICBpZiAodGhpcy5kYXRhU291cmNlSWRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBkb2NSZWZzID0gdGhpcy5kYXRhU291cmNlSWRzLm1hcCgoZGF0YVNvdXJjZUlkKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5jbXNDbGllbnQuZGJEYXRhU291cmNlRGF0YVJlZihkYXRhU291cmNlSWQsIHtcbiAgICAgICAgbW9kZTogdGhpcy5vcHRpb25zLm1vZGUsXG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBjb25zdCBkb2NzID0gYXdhaXQgdGhpcy5kYi5nZXRBbGwoLi4uZG9jUmVmcyk7XG4gICAgdGhpcy5kYXRhU291cmNlSWRzLmZvckVhY2goKGRhdGFTb3VyY2VJZCwgaSkgPT4ge1xuICAgICAgY29uc3QgZG9jID0gZG9jc1tpXTtcbiAgICAgIGlmICghZG9jLmV4aXN0cykge1xuICAgICAgICBjb25zb2xlLndhcm4oYFwiZGF0YSBzb3VyY2UgXCIke2RhdGFTb3VyY2VJZH1cIiBkb2VzIG5vdCBleGlzdGApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICByZXMuZGF0YVNvdXJjZXNbZGF0YVNvdXJjZUlkXSA9IGRvYy5kYXRhKCkgYXMgRGF0YVNvdXJjZURhdGE7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoVHJhbnNsYXRpb25zKHJlczogQmF0Y2hSZXNwb25zZSkge1xuICAgIGlmICh0aGlzLnRyYW5zbGF0aW9uc0lkcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBkb2NSZWZzID0gdGhpcy50cmFuc2xhdGlvbnNJZHMubWFwKCh0cmFuc2xhdGlvbnNJZCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuY21zQ2xpZW50LmRiVHJhbnNsYXRpb25zUmVmKHRyYW5zbGF0aW9uc0lkLCB7XG4gICAgICAgIG1vZGU6IHRoaXMub3B0aW9ucy5tb2RlLFxuICAgICAgfSk7XG4gICAgfSk7XG4gICAgY29uc3QgZG9jcyA9IGF3YWl0IHRoaXMuZGIuZ2V0QWxsKC4uLmRvY1JlZnMpO1xuICAgIHRoaXMudHJhbnNsYXRpb25zSWRzLmZvckVhY2goKHRyYW5zbGF0aW9uc0lkLCBpKSA9PiB7XG4gICAgICBjb25zdCBkb2MgPSBkb2NzW2ldO1xuICAgICAgaWYgKCFkb2MuZXhpc3RzKSB7XG4gICAgICAgIC8vIGNvbnNvbGUud2FybihgdHJhbnNsYXRpb25zIFwiJHt0cmFuc2xhdGlvbnNJZH1cIiBkb2VzIG5vdCBleGlzdGApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICByZXMudHJhbnNsYXRpb25zW3RyYW5zbGF0aW9uc0lkXSA9IGRvYy5kYXRhKCkgYXMgVHJhbnNsYXRpb25zRG9jO1xuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBCYXRjaFJlc3BvbnNlIHtcbiAgZG9jczogUmVjb3JkPHN0cmluZywgRG9jPiA9IHt9O1xuICBxdWVyaWVzOiBSZWNvcmQ8c3RyaW5nLCBEb2NbXT4gPSB7fTtcbiAgZGF0YVNvdXJjZXM6IFJlY29yZDxzdHJpbmcsIERhdGFTb3VyY2VEYXRhPiA9IHt9O1xuICB0cmFuc2xhdGlvbnM6IFJlY29yZDxzdHJpbmcsIFRyYW5zbGF0aW9uc0RvYz4gPSB7fTtcblxuICAvKipcbiAgICogUmV0dXJucyBhIG1hcCBvZiB0cmFuc2xhdGlvbnMgZm9yIGEgZ2l2ZW4gbG9jYWxlIG9yIGxvY2FsZSBmYWxsYmFja3MuXG4gICAqXG4gICAqIFRoZSBpbnB1dCBpcyBlaXRoZXIgYSBzaW5nbGUgbG9jYWxlIChlLmcuIFwiZGVcIikgb3IgYW4gYXJyYXkgb2YgbG9jYWxlc1xuICAgKiByZXByZXNlbnRpbmcgdGhlIGZhbGxiYWNrIHRyZWUsIGUuZy4gW1wiZW4tQ0FcIiwgXCJlbi1HQlwiLCBcImVuXCJdLlxuICAgKlxuICAgKiBUaGUgcmV0dXJuZWQgdmFsdWUgaXMgYSBmbGF0IG1hcCBvZiBzb3VyY2Ugc3RyaW5nIHRvIHRyYW5zbGF0ZWQgc3RyaW5nLFxuICAgKiBlLmcuOlxuICAgKiB7XCI8c291cmNlPlwiOiBcIjx0cmFuc2xhdGlvbj5cIn1cbiAgICovXG4gIGdldFRyYW5zbGF0aW9ucyhsb2NhbGU6IHN0cmluZyB8IHN0cmluZ1tdKTogTG9jYWxlVHJhbnNsYXRpb25zIHtcbiAgICBjb25zdCB0cmFuc2xhdGlvbnNNYXAgPSB0aGlzLmdldFRyYW5zbGF0aW9uc01hcCgpO1xuICAgIGNvbnN0IHRyYW5zbGF0aW9ucyA9IHRyYW5zbGF0aW9uc0ZvckxvY2FsZSh0cmFuc2xhdGlvbnNNYXAsIGxvY2FsZSk7XG4gICAgcmV0dXJuIHRyYW5zbGF0aW9ucztcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXJnZXMgdGhlIHN0cmluZ3MgZnJvbSBhbGwgdHJhbnNsYXRpb25zIGZpbGVzIHJldHJpZXZlZCBpbiB0aGUgcmVxdWVzdC5cbiAgICogVGhlIHJldHVybmVkIHZhbHVlIGlzIGEgbWFwIG9mIHN0cmluZyB0byB0cmFuc2xhdGlvbnMsIGUuZy46XG4gICAqXG4gICAqIHtcIjxoYXNoPlwiOiB7XCJzb3VyY2VcIjogXCI8c291cmNlPlwiLCBcIjxsb2NhbGU+XCI6IFwiPHRyYW5zbGF0aW9uPlwifX1cbiAgICovXG4gIHByaXZhdGUgZ2V0VHJhbnNsYXRpb25zTWFwKCk6IFRyYW5zbGF0aW9uc01hcCB7XG4gICAgLy8gTG9hZCB0cmFuc2xhdGlvbnMgaW4gdGhlIGZvbGxvd2luZyBvcmRlcjpcbiAgICAvLyAtIGdlbmVyaWMgdHJhbnNsYXRpb25zIChlLmcuIFwiZ2xvYmFsXCIpXG4gICAgLy8gLSBkb2NzIHJldHVybmVkIGZyb20gcXVlcmllcyAoZS5nLiBcImxpc3QgYWxsIGJsb2cgcG9zdHNcIilcbiAgICAvLyAtIHNwZWNpZmljIGRvY3MgKGUuZy4gXCJQYWdlcy9pbmRleFwiKVxuICAgIGNvbnN0IHRyYW5zbGF0aW9uc0RvY3MgPSBPYmplY3QudmFsdWVzKHRoaXMudHJhbnNsYXRpb25zKS5yZXZlcnNlKCk7XG5cbiAgICAvLyBDb25zb2xpZGF0ZSB0aGUgc3RyaW5ncyBmcm9tIGFsbCBvZiB0aGUgdHJhbnNsYXRpb25zIGZpbGVzLlxuICAgIC8vIHtcIjxoYXNoPlwiOiB7XCJzb3VyY2VcIjogXCI8c291cmNlPlwiLCBcIjxsb2NhbGU+XCI6IFwiPHRyYW5zbGF0aW9uPlwifX1cbiAgICBjb25zdCB0cmFuc2xhdGlvbnNNYXA6IFRyYW5zbGF0aW9uc01hcCA9IHt9O1xuICAgIGZvciAoY29uc3QgdHJhbnNsYXRpb25zRG9jIG9mIHRyYW5zbGF0aW9uc0RvY3MpIHtcbiAgICAgIGNvbnN0IHN0cmluZ3MgPSB0cmFuc2xhdGlvbnNEb2Muc3RyaW5ncyB8fCB7fTtcbiAgICAgIGZvciAoY29uc3QgaGFzaCBpbiBzdHJpbmdzKSB7XG4gICAgICAgIGNvbnN0IHRyYW5zbGF0aW9ucyA9IHN0cmluZ3NbaGFzaF07XG4gICAgICAgIHRyYW5zbGF0aW9uc01hcFtoYXNoXSA/Pz0ge3NvdXJjZTogdHJhbnNsYXRpb25zLnNvdXJjZX07XG4gICAgICAgIGZvciAoY29uc3QgbG9jYWxlIGluIHRyYW5zbGF0aW9ucykge1xuICAgICAgICAgIGlmIChsb2NhbGUgIT09ICdzb3VyY2UnICYmIHRyYW5zbGF0aW9uc1tsb2NhbGVdKSB7XG4gICAgICAgICAgICB0cmFuc2xhdGlvbnNNYXBbaGFzaF1bbG9jYWxlXSA9IHRyYW5zbGF0aW9uc1tsb2NhbGVdO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cmFuc2xhdGlvbnNNYXA7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIGBkYXRhYCBpcyBhIHJpY2ggdGV4dCBkYXRhIG9iamVjdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUmljaFRleHREYXRhKGRhdGE6IGFueSkge1xuICAvLyBUaGUgUmljaFRleHRFZGl0b3IgdXNlcyBlZGl0b3JqcyB1bmRlciB0aGUgaG9vZCwgdGhlIGRhdGEgZm9ybWF0IGlzXG4gIC8vIHNvbWV0aGluZyBsaWtlOlxuICAvLyAge1xuICAvLyAgIFwidGltZVwiOiAxNzIxNzYxMjExNzIwLFxuICAvLyAgIFwidmVyc2lvblwiOiBcIjIuMjguMlwiLFxuICAvLyAgIFwiYmxvY2tzXCI6IFsuLi5dXG4gIC8vIH1cbiAgcmV0dXJuIEJvb2xlYW4oXG4gICAgaXNPYmplY3QoZGF0YSkgJiYgQXJyYXkuaXNBcnJheShkYXRhLmJsb2NrcykgJiYgZGF0YS50aW1lICYmIGRhdGEudmVyc2lvblxuICApO1xufVxuXG4vKipcbiAqIFdhbGtzIHRoZSBkYXRhIHRyZWUgYW5kIGNvbnZlcnRzIGFueSBhcnJheSBvZiBvYmplY3RzIGludG8gXCJhcnJheSBvYmplY3RzXCJcbiAqIGZvciBzdG9yYWdlIGluIGZpcmVzdG9yZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hcnNoYWxEYXRhKGRhdGE6IGFueSk6IGFueSB7XG4gIC8vIEF2b2lkIGNoYW5naW5nIHRoZSBmb3JtYXQgb2YgcmljaCB0ZXh0IGRhdGEuXG4gIGlmIChpc1JpY2hUZXh0RGF0YShkYXRhKSkge1xuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgY29uc3QgcmVzdWx0OiBhbnkgPSB7fTtcbiAgZm9yIChjb25zdCBrZXkgaW4gZGF0YSkge1xuICAgIGNvbnN0IHZhbCA9IGRhdGFba2V5XTtcbiAgICBpZiAoaXNPYmplY3QodmFsKSkge1xuICAgICAgcmVzdWx0W2tleV0gPSBtYXJzaGFsRGF0YSh2YWwpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKSB7XG4gICAgICBpZiAodmFsLmxlbmd0aCA+IDAgJiYgdmFsLnNvbWUoKGl0ZW0pID0+IGlzT2JqZWN0KGl0ZW0pKSkge1xuICAgICAgICBjb25zdCBpdGVtcyA9IHZhbC5tYXAoKGl0ZW0pID0+IHtcbiAgICAgICAgICBpZiAoaXNPYmplY3QoaXRlbSkpIHtcbiAgICAgICAgICAgIHJldHVybiBtYXJzaGFsRGF0YShpdGVtKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgICAgIH0pO1xuICAgICAgICByZXN1bHRba2V5XSA9IHRvQXJyYXlPYmplY3QoaXRlbXMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0W2tleV0gPSB2YWw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdFtrZXldID0gdmFsO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIFdhbGtzIHRoZSBkYXRhIHRyZWUgYW5kIGNvbnZlcnRzIGFueSBUaW1lc3RhbXAgb2JqZWN0cyB0byBtaWxsaXMgYW5kIGFueVxuICogX2FycmF5IG1hcHMgdG8gbm9ybWFsIGFycmF5cy5cbiAqXG4gKiBFLmcuOlxuICpcbiAqIG5vcm1hbGl6ZURhdGEoe1xuICogICBzeXM6IHttb2RpZmllZEF0OiBUaW1lc3RhbXAoMTIzKX0sXG4gKiAgIGZpZWxkczoge1xuICogICAgIF9hcnJheTogWydhc2RmJ10sXG4gKiAgICAgYXNkZjoge3RpdGxlOiAnaGVsbG8nfVxuICogICB9XG4gKiB9KVxuICogLy8gPT4ge3N5czoge21vZGlmaWVkQXQ6IDEyM30sIGZpZWxkczoge2ZvbzogW3t0aXRsZTogJ2hlbGxvJ31dfX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVubWFyc2hhbERhdGEoZGF0YTogYW55KTogYW55IHtcbiAgY29uc3QgcmVzdWx0OiBhbnkgPSB7fTtcbiAgZm9yIChjb25zdCBrZXkgaW4gZGF0YSkge1xuICAgIGNvbnN0IHZhbCA9IGRhdGFba2V5XTtcbiAgICBpZiAoaXNPYmplY3QodmFsKSkge1xuICAgICAgaWYgKHZhbC50b01pbGxpcykge1xuICAgICAgICByZXN1bHRba2V5XSA9IHZhbC50b01pbGxpcygpO1xuICAgICAgfSBlbHNlIGlmIChPYmplY3QuaGFzT3duKHZhbCwgJ19hcnJheScpICYmIEFycmF5LmlzQXJyYXkodmFsLl9hcnJheSkpIHtcbiAgICAgICAgY29uc3QgYXJyID0gdmFsLl9hcnJheS5tYXAoKGFycmF5S2V5OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4udW5tYXJzaGFsRGF0YSh2YWxbYXJyYXlLZXldIHx8IHt9KSxcbiAgICAgICAgICAgIF9hcnJheUtleTogYXJyYXlLZXksXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3VsdFtrZXldID0gYXJyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0W2tleV0gPSB1bm1hcnNoYWxEYXRhKHZhbCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdFtrZXldID0gdmFsO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKiogQGRlcHJlY2F0ZWQgVXNlIGB1bm1hcnNoYWxEYXRhKClgIGluc3RlYWQuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplRGF0YShkYXRhOiBhbnkpOiBhbnkge1xuICByZXR1cm4gdW5tYXJzaGFsRGF0YShkYXRhKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBcnJheU9iamVjdCB7XG4gIFtrZXk6IHN0cmluZ106IGFueTtcbiAgX2FycmF5OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBTZXJpYWxpemVzIGFuIGFycmF5IGludG8gYW4gYEFycmF5T2JqZWN0YCwgZS5nLjpcbiAqXG4gKiBgYGBcbiAqIG1hcnNoYWxBcnJheShbMSwgMiwgM10pXG4gKiAvLyA9PiB7YTogMSwgYjogMiwgYzogMywgX2FycmF5OiBbJ2EnLCAnYicsICdjJ119XG4gKiBgYGBcbiAqXG4gKiBUaGlzIGRhdGFiYXNlIHN0b3JhZ2UgbWV0aG9kIG1ha2VzIGl0IGVhc2llciB0byB1cGRhdGUgYSBzaW5nbGUgZmllbGQgaW4gYVxuICogZGVlcGx5IG5lc3RlZCBhcnJheSBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b0FycmF5T2JqZWN0KGFycjogYW55W10pOiBBcnJheU9iamVjdCB7XG4gIGlmICghQXJyYXkuaXNBcnJheShhcnIpKSB7XG4gICAgcmV0dXJuIGFycjtcbiAgfVxuICBjb25zdCBhcnJPYmplY3Q6IEFycmF5T2JqZWN0ID0ge19hcnJheTogW119O1xuICBmb3IgKGNvbnN0IGl0ZW0gb2YgYXJyKSB7XG4gICAgY29uc3Qga2V5ID0gcmFuZFN0cmluZyg2KTtcbiAgICBhcnJPYmplY3Rba2V5XSA9IGl0ZW07XG4gICAgYXJyT2JqZWN0Ll9hcnJheS5wdXNoKGtleSk7XG4gIH1cbiAgcmV0dXJuIGFyck9iamVjdDtcbn1cblxuZXhwb3J0IGNvbnN0IG1hcnNoYWxBcnJheSA9IHRvQXJyYXlPYmplY3Q7XG5cbi8qKlxuICogQ29udmVydHMgYW4gYEFycmF5T2JqZWN0YCB0byBhIG5vcm1hbCBhcnJheS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVubWFyc2hhbEFycmF5KGFyck9iamVjdDogQXJyYXlPYmplY3QpOiBhbnlbXSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShhcnJPYmplY3Q/Ll9hcnJheSkpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgY29uc3QgYXJyID0gYXJyT2JqZWN0Ll9hcnJheS5tYXAoKGs6IHN0cmluZykgPT4gYXJyT2JqZWN0W2tdKTtcbiAgcmV0dXJuIGFycjtcbn1cblxuZnVuY3Rpb24gaXNPYmplY3QoZGF0YTogYW55KTogYm9vbGVhbiB7XG4gIHJldHVybiB0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkoZGF0YSkgJiYgZGF0YSAhPT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gcmFuZFN0cmluZyhsZW46IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IHJlc3VsdCA9IFtdO1xuICBjb25zdCBjaGFycyA9XG4gICAgJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5JztcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgIGNvbnN0IHJhbmQgPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBjaGFycy5sZW5ndGgpO1xuICAgIHJlc3VsdC5wdXNoKGNoYXJzLmNoYXJBdChyYW5kKSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdC5qb2luKCcnKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHRyYW5zbGF0aW9ucyBtYXAgZnJvbSBgbG9hZFRyYW5zbGF0aW9ucygpYCB0byBhIG1hcCBvZiBzb3VyY2UgdG9cbiAqIHRyYW5zbGF0ZWQgc3RyaW5nIGZvciBhIHBhcnRpY3VsYXIgbG9jYWxlLlxuICpcbiAqIFJldHVybnMgYSBtYXAgbGlrZTpcbiAqIGBgYFxuICoge1xuICogICBcIkhlbGxvXCI6IFwiQm9uam91clwiLFxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2xhdGlvbnNGb3JMb2NhbGUoXG4gIHRyYW5zbGF0aW9uc01hcDogVHJhbnNsYXRpb25zTWFwLFxuICBsb2NhbGU6IHN0cmluZyB8IHN0cmluZ1tdXG4pIHtcbiAgY29uc3QgbG9jYWxlVHJhbnNsYXRpb25zOiBMb2NhbGVUcmFuc2xhdGlvbnMgPSB7fTtcblxuICBjb25zdCBmYWxsYmFja0xvY2FsZXMgPSBBcnJheS5pc0FycmF5KGxvY2FsZSkgPyBsb2NhbGUgOiBbbG9jYWxlXTtcbiAgaWYgKCFmYWxsYmFja0xvY2FsZXMuaW5jbHVkZXMoJ2VuJykpIHtcbiAgICBmYWxsYmFja0xvY2FsZXMucHVzaCgnZW4nKTtcbiAgfVxuXG4gIE9iamVjdC52YWx1ZXModHJhbnNsYXRpb25zTWFwKS5mb3JFYWNoKChzdHJpbmcpID0+IHtcbiAgICBjb25zdCBzb3VyY2UgPSBzdHJpbmcuc291cmNlO1xuICAgIGxldCB0cmFuc2xhdGlvbiA9IHNvdXJjZTtcbiAgICBmb3IgKGNvbnN0IGZhbGxiYWNrTG9jYWxlIG9mIGZhbGxiYWNrTG9jYWxlcykge1xuICAgICAgaWYgKHN0cmluZ1tmYWxsYmFja0xvY2FsZV0pIHtcbiAgICAgICAgdHJhbnNsYXRpb24gPSBzdHJpbmdbZmFsbGJhY2tMb2NhbGVdO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgbG9jYWxlVHJhbnNsYXRpb25zW3NvdXJjZV0gPSB0cmFuc2xhdGlvbjtcbiAgfSk7XG4gIHJldHVybiBsb2NhbGVUcmFuc2xhdGlvbnM7XG59XG5cbi8qKiBBIHByZXR0eSBwcmludGVyIGZvciBKYXZhU2NyaXB0IG9iamVjdHMuICovXG5mdW5jdGlvbiBzdHJpbmdpZnlPYmoob2JqOiBhbnkpIHtcbiAgZnVuY3Rpb24gZm9ybWF0KG9iajogYW55KTogc3RyaW5nIHtcbiAgICBpZiAob2JqID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gJ251bGwnO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG9iaiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiAndW5kZWZpbmVkJztcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBvYmogPT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gYFwiJHtvYmoucmVwbGFjZUFsbCgnXCInLCAnXFxcXFwiJyl9XCJgO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG9iaiAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICB9XG4gICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgICAgcmV0dXJuIGBbJHtvYmoubWFwKGZvcm1hdCkuam9pbignLCAnKX1dYDtcbiAgICB9XG4gICAgY29uc3QgZW50cmllczogc3RyaW5nW10gPSBPYmplY3QuZW50cmllcyhvYmopLm1hcCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICByZXR1cm4gYCR7a2V5fTogJHtmb3JtYXQodmFsdWUpfWA7XG4gICAgfSk7XG4gICAgcmV0dXJuIGB7JHtlbnRyaWVzLmpvaW4oJywgJyl9fWA7XG4gIH1cbiAgcmV0dXJuIGZvcm1hdChvYmopO1xufVxuXG4vKipcbiAqIFBhcnNlcyBhIGRvY0lkIChlLmcuIGBQYWdlcy9mb29gKSBhbmQgcmV0dXJucyB0aGUgYGNvbGxlY3Rpb25gIGFuZCBgc2x1Z2AuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZURvY0lkKGRvY0lkOiBzdHJpbmcpIHtcbiAgY29uc3Qgc2VwSW5kZXggPSBkb2NJZC5pbmRleE9mKCcvJyk7XG4gIGlmIChzZXBJbmRleCA8PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGRvYyBpZDogJHtkb2NJZH1gKTtcbiAgfVxuICBjb25zdCBjb2xsZWN0aW9uID0gZG9jSWQuc2xpY2UoMCwgc2VwSW5kZXgpO1xuICBjb25zdCBzbHVnID0gZG9jSWQuc2xpY2Uoc2VwSW5kZXggKyAxKS5yZXBsYWNlQWxsKCcvJywgJy0tJyk7XG4gIGlmICghY29sbGVjdGlvbiB8fCAhc2x1Zykge1xuICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkb2MgaWQ6ICR7ZG9jSWR9YCk7XG4gIH1cbiAgcmV0dXJuIHtjb2xsZWN0aW9uLCBzbHVnfTtcbn1cblxuZXhwb3J0IHtnZXRDbXNQbHVnaW59O1xuIiwgImltcG9ydCB7cHJvbWlzZXMgYXMgZnN9IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7ZmlsZVVSTFRvUGF0aH0gZnJvbSAnbm9kZTp1cmwnO1xuaW1wb3J0IHR5cGUge1xuICBDb25maWd1cmVTZXJ2ZXJPcHRpb25zLFxuICBOZXh0RnVuY3Rpb24sXG4gIFBsdWdpbixcbiAgUmVxdWVzdCxcbiAgUmVzcG9uc2UsXG4gIFJvb3RDb25maWcsXG4gIFNlcnZlcixcbn0gZnJvbSAnQGJsaW5ray9yb290JztcbmltcG9ydCBib2R5UGFyc2VyIGZyb20gJ2JvZHktcGFyc2VyJztcbmltcG9ydCB7XG4gIEFwcCxcbiAgYXBwbGljYXRpb25EZWZhdWx0LFxuICBnZXRBcHAsXG4gIGluaXRpYWxpemVBcHAsXG59IGZyb20gJ2ZpcmViYXNlLWFkbWluL2FwcCc7XG5pbXBvcnQge2dldEF1dGgsIERlY29kZWRJZFRva2VufSBmcm9tICdmaXJlYmFzZS1hZG1pbi9hdXRoJztcbmltcG9ydCB7RmlyZXN0b3JlLCBnZXRGaXJlc3RvcmV9IGZyb20gJ2ZpcmViYXNlLWFkbWluL2ZpcmVzdG9yZSc7XG5pbXBvcnQgKiBhcyBqc29ud2VidG9rZW4gZnJvbSAnanNvbndlYnRva2VuJztcbmltcG9ydCBzaXJ2IGZyb20gJ3NpcnYnO1xuaW1wb3J0IHthcGl9IGZyb20gJy4vYXBpLmpzJztcbmltcG9ydCB7QWN0aW9uLCBSb290Q01TQ2xpZW50fSBmcm9tICcuL2NsaWVudC5qcyc7XG5pbXBvcnQge3J1bkNvbXBhdGliaWxpdHlDaGVja3N9IGZyb20gJy4vY29tcGF0aWJpbGl0eS5qcyc7XG5cbmNvbnN0IF9fZGlybmFtZSA9IHBhdGguZGlybmFtZShmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpO1xuXG50eXBlIEFwcE1vZHVsZSA9IHR5cGVvZiBpbXBvcnQoJy4vYXBwLmpzJyk7XG5cbi8vIFRoZSBzZXNzaW9uIGtleSBuYW1lIHVzZWQgZm9yIFJvb3QgQ01TIGF1dGhlbnRpY2F0aW9uLlxuY29uc3QgU0VTU0lPTl9DT09LSUVfQVVUSCA9ICdyb290LWNtcy1hdXRoJztcblxuZXhwb3J0IGludGVyZmFjZSBDTVNVc2VyIHtcbiAgZW1haWw6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDTVNBSUNvbmZpZyB7XG4gIC8qKiBDdXN0b20gQVBJIGVuZHBvaW50IGZvciBjaGF0IHByb21wdHMuICovXG4gIGVuZHBvaW50Pzogc3RyaW5nO1xuICAvKiogR2VuIEFJIG1vZGVsIHRvIHVzZS4gRGVmYXVsdHMgdG8gJ2dlbWluaS0xLjUtZmxhc2gnLiAqL1xuICBtb2RlbD86ICdnZW1pbmktMS41LWZsYXNoJyB8ICdnZW1pbmktMS41LXBybyc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ01TU2lkZWJhclRvb2wge1xuICAvKiogVVJMIGZvciB0aGUgc2lkZWJhciBpY29uIGltYWdlLiAqL1xuICBpY29uPzogc3RyaW5nO1xuICAvKiogTGFiZWwuICovXG4gIGxhYmVsPzogc3RyaW5nO1xuICAvKiogSWZyYW1lIFVSTCB0byByZW5kZXIgZm9yIHRoZSB0b29sLiAqL1xuICBpZnJhbWVVcmw/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIENNU1BsdWdpbk9wdGlvbnMgPSB7XG4gIC8qKlxuICAgKiBUaGUgSUQgb2YgdGhlIHByb2plY3QuIERhdGEgd2lsbCBiZSBzdG9yZWQgdW5kZXIgdGhlIG5hbWVzcGFjZVxuICAgKiBgUHJvamVjdHMvJHtpZH1gIGluIGZpcmVzdG9yZS5cbiAgICovXG4gIGlkPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgcHJvamVjdC4gVXNlZCBpbiB0aGUgaGVhZGVyIG9mIHRoZSBDTVMgdG8gaGVscCBpZGVudGlmeVxuICAgKiB0aGUgcHJvamVjdC5cbiAgICovXG4gIG5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEZpcmViYXNlIGNvbmZpZyBvYmplY3QsIHdoaWNoIGNhbiBiZSBvYnRhaW5lZCBpbiB0aGUgRmlyZWJhc2UgQ29uc29sZSBieVxuICAgKiBnb2luZyB0byBcIlByb2plY3QgU2V0dGluZ3NcIi5cbiAgICovXG4gIGZpcmViYXNlQ29uZmlnOiB7XG4gICAgW2tleTogc3RyaW5nXTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIGFwaUtleTogc3RyaW5nO1xuICAgIGF1dGhEb21haW46IHN0cmluZztcbiAgICBwcm9qZWN0SWQ6IHN0cmluZztcbiAgICBzdG9yYWdlQnVja2V0OiBzdHJpbmc7XG4gICAgZGF0YWJhc2VJZD86IHN0cmluZztcbiAgfTtcblxuICAvKipcbiAgICogR0FQSSBjcmVkZW50aWFscy4gSW5jbHVkZSBpZiB1c2luZyBHb29nbGUgRHJpdmUgYW5kIEdvb2dsZSBTaGVldHMgZmVhdHVyZXMuXG4gICAqIFNlZTogaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2dsZS5jb20vc2hlZXRzL2FwaS9xdWlja3N0YXJ0L2pzXG4gICAqL1xuICBnYXBpPzoge1xuICAgIC8qKiBodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS9zaGVldHMvYXBpL3F1aWNrc3RhcnQvanMjY3JlYXRlX2FuX2FwaV9rZXkgKi9cbiAgICBhcGlLZXk6IHN0cmluZztcbiAgICAvKiogaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2dsZS5jb20vc2hlZXRzL2FwaS9xdWlja3N0YXJ0L2pzI2F1dGhvcml6ZV9jcmVkZW50aWFsc19mb3JfYV93ZWJfYXBwbGljYXRpb24gKi9cbiAgICBjbGllbnRJZDogc3RyaW5nO1xuICB9O1xuXG4gIC8qKlxuICAgKiBTZWNyZXQgdmFsdWUocykgdXNlZCBmb3Igc2lnbmluZyB0aGUgdXNlciBhdXRoZW50aWNhdGlvbiBjb29raWUuXG4gICAqIEBkZXByZWNhdGVkIFRoaXMgaXMgbm93IGhhbmRsZWQgZGlyZWN0bHkgYnkgcm9vdCdzIHNlc3Npb25NaWRkbGV3YXJlIHVuZGVyXG4gICAqIGBzZXJ2ZXIuc2Vzc2lvbkNvb2tpZVNlY3JldGAgaW4gcm9vdC5jb25maWcudHMuXG4gICAqL1xuICBjb29raWVTZWNyZXQ/OiBzdHJpbmcgfCBzdHJpbmdbXTtcblxuICAvKiogRnVuY3Rpb24gY2FsbGVkIHRvIGNoZWNrIGlmIGEgdXNlciBzaG91bGQgaGF2ZSBhY2Nlc3MgdG8gdGhlIENNUy4gKi9cbiAgaXNVc2VyQXV0aG9yaXplZD86IChcbiAgICByZXE6IFJlcXVlc3QsXG4gICAgdXNlcjogQ01TVXNlclxuICApID0+IGJvb2xlYW4gfCBQcm9taXNlPGJvb2xlYW4+O1xuXG4gIC8qKlxuICAgKiBGdW5jdGlvbiB0byBjYWxsIHRvIGNoZWNrIGlmIGxvZ2luIGlzIHJlcXVpcmVkIGZvciBhIHBhcnRpY3VsYXIgcmVxdWVzdC5cbiAgICovXG4gIGlzTG9naW5SZXF1aXJlZD86IChyZXE6IFJlcXVlc3QpID0+IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEJ5IGRlZmF1bHQsIGlmcmFtaW5nIHRoZSBDTVMgaXMgZGlzYWxsb3dlZC4gU2V0dGluZyB0aGlzIHZhbHVlIHdpbGwgYWxsb3dcbiAgICogaWZyYW1lcyBmcm9tIHRoZSBzcGVjaWZpZWQgb3JpZ2lucy4gRXhhbXBsZTpcbiAgICogYGBgXG4gICAqIGFsbG93ZWRJZnJhbWVPcmlnaW5zOiBbJ2h0dHBzOi8vYXBwLmV4YW1wbGUuY29tJ11cbiAgICogYGBgXG4gICAqL1xuICBhbGxvd2VkSWZyYW1lT3JpZ2lucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBVUkwgdG8gR0NJIHNlcnZpY2UgZm9yIHRyYW5zZm9ybWluZyB1cGxvYWRlZCBHQ1MgaW1hZ2VzIHRvIGEgR29vZ2xlIEFwcFxuICAgKiBFbmdpbmUgSW1hZ2VzIEFQSSBzZXJ2aW5nIFVSTC5cbiAgICpcbiAgICogU2V0dGluZyB0aGlzIHRvIGB0cnVlYCB1c2VzIHRoZSBkZWZhdWx0IGhvc3RlZCBzZXJ2aWNlIGF0XG4gICAqIGh0dHBzOi8vZ2NpLnJvb3Rqcy5kZXYuXG4gICAqXG4gICAqIFRvIHNldCB1cCBHQ0k6XG4gICAqXG4gICAqIC0gQ3JlYXRlIGEgR0NTIGJ1Y2tldCB3aXRoIGZpbmUtZ3JhaW5lZCBwZXJtaXNzaW9uc1xuICAgKiAtIFNoYXJlIG93bmVyIGFjY2VzcyB0byB0aGUgYnVja2V0IHdpdGggdGhlIHNlcnZpY2UgYWNjb3VudCByZXR1cm5lZCBpblxuICAgKiAgIGh0dHBzOi8vZ2NpLnJvb3Rqcy5kZXYvXy9zZXJ2aWNlX2FjY291bnRcbiAgICpcbiAgICogVG8gZGlzYWJsZSBHQ0ksIGxlYXZlIHRoaXMgdmFsdWUgZW1wdHkgb3Igc2V0IHRvIGBmYWxzZWAsIHdoaWNoIHdoaWNoIHdpbGxcbiAgICogc2VydmUgaW1hZ2VzIGRpcmVjdGx5IGZyb20gR0NTIGluc3RlYWQuXG4gICAqL1xuICBnY2k/OiBzdHJpbmcgfCBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBDdXN0b21pemF0aW9uIG9wdGlvbnMgZm9yIHRoZSBDTVMgc2lkZWJhci5cbiAgICovXG4gIHNpZGViYXI/OiB7XG4gICAgLyoqXG4gICAgICogU2lkZWJhciB0b29scywgYSBtYXAgb2YgdGhlIHNpZGViYXIgaWQgdG8gY29uZmlnIG9wdGlvbnMuIFRoZSBzaWRlYmFyXG4gICAgICogdG9vbCBpcyB1cmwtbWFwcGVkIHRvIGAvY21zL3Rvb2xzLzppZGAgYW5kIGRpc3BsYXlzIHRoZSB0b29sIGluIGFuXG4gICAgICogaWZyYW1lLlxuICAgICAqL1xuICAgIHRvb2xzPzogUmVjb3JkPHN0cmluZywgQ01TU2lkZWJhclRvb2w+O1xuICB9O1xuXG4gIC8qKlxuICAgKiBDYWxsYmFjayB3aGVuIGFuIGFjdGlvbiBvY2N1cnMuXG4gICAqL1xuICBvbkFjdGlvbj86IChhY3Rpb246IEFjdGlvbikgPT4gYW55O1xuXG4gIC8qKlxuICAgKiBFeHBlcmltZW50YWwgY29uZmlnIG9wdGlvbnMuIE5vdGU6IHRoZXNlIGFyZSBzdWJqZWN0IHRvIGNoYW5nZSBhdCBhbnkgdGltZS5cbiAgICovXG4gIGV4cGVyaW1lbnRzPzoge1xuICAgIGFpPzogYm9vbGVhbiB8IENNU0FJQ29uZmlnO1xuICB9O1xuXG4gIC8qKlxuICAgKiBBZGp1c3QgY29uc29sZSBvdXRwdXQgdmVyYm9zaXR5LiBEZWZhdWx0IGlzIGAnaW5mbydgLlxuICAgKi9cbiAgbG9nTGV2ZWw/OiAnaW5mbycgfCAnd2FybicgfCAnZXJyb3InIHwgJ3NpbGVudCcgfCAnZGVidWcnO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGVuYWJsZS9kaXNhYmxlIGZpbGUgd2F0Y2hpbmcgaW4gZGV2IChlLmcuIGZvciBnZW5lcmF0aW5nXG4gICAqIGByb290LWNtcy5kLnRzYCkuIERlZmF1bHRzIHRvIGB0cnVlYC5cbiAgICovXG4gIHdhdGNoPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCB0eXBlIENNU1BsdWdpbiA9IFBsdWdpbiAmIHtcbiAgbmFtZTogJ3Jvb3QtY21zJztcbiAgZ2V0Q29uZmlnOiAoKSA9PiBDTVNQbHVnaW5PcHRpb25zO1xuICBnZXRGaXJlYmFzZUFwcDogKCkgPT4gQXBwO1xuICBnZXRGaXJlc3RvcmU6ICgpID0+IEZpcmVzdG9yZTtcbn07XG5cbmZ1bmN0aW9uIGlzRXhwaXJlZChkZWNvZGVkSWRUb2tlbjogRGVjb2RlZElkVG9rZW4pIHtcbiAgY29uc3QgdHMgPSBNYXRoLmZsb29yKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC8gMTAwMCk7XG4gIHJldHVybiB0cyA+PSBkZWNvZGVkSWRUb2tlbi5leHA7XG59XG5cbmZ1bmN0aW9uIGdldEZpcmViYXNlQXBwKGdjcFByb2plY3RJZDogc3RyaW5nKTogQXBwIHtcbiAgY29uc3QgYXBwTmFtZSA9ICdyb290LWNtcyc7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGdldEFwcChhcHBOYW1lKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKGVyciAmJiBlcnIuY29kZSA9PT0gJ2FwcC9uby1hcHAnKSB7XG4gICAgICByZXR1cm4gaW5pdGlhbGl6ZUFwcChcbiAgICAgICAge1xuICAgICAgICAgIHByb2plY3RJZDogZ2NwUHJvamVjdElkLFxuICAgICAgICAgIGNyZWRlbnRpYWw6IGFwcGxpY2F0aW9uRGVmYXVsdCgpLFxuICAgICAgICB9LFxuICAgICAgICBhcHBOYW1lXG4gICAgICApO1xuICAgIH1cbiAgICB0aHJvdyBlcnI7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNtc1BsdWdpbihvcHRpb25zOiBDTVNQbHVnaW5PcHRpb25zKTogQ01TUGx1Z2luIHtcbiAgY29uc3QgbG9nTGV2ZWwgPSBvcHRpb25zLmxvZ0xldmVsIHx8ICdpbmZvJztcblxuICBpZiAoIW9wdGlvbnMuZmlyZWJhc2VDb25maWcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnbWlzc2luZyBmaXJlYmFzZUNvbmZpZy4gY3JlYXRlIGEgbmV3IGFwcCBpbiB0aGUgZmlyZWJhc2UgYWRtaW4gY29uc29sZSBhbmQgY29weSB0aGUgZmlyZWJhc2UgY29uZmlnIG9iamVjdCB0byByb290LmNvbmZpZy50cydcbiAgICApO1xuICB9XG5cbiAgY29uc3QgZmlyZWJhc2VDb25maWcgPSBvcHRpb25zLmZpcmViYXNlQ29uZmlnIHx8IHt9O1xuICBjb25zdCBhcHAgPSBnZXRGaXJlYmFzZUFwcChmaXJlYmFzZUNvbmZpZy5wcm9qZWN0SWQpO1xuICBjb25zdCBhdXRoID0gZ2V0QXV0aChhcHApO1xuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgbG9naW4gaXMgcmVxdWlyZWQgZm9yIHRoZSByZXF1ZXN0LiBDdXJyZW50bHkgcmV0dXJucyBgdHJ1ZWAgaWZcbiAgICogdGhlIFVSTCBwYXRoIHN0YXJ0cyB3aXRoIC9jbXMgb3IgaWYgP3ByZXZpZXc9dHJ1ZSBpcyBpbiB0aGUgVVJMLlxuICAgKi9cbiAgZnVuY3Rpb24gbG9naW5SZXF1aXJlZChyZXE6IFJlcXVlc3QpOiBib29sZWFuIHtcbiAgICBjb25zdCB1cmxQYXRoID0gU3RyaW5nKHJlcS5vcmlnaW5hbFVybCkuc3BsaXQoJz8nKVswXS50b0xvd2VyQ2FzZSgpO1xuICAgIC8vIEFsbG93IHRoZSBjcm9uIHRvIHJ1biB1bmF1dGhlbnRpY2F0ZWQuIFRoZSBjcm9uIGpvYiBpcyByZXNwb25zaWJsZVxuICAgIC8vIGZvciBzYXZpbmcgdmVyc2lvbiBoaXN0b3J5LlxuICAgIGlmICh1cmxQYXRoID09PSAnL2Ntcy9hcGkvY3Jvbi5ydW4nKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8vIEFsbG93IHRoZSBzaWduaW4uY3NzIGFuZCBzaWduaW4uanMgZmlsZXMgdG8gYmUgcmVuZGVyZWQgd2l0aG91dCBhdXRoLlxuICAgIGlmIChcbiAgICAgIHVybFBhdGggPT09ICcvY21zL3N0YXRpYy9zaWduaW4uY3NzJyB8fFxuICAgICAgdXJsUGF0aCA9PT0gJy9jbXMvc3RhdGljL3NpZ25pbi5qcydcbiAgICApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLy8gUmVxdWlyZSBsb2dpbiBvbiBhbGwgYC9jbXMvYCBwYXRocy5cbiAgICBpZiAodXJsUGF0aC5zdGFydHNXaXRoKCcvY21zJykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICAvLyBSZXF1aXJlIGxvZ2luIG9uIGFsbCBwYXRocyB0aGF0IGhhdmUgYD9wcmV2aWV3PXRydWVgLCB3aGljaCBpcyB1c2VkIGJ5XG4gICAgLy8gdGhlIHByZXZpZXcgaWZyYW1lIHRvIHJlbmRlciB0aGUgcHJldmlldyBmb3IgYSBwYWdlLlxuICAgIGlmIChTdHJpbmcocmVxLnF1ZXJ5LnByZXZpZXcpID09PSAndHJ1ZScpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5pc0xvZ2luUmVxdWlyZWQgJiYgb3B0aW9ucy5pc0xvZ2luUmVxdWlyZWQocmVxKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZmllcyBhIG5ldyBsb2dpbiByZXF1ZXN0IGZvciBhIHVzZXIuIFRoZSByZXF1ZXN0IGJvZHkgc2hvdWxkIGNvbnRhaW5cbiAgICogYW4gaWRUb2tlbiwgd2hpY2ggaXMgdmVyaWZpZWQgb24gcHJvZCB1c2luZyBGaXJlYmFzZSBBZG1pbiBhbmQgSWRlbnRpdHlcbiAgICogVG9vbGtpdC4gSWYgYSBgaXNVc2VyQXV0aG9yaXplZCgpYCBjb25maWcgaXMgc2V0LCB0aGlzIGZ1bmN0aW9uIHdpbGwgYWxzb1xuICAgKiB2ZXJpZnkgdmlhIHRoYXQgZnVuY3Rpb24uIFJldHVybnMgdHJ1ZSBpZiB0aGUgbG9naW4gdmVyaWZpY2F0aW9uIHN1Y2NlZWRzLlxuICAgKi9cbiAgYXN5bmMgZnVuY3Rpb24gdmVyaWZ5VXNlckxvZ2luKFxuICAgIHJlcTogUmVxdWVzdFxuICApOiBQcm9taXNlPHthdXRob3JpemVkOiBib29sZWFuOyByZWFzb24/OiBzdHJpbmd9PiB7XG4gICAgY29uc3QgaWRUb2tlbiA9IHJlcS5ib2R5Py5pZFRva2VuO1xuICAgIGlmICghaWRUb2tlbikge1xuICAgICAgY29uc29sZS5sb2coJ2xvZ2luIGZhaWxlZDogbm8gaWQgdG9rZW4nKTtcbiAgICAgIHJldHVybiB7YXV0aG9yaXplZDogZmFsc2UsIHJlYXNvbjogJ25vIHRva2VuJ307XG4gICAgfVxuXG4gICAgbGV0IHVzZXI6IENNU1VzZXI7XG5cbiAgICAvLyBPbiBsb2NhbCBkZXYsIHNpbXBseSB2ZXJpZnkgdGhlIGRlY29kZWQgaWRUb2tlbidzIGVtYWlsIGlzIHNldC4gVGhlXG4gICAgLy8gaWRlbnRpdHkgdG9vbGtpdCB0aGF0IHZlcmlmaWVzIGlkIHRva2VucyByZXF1aXJlcyBhIHNlcnZpY2UgYWNjb3VudCxcbiAgICAvLyB3aGljaCB3ZSB3YW50IHRvIGF2b2lkIGhhdmluZyB0byBzZXQgdXAgd2hlbiB1c2VycyBhcmUgZG9pbmcgbG9jYWwgZGV2LlxuICAgIC8vIEF1dGhlbnRpY2F0aW9uIGlzIHN0aWxsIHJlcXVpcmVkIGJ5IHRoZSBmcm9udGVuZCB1c2luZyBGaXJlYmFzZSBBdXRoLFxuICAgIC8vIHRoaXMganVzdCBieXBhc3NlcyB0aGUgaW5pdGlhbCBzZXJ2ZXIgY2hlY2sgYmVmb3JlIHRoZSB1aSBpcyByZW5kZXJlZC5cbiAgICB0cnkge1xuICAgICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAnZGV2ZWxvcG1lbnQnKSB7XG4gICAgICAgIGNvbnN0IGp3dCA9IGpzb253ZWJ0b2tlbi5kZWNvZGUoaWRUb2tlbikgYXMganNvbndlYnRva2VuLkp3dFBheWxvYWQ7XG4gICAgICAgIGlmICghand0LmVtYWlsIHx8ICFqd3QuZW1haWxfdmVyaWZpZWQpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnbG9naW4gZmFpbGVkOiBlbWFpbCB1bnZlcmlmaWVkJyk7XG4gICAgICAgICAgcmV0dXJuIHthdXRob3JpemVkOiBmYWxzZSwgcmVhc29uOiAnbG9naW4gZmFpbGVkJ307XG4gICAgICAgIH1cbiAgICAgICAgdXNlciA9IHtlbWFpbDogand0LmVtYWlsfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGp3dCA9IGF3YWl0IGF1dGgudmVyaWZ5SWRUb2tlbihpZFRva2VuLCB0cnVlKTtcbiAgICAgICAgaWYgKGlzRXhwaXJlZChqd3QpKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJ2xvZ2luIGZhaWxlZDogaWQgdG9rZW4gaXMgZXhwaXJlZCcpO1xuICAgICAgICAgIHJldHVybiB7YXV0aG9yaXplZDogZmFsc2UsIHJlYXNvbjogJ2xvZ2luIGZhaWxlZCd9O1xuICAgICAgICB9XG4gICAgICAgIGlmICghand0LmVtYWlsIHx8ICFqd3QuZW1haWxfdmVyaWZpZWQpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnbG9naW4gZmFpbGVkOiBlbWFpbCB1bnZlcmlmaWVkJyk7XG4gICAgICAgICAgcmV0dXJuIHthdXRob3JpemVkOiBmYWxzZSwgcmVhc29uOiAnbG9naW4gZmFpbGVkJ307XG4gICAgICAgIH1cbiAgICAgICAgdXNlciA9IHtlbWFpbDogand0LmVtYWlsfTtcbiAgICAgIH1cblxuICAgICAgLy8gVmVyaWZ5IHRoZSBwcm9qZWN0J3MgYGlzVXNlckF1dGhvcml6ZWQoKWAgY29uZmlnIG9wdGlvbi5cbiAgICAgIGlmIChvcHRpb25zLmlzVXNlckF1dGhvcml6ZWQpIHtcbiAgICAgICAgY29uc3QgYXV0aG9yaXplZCA9IGF3YWl0IG9wdGlvbnMuaXNVc2VyQXV0aG9yaXplZChyZXEsIHtcbiAgICAgICAgICBlbWFpbDogdXNlci5lbWFpbCxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghYXV0aG9yaXplZCkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdsb2dpbiBmYWlsZWQ6IHVzZXIgaXMgbm90IGF1dGhvcml6ZWQnKTtcbiAgICAgICAgICByZXR1cm4ge2F1dGhvcml6ZWQ6IGZhbHNlLCByZWFzb246ICdub3QgYXV0aG9yaXplZCd9O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFZlcmlmeSB0aGUgdXNlciBleGlzdHMgaW4gdGhlIERCJ3MgQUNMIGxpc3QuXG4gICAgICBjb25zdCBjbXNDbGllbnQgPSBuZXcgUm9vdENNU0NsaWVudChyZXEucm9vdENvbmZpZyEpO1xuICAgICAgY29uc3QgdXNlckhhc0FjY2VzcyA9IGF3YWl0IGNtc0NsaWVudC51c2VyRXhpc3RzSW5BY2wodXNlci5lbWFpbCk7XG4gICAgICBpZiAoIXVzZXJIYXNBY2Nlc3MpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2xvZ2luIGZhaWxlZDogdXNlciBpcyBub3QgaW4gdGhlIGZpcmVzdG9yZSBhY2wgbGlzdCcpO1xuICAgICAgICByZXR1cm4ge2F1dGhvcml6ZWQ6IGZhbHNlLCByZWFzb246ICdub3QgYXV0aG9yaXplZCd9O1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcignZmFpbGVkIHRvIHZlcmlmeSBqd3QgdG9rZW4nKTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcbiAgICAgIHJldHVybiB7YXV0aG9yaXplZDogZmFsc2UsIHJlYXNvbjogJ3Vua25vd24gZXJyb3InfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge2F1dGhvcml6ZWQ6IHRydWV9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGN1cnJlbnQgdXNlciBiYXNlZCBvbiB0aGUgcmVxdWVzdCdzIHNlc3Npb24gY29va2llLiBUaGVcbiAgICogc2Vzc2lvbiBjb29raWUgaXMgY2hlY2tlZCBmb3IgdmFsaWRpdHkgdGhyb3VnaCBGaXJlYmFzZSBBdXRoIGFuZCB0aGUgdXNlcidzXG4gICAqIGVtYWlsIGlzIHZlcmlmaWVkIHRvIGhhdmUgYWNjZXNzIHRvIFJvb3QgQ01TLCBvdGhlcndpc2UgcmV0dXJucyBgbnVsbGAuXG4gICAqL1xuICBhc3luYyBmdW5jdGlvbiBnZXRDdXJyZW50VXNlcihyZXE6IFJlcXVlc3QpOiBQcm9taXNlPENNU1VzZXIgfCBudWxsPiB7XG4gICAgY29uc3Qgc2Vzc2lvbkNvb2tpZSA9IHJlcS5zZXNzaW9uLmdldEl0ZW0oU0VTU0lPTl9DT09LSUVfQVVUSCk7XG4gICAgaWYgKCFzZXNzaW9uQ29va2llKSB7XG4gICAgICBpZiAobG9nTGV2ZWwgPT09ICdkZWJ1ZycpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ25vIGxvZ2luIHNlc3Npb24gY29va2llJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBPbiBsb2NhbCBkZXYsIHZlcmlmeSB0aGUgZGVjb2RlZCBpZFRva2VuIGhhcyBhIHZhbGlkIGVtYWlsLiBUaGUgZmlyZWJhc2VcbiAgICAvLyBhdXRoIHZlcmlmaWNhdGlvbiBvdGhlcndpc2Ugd291bGQgcmVxdWlyZSBhIHNlcnZpY2UgYWNjb3VudC5cbiAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdkZXZlbG9wbWVudCcpIHtcbiAgICAgIGNvbnN0IGp3dCA9IGpzb253ZWJ0b2tlbi5kZWNvZGUoc2Vzc2lvbkNvb2tpZSkgYXMganNvbndlYnRva2VuLkp3dFBheWxvYWQ7XG4gICAgICBpZiAoIWp3dD8uZW1haWwgfHwgIWp3dD8uZW1haWxfdmVyaWZpZWQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICAvLyBDaGVjayB3aGV0aGVyIHVzZXIgaXMgYXV0aG9yaXplZC5cbiAgICAgIGlmIChvcHRpb25zLmlzVXNlckF1dGhvcml6ZWQpIHtcbiAgICAgICAgY29uc3QgYXV0aG9yaXplZCA9IGF3YWl0IG9wdGlvbnMuaXNVc2VyQXV0aG9yaXplZChyZXEsIHtcbiAgICAgICAgICBlbWFpbDogand0LmVtYWlsLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCFhdXRob3JpemVkKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJ3Nlc3Npb24gZmFpbGVkOiBub3QgYXV0aG9yaXplZCcpO1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBWZXJpZnkgdGhlIHVzZXIgZXhpc3RzIGluIHRoZSBEQidzIEFDTCBsaXN0LlxuICAgICAgY29uc3QgY21zQ2xpZW50ID0gbmV3IFJvb3RDTVNDbGllbnQocmVxLnJvb3RDb25maWchKTtcbiAgICAgIGNvbnN0IHVzZXJIYXNBY2Nlc3MgPSBhd2FpdCBjbXNDbGllbnQudXNlckV4aXN0c0luQWNsKGp3dC5lbWFpbCk7XG4gICAgICBpZiAoIXVzZXJIYXNBY2Nlc3MpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ3Nlc3Npb24gZmFpbGVkOiB1c2VyIGlzIG5vdCBpbiB0aGUgZmlyZXN0b3JlIGFjbCBsaXN0Jyk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHtlbWFpbDogand0LmVtYWlsfTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgLy8gVmVyaWZ5IHRoZSBpZFRva2VuIHVzaW5nIGZpcmViYXNlIGF1dGgsIGNoZWNraW5nIGZvciB0b2tlbiByZXZvY2F0aW9ucy5cbiAgICAgIGNvbnN0IGp3dCA9IGF3YWl0IGF1dGgudmVyaWZ5U2Vzc2lvbkNvb2tpZShzZXNzaW9uQ29va2llLCB0cnVlKTtcbiAgICAgIGlmIChpc0V4cGlyZWQoand0KSkge1xuICAgICAgICBjb25zb2xlLmxvZygnc2Vzc2lvbiBmYWlsZWQ6IHRva2VuIGlzIGV4cGlyZWQnKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICAvLyBWZXJpZnkgdXNlcidzIGVtYWlsIGlzIHZlcmlmaWVkLlxuICAgICAgaWYgKCFqd3QuZW1haWwgfHwgIWp3dC5lbWFpbF92ZXJpZmllZCkge1xuICAgICAgICBjb25zb2xlLmxvZygnc2Vzc2lvbiBmYWlsZWQ6IGVtYWlsIG5vdCB2ZXJpZmllZCcpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIENoZWNrIHdoZXRoZXIgdXNlciBpcyBhdXRob3JpemVkLlxuICAgICAgaWYgKG9wdGlvbnMuaXNVc2VyQXV0aG9yaXplZCkge1xuICAgICAgICBjb25zdCBhdXRob3JpemVkID0gYXdhaXQgb3B0aW9ucy5pc1VzZXJBdXRob3JpemVkKHJlcSwge1xuICAgICAgICAgIGVtYWlsOiBqd3QuZW1haWwhLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCFhdXRob3JpemVkKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJ3Nlc3Npb24gZmFpbGVkOiBub3QgYXV0aG9yaXplZCcpO1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBWZXJpZnkgdGhlIHVzZXIgZXhpc3RzIGluIHRoZSBEQidzIEFDTCBsaXN0LlxuICAgICAgY29uc3QgY21zQ2xpZW50ID0gbmV3IFJvb3RDTVNDbGllbnQocmVxLnJvb3RDb25maWchKTtcbiAgICAgIGNvbnN0IHVzZXJIYXNBY2Nlc3MgPSBhd2FpdCBjbXNDbGllbnQudXNlckV4aXN0c0luQWNsKGp3dC5lbWFpbCk7XG4gICAgICBpZiAoIXVzZXJIYXNBY2Nlc3MpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ3Nlc3Npb24gZmFpbGVkOiB1c2VyIGlzIG5vdCBpbiB0aGUgZmlyZXN0b3JlIGFjbCBsaXN0Jyk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgLy8gSldUIHZlcmlmaWVkLlxuICAgICAgcmV0dXJuIHtlbWFpbDogand0LmVtYWlsIX07XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdmYWlsZWQgdG8gdmVyaWZ5IGp3dCB0b2tlbicpO1xuICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcmVkaXJlY3RUb0xvZ2luKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkge1xuICAgIGlmIChTdHJpbmcocmVxLm9yaWdpbmFsVXJsKS50b0xvd2VyQ2FzZSgpLnN0YXJ0c1dpdGgoJy9jbXMvYXBpJykpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAxKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdOT1RfQVVUSE9SSVpFRCd9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc29sZS5sb2coJ3JlZGlyZWN0aW5nIHRvIGxvZ2luIHBhZ2UnKTtcbiAgICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcbiAgICAgIGNvbnRpbnVlOiByZXEub3JpZ2luYWxVcmwsXG4gICAgfSk7XG4gICAgcmVzLnJlZGlyZWN0KGAvY21zL2xvZ2luPyR7cGFyYW1zLnRvU3RyaW5nKCl9YCk7XG4gIH1cblxuICBjb25zdCBwbHVnaW46IENNU1BsdWdpbiA9IHtcbiAgICBuYW1lOiAncm9vdC1jbXMnLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY29uZmlnIG9wdGlvbnMgcGFzc2VkIHRvIHRoZSBwbHVnaW4uXG4gICAgICovXG4gICAgZ2V0Q29uZmlnOiAoKSA9PiB7XG4gICAgICByZXR1cm4gb3B0aW9ucztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgRmlyZWJhc2UgQXBwIGluc3RhbmNlIHVzZWQgYnkgdGhlIHBsdWdpbi5cbiAgICAgKi9cbiAgICBnZXRGaXJlYmFzZUFwcDogKCkgPT4ge1xuICAgICAgcmV0dXJuIGFwcDtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgRmlyZXN0b3JlIGluc3RhbmNlIHVzZWQgYnkgdGhlIHBsdWdpbi5cbiAgICAgKi9cbiAgICBnZXRGaXJlc3RvcmU6ICgpID0+IHtcbiAgICAgIGNvbnN0IGRhdGFiYXNlSWQgPSBmaXJlYmFzZUNvbmZpZy5kYXRhYmFzZUlkIHx8ICcoZGVmYXVsdCknO1xuICAgICAgcmV0dXJuIGdldEZpcmVzdG9yZShhcHAsIGRhdGFiYXNlSWQpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBBIG1hcCBvZiBzc3IgZmlsZXMgdG8gaW5jbHVkZSB3aGVuIHJ1bm5pbmcgYHJvb3QgYnVpbGRgLlxuICAgICAqL1xuICAgIHNzcklucHV0OiAoKSA9PiAoe1xuICAgICAgY21zOiBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi9hcHAuanMnKSxcbiAgICB9KSxcblxuICAgIGhvb2tzOiB7XG4gICAgICAvKipcbiAgICAgICAqIFN0YXJ0dXAgaG9vay4gT24gYGRldmAgYW5kIGBidWlsZGAgY29tbWFuZHMsIHRoZSBwbHVnaW4gZG9lc1xuICAgICAgICogY29tcGF0aWJpbGl0eSBjaGVja3MuXG4gICAgICAgKi9cbiAgICAgIHN0YXJ0dXA6IGFzeW5jICh7Y29tbWFuZCwgcm9vdENvbmZpZ30pID0+IHtcbiAgICAgICAgaWYgKGNvbW1hbmQgPT09ICdkZXYnIHx8IGNvbW1hbmQgPT09ICdidWlsZCcpIHtcbiAgICAgICAgICBhd2FpdCBydW5Db21wYXRpYmlsaXR5Q2hlY2tzKHJvb3RDb25maWcpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBBdHRhY2hlcyBDTVMtc3BlY2lmaWMgbWlkZGxld2FyZSB0byB0aGUgUm9vdC5qcyBzZXJ2ZXIuXG4gICAgICovXG4gICAgY29uZmlndXJlU2VydmVyOiBhc3luYyAoXG4gICAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICAgIHNlcnZlck9wdGlvbnM6IENvbmZpZ3VyZVNlcnZlck9wdGlvbnNcbiAgICApID0+IHtcbiAgICAgIHNlcnZlci51c2UoYm9keVBhcnNlci5qc29uKCkpO1xuXG4gICAgICBhc3luYyBmdW5jdGlvbiBnZXRSZW5kZXJlcihyZXE6IFJlcXVlc3QpOiBQcm9taXNlPEFwcE1vZHVsZT4ge1xuICAgICAgICBpZiAoc2VydmVyT3B0aW9ucy50eXBlID09PSAnZGV2Jykge1xuICAgICAgICAgIGNvbnN0IGFwcEZpbGVQYXRoID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4vYXBwLmpzJyk7XG4gICAgICAgICAgY29uc3QgYXBwID0gKGF3YWl0IHJlcS52aXRlU2VydmVyIS5zc3JMb2FkTW9kdWxlKFxuICAgICAgICAgICAgYXBwRmlsZVBhdGhcbiAgICAgICAgICApKSBhcyBBcHBNb2R1bGU7XG4gICAgICAgICAgcmV0dXJuIGFwcDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFwcEltcG9ydFBhdGggPSBwYXRoLnJlc29sdmUoXG4gICAgICAgICAgcmVxLnJvb3RDb25maWchLnJvb3REaXIsXG4gICAgICAgICAgJ2Rpc3Qvc2VydmVyL2Ntcy5qcydcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCEoYXdhaXQgZmlsZUV4aXN0cyhhcHBJbXBvcnRQYXRoKSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnZGlzdC9zZXJ2ZXIvY21zLmpzIG5vdCBmb3VuZC4gcnVuIGByb290IGJ1aWxkYCB0byBjcmVhdGUgaXQuJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYXBwID0gKGF3YWl0IGltcG9ydChhcHBJbXBvcnRQYXRoKSkgYXMgQXBwTW9kdWxlO1xuICAgICAgICByZXR1cm4gYXBwO1xuICAgICAgfVxuXG4gICAgICAvLyBMb2dpbiBoYW5kbGVyLlxuICAgICAgc2VydmVyLnVzZSgnL2Ntcy9sb2dpbicsIGFzeW5jIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHJlcS5tZXRob2QgPT09ICdQVVQnICYmXG4gICAgICAgICAgcmVxLmhlYWRlcnNbJ2NvbnRlbnQtdHlwZSddID09PSAnYXBwbGljYXRpb24vanNvbidcbiAgICAgICAgKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHthdXRob3JpemVkLCByZWFzb259ID0gYXdhaXQgdmVyaWZ5VXNlckxvZ2luKHJlcSk7XG4gICAgICAgICAgICBpZiAoIWF1dGhvcml6ZWQpIHtcbiAgICAgICAgICAgICAgcmVzXG4gICAgICAgICAgICAgICAgLnN0YXR1cyg0MDEpXG4gICAgICAgICAgICAgICAgLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogJ05PVF9BVVRIT1JJWkVEJywgcmVhc29ufSk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHNlc3Npb24gZXhwaXJhdGlvbiB0byA1IGRheXMuXG4gICAgICAgICAgICBjb25zdCBleHBpcmVzSW4gPSA2MCAqIDYwICogMjQgKiA1ICogMTAwMDtcbiAgICAgICAgICAgIGNvbnN0IGlkVG9rZW4gPSByZXEuYm9keS5pZFRva2VuITtcblxuICAgICAgICAgICAgbGV0IHNlc3Npb25Db29raWU6IHN0cmluZztcbiAgICAgICAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50Jykge1xuICAgICAgICAgICAgICBzZXNzaW9uQ29va2llID0gaWRUb2tlbjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHNlc3Npb25Db29raWUgPSBhd2FpdCBhdXRoLmNyZWF0ZVNlc3Npb25Db29raWUoaWRUb2tlbiwge1xuICAgICAgICAgICAgICAgIGV4cGlyZXNJbixcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMuc2Vzc2lvbi5zZXRJdGVtKFNFU1NJT05fQ09PS0lFX0FVVEgsIHNlc3Npb25Db29raWUpO1xuICAgICAgICAgICAgcmVzLnNhdmVTZXNzaW9uKCk7XG4gICAgICAgICAgICByZXMuanNvbih7c3VjY2VzczogdHJ1ZX0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgICAgICAgaWYgKGVyci5zdGFjaykge1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVyci5zdGFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXNcbiAgICAgICAgICAgICAgLnN0YXR1cyg1MDApXG4gICAgICAgICAgICAgIC5qc29uKHtzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdVTktOT1dOX1NFUlZFUl9FUlJPUid9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBhcHAgPSBhd2FpdCBnZXRSZW5kZXJlcihyZXEpO1xuICAgICAgICAgIGFwcC5yZW5kZXJTaWduSW4ocmVxLCByZXMsIHtcbiAgICAgICAgICAgIHJvb3RDb25maWc6IHJlcS5yb290Q29uZmlnISxcbiAgICAgICAgICAgIGNtc0NvbmZpZzogb3B0aW9ucyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgICAgIGlmIChlcnIuc3RhY2spIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyLnN0YWNrKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzLnN0YXR1cyg1MDApLnNlbmQoJ1VOS05PV04gU0VSVkVSIEVSUk9SJyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBMb2dvdXQgaGFuZGxlci5cbiAgICAgIHNlcnZlci51c2UoJy9jbXMvbG9nb3V0JywgYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgICByZXMuc2Vzc2lvbi5yZW1vdmVJdGVtKFNFU1NJT05fQ09PS0lFX0FVVEgpO1xuICAgICAgICByZXMuc2F2ZVNlc3Npb24oKTtcbiAgICAgICAgcmVzLnJlZGlyZWN0KCcvY21zL2xvZ2luJyk7XG4gICAgICB9KTtcblxuICAgICAgLy8gSW5qZWN0IHRoZSBjdXJyZW50IHVzZXIgaW50byB0aGUgcmVxIG9iamVjdCBhbmQgY2hlY2sgaWYgbG9naW4gaXNcbiAgICAgIC8vIHJlcXVpcmVkLCBzZW5kaW5nIHVuYXV0aGVudGljYXRlZCB1c2VycyB0byB0aGUgbG9naW4gcGFnZS5cbiAgICAgIHNlcnZlci51c2UoYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKSA9PiB7XG4gICAgICAgIGNvbnN0IHVzZXIgPSBhd2FpdCBnZXRDdXJyZW50VXNlcihyZXEpO1xuICAgICAgICBpZiAodXNlcikge1xuICAgICAgICAgIHJlcS51c2VyID0gdXNlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIG5vIHVzZXIgYW5kIGxvZ2luIGlzIHJlcXVpcmVkIGZvciB0aGUgZ2l2ZW4gcGF0aCwgcmVkaXJlY3QgdG8gdGhlXG4gICAgICAgIC8vIGxvZ2luIHBhZ2UuXG4gICAgICAgIGlmICghdXNlciAmJiBsb2dpblJlcXVpcmVkKHJlcSkpIHtcbiAgICAgICAgICByZWRpcmVjdFRvTG9naW4ocmVxLCByZXMpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIG5leHQoKTtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBzdGF0aWNEaXIgPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAndWknKTtcbiAgICAgIHNlcnZlci51c2UoJy9jbXMvc3RhdGljJywgc2lydihzdGF0aWNEaXIsIHtkZXY6IGZhbHNlfSkpO1xuXG4gICAgICAvLyBSZWdpc3RlciBBUEkgaGFuZGxlcnMuXG4gICAgICBhcGkoc2VydmVyKTtcblxuICAgICAgLy8gUmVuZGVyIHRoZSBDTVMgU1BBLlxuICAgICAgc2VydmVyLnVzZSgnL2NtcycsIGFzeW5jIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyBFbmZvcmNlIGxvZ2luIGZvciBhbGwgQ01TIHBhdGhzLiBUaGUgYHJlcS51c2VyYCB3b3VsZCBvbmx5IGJlXG4gICAgICAgICAgLy8gcG9wdWxhdGVkIGlmIHRoZSBmaXJlYmFzZSBhdXRoIHRva2VuIGlzIHZhbGlkIGFuZCB0aGUgdXNlciBoYXNcbiAgICAgICAgICAvLyBhY2Nlc3MgdmlhIHRoZSBSb290IENNUyBzaGFyZWJveC5cbiAgICAgICAgICBpZiAoIXJlcS51c2VyKSB7XG4gICAgICAgICAgICByZWRpcmVjdFRvTG9naW4ocmVxLCByZXMpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBhcHAgPSBhd2FpdCBnZXRSZW5kZXJlcihyZXEpO1xuICAgICAgICAgIGF3YWl0IGFwcC5yZW5kZXJBcHAocmVxLCByZXMsIHtcbiAgICAgICAgICAgIHJvb3RDb25maWc6IHJlcS5yb290Q29uZmlnISxcbiAgICAgICAgICAgIGNtc0NvbmZpZzogb3B0aW9ucyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgLy8gVE9ETyhzdGV2ZW5sZSk6IHJlbmRlciBhIGN1c3RvbSBlcnJvciBwYWdlLlxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcbiAgICAgICAgICByZXMuc3RhdHVzKDUwMCkuc2VuZCgnVU5LTk9XTiBTRVJWRVIgRVJST1InKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcblxuICBpZiAob3B0aW9ucy53YXRjaCAhPT0gZmFsc2UpIHtcbiAgICBwbHVnaW4ub25GaWxlQ2hhbmdlID0gKFxuICAgICAgZXZlbnROYW1lOiAnYWRkJyB8ICdhZGREaXInIHwgJ2NoYW5nZScgfCAndW5saW5rJyB8ICd1bmxpbmtEaXInLFxuICAgICAgZmlsZXBhdGg6IHN0cmluZ1xuICAgICkgPT4ge1xuICAgICAgaWYgKGZpbGVwYXRoLmVuZHNXaXRoKCcuc2NoZW1hLnRzJykpIHtcbiAgICAgICAgLy8gQXZvaWQgbG9hZGluZyB0aGUgYGdlbmVyYXRlLXR5cGVzLmpzYCBtb2R1bGUgaWYgaXQgaXMgbm90IG5lZWRlZC5cbiAgICAgICAgLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vYmxpbmtrL3Jvb3Rqcy9pc3N1ZXMvNDI2XG4gICAgICAgIGltcG9ydCgnLi4vY2xpL2dlbmVyYXRlLXR5cGVzLmpzJykudGhlbigoZ2VuZXJhdGVUeXBlc01vZHVsZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGdlbmVyYXRlVHlwZXMgPSBnZW5lcmF0ZVR5cGVzTW9kdWxlLmdlbmVyYXRlVHlwZXM7XG4gICAgICAgICAgZ2VuZXJhdGVUeXBlcygpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHBsdWdpbjtcbn1cblxuZnVuY3Rpb24gZmlsZUV4aXN0cyhmaWxlcGF0aDogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIHJldHVybiBmc1xuICAgIC5hY2Nlc3MoZmlsZXBhdGgpXG4gICAgLnRoZW4oKCkgPT4gdHJ1ZSlcbiAgICAuY2F0Y2goKCkgPT4gZmFsc2UpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q21zUGx1Z2luKHJvb3RDb25maWc6IFJvb3RDb25maWcpOiBDTVNQbHVnaW4ge1xuICBjb25zdCBwbHVnaW5zOiBQbHVnaW5bXSA9IHJvb3RDb25maWcucGx1Z2lucyB8fCBbXTtcbiAgY29uc3QgcGx1Z2luID0gcGx1Z2lucy5maW5kKChwbHVnaW4pID0+IHBsdWdpbi5uYW1lID09PSAncm9vdC1jbXMnKTtcbiAgaWYgKCFwbHVnaW4pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkIG5vdCBmaW5kIHJvb3QtY21zIHBsdWdpbiBjb25maWcgaW4gcm9vdC5jb25maWcudHMnKTtcbiAgfVxuICByZXR1cm4gcGx1Z2luIGFzIENNU1BsdWdpbjtcbn1cbiIsICJpbXBvcnQge1NlcnZlciwgUmVxdWVzdCwgUmVzcG9uc2V9IGZyb20gJ0BibGlua2svcm9vdCc7XG5pbXBvcnQge211bHRpcGFydE1pZGRsZXdhcmV9IGZyb20gJ0BibGlua2svcm9vdC9taWRkbGV3YXJlJztcbmltcG9ydCB7Q2hhdCwgQ2hhdENsaWVudH0gZnJvbSAnLi9haS5qcyc7XG5pbXBvcnQge1Jvb3RDTVNDbGllbnR9IGZyb20gJy4vY2xpZW50LmpzJztcbmltcG9ydCB7cnVuQ3JvbkpvYnN9IGZyb20gJy4vY3Jvbi5qcyc7XG5pbXBvcnQge2FycmF5VG9Dc3YsIGNzdlRvQXJyYXl9IGZyb20gJy4vY3N2LmpzJztcblxuLyoqXG4gKiBSZWdpc3RlcnMgQVBJIG1pZGRsZXdhcmUgaGFuZGxlcnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcGkoc2VydmVyOiBTZXJ2ZXIpIHtcbiAgLyoqXG4gICAqIFJ1bnMgQ01TIGNyb24gam9icy5cbiAgICovXG4gIHNlcnZlci51c2UoJy9jbXMvYXBpL2Nyb24ucnVuJywgYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBydW5Dcm9uSm9icyhyZXEucm9vdENvbmZpZyEpO1xuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oe3N1Y2Nlc3M6IHRydWV9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZX0pO1xuICAgIH1cbiAgfSk7XG5cbiAgLyoqXG4gICAqIEFjY2VwdHMgYSBKU09OIG9iamVjdCBjb250YWluaW5nIHtoZWFkZXJzOiBbLi4uXSwgcm93czogWy4uLl19IGFuZCBzZW5kc1xuICAgKiBhbiBIVFRQIHJlc3BvbnNlIHdpdGggYSBjb3JyZXNwb25kaW5nIENTViBmaWxlIGFzIGFuIGF0dGFjaG1lbnQuXG4gICAqXG4gICAqIFNhbXBsZSByZXF1ZXN0OlxuICAgKlxuICAgKiBgYGBqc29uXG4gICAqIHtcbiAgICogICBcImhlYWRlcnNcIjogW1wiZm9vXCJdLFxuICAgKiAgIFwicm93c1wiOiBbXG4gICAqICAgICB7XCJmb29cIjogXCJiYXJcIn0sXG4gICAqICAgICB7XCJmb29cIjogXCJiYXpcIn0sXG4gICAqICAgXVxuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgc2VydmVyLnVzZSgnL2Ntcy9hcGkvY3N2LmRvd25sb2FkJywgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIGlmIChcbiAgICAgIHJlcS5tZXRob2QgIT09ICdQT1NUJyB8fFxuICAgICAgIVN0cmluZyhyZXEuZ2V0KCdjb250ZW50LXR5cGUnKSkuc3RhcnRzV2l0aCgnYXBwbGljYXRpb24vanNvbicpXG4gICAgKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7c3VjY2VzczogZmFsc2UsIGVycm9yOiAnQkFEX1JFUVVFU1QnfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGJvZHkgPSByZXEuYm9keSB8fCB7fTtcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSBib2R5LmhlYWRlcnMgfHwgW107XG4gICAgICBjb25zdCByb3dzID0gYm9keS5yb3dzIHx8IFtdO1xuICAgICAgY29uc3QgY3N2ID0gYXJyYXlUb0Nzdih7aGVhZGVycywgcm93c30pO1xuICAgICAgcmVzLnNldEhlYWRlcignQ29udGVudC1UeXBlJywgJ3RleHQvY3N2Jyk7XG4gICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LURpc3Bvc2l0aW9uJywgJ2F0dGFjaG1lbnQ7IGZpbGVuYW1lPVwiZGF0YS5jc3ZcIicpO1xuICAgICAgcmVzLnN0YXR1cygyMDApLmVuZChjc3YpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2sgfHwgZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdVTktOT1dOJ30pO1xuICAgIH1cbiAgfSk7XG5cbiAgLyoqXG4gICAqIEltcG9ydHMgYSBDU1YgZmlsZSBhbmQgcmV0dXJucyBhIEpTT04gYXJyYXkgb2Ygb2JqZWN0cyByZXByZXNlbnRpbmcgdGhlXG4gICAqIENTVi5cbiAgICpcbiAgICogU2FtcGxlIHJlc3BvbnNlOlxuICAgKlxuICAgKiBgYGBqc29uXG4gICAqIHtcbiAgICogICBcInN1Y2Nlc3NcIjogdHJ1ZSxcbiAgICogICBcImRhdGFcIjogW1xuICAgKiAgICAge1wiZm9vXCI6IFwiYmFyXCJ9LFxuICAgKiAgICAge1wiZm9vXCI6IFwiYmF6XCJ9LFxuICAgKiAgIF1cbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIHNlcnZlci51c2UoXG4gICAgJy9jbXMvYXBpL2Nzdi5pbXBvcnQnLFxuICAgIG11bHRpcGFydE1pZGRsZXdhcmUoKSxcbiAgICAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgICBpZiAocmVxLm1ldGhvZCAhPT0gJ1BPU1QnIHx8ICFyZXEuZmlsZXMgfHwgIXJlcS5maWxlcy5maWxlKSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdCQURfUkVRVUVTVCd9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBmaWxlID0gcmVxLmZpbGVzLmZpbGU7XG4gICAgICAgIGNvbnN0IGNzdlN0cmluZyA9IGZpbGUuYnVmZmVyLnRvU3RyaW5nKCd1dGY4Jyk7XG4gICAgICAgIGNvbnN0IHJvd3MgPSBjc3ZUb0FycmF5KGNzdlN0cmluZyk7XG4gICAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtzdWNjZXNzOiB0cnVlLCBkYXRhOiByb3dzfSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2sgfHwgZXJyKTtcbiAgICAgICAgcmVzLnN0YXR1cyg1MDApLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogJ1VOS05PV04nfSk7XG4gICAgICB9XG4gICAgfVxuICApO1xuXG4gIC8qKlxuICAgKiBSdW5zIGEgZGF0YSBzb3VyY2Ugc3luYy5cbiAgICovXG4gIHNlcnZlci51c2UoJy9jbXMvYXBpL2RhdGEuc3luYycsIGFzeW5jIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICBpZiAoXG4gICAgICByZXEubWV0aG9kICE9PSAnUE9TVCcgfHxcbiAgICAgICFTdHJpbmcocmVxLmdldCgnY29udGVudC10eXBlJykpLnN0YXJ0c1dpdGgoJ2FwcGxpY2F0aW9uL2pzb24nKVxuICAgICkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogJ0JBRF9SRVFVRVNUJ30pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghcmVxLnVzZXI/LmVtYWlsKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMSkuanNvbih7c3VjY2VzczogZmFsc2UsIGVycm9yOiAnVU5BVVRIT1JJWkVEJ30pO1xuICAgIH1cblxuICAgIGNvbnN0IHJlcUJvZHkgPSByZXEuYm9keSB8fCB7fTtcbiAgICBjb25zdCBkYXRhU291cmNlSWQgPSByZXFCb2R5LmlkO1xuICAgIGlmICghZGF0YVNvdXJjZUlkKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7c3VjY2VzczogZmFsc2UsIGVycm9yOiAnTUlTU0lOR19JRCd9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgY21zQ2xpZW50ID0gbmV3IFJvb3RDTVNDbGllbnQocmVxLnJvb3RDb25maWchKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgY21zQ2xpZW50LnN5bmNEYXRhU291cmNlKGRhdGFTb3VyY2VJZCwge3N5bmNlZEJ5OiByZXEudXNlci5lbWFpbH0pO1xuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oe3N1Y2Nlc3M6IHRydWUsIGlkOiBkYXRhU291cmNlSWR9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyLnN0YWNrIHx8IGVycik7XG4gICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7c3VjY2VzczogZmFsc2UsIGVycm9yOiAnVU5LTk9XTid9KTtcbiAgICB9XG4gIH0pO1xuXG4gIC8qKlxuICAgKiBMb2dzIGFuIGFjdGlvbi5cbiAgICovXG4gIHNlcnZlci51c2UoJy9jbXMvYXBpL2FjdGlvbnMubG9nJywgYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIGlmIChcbiAgICAgIHJlcS5tZXRob2QgIT09ICdQT1NUJyB8fFxuICAgICAgIVN0cmluZyhyZXEuZ2V0KCdjb250ZW50LXR5cGUnKSkuc3RhcnRzV2l0aCgnYXBwbGljYXRpb24vanNvbicpXG4gICAgKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7c3VjY2VzczogZmFsc2UsIGVycm9yOiAnQkFEX1JFUVVFU1QnfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFyZXEudXNlcj8uZW1haWwpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAxKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdVTkFVVEhPUklaRUQnfSk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxQm9keSA9IHJlcS5ib2R5IHx8IHt9O1xuICAgIGNvbnN0IGFjdGlvbiA9IHJlcUJvZHkuYWN0aW9uO1xuICAgIGlmICghYWN0aW9uKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7XG4gICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICBlcnJvcjogJ01JU1NJTkdfUkVRVUlSRURfRklFTEQnLFxuICAgICAgICBmaWVsZDogJ2FjdGlvbicsXG4gICAgICB9KTtcbiAgICB9XG4gICAgY29uc3QgbWV0YWRhdGEgPSByZXFCb2R5Lm1ldGFkYXRhIHx8IHt9O1xuXG4gICAgY29uc3QgY21zQ2xpZW50ID0gbmV3IFJvb3RDTVNDbGllbnQocmVxLnJvb3RDb25maWchKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgY21zQ2xpZW50LmxvZ0FjdGlvbihhY3Rpb24sIHtcbiAgICAgICAgYnk6IHJlcS51c2VyPy5lbWFpbCxcbiAgICAgICAgbWV0YWRhdGE6IG1ldGFkYXRhLFxuICAgICAgfSk7XG4gICAgICByZXMuc3RhdHVzKDIwMCkuanNvbih7c3VjY2VzczogdHJ1ZX0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2sgfHwgZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdVTktOT1dOJ30pO1xuICAgIH1cbiAgfSk7XG5cbiAgLyoqXG4gICAqIEFJIGNoYXRib3QuXG4gICAqL1xuICBzZXJ2ZXIudXNlKCcvY21zL2FwaS9haS5jaGF0JywgYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIGlmIChcbiAgICAgIHJlcS5tZXRob2QgIT09ICdQT1NUJyB8fFxuICAgICAgIVN0cmluZyhyZXEuZ2V0KCdjb250ZW50LXR5cGUnKSkuc3RhcnRzV2l0aCgnYXBwbGljYXRpb24vanNvbicpXG4gICAgKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7c3VjY2VzczogZmFsc2UsIGVycm9yOiAnQkFEX1JFUVVFU1QnfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghcmVxLnVzZXI/LmVtYWlsKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMSkuanNvbih7c3VjY2VzczogZmFsc2UsIGVycm9yOiAnVU5BVVRIT1JJWkVEJ30pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCByZXFCb2R5ID0gcmVxLmJvZHkgfHwge307XG4gICAgaWYgKCFyZXFCb2R5LnByb21wdCkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogJ01JU1NJTkdfUFJPTVBUJ30pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBwcm9tcHQgPSByZXFCb2R5LnByb21wdDtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBjbXNDbGllbnQgPSBuZXcgUm9vdENNU0NsaWVudChyZXEucm9vdENvbmZpZyEpO1xuICAgICAgY29uc3QgY2hhdENsaWVudCA9IG5ldyBDaGF0Q2xpZW50KGNtc0NsaWVudCwgcmVxLnVzZXIuZW1haWwpO1xuICAgICAgbGV0IGNoYXQ6IENoYXQ7XG4gICAgICBpZiAocmVxQm9keS5jaGF0SWQpIHtcbiAgICAgICAgY2hhdCA9IGF3YWl0IGNoYXRDbGllbnQuZ2V0Q2hhdChyZXFCb2R5LmNoYXRJZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGF0ID0gYXdhaXQgY2hhdENsaWVudC5jcmVhdGVDaGF0KCk7XG4gICAgICB9XG4gICAgICBjb25zdCBjaGF0UmVzcG9uc2UgPSBhd2FpdCBjaGF0LnNlbmRQcm9tcHQocHJvbXB0KTtcbiAgICAgIHJlc1xuICAgICAgICAuc3RhdHVzKDIwMClcbiAgICAgICAgLmpzb24oe3N1Y2Nlc3M6IHRydWUsIGNoYXRJZDogY2hhdC5pZCwgcmVzcG9uc2U6IGNoYXRSZXNwb25zZX0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2sgfHwgZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdVTktOT1dOJ30pO1xuICAgIH1cbiAgfSk7XG5cbiAgc2VydmVyLnVzZSgnL2Ntcy9hcGkvYWkubGlzdF9jaGF0cycsIGFzeW5jIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICBpZiAoXG4gICAgICByZXEubWV0aG9kICE9PSAnUE9TVCcgfHxcbiAgICAgICFTdHJpbmcocmVxLmdldCgnY29udGVudC10eXBlJykpLnN0YXJ0c1dpdGgoJ2FwcGxpY2F0aW9uL2pzb24nKVxuICAgICkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogJ0JBRF9SRVFVRVNUJ30pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIXJlcS51c2VyPy5lbWFpbCkge1xuICAgICAgcmVzLnN0YXR1cyg0MDEpLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogJ1VOQVVUSE9SSVpFRCd9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgcmVxQm9keSA9IHJlcS5ib2R5IHx8IHt9O1xuICAgIGNvbnN0IGxpbWl0ID0gcmVxQm9keS5saW1pdDtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBjbXNDbGllbnQgPSBuZXcgUm9vdENNU0NsaWVudChyZXEucm9vdENvbmZpZyEpO1xuICAgICAgY29uc3QgY2hhdENsaWVudCA9IG5ldyBDaGF0Q2xpZW50KGNtc0NsaWVudCwgcmVxLnVzZXIuZW1haWwpO1xuICAgICAgY29uc3QgY2hhdHMgPSBhd2FpdCBjaGF0Q2xpZW50Lmxpc3RDaGF0cyh7bGltaXR9KTtcbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtzdWNjZXNzOiB0cnVlLCBjaGF0c30pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2sgfHwgZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdVTktOT1dOJ30pO1xuICAgIH1cbiAgfSk7XG59XG4iLCAiaW1wb3J0IGNyeXB0byBmcm9tICdub2RlOmNyeXB0byc7XG5pbXBvcnQge2dlbmVyYXRlfSBmcm9tICdAZ2Vua2l0LWFpL2FpJztcbmltcG9ydCB7Y29uZmlndXJlR2Vua2l0fSBmcm9tICdAZ2Vua2l0LWFpL2NvcmUnO1xuaW1wb3J0IHt2ZXJ0ZXhBSX0gZnJvbSAnQGdlbmtpdC1haS92ZXJ0ZXhhaSc7XG5pbXBvcnQge2dlbWluaTE1UHJvUHJldmlldywgZ2VtaW5pMTVGbGFzaFByZXZpZXd9IGZyb20gJ0BnZW5raXQtYWkvdmVydGV4YWknO1xuaW1wb3J0IHtUaW1lc3RhbXB9IGZyb20gJ2ZpcmViYXNlLWFkbWluL2ZpcmVzdG9yZSc7XG5pbXBvcnQge1Jvb3RDTVNDbGllbnR9IGZyb20gJy4vY2xpZW50LmpzJztcbmltcG9ydCB7Q01TUGx1Z2luT3B0aW9uc30gZnJvbSAnLi9wbHVnaW4uanMnO1xuXG5sZXQgZ2Vua2l0SXNDb25maWd1cmVkID0gZmFsc2U7XG5cbmludGVyZmFjZSBDaGF0UHJvbXB0IHtcbiAgdGV4dD86IHN0cmluZztcbiAgbWVkaWE/OiB7XG4gICAgdXJsOiBzdHJpbmc7XG4gICAgY29udGVudFR5cGU6IHN0cmluZztcbiAgfTtcbn1cblxuZXhwb3J0IGNsYXNzIENoYXQge1xuICBjaGF0Q2xpZW50OiBDaGF0Q2xpZW50O1xuICBjbXNDbGllbnQ6IFJvb3RDTVNDbGllbnQ7XG4gIGNtc1BsdWdpbk9wdGlvbnM6IENNU1BsdWdpbk9wdGlvbnM7XG4gIGlkOiBzdHJpbmc7XG4gIGhpc3Rvcnk/OiBhbnk7XG4gIG1vZGVsPzogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGNoYXRDbGllbnQ6IENoYXRDbGllbnQsXG4gICAgaWQ6IHN0cmluZyxcbiAgICBvcHRpb25zPzoge2hpc3Rvcnk/OiBhbnk7IG1vZGVsPzogc3RyaW5nfVxuICApIHtcbiAgICB0aGlzLmNoYXRDbGllbnQgPSBjaGF0Q2xpZW50O1xuICAgIHRoaXMuY21zQ2xpZW50ID0gY2hhdENsaWVudC5jbXNDbGllbnQ7XG4gICAgdGhpcy5jbXNQbHVnaW5PcHRpb25zID0gdGhpcy5jbXNDbGllbnQuY21zUGx1Z2luLmdldENvbmZpZygpO1xuICAgIHRoaXMuaWQgPSBpZDtcbiAgICB0aGlzLmhpc3RvcnkgPSBvcHRpb25zPy5oaXN0b3J5O1xuICAgIHRoaXMubW9kZWwgPSBvcHRpb25zPy5tb2RlbDtcbiAgICBpZiAoIXRoaXMubW9kZWwpIHtcbiAgICAgIGlmICh0eXBlb2YgdGhpcy5jbXNQbHVnaW5PcHRpb25zLmV4cGVyaW1lbnRzPy5haSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgaWYgKHRoaXMuY21zUGx1Z2luT3B0aW9ucy5leHBlcmltZW50cy5haS5tb2RlbCkge1xuICAgICAgICAgIHRoaXMubW9kZWwgPSB0aGlzLmNtc1BsdWdpbk9wdGlvbnMuZXhwZXJpbWVudHMuYWkubW9kZWw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhc3luYyBzZW5kUHJvbXB0KHByb21wdDogc3RyaW5nIHwgQ2hhdFByb21wdCB8IENoYXRQcm9tcHRbXSk6IFByb21pc2U8YW55PiB7XG4gICAgaWYgKCFnZW5raXRJc0NvbmZpZ3VyZWQpIHtcbiAgICAgIGNvbnN0IGZpcmViYXNlQ29uZmlnID0gdGhpcy5jbXNQbHVnaW5PcHRpb25zLmZpcmViYXNlQ29uZmlnO1xuICAgICAgY29uZmlndXJlR2Vua2l0KHtcbiAgICAgICAgcGx1Z2luczogW1xuICAgICAgICAgIHZlcnRleEFJKHtcbiAgICAgICAgICAgIHByb2plY3RJZDogZmlyZWJhc2VDb25maWcucHJvamVjdElkLFxuICAgICAgICAgICAgLy8gVE9ETyhzdGV2ZW5sZSk6IGZpZ3VyZSBvdXQgd2hlcmUgdG8gZ2V0IHRoaXMuXG4gICAgICAgICAgICBsb2NhdGlvbjogZmlyZWJhc2VDb25maWcubG9jYXRpb24gfHwgJ3VzLWNlbnRyYWwxJyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuICAgICAgZ2Vua2l0SXNDb25maWd1cmVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBsZXQgbW9kZWwgPSBnZW1pbmkxNUZsYXNoUHJldmlldztcbiAgICBpZiAodGhpcy5tb2RlbCA9PT0gJ2dlbWluaS0xLjUtcHJvJykge1xuICAgICAgbW9kZWwgPSBnZW1pbmkxNVByb1ByZXZpZXc7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmhpc3RvcnkpIHtcbiAgICAgIC8vIFNlZWQgdGhlIEFJIHdpdGggaW5mb3JtYXRpb24uXG4gICAgICBhd2FpdCB0aGlzLmluaXRIaXN0b3J5KCk7XG4gICAgfVxuXG4gICAgLy8gY29uc29sZS5sb2coJ3Byb21wdDonLCBwcm9tcHQpO1xuICAgIC8vIGlmICh0aGlzLmhpc3RvcnkpIHtcbiAgICAvLyAgIGNvbnNvbGUubG9nKCdoaXN0b3J5OicsIHRoaXMuaGlzdG9yeSk7XG4gICAgLy8gfVxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGdlbmVyYXRlKHtcbiAgICAgIG1vZGVsOiBtb2RlbCxcbiAgICAgIHByb21wdDogcHJvbXB0IGFzIGFueSxcbiAgICAgIGhpc3Rvcnk6IHRoaXMuaGlzdG9yeSxcbiAgICB9KTtcbiAgICBjb25zb2xlLmxvZyhyZXMudGV4dCgpKTtcbiAgICBjb25zdCBoaXN0b3J5ID0gcmVzLnRvSGlzdG9yeSgpO1xuICAgIHRoaXMuaGlzdG9yeSA9IGhpc3Rvcnk7XG4gICAgYXdhaXQgdGhpcy5kYkRvYygpLnVwZGF0ZSh7aGlzdG9yeSwgbW9kaWZpZWRBdDogVGltZXN0YW1wLm5vdygpfSk7XG4gICAgcmV0dXJuIHJlcy50ZXh0KCk7XG4gIH1cblxuICBkYkRvYygpIHtcbiAgICByZXR1cm4gdGhpcy5jaGF0Q2xpZW50LmRiQ29sbGVjdGlvbigpLmRvYyh0aGlzLmlkKTtcbiAgfVxuXG4gIGFzeW5jIGluaXRIaXN0b3J5KCkge1xuICAgIGNvbnN0IHN5c3RlbVRleHQgPSBbXG4gICAgICBgWW91IGFyZSBhbiBhc3Npc3RhbnQgZm9yIGEgaGVhZGxlc3MgQ01TIGNhbGxlZCBSb290IENNUyB3aGljaCBpcyB1c2VkIG9uIGEgd2Vic2l0ZSBjYWxsZWQgJHtcbiAgICAgICAgdGhpcy5jbXNQbHVnaW5PcHRpb25zLm5hbWUgfHwgdGhpcy5jbXNQbHVnaW5PcHRpb25zLmlkXG4gICAgICB9LiBZb3VyIGpvYiBpcyB0byBhbnN3ZXIgcXVlc3Rpb25zIGFib3V0IHRoZSBkb2NzIGluIHRoZSBzeXN0ZW0sIGFuZCBpZiByZXF1ZXN0ZWQsIGhlbHAgc3VnZ2VzdCBjaGFuZ2VzIHRvIHRoZSBKU09OIGRhdGEgaW4gdGhlIGRvY3MuIElmIHlvdSBkb24ndCBrbm93IHRoZSBhbnN3ZXIsIGp1c3Qgc2F5IHRoYXQgeW91IGRvbid0IGtub3csIGRvbid0IHRyeSB0byBtYWtlIHVwIGFuIGFuc3dlci4gQmUgZnJpZW5kbHkgYW5kIHBsYXlmdWwgd2l0aCB5b3VyIG1lc3NhZ2luZy5gLFxuICAgICAgJycsXG4gICAgICAnSGVyZSBpcyB0aGUgcm9vdC5jb25maWcudHMgZmlsZSBmb3IgdGhlIHNpdGU6JyxcbiAgICAgICdgYGAnLFxuICAgICAgSlNPTi5zdHJpbmdpZnkodGhpcy5jbXNDbGllbnQucm9vdENvbmZpZywgbnVsbCwgMiksXG4gICAgICAnYGBgJyxcbiAgICAgICcnLFxuICAgICAgJ0hlcmUgYXJlIHRoZSBkb2NzIHRoYXQgZXhpc3QgaW4gdGhlIHN5c3RlbTonLFxuICAgIF07XG5cbiAgICAvLyBUT0RPKHN0ZXZlbmxlKTogcmVhZCBmcm9tIGFsbCB0aGUgY29sbGVjdGlvbnMgaW4gdGhlIHN5c3RlbS5cbiAgICBjb25zdCBwYWdlcyA9IGF3YWl0IHRoaXMuY21zQ2xpZW50Lmxpc3REb2NzKCdQYWdlcycsIHttb2RlOiAnZHJhZnQnfSk7XG4gICAgcGFnZXMuZG9jcy5mb3JFYWNoKChkb2M6IGFueSkgPT4ge1xuICAgICAgc3lzdGVtVGV4dC5wdXNoKEpTT04uc3RyaW5naWZ5KGRvYykpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5oaXN0b3J5ID0gW3tyb2xlOiAnc3lzdGVtJywgY29udGVudDogW3t0ZXh0OiBzeXN0ZW1UZXh0LmpvaW4oJ1xcbicpfV19XTtcbiAgICBjb25zb2xlLmxvZyh0aGlzLmhpc3RvcnkpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBDaGF0Q2xpZW50IHtcbiAgY21zQ2xpZW50OiBSb290Q01TQ2xpZW50O1xuICB1c2VyOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoY21zQ2xpZW50OiBSb290Q01TQ2xpZW50LCB1c2VyOiBzdHJpbmcpIHtcbiAgICB0aGlzLmNtc0NsaWVudCA9IGNtc0NsaWVudDtcbiAgICB0aGlzLnVzZXIgPSB1c2VyO1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlQ2hhdChvcHRpb25zPzoge21vZGVsPzogc3RyaW5nfSk6IFByb21pc2U8Q2hhdD4ge1xuICAgIGNvbnN0IGNoYXRJZCA9IGNyeXB0by5yYW5kb21VVUlEKCk7XG4gICAgLy8gU2F2ZSBjaGF0IHRvIGRiIHNvIHRoYXQgdXNlciBoYXMgYSBjaGF0IGhpc3RvcnkgYW5kIGNhbiBlbmFibGUgXCJzaGFyaW5nXCJcbiAgICAvLyB3aXRoIG90aGVycy4gU3RvcmUgdGhlIG1vZGVsIHVzZWQgd2l0aCB0aGUgbWV0YWRhdGEuXG4gICAgY29uc3QgZG9jUmVmID0gdGhpcy5kYkNvbGxlY3Rpb24oKS5kb2MoY2hhdElkKTtcbiAgICBhd2FpdCBkb2NSZWYuc2V0KHtcbiAgICAgIGlkOiBjaGF0SWQsXG4gICAgICBjcmVhdGVkQnk6IHRoaXMudXNlcixcbiAgICAgIGNyZWF0ZWRBdDogVGltZXN0YW1wLm5vdygpLFxuICAgICAgbW9kaWZpZWRBdDogVGltZXN0YW1wLm5vdygpLFxuICAgICAgbW9kZWw6IG9wdGlvbnM/Lm1vZGVsIHx8ICdnZW1pbmktMS41LWZsYXNoJyxcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENoYXQodGhpcywgY2hhdElkKTtcbiAgfVxuXG4gIGFzeW5jIGdldENoYXQoY2hhdElkOiBzdHJpbmcpOiBQcm9taXNlPENoYXQ+IHtcbiAgICAvLyBGZXRjaCBjaGF0IGZyb20gZGIgdG8gcHJlc2VydmUgdGhlIGNvbnZlcnNhdGlvbidzIGhpc3RvcnkuXG4gICAgY29uc3QgZG9jUmVmID0gdGhpcy5kYkNvbGxlY3Rpb24oKS5kb2MoY2hhdElkKTtcbiAgICBjb25zdCBjaGF0RG9jID0gYXdhaXQgZG9jUmVmLmdldCgpO1xuICAgIGlmICghY2hhdERvYy5leGlzdHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjaGF0SWR9IGRvZXMgbm90IGV4aXN0YCk7XG4gICAgfVxuICAgIGNvbnN0IGNoYXREYXRhID0gY2hhdERvYy5kYXRhKCkgfHwge307XG4gICAgcmV0dXJuIG5ldyBDaGF0KHRoaXMsIGNoYXRJZCwge1xuICAgICAgaGlzdG9yeTogY2hhdERhdGEuaGlzdG9yeSxcbiAgICAgIG1vZGVsOiBjaGF0RGF0YS5tb2RlbCxcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGxpc3RDaGF0cyhvcHRpb25zPzoge2xpbWl0PzogbnVtYmVyfSk6IFByb21pc2U8YW55W10+IHtcbiAgICBjb25zdCBsaW1pdCA9IG9wdGlvbnM/LmxpbWl0IHx8IDIwO1xuICAgIGNvbnN0IHF1ZXJ5ID0gdGhpcy5kYkNvbGxlY3Rpb24oKVxuICAgICAgLndoZXJlKCdjcmVhdGVkQnknLCAnPT0nLCB0aGlzLnVzZXIpXG4gICAgICAubGltaXQobGltaXQpXG4gICAgICAub3JkZXJCeSgnY3JlYXRlZEF0JywgJ2Rlc2MnKTtcbiAgICBjb25zdCByZXMgPSBhd2FpdCBxdWVyeS5nZXQoKTtcbiAgICByZXR1cm4gcmVzLmRvY3MubWFwKChkb2MpID0+IGRvYy5kYXRhKCkpO1xuICB9XG5cbiAgZGJDb2xsZWN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmNtc0NsaWVudC5kYi5jb2xsZWN0aW9uKFxuICAgICAgYFByb2plY3RzLyR7dGhpcy5jbXNDbGllbnQucHJvamVjdElkfS9FeHBlcmltZW50cy9haS9DaGF0YFxuICAgICk7XG4gIH1cbn1cbiIsICIvKipcbiAqIERvY3VtZW50IHZlcmlvbiBoaXN0b3J5LlxuICpcbiAqIFZlcmlvbnMgc2F2ZSB0aGUgc3RhdGUgb2YgYSBkb2N1bWVudCBhdCBkaWZmZXJlbnQgbW9tZW50cyBpbiB0aW1lLCBhbGxvd2luZ1xuICogdXNlcnMgdG8gcmV2ZXJ0IGJhY2sgdG8gYSB2ZXJzaW9uIGlmL3doZW4gbmVlZGVkLlxuICpcbiAqIFRoZSBzYXZlVmVyc2lvbnMoKSBmdW5jdGlvbiBpcyBtZWFudCB0byBiZSBydW4gd2l0aGluIGEgY3JvbiBqb2IgKGUuZyB1c2luZ1xuICogZmlyZWJhc2UgZnVuY3Rpb25zKS4gRXZlcnkgbWludXRlLCB0aGUgcnVubmVyIGNoZWNrcyBmb3IgYWxsIGRvY3VtZW50cyB0aGF0XG4gKiBoYXZlIGJlZW4gZWRpdGVkIHNpbmNlIHRoZSBsYXN0IHJ1bi4gVG8gYXZvaWQgc2F2aW5nIFwicGFydGlhbFwiIHZlcnNpb25zXG4gKiAod2hlbiB0aGUgdXNlciBtaWdodCBiZSBpbiB0aGUgbWlkZGxlIG9mIGVkaXRpbmcgYSBkb2N1bWVudCksIHZlcnNpb25zIG9ubHlcbiAqIHJ1biBvbiBkb2N1bWVudHMgdGhhdCBoYXZlbid0IGJlZW4gZWRpdGVkIHdpdGhpbiB0aGUgbGFzdCA1IG1pbnMgdG8gZW5zdXJlXG4gKiB0aGF0IHZlcnNpb24gaXMgXCJzdGFibGVcIi5cbiAqXG4gKiBJbiB0aGUgZGF0YWJhc2UsIHZlcnNpb25zIGFyZSBzdG9yZWQgYXM6XG4gKiAvUHJvamVjdHMvPHByb2plY3RJZD4vQ29sbGVjdGlvbnMvPGNvbGxlY3Rpb25JZD4vRHJhZnRzLzxkb2NJZD4vVmVyc2lvbnMvPHRpbWVzdGFtcD5cbiAqXG4gKiBXaGVyZSA8dGltZXN0YW1wPiBpcyB0aGUgdW5peCB0aW1lc3RhbXAgKG1pbGxpcykgdGhhdCB0aGUgZG9jdW1lbnQgd2FzIGxhc3RcbiAqIGVkaXRlZC5cbiAqL1xuXG5pbXBvcnQgcGF0aCBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHtSb290Q29uZmlnfSBmcm9tICdAYmxpbmtrL3Jvb3QnO1xuaW1wb3J0IHtGaXJlc3RvcmUsIFF1ZXJ5LCBUaW1lc3RhbXB9IGZyb20gJ2ZpcmViYXNlLWFkbWluL2ZpcmVzdG9yZSc7XG5pbXBvcnQgZ2xvYiBmcm9tICd0aW55LWdsb2InO1xuaW1wb3J0IHtnZXRDbXNQbHVnaW59IGZyb20gJy4vY2xpZW50LmpzJztcblxuLy8gVG8gYXZvaWQgc2F2aW5nIFwicGFydGlhbFwiIHZlcnNpb25zICh3aGVuIHRoZSB1c2VyIG1pZ2h0IGJlIGluIHRoZSBtaWRkbGUgb2Zcbi8vIGVkaXRpbmcgYSBkb2N1bWVudCksIHZlcnNpb25zIG9ubHkgcnVuIG9uIGRvY3VtZW50cyB0aGF0IGhhdmVuJ3QgYmVlbiBlZGl0ZWRcbi8vIHdpdGhpbiB0aGUgbGFzdCA1IG1pbnMgdG8gZW5zdXJlIHRoYXQgdmVyc2lvbiBpcyBcInN0YWJsZVwiLlxuY29uc3QgRE9DVU1FTlRfU0FWRV9PRkZTRVQgPSA1ICogNjAgKiAxMDAwO1xuXG5pbnRlcmZhY2UgUGFydGlhbENNU0RvYyB7XG4gIFtrZXk6IHN0cmluZ106IGFueTtcbiAgaWQ6IHN0cmluZztcbiAgY29sbGVjdGlvbjogc3RyaW5nO1xuICBzbHVnOiBzdHJpbmc7XG4gIHN5czoge1xuICAgIG1vZGlmaWVkQXQ6IFRpbWVzdGFtcDtcbiAgICBtb2RpZmllZEJ5OiBzdHJpbmc7XG4gIH07XG59XG5cbmV4cG9ydCBjbGFzcyBWZXJzaW9uc1NlcnZpY2Uge1xuICBwcml2YXRlIHJlYWRvbmx5IHJvb3RDb25maWc6IFJvb3RDb25maWc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvamVjdElkOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGI6IEZpcmVzdG9yZTtcblxuICBjb25zdHJ1Y3Rvcihyb290Q29uZmlnOiBSb290Q29uZmlnKSB7XG4gICAgdGhpcy5yb290Q29uZmlnID0gcm9vdENvbmZpZztcbiAgICBjb25zdCBjbXNQbHVnaW4gPSBnZXRDbXNQbHVnaW4ocm9vdENvbmZpZyk7XG4gICAgY29uc3QgY21zUGx1Z2luT3B0aW9ucyA9IGNtc1BsdWdpbi5nZXRDb25maWcoKTtcbiAgICBjb25zdCBwcm9qZWN0SWQgPSBjbXNQbHVnaW5PcHRpb25zLmlkIHx8ICdkZWZhdWx0JztcbiAgICB0aGlzLnByb2plY3RJZCA9IHByb2plY3RJZDtcbiAgICB0aGlzLmRiID0gY21zUGx1Z2luLmdldEZpcmVzdG9yZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNhdmVzIGEgdmVyc2lvbiBvZiBhbGwgZG9jdW1lbnRzIHRoYXQgaGF2ZSBiZWVuIGVkaXRlZCBzaW5jZSB0aGUgbGFzdCBydW4uXG4gICAqL1xuICBhc3luYyBzYXZlVmVyc2lvbnMoKSB7XG4gICAgLy8gT2Zmc2V0IHRoZSBcImxhc3QgcnVuXCIgdGltZSBieSA1IG1pbnMuIFZlcnNpb25zIGlnbm9yZSBkb2NzIHRoYXQgd2VyZVxuICAgIC8vIGVkaXRlZCB3aXRoaW4gdGhlIGxhc3QgNSBtaW5zIHRvIGF2b2lkIHBvdGVudGlhbCBcInBhcnRpYWxcIiB2ZXJzaW9ucyB3aGVuXG4gICAgLy8gdXNlciBpcyBpbiB0aGUgbWlkZGxlIG9mIGVkaXRpbmcgYSBkb2N1bWVudC5cbiAgICBjb25zdCBsYXN0UnVuID0gYXdhaXQgdGhpcy5nZXRMYXN0UnVuKCk7XG4gICAgY29uc3QgbGFzdFJ1bldpdGhPZmZzZXQgPVxuICAgICAgbGFzdFJ1biA9PT0gMCA/IGxhc3RSdW4gOiBsYXN0UnVuIC0gRE9DVU1FTlRfU0FWRV9PRkZTRVQ7XG4gICAgY29uc3QgY2hhbmdlZERvY3MgPSBhd2FpdCB0aGlzLmdldERvY3NNb2RpZmllZEFmdGVyKGxhc3RSdW5XaXRoT2Zmc2V0KTtcbiAgICBjb25zdCBub3cgPSBUaW1lc3RhbXAubm93KCkudG9NaWxsaXMoKTtcbiAgICBjb25zdCB2ZXJzaW9ucyA9IGNoYW5nZWREb2NzLmZpbHRlcigoZG9jKSA9PiB7XG4gICAgICBjb25zdCBtb2RpZmllZEF0ID0gZG9jLnN5cy5tb2RpZmllZEF0LnRvTWlsbGlzKCk7XG4gICAgICByZXR1cm4gbW9kaWZpZWRBdCA8PSBub3cgLSBET0NVTUVOVF9TQVZFX09GRlNFVDtcbiAgICB9KTtcbiAgICBpZiAodmVyc2lvbnMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5zYXZlVmVyc2lvbnNUb0ZpcmVzdG9yZSh2ZXJzaW9ucyk7XG4gICAgfVxuICAgIHRoaXMuc2F2ZUxhc3RSdW4obm93KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2F2ZVZlcnNpb25zVG9GaXJlc3RvcmUodmVyc2lvbnM6IFBhcnRpYWxDTVNEb2NbXSkge1xuICAgIGNvbnN0IGJhdGNoID0gdGhpcy5kYi5iYXRjaCgpO1xuICAgIHZlcnNpb25zLmZvckVhY2goKHZlcnNpb24pID0+IHtcbiAgICAgIGlmICghdmVyc2lvbi5jb2xsZWN0aW9uIHx8ICF2ZXJzaW9uLnNsdWcgfHwgIXZlcnNpb24uc3lzPy5tb2RpZmllZEF0KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG1vZGlmaWVkQXRNaWxsaXMgPSB2ZXJzaW9uLnN5cy5tb2RpZmllZEF0LnRvTWlsbGlzKCk7XG4gICAgICBjb25zdCB2ZXJzaW9uUGF0aCA9IGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9Db2xsZWN0aW9ucy8ke3ZlcnNpb24uY29sbGVjdGlvbn0vRHJhZnRzLyR7dmVyc2lvbi5zbHVnfS9WZXJzaW9ucy8ke21vZGlmaWVkQXRNaWxsaXN9YDtcbiAgICAgIGNvbnNvbGUubG9nKHZlcnNpb25QYXRoKTtcbiAgICAgIGNvbnN0IHZlcnNpb25SZWYgPSB0aGlzLmRiLmRvYyh2ZXJzaW9uUGF0aCk7XG4gICAgICBiYXRjaC5zZXQodmVyc2lvblJlZiwgdmVyc2lvbik7XG4gICAgfSk7XG4gICAgYXdhaXQgYmF0Y2guY29tbWl0KCk7XG4gICAgY29uc29sZS5sb2coYHZlcnNpb25zOiBzYXZlZCAke3ZlcnNpb25zLmxlbmd0aH0gdmVyc2lvbnNgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBsYXN0IHRpbWUgKGluIG1pbGxpcykgc2F2ZVZlcnNpb25zKCkgd2FzIHJ1biwgb3IgMCBpZiBoYXNcbiAgICogbmV2ZXIgYmVlbiBydW4uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldExhc3RSdW4oKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCBwcm9qZWN0RG9jUmVmID0gdGhpcy5kYi5jb2xsZWN0aW9uKCdQcm9qZWN0cycpLmRvYyh0aGlzLnByb2plY3RJZCk7XG4gICAgY29uc3QgcHJvamVjdERvYyA9IGF3YWl0IHByb2plY3REb2NSZWYuZ2V0KCk7XG4gICAgaWYgKHByb2plY3REb2MuZXhpc3RzKSB7XG4gICAgICBjb25zdCBkYXRhID0gcHJvamVjdERvYy5kYXRhKCkgfHwge307XG4gICAgICBjb25zdCB0cyA9IGRhdGEudmVyc2lvbnNMYXN0UnVuIGFzIFRpbWVzdGFtcDtcbiAgICAgIGlmICh0cykge1xuICAgICAgICByZXR1cm4gdHMudG9NaWxsaXMoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIDA7XG4gIH1cblxuICAvKipcbiAgICogU2F2ZXMge3ZlcnNpb25MYXN0UnVuOiA8dGltZXN0YW1wPn0gdG8gdGhlIFByb2plY3RzLzxwcm9qZWN0SWQ+IGRvYy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc2F2ZUxhc3RSdW4obWlsbGlzOiBudW1iZXIpIHtcbiAgICBjb25zdCB0cyA9IFRpbWVzdGFtcC5mcm9tTWlsbGlzKG1pbGxpcyk7XG4gICAgY29uc3QgcHJvamVjdERvY1JlZiA9IHRoaXMuZGIuY29sbGVjdGlvbignUHJvamVjdHMnKS5kb2ModGhpcy5wcm9qZWN0SWQpO1xuICAgIGF3YWl0IHByb2plY3REb2NSZWYuc2V0KHt2ZXJzaW9uc0xhc3RSdW46IHRzfSwge21lcmdlOiB0cnVlfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGxpc3Qgb2YgYWxsIGRvY3MgdGhhdCB3ZXJlIGVkaXRlZCBhZnRlciBhIGNlcnRhaW4gdGltZS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZ2V0RG9jc01vZGlmaWVkQWZ0ZXIobWlsbGlzOiBudW1iZXIpOiBQcm9taXNlPFBhcnRpYWxDTVNEb2NbXT4ge1xuICAgIGNvbnN0IHRzID0gVGltZXN0YW1wLmZyb21NaWxsaXMobWlsbGlzKTtcbiAgICBjb25zdCByZXN1bHRzOiBQYXJ0aWFsQ01TRG9jW10gPSBbXTtcbiAgICBjb25zdCBjb2xsZWN0aW9uSWRzID0gYXdhaXQgdGhpcy5saXN0Q29sbGVjdGlvbnMoKTtcbiAgICAvLyBOT1RFOiBJbmRpdmlkdWFsIGNvbGxlY3Rpb25zIGFyZSBxdWVyaWVkIGluc3RlYWQgb2YgdXNpbmcgYVxuICAgIC8vIGNvbGxlY3Rpb25Hcm91cCBxdWVyeSBiZWNhdXNlIHRoZSBsYXR0ZXIgcmVxdWlyZXMgYSBmaXJlc3RvcmUgaW5kZXggdG8gYmVcbiAgICAvLyBzZXQgdXAuXG4gICAgZm9yIChjb25zdCBjb2xsZWN0aW9uSWQgb2YgY29sbGVjdGlvbklkcykge1xuICAgICAgY29uc3QgY29sbGVjdGlvblBhdGggPSBgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH0vQ29sbGVjdGlvbnMvJHtjb2xsZWN0aW9uSWR9L0RyYWZ0c2A7XG4gICAgICBjb25zdCBxdWVyeTogUXVlcnkgPSB0aGlzLmRiXG4gICAgICAgIC5jb2xsZWN0aW9uKGNvbGxlY3Rpb25QYXRoKVxuICAgICAgICAud2hlcmUoJ3N5cy5tb2RpZmllZEF0JywgJz49JywgdHMpO1xuICAgICAgY29uc3QgcXVlcnlTbmFwc2hvdCA9IGF3YWl0IHF1ZXJ5LmdldCgpO1xuICAgICAgcXVlcnlTbmFwc2hvdC5mb3JFYWNoKChkb2MpID0+IHtcbiAgICAgICAgcmVzdWx0cy5wdXNoKGRvYy5kYXRhKCkgYXMgUGFydGlhbENNU0RvYyk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGxpc3Qgb2YgY29sbGVjdGlvbiBpZHMgZm9yIHRoZSBSb290IHByb2plY3QuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGxpc3RDb2xsZWN0aW9ucygpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgY29uc3QgY29sbGVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCBjb2xsZWN0aW9uRmlsZU5hbWVzID0gYXdhaXQgZ2xvYignKi5zY2hlbWEudHMnLCB7XG4gICAgICBjd2Q6IHBhdGguam9pbih0aGlzLnJvb3RDb25maWcucm9vdERpciwgJ2NvbGxlY3Rpb25zJyksXG4gICAgfSk7XG4gICAgY29sbGVjdGlvbkZpbGVOYW1lcy5mb3JFYWNoKChmaWxlbmFtZSkgPT4ge1xuICAgICAgY29sbGVjdGlvbklkcy5wdXNoKGZpbGVuYW1lLnNsaWNlKDAsIC0xMCkpO1xuICAgIH0pO1xuICAgIHJldHVybiBjb2xsZWN0aW9uSWRzO1xuICB9XG59XG4iLCAiaW1wb3J0IHtwYXJzZSBhcyBjc3ZQYXJzZX0gZnJvbSAnY3N2LXBhcnNlL3N5bmMnO1xuaW1wb3J0IHtzdHJpbmdpZnkgYXMgY3N2U3RyaW5naWZ5fSBmcm9tICdjc3Ytc3RyaW5naWZ5L3N5bmMnO1xuXG5leHBvcnQgZnVuY3Rpb24gYXJyYXlUb0NzdihyZXE6IHtcbiAgaGVhZGVyczogc3RyaW5nW107XG4gIHJvd3M6IEFycmF5PFJlY29yZDxzdHJpbmcsIGFueT4+O1xufSk6IHN0cmluZyB7XG4gIGNvbnN0IGhlYWRlcnMgPSByZXEuaGVhZGVycyB8fCBbXTtcbiAgY29uc3Qgcm93cyA9IHJlcS5yb3dzIHx8IFtdO1xuICByZXR1cm4gY3N2U3RyaW5naWZ5KHJvd3MsIHtcbiAgICBoZWFkZXI6IHRydWUsXG4gICAgY29sdW1uczogaGVhZGVycyxcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjc3ZUb0FycmF5KGNzdlN0cmluZzogc3RyaW5nKSB7XG4gIGNvbnN0IHJvd3MgPSBjc3ZQYXJzZShjc3ZTdHJpbmcsIHtcbiAgICBjb2x1bW5zOiB0cnVlLFxuICAgIHNraXBfZW1wdHlfbGluZXM6IHRydWUsXG4gIH0pO1xuICByZXR1cm4gcm93cztcbn1cbiIsICJpbXBvcnQge1Jvb3RDb25maWd9IGZyb20gJ0BibGlua2svcm9vdCc7XG5pbXBvcnQge1RpbWVzdGFtcH0gZnJvbSAnZmlyZWJhc2UtYWRtaW4vZmlyZXN0b3JlJztcbmltcG9ydCB7Um9vdENNU0NsaWVudCwgVHJhbnNsYXRpb24sIFRyYW5zbGF0aW9uc0RvY30gZnJvbSAnLi9jbGllbnQuanMnO1xuXG4vKipcbiAqIFJ1bnMgY29tcGF0aWJpbGl0eSBjaGVja3MgdG8gZW5zdXJlIHRoZSBjdXJyZW50IHZlcnNpb24gb2Ygcm9vdCBzdXBwb3J0c1xuICogYW55IGJhY2t3YXJkcy1pbmNvbXBhdGlibGUgZGIgY2hhbmdlcy5cbiAqXG4gKiBDb21wYXRpYmlsaXR5IHZlcnNpb25zIGFyZSBzdG9yZWQgaW4gdGhlIGRiIGluIFByb2plY3RzLzxwcm9qZWN0SWQ+IHVuZGVyXG4gKiB0aGUgXCJjb21wYXRpYmlsaXR5XCIga2V5LiBJZiB0aGUgY29tcGF0aWJpbGl0eSB2ZXJzaW9uIGlzIGxlc3MgdGhhbiB0aGVcbiAqIGxhdGVzdCB2ZXJzaW9uLCBhIGJhY2t3YXJkcy1mcmllbmRseSBcIm1pZ3JhdGlvblwiIGlzIGRvbmUgdG8gZW5zdXJlXG4gKiBjb21wYXRpYmlsaXR5IG9uIGJvdGggdGhlIG9sZCBhbmQgbmV3IHZlcnNpb25zLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuQ29tcGF0aWJpbGl0eUNoZWNrcyhyb290Q29uZmlnOiBSb290Q29uZmlnKSB7XG4gIGNvbnN0IGNtc0NsaWVudCA9IG5ldyBSb290Q01TQ2xpZW50KHJvb3RDb25maWcpO1xuICBjb25zdCBwcm9qZWN0SWQgPSBjbXNDbGllbnQucHJvamVjdElkO1xuICBjb25zdCBkYiA9IGNtc0NsaWVudC5kYjtcbiAgY29uc3QgcHJvamVjdENvbmZpZ0RvY1JlZiA9IGRiLmRvYyhgUHJvamVjdHMvJHtwcm9qZWN0SWR9YCk7XG4gIGNvbnN0IHByb2plY3RDb25maWdEb2MgPSBhd2FpdCBwcm9qZWN0Q29uZmlnRG9jUmVmLmdldCgpO1xuICBjb25zdCBwcm9qZWN0Q29uZmlnID0gcHJvamVjdENvbmZpZ0RvYy5kYXRhKCkgfHwge307XG5cbiAgY29uc3QgY29tcGF0aWJpbGl0eVZlcnNpb25zID0gcHJvamVjdENvbmZpZy5jb21wYXRpYmlsaXR5IHx8IHt9O1xuICBsZXQgdmVyc2lvbnNDaGFuZ2VkID0gZmFsc2U7XG5cbiAgY29uc3QgdHJhbnNsYXRpb25zVmVyc2lvbiA9IGNvbXBhdGliaWxpdHlWZXJzaW9ucy50cmFuc2xhdGlvbnMgfHwgMDtcbiAgaWYgKHRyYW5zbGF0aW9uc1ZlcnNpb24gPCAyKSB7XG4gICAgYXdhaXQgbWlncmF0ZVRyYW5zbGF0aW9uc1RvVjIocm9vdENvbmZpZywgY21zQ2xpZW50KTtcbiAgICBjb21wYXRpYmlsaXR5VmVyc2lvbnMudHJhbnNsYXRpb25zID0gMjtcbiAgICB2ZXJzaW9uc0NoYW5nZWQgPSB0cnVlO1xuICB9XG5cbiAgaWYgKHZlcnNpb25zQ2hhbmdlZCkge1xuICAgIGF3YWl0IHByb2plY3RDb25maWdEb2NSZWYudXBkYXRlKHtjb21wYXRpYmlsaXR5OiBjb21wYXRpYmlsaXR5VmVyc2lvbnN9KTtcbiAgICBjb25zb2xlLmxvZygnW3Jvb3QgY21zXSB1cGRhdGVkIGRiIGNvbXBhdGliaWxpdHknKTtcbiAgfVxufVxuXG4vKipcbiAqIE1pZ3JhdGVzIHRyYW5zbGF0aW9ucyBmcm9tIHRoZSBcInYxXCIgZm9ybWF0IHRvIFwidjJcIi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbWlncmF0ZVRyYW5zbGF0aW9uc1RvVjIoXG4gIHJvb3RDb25maWc6IFJvb3RDb25maWcsXG4gIGNtc0NsaWVudDogUm9vdENNU0NsaWVudFxuKSB7XG4gIGlmIChyb290Q29uZmlnLmV4cGVyaW1lbnRzPy5yb290Q21zRGlzYWJsZVRyYW5zbGF0aW9uc1RvVjJDaGVjaykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHByb2plY3RJZCA9IGNtc0NsaWVudC5wcm9qZWN0SWQ7XG4gIGNvbnN0IGRiID0gY21zQ2xpZW50LmRiO1xuICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHtwcm9qZWN0SWR9L1RyYW5zbGF0aW9uc2A7XG4gIGNvbnN0IHF1ZXJ5ID0gZGIuY29sbGVjdGlvbihkYlBhdGgpO1xuICBjb25zdCBxdWVyeVNuYXBzaG90ID0gYXdhaXQgcXVlcnkuZ2V0KCk7XG4gIGlmIChxdWVyeVNuYXBzaG90LnNpemUgPT09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zb2xlLmxvZygnW3Jvb3QgY21zXSB1cGRhdGluZyB0cmFuc2xhdGlvbnMgdjIgY29tcGF0aWJpbGl0eScpO1xuXG4gIGNvbnN0IHRyYW5zbGF0aW9uc0RvY3M6IFJlY29yZDxzdHJpbmcsIFRyYW5zbGF0aW9uc0RvYz4gPSB7fTtcbiAgcXVlcnlTbmFwc2hvdC5mb3JFYWNoKChkb2MpID0+IHtcbiAgICBjb25zdCBoYXNoID0gZG9jLmlkO1xuICAgIGNvbnN0IHRyYW5zbGF0aW9uID0gZG9jLmRhdGEoKSBhcyBUcmFuc2xhdGlvbjtcbiAgICBjb25zdCB0YWdzID0gKHRyYW5zbGF0aW9uLnRhZ3MgfHwgW10pIGFzIHN0cmluZ1tdO1xuICAgIGRlbGV0ZSB0cmFuc2xhdGlvbi50YWdzO1xuICAgIGZvciAoY29uc3QgdGFnIG9mIHRhZ3MpIHtcbiAgICAgIGlmICh0YWcuaW5jbHVkZXMoJy8nKSkge1xuICAgICAgICBjb25zdCB0cmFuc2xhdGlvbnNJZCA9IHRhZztcbiAgICAgICAgdHJhbnNsYXRpb25zRG9jc1t0cmFuc2xhdGlvbnNJZF0gPz89IHtcbiAgICAgICAgICBpZDogdHJhbnNsYXRpb25zSWQsXG4gICAgICAgICAgc3lzOiB7XG4gICAgICAgICAgICBtb2RpZmllZEF0OiBUaW1lc3RhbXAubm93KCksXG4gICAgICAgICAgICBtb2RpZmllZEJ5OiAncm9vdC1jbXMtY2xpZW50JyxcbiAgICAgICAgICAgIHB1Ymxpc2hlZEF0OiBUaW1lc3RhbXAubm93KCksXG4gICAgICAgICAgICBwdWJsaXNoZWRCeTogJ3Jvb3QtY21zLWNsaWVudCcsXG4gICAgICAgICAgICB0YWdzOiB0YWdzLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgc3RyaW5nczoge30sXG4gICAgICAgIH07XG4gICAgICAgIHRyYW5zbGF0aW9uc0RvY3NbdHJhbnNsYXRpb25zSWRdLnN0cmluZ3NbaGFzaF0gPSB0cmFuc2xhdGlvbjtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIGlmIChPYmplY3Qua2V5cyh0cmFuc2xhdGlvbnNEb2NzKS5sZW5ndGggPT09IDApIHtcbiAgICBjb25zb2xlLmxvZygnW3Jvb3QgY21zXSBubyB0cmFuc2xhdGlvbnMgdG8gc2F2ZScpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIE1vdmUgdGhlIGRvYydzIFwibDEwblNoZWV0XCIgdG8gdGhlIHRyYW5zbGF0aW9ucyBkb2MncyBcImxpbmtlZFNoZWV0XCIuXG5cbiAgZm9yIChjb25zdCBkb2NJZCBpbiB0cmFuc2xhdGlvbnNEb2NzKSB7XG4gICAgY29uc3QgW2NvbGxlY3Rpb24sIHNsdWddID0gZG9jSWQuc3BsaXQoJy8nKTtcbiAgICBpZiAoY29sbGVjdGlvbiAmJiBzbHVnKSB7XG4gICAgICBjb25zdCBkb2M6IGFueSA9IGF3YWl0IGNtc0NsaWVudC5nZXREb2MoY29sbGVjdGlvbiwgc2x1Zywge1xuICAgICAgICBtb2RlOiAnZHJhZnQnLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBsaW5rZWRTaGVldCA9IGRvYz8uc3lzPy5sMTBuU2hlZXQ7XG4gICAgICBpZiAobGlua2VkU2hlZXQpIHtcbiAgICAgICAgdHJhbnNsYXRpb25zRG9jc1tkb2NJZF0uc3lzLmxpbmtlZFNoZWV0ID0gbGlua2VkU2hlZXQ7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc3QgYmF0Y2ggPSBkYi5iYXRjaCgpO1xuICBPYmplY3QuZW50cmllcyh0cmFuc2xhdGlvbnNEb2NzKS5mb3JFYWNoKChbdHJhbnNsYXRpb25zSWQsIGRhdGFdKSA9PiB7XG4gICAgY29uc3QgZHJhZnRSZWYgPSBkYi5kb2MoXG4gICAgICBgUHJvamVjdHMvJHtwcm9qZWN0SWR9L1RyYW5zbGF0aW9uc01hbmFnZXIvZHJhZnQvVHJhbnNsYXRpb25zLyR7dHJhbnNsYXRpb25zSWR9YFxuICAgICk7XG4gICAgY29uc3QgcHVibGlzaGVkUmVmID0gZGIuZG9jKFxuICAgICAgYFByb2plY3RzLyR7cHJvamVjdElkfS9UcmFuc2xhdGlvbnNNYW5hZ2VyL3B1Ymxpc2hlZC9UcmFuc2xhdGlvbnMvJHt0cmFuc2xhdGlvbnNJZH1gXG4gICAgKTtcbiAgICBiYXRjaC5zZXQoZHJhZnRSZWYsIGRhdGEsIHttZXJnZTogdHJ1ZX0pO1xuICAgIGJhdGNoLnNldChwdWJsaXNoZWRSZWYsIGRhdGEsIHttZXJnZTogdHJ1ZX0pO1xuICAgIGNvbnN0IGxlbiA9IE9iamVjdC5rZXlzKGRhdGEuc3RyaW5ncykubGVuZ3RoO1xuICAgIGNvbnNvbGUubG9nKGBbcm9vdCBjbXNdIHNhdmluZyAke2xlbn0gc3RyaW5nKHMpIHRvICR7dHJhbnNsYXRpb25zSWR9Li4uYCk7XG4gIH0pO1xuICBhd2FpdCBiYXRjaC5jb21taXQoKTtcblxuICBjb25zb2xlLmxvZygnW3Jvb3QgY21zXSBkb25lIG1pZ3JhdGluZyB0cmFuc2xhdGlvbnMgdG8gdjInKTtcbn1cbiIsICJpbXBvcnQge1xuICBHZXRTdGF0aWNQYXRocyxcbiAgR2V0U3RhdGljUHJvcHMsXG4gIEhhbmRsZXJDb250ZXh0LFxuICBSZXF1ZXN0LFxuICBSZXNwb25zZSxcbiAgUm91dGVQYXJhbXMsXG59IGZyb20gJ0BibGlua2svcm9vdCc7XG5pbXBvcnQge0JhdGNoUmVxdWVzdCwgUm9vdENNU0NsaWVudH0gZnJvbSAnLi9jbGllbnQuanMnO1xuXG5leHBvcnQgdHlwZSBDTVNSZXF1ZXN0ID0gUmVxdWVzdCAmIHtcbiAgY21zQ2xpZW50OiBSb290Q01TQ2xpZW50O1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBDTVNSb3V0ZUNvbnRleHQge1xuICAvKiogSFRUUCByZXF1ZXN0IG9iamVjdC4gT25seSBhdmFpbGFibGUgaW4gU1NSIG1vZGUuICovXG4gIHJlcT86IENNU1JlcXVlc3Q7XG4gIHNsdWc6IHN0cmluZztcbiAgbW9kZTogJ2RyYWZ0JyB8ICdwdWJsaXNoZWQnO1xuICBjbXNDbGllbnQ6IFJvb3RDTVNDbGllbnQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ01TUm91dGVPcHRpb25zIHtcbiAgLyoqXG4gICAqIENvbGxlY3Rpb24gbWFwcGVkIHRvIHRoZSByb3V0ZS5cbiAgICovXG4gIGNvbGxlY3Rpb246IHN0cmluZztcblxuICAvKipcbiAgICogUm91dGUgcGFyYW0gbmFtZSB1c2VkIGZvciB0aGUgc2x1Zy4gVXNlZCBmb3IgZHluYW1pYyByb3V0ZXMsIGUuZy5cbiAgICogYFsuLi5zbHVnXS50c3hgLiBEZWZhdWx0cyB0byBcInNsdWdcIi5cbiAgICovXG4gIHNsdWdQYXJhbT86IHN0cmluZztcblxuICAvKipcbiAgICogU2x1ZyB0byB1c2UgZm9yIHRoZSByb3V0ZS4gVXNlZCBmb3Igbm9uLWR5bmFtaWMsIHNpbmdsZS1kb2N1bWVudCByb3V0ZXMuXG4gICAqL1xuICBzbHVnPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBIb29rIHRoYXQgYWxsb3dzIGNhbGxlcnMgdG8gbW9kaWZ5IHRoZSBSb290IENNUyBgQmF0Y2hSZXF1ZXN0YCBvYmplY3QuIElmIGFcbiAgICogbmV3IGBCYXRjaFJlcXVlc3RgIGlzIHJldHVybmVkLCBpdCB3aWxsIHJlcGxhY2UgdGhlIGRlZmF1bHQgb25lIGNyZWF0ZWQgYnlcbiAgICogYGNtc1JvdXRlKClgLlxuICAgKi9cbiAgcHJlUmVxdWVzdEhvb2s/OiAoXG4gICAgYmF0Y2hSZXF1ZXN0OiBCYXRjaFJlcXVlc3QsXG4gICAgY29udGV4dDogQ01TUm91dGVDb250ZXh0XG4gICkgPT4gdm9pZCB8IEJhdGNoUmVxdWVzdDtcblxuICAvKipcbiAgICogQ2FsbGJhY2sgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgbWFwIG9mIFByb21pc2VzIHRoYXQgY29udGFpbiBmZXRjaGVkIGRhdGEuXG4gICAqIE9uY2UgdGhlIHByb21pc2UgaXMgcmVzb2x2ZWQsIHRoZSB2YWx1ZXMgYXJlIGluamVjdGVkIGludG8gcGFnZSdzIHByb3BzXG4gICAqIGZvciByZW5kZXJpbmcuXG4gICAqL1xuICBmZXRjaERhdGE/OiAoY29udGV4dDogQ01TUm91dGVDb250ZXh0KSA9PiBSZWNvcmQ8c3RyaW5nLCBQcm9taXNlPGFueT4+O1xuXG4gIC8qKlxuICAgKiBIb29rIGZvciBhbWVuZGluZyBhbnkgcHJvcHMgdmFsdWVzIGJlZm9yZSBiZWluZyBwYXNzZWQgdG8gdGhlIHBhZ2VcbiAgICogY29tcG9uZW50LlxuICAgKi9cbiAgcHJlUmVuZGVySG9vaz86IChwcm9wczogYW55LCBjb250ZXh0OiBDTVNSb3V0ZUNvbnRleHQpID0+IGFueSB8IFByb21pc2U8YW55PjtcblxuICAvKipcbiAgICogSG9vayBmb3Igc2V0dGluZyBhbnkgcmVzcG9uc2UgaGVhZGVycy5cbiAgICovXG4gIHNldFJlc3BvbnNlSGVhZGVycz86IChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHZvaWQ7XG5cbiAgLyoqXG4gICAqIFNldHMgQ2FjaGUtQ29udHJvbCBoZWFkZXIgdG8gYHByaXZhdGVgLlxuICAgKi9cbiAgZGlzYWJsZUNhY2hlQ29udHJvbD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEVuYWJsZXMgU1NHIG1vZGUgZm9yIHNpdGVzIHRoYXQgc2VydmUgb24gU0NTIG9yIG90aGVyIHN0YXRpYyBzZXJ2ZXJzLlxuICAgKi9cbiAgZW5hYmxlU1NHPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDTVNEb2Mge1xuICBpZDogc3RyaW5nO1xuICBzbHVnOiBzdHJpbmc7XG4gIHN5cz86IHtcbiAgICBsb2NhbGVzPzogc3RyaW5nW107XG4gIH07XG59XG5cbi8qKlxuICogVXRpbGl0eSBmb3IgZ2VuZXJhdGluZyBTU1IgYW5kIFNTRyBoYW5kbGVycyBpbiBhIFJvb3Qgcm91dGUgZmlsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNtc1JvdXRlKG9wdGlvbnM6IENNU1JvdXRlT3B0aW9ucykge1xuICBsZXQgY21zQ2xpZW50OiBSb290Q01TQ2xpZW50IHwgbnVsbCA9IG51bGw7XG5cbiAgZnVuY3Rpb24gZ2V0U2x1ZyhwYXJhbXM6IFJvdXRlUGFyYW1zKSB7XG4gICAgaWYgKG9wdGlvbnMuc2x1Zykge1xuICAgICAgcmV0dXJuIG9wdGlvbnMuc2x1ZztcbiAgICB9XG4gICAgY29uc3Qgc2x1Z1BhcmFtID0gb3B0aW9ucy5zbHVnUGFyYW0gfHwgJ3NsdWcnO1xuICAgIHJldHVybiAocGFyYW1zW3NsdWdQYXJhbV0gfHwgJ2luZGV4JykucmVwbGFjZUFsbCgnLycsICctLScpO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gZmV0Y2hEYXRhKFxuICAgIGZldGNoT3B0aW9uczogQ01TUm91dGVDb250ZXh0XG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICAgIGlmICghb3B0aW9ucy5mZXRjaERhdGEpIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gICAgY29uc3QgcHJvbWlzZXNNYXAgPSBvcHRpb25zLmZldGNoRGF0YShmZXRjaE9wdGlvbnMpO1xuICAgIHJldHVybiByZXNvbHZlUHJvbWlzZXNNYXAocHJvbWlzZXNNYXApO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVQcm9wcyhcbiAgICByb3V0ZUNvbnRleHQ6IENNU1JvdXRlQ29udGV4dCxcbiAgICBwcmVmZXJyZWRMb2NhbGU6IHN0cmluZyB8ICgoZG9jOiBDTVNEb2MpID0+IHN0cmluZylcbiAgKSB7XG4gICAgY29uc3Qge3NsdWcsIG1vZGV9ID0gcm91dGVDb250ZXh0O1xuXG4gICAgY29uc3QgcHJpbWFyeURvY0lkID0gYCR7b3B0aW9ucy5jb2xsZWN0aW9ufS8ke3NsdWd9YDtcbiAgICBsZXQgYmF0Y2hSZXF1ZXN0ID0gcm91dGVDb250ZXh0LmNtc0NsaWVudC5jcmVhdGVCYXRjaFJlcXVlc3Qoe1xuICAgICAgbW9kZSxcbiAgICAgIHRyYW5zbGF0ZTogdHJ1ZSxcbiAgICB9KTtcbiAgICBiYXRjaFJlcXVlc3QuYWRkRG9jKHByaW1hcnlEb2NJZCk7XG5cbiAgICAvLyBDYWxsIHRoZSBwcmUtcmVxdWVzdCBob29rIHRvIGFsbG93IHVzZXJzIHRvIG1vZGlmeSB0aGUgYmF0Y2ggcmVxdWVzdC5cbiAgICBpZiAob3B0aW9ucy5wcmVSZXF1ZXN0SG9vaykge1xuICAgICAgY29uc3Qgb3ZlcnJpZGVkQmF0Y2hSZXF1ZXN0ID0gb3B0aW9ucy5wcmVSZXF1ZXN0SG9vayhcbiAgICAgICAgYmF0Y2hSZXF1ZXN0LFxuICAgICAgICByb3V0ZUNvbnRleHRcbiAgICAgICk7XG4gICAgICBpZiAob3ZlcnJpZGVkQmF0Y2hSZXF1ZXN0KSB7XG4gICAgICAgIGJhdGNoUmVxdWVzdCA9IG92ZXJyaWRlZEJhdGNoUmVxdWVzdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBGZXRjaCB0aGUgUm9vdCBDTVMgQmF0Y2hSZXF1ZXN0IGluIHBhcmFsbGVsIHdpdGggYW55IG90aGVyIGRhdGEgdGhlXG4gICAgLy8gY2FsbGVyIG5lZWRzIHRvIGZldGNoIHRvIHJlbmRlciB0aGUgcm91dGUuXG4gICAgY29uc3QgW2JhdGNoUmVzLCBkYXRhXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIGJhdGNoUmVxdWVzdC5mZXRjaCgpLFxuICAgICAgZmV0Y2hEYXRhKHJvdXRlQ29udGV4dCksXG4gICAgXSk7XG4gICAgY29uc3QgZG9jID0gYmF0Y2hSZXMuZG9jc1twcmltYXJ5RG9jSWRdO1xuICAgIGlmICghZG9jKSB7XG4gICAgICByZXR1cm4ge25vdEZvdW5kOiB0cnVlfTtcbiAgICB9XG5cbiAgICAvLyBEZXRlcm1pbmUgdGhlIHByZWZlcnJlZCBsb2NhbGUgdG8gcmVuZGVyLlxuICAgIGxldCBsb2NhbGU6IHN0cmluZztcbiAgICBpZiAodHlwZW9mIHByZWZlcnJlZExvY2FsZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGxvY2FsZSA9IHByZWZlcnJlZExvY2FsZTtcbiAgICB9IGVsc2Uge1xuICAgICAgbG9jYWxlID0gcHJlZmVycmVkTG9jYWxlKGRvYyk7XG4gICAgfVxuICAgIGNvbnN0IGRvY0xvY2FsZXMgPSBkb2Muc3lzPy5sb2NhbGVzIHx8IFsnZW4nXTtcbiAgICBpZiAoIWxvY2FsZSB8fCAhZG9jTG9jYWxlcy5pbmNsdWRlcyhsb2NhbGUpKSB7XG4gICAgICByZXR1cm4ge25vdEZvdW5kOiB0cnVlfTtcbiAgICB9XG5cbiAgICAvLyBGcm9tIHRoZSBwcmVmZXJyZWQgbG9jYWxlLCBnZW5lcmF0ZSBhIHRyYW5zbGF0aW9ucyBtYXAuXG4gICAgY29uc3QgaTE4bkZhbGxiYWNrcyA9XG4gICAgICByb3V0ZUNvbnRleHQuY21zQ2xpZW50LnJvb3RDb25maWcuaTE4bj8uZmFsbGJhY2tzIHx8IHt9O1xuICAgIGNvbnN0IHRyYW5zbGF0aW9uRmFsbGJhY2tMb2NhbGVzID0gaTE4bkZhbGxiYWNrc1tsb2NhbGVdIHx8IFtsb2NhbGVdO1xuICAgIGNvbnN0IHRyYW5zbGF0aW9ucyA9IGJhdGNoUmVzLmdldFRyYW5zbGF0aW9ucyh0cmFuc2xhdGlvbkZhbGxiYWNrTG9jYWxlcyk7XG5cbiAgICBsZXQgcHJvcHM6IGFueSA9IHsuLi5kYXRhLCBsb2NhbGUsIG1vZGUsIHNsdWcsIGRvY307XG5cbiAgICAvLyBGb3IgU1NSIGhhbmRsZXJzLCBpbmplY3QgdGhlIHVzZXIncyBjb3VudHJ5IG9mIG9yaWdpbiB0byBwcm9wcy5cbiAgICBpZiAocm91dGVDb250ZXh0LnJlcSkge1xuICAgICAgY29uc3QgY291bnRyeSA9XG4gICAgICAgIGdldEZpcnN0UXVlcnlQYXJhbShyb3V0ZUNvbnRleHQucmVxLCAnZ2wnKSB8fFxuICAgICAgICByb3V0ZUNvbnRleHQucmVxLmdldCgneC1jb3VudHJ5LWNvZGUnKSB8fFxuICAgICAgICByb3V0ZUNvbnRleHQucmVxLmdldCgneC1hcHBlbmdpbmUtY291bnRyeScpIHx8XG4gICAgICAgIG51bGw7XG4gICAgICBwcm9wcy5jb3VudHJ5ID0gY291bnRyeTtcbiAgICB9XG5cbiAgICAvLyBDYWxsIHRoZSBwcmUtcmVuZGVyIGhvb2sgd2hpY2ggYWxsb3dzIGEgY2FsbGVyIHRvIG1vZGlmeSBwcm9wcyBiZWZvcmVcbiAgICAvLyBpdCBpcyBwYXNzZWQgdG8gdGhlIHJvdXRlIGNvbXBvbmVudC5cbiAgICBpZiAob3B0aW9ucy5wcmVSZW5kZXJIb29rKSB7XG4gICAgICBwcm9wcyA9IGF3YWl0IG9wdGlvbnMucHJlUmVuZGVySG9vayhwcm9wcywgcm91dGVDb250ZXh0KTtcbiAgICB9XG5cbiAgICByZXR1cm4ge3Byb3BzLCBsb2NhbGUsIHRyYW5zbGF0aW9uc307XG4gIH1cblxuICAvLyBTU0cgaGFuZGxlcnMgYXJlIGRpc2FibGVkIGJ5IGRlZmF1bHQuIFBhc3MgYHtlbmFibGVTU0c6IHRydWV9YCB0byBlbmFibGUuXG4gIGxldCBnZXRTdGF0aWNQYXRoczogR2V0U3RhdGljUGF0aHMgfCBudWxsID0gbnVsbDtcbiAgbGV0IGdldFN0YXRpY1Byb3BzOiBHZXRTdGF0aWNQcm9wcyB8IG51bGwgPSBudWxsO1xuXG4gIGlmIChvcHRpb25zLmVuYWJsZVNTRykge1xuICAgIGdldFN0YXRpY1BhdGhzID0gYXN5bmMgKGN0eCkgPT4ge1xuICAgICAgaWYgKCFvcHRpb25zLnNsdWdQYXJhbSkge1xuICAgICAgICByZXR1cm4ge3BhdGhzOiBbXX07XG4gICAgICB9XG4gICAgICBpZiAoIWNtc0NsaWVudCkge1xuICAgICAgICBjbXNDbGllbnQgPSBuZXcgUm9vdENNU0NsaWVudChjdHgucm9vdENvbmZpZyk7XG4gICAgICB9XG4gICAgICBjb25zdCBtb2RlID0gJ3B1Ymxpc2hlZCc7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBjbXNDbGllbnQubGlzdERvY3M8Q01TRG9jPihvcHRpb25zLmNvbGxlY3Rpb24sIHttb2RlfSk7XG4gICAgICBjb25zdCBzc2dQYXRoczogQXJyYXk8e3BhcmFtczogUmVjb3JkPHN0cmluZywgc3RyaW5nPn0+ID0gW107XG4gICAgICByZXMuZG9jcy5mb3JFYWNoKChkb2MpID0+IHtcbiAgICAgICAgY29uc3QgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgICAgIHBhcmFtc1tvcHRpb25zLnNsdWdQYXJhbSFdID0gZG9jLnNsdWc7XG4gICAgICAgIHNzZ1BhdGhzLnB1c2goe3BhcmFtc30pO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4ge3BhdGhzOiBzc2dQYXRoc307XG4gICAgfTtcblxuICAgIGdldFN0YXRpY1Byb3BzID0gYXN5bmMgKGN0eCkgPT4ge1xuICAgICAgaWYgKCFjbXNDbGllbnQpIHtcbiAgICAgICAgY21zQ2xpZW50ID0gbmV3IFJvb3RDTVNDbGllbnQoY3R4LnJvb3RDb25maWcpO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2x1ZyA9IGdldFNsdWcoY3R4LnBhcmFtcyk7XG4gICAgICBjb25zdCBtb2RlID0gJ3B1Ymxpc2hlZCc7XG4gICAgICBjb25zdCByb3V0ZUNvbnRleHQ6IENNU1JvdXRlQ29udGV4dCA9IHtzbHVnLCBtb2RlLCBjbXNDbGllbnR9O1xuICAgICAgcmV0dXJuIGdlbmVyYXRlUHJvcHMocm91dGVDb250ZXh0LCBjdHgucGFyYW1zLiRsb2NhbGUpO1xuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIC8vIFNTRyBoYW5kbGVycyAob25seSBlbmFibGVkIHdpdGggYHtlbmFibGVTU0c6IHRydWV9YCkuXG4gICAgZ2V0U3RhdGljUGF0aHM6IGdldFN0YXRpY1BhdGhzLFxuICAgIGdldFN0YXRpY1Byb3BzOiBnZXRTdGF0aWNQcm9wcyxcblxuICAgIC8vIFNTUiBoYW5kbGVyLlxuICAgIGhhbmRsZTogYXN5bmMgKHJlcTogQ01TUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgaWYgKCFjbXNDbGllbnQpIHtcbiAgICAgICAgY21zQ2xpZW50ID0gbmV3IFJvb3RDTVNDbGllbnQocmVxLnJvb3RDb25maWchKTtcbiAgICAgIH1cbiAgICAgIHJlcS5jbXNDbGllbnQgPSBjbXNDbGllbnQ7XG4gICAgICBjb25zdCBjdHggPSByZXEuaGFuZGxlckNvbnRleHQgYXMgSGFuZGxlckNvbnRleHQ7XG4gICAgICBjb25zdCBzbHVnID0gZ2V0U2x1ZyhjdHgucGFyYW1zKTtcbiAgICAgIGlmIChzbHVnLmluY2x1ZGVzKCcuJykpIHtcbiAgICAgICAgcmVzLnNldEhlYWRlcignY2FjaGUtY29udHJvbCcsICdwcml2YXRlJyk7XG4gICAgICAgIHJldHVybiBjdHgucmVuZGVyNDA0KCk7XG4gICAgICB9XG4gICAgICBjb25zdCBtb2RlID0gU3RyaW5nKHJlcS5xdWVyeS5wcmV2aWV3KSA9PT0gJ3RydWUnID8gJ2RyYWZ0JyA6ICdwdWJsaXNoZWQnO1xuICAgICAgY29uc3Qgcm91dGVDb250ZXh0OiBDTVNSb3V0ZUNvbnRleHQgPSB7cmVxLCBzbHVnLCBtb2RlLCBjbXNDbGllbnR9O1xuXG4gICAgICBmdW5jdGlvbiBnZXRMb2NhbGUoZG9jOiBDTVNEb2MpIHtcbiAgICAgICAgY29uc3QgZG9jTG9jYWxlcyA9IGRvYy5zeXM/LmxvY2FsZXMgfHwgWydlbiddO1xuICAgICAgICBsZXQgbG9jYWxlID0gY3R4LnJvdXRlLmxvY2FsZTtcbiAgICAgICAgaWYgKGN0eC5yb3V0ZS5pc0RlZmF1bHRMb2NhbGUpIHtcbiAgICAgICAgICBsb2NhbGUgPSBjdHguZ2V0UHJlZmVycmVkTG9jYWxlKGRvY0xvY2FsZXMpO1xuICAgICAgICAgIGlmIChkb2NMb2NhbGVzLmxlbmd0aCA+IDAgJiYgIWRvY0xvY2FsZXMuaW5jbHVkZXMobG9jYWxlKSkge1xuICAgICAgICAgICAgbG9jYWxlID0gZG9jTG9jYWxlc1swXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxvY2FsZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzRGF0YSA9IGF3YWl0IGdlbmVyYXRlUHJvcHMocm91dGVDb250ZXh0LCBnZXRMb2NhbGUpO1xuICAgICAgaWYgKHJlc0RhdGEubm90Rm91bmQpIHtcbiAgICAgICAgcmVzLnNldEhlYWRlcignY2FjaGUtY29udHJvbCcsICdwcml2YXRlJyk7XG4gICAgICAgIHJldHVybiBjdHgucmVuZGVyNDA0KCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHtwcm9wcywgbG9jYWxlLCB0cmFuc2xhdGlvbnN9ID0gcmVzRGF0YTtcblxuICAgICAgaWYgKHByb3BzLiRyZWRpcmVjdCkge1xuICAgICAgICBjb25zdCByZWRpcmVjdENvZGUgPSBwcm9wcy4kcmVkaXJlY3RDb2RlIHx8IDMwMjtcbiAgICAgICAgY29uc29sZS5sb2coYHJlZGlyZWN0aW5nIHRvOiAke3Byb3BzLiRyZWRpcmVjdH0gKCR7cmVkaXJlY3RDb2RlfSlgKTtcbiAgICAgICAgcmVkaXJlY3RXaXRoUXVlcnkocmVxLCByZXMsIHJlZGlyZWN0Q29kZSwgcHJvcHMuJHJlZGlyZWN0KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy5kaXNhYmxlQ2FjaGVDb250cm9sKSB7XG4gICAgICAgIHJlcy5zZXRIZWFkZXIoJ2NhY2hlLWNvbnRyb2wnLCAncHJpdmF0ZScpO1xuICAgICAgfSBlbHNlIGlmIChtb2RlID09PSAncHVibGlzaGVkJykge1xuICAgICAgICByZXMuc2V0SGVhZGVyKCdjYWNoZS1jb250cm9sJywgJ3B1YmxpYywgbWF4LWFnZT0xNSwgcy1tYXhhZ2U9MzAnKTtcbiAgICAgICAgaWYgKGN0eC5yb3V0ZS5pc0RlZmF1bHRMb2NhbGUpIHtcbiAgICAgICAgICByZXMuc2V0SGVhZGVyKCd2YXJ5JywgJ2FjY2VwdC1sYW5ndWFnZSwgeC1jb3VudHJ5LWNvZGUnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKG9wdGlvbnMuc2V0UmVzcG9uc2VIZWFkZXJzKSB7XG4gICAgICAgIG9wdGlvbnMuc2V0UmVzcG9uc2VIZWFkZXJzKHJlcSwgcmVzKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjdHgucmVuZGVyKHByb3BzLCB7bG9jYWxlLCB0cmFuc2xhdGlvbnN9KTtcbiAgICB9LFxuICB9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZVByb21pc2VzTWFwKFxuICBwcm9taXNlc01hcDogUmVjb3JkPHN0cmluZywgUHJvbWlzZTxhbnk+PlxuKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhwcm9taXNlc01hcCk7XG4gIGNvbnN0IHByb21pc2VzID0gT2JqZWN0LnZhbHVlcyhwcm9taXNlc01hcCk7XG4gIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gIGNvbnN0IHJlc3VsdE1hcDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICBrZXlzLmZvckVhY2goKGtleSwgaW5kZXgpID0+IHtcbiAgICByZXN1bHRNYXBba2V5XSA9IHJlc3VsdHNbaW5kZXhdO1xuICB9KTtcbiAgcmV0dXJuIHJlc3VsdE1hcDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBmaXJzdCBxdWVyeSBwYXJhbSB2YWx1ZSBpbiBhIGdpdmVuIHJlcXVlc3QuXG4gKlxuICogRm9yIGV4YW1wbGUsIGZvciBhIFVSTCBsaWtlIGAvP2Zvbz1iYXImZm9vPWJhemAsIGNhbGxpbmdcbiAqIGBnZXRGaXJzdFF1ZXJ5UGFyYW0ocmVxLCAnZm9vJylgIHdvdWxkIHJldHVybiBgXCJiYXJcImAuXG4gKi9cbmZ1bmN0aW9uIGdldEZpcnN0UXVlcnlQYXJhbShyZXE6IFJlcXVlc3QsIGtleTogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGNvbnN0IHZhbCA9IHJlcS5xdWVyeVtrZXldO1xuICBpZiAodmFsID09PSBudWxsIHx8IHZhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgaWYgKEFycmF5LmlzQXJyYXkodmFsKSkge1xuICAgIGlmICh2YWwubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIFN0cmluZyh2YWxbMF0pO1xuICB9XG4gIHJldHVybiBTdHJpbmcodmFsKTtcbn1cblxuLyoqXG4gKiBJc3N1ZXMgYW4gSFRUUCByZWRpcmVjdCwgcHJlc2VydmluZyBhbnkgcXVlcnkgcGFyYW1zIGZyb20gdGhlIG9yaWdpbmFsIHJlcS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZGlyZWN0V2l0aFF1ZXJ5KFxuICByZXE6IFJlcXVlc3QsXG4gIHJlczogUmVzcG9uc2UsXG4gIHJlZGlyZWN0Q29kZTogbnVtYmVyLFxuICByZWRpcmVjdFBhdGg6IHN0cmluZ1xuKSB7XG4gIC8vIE9ubHkgcHJlc2VydmUgcXVlcnkgcGFyYW1zIGZvciByZWxhdGl2ZSB1cmxzLlxuICBpZiAoIXJlZGlyZWN0UGF0aC5zdGFydHNXaXRoKCcvJykpIHtcbiAgICByZXMucmVkaXJlY3QocmVkaXJlY3RDb2RlLCByZWRpcmVjdFBhdGgpO1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBxdWVyeVN0ciA9IGdldFF1ZXJ5U3RyKHJlcSk7XG4gIGNvbnN0IHJlZGlyZWN0VXJsID0gcXVlcnlTdHIgPyBgJHtyZWRpcmVjdFBhdGh9PyR7cXVlcnlTdHJ9YCA6IHJlZGlyZWN0UGF0aDtcbiAgcmVzLnJlZGlyZWN0KHJlZGlyZWN0Q29kZSwgcmVkaXJlY3RVcmwpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHF1ZXJ5IHN0cmluZyBmb3IgYSByZXF1ZXN0LCBvciBlbXB0eSBzdHJpbmcgaWYgbm8gcXVlcnkuXG4gKi9cbmZ1bmN0aW9uIGdldFF1ZXJ5U3RyKHJlcTogUmVxdWVzdCk6IHN0cmluZyB7XG4gIGNvbnN0IHFJbmRleCA9IHJlcS5vcmlnaW5hbFVybC5pbmRleE9mKCc/Jyk7XG4gIGlmIChxSW5kZXggPT09IC0xKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG4gIHJldHVybiByZXEub3JpZ2luYWxVcmwuc2xpY2UocUluZGV4ICsgMSk7XG59XG4iLCAiLyoqIEBkZXByZWNhdGVkIFVzZSBjbGllbnQudHMgaW5zdGVhZC4gKi9cblxuaW1wb3J0IHtSb290Q29uZmlnfSBmcm9tICdAYmxpbmtrL3Jvb3QnO1xuaW1wb3J0IHtGaWVsZFZhbHVlLCBRdWVyeSwgVGltZXN0YW1wfSBmcm9tICdmaXJlYmFzZS1hZG1pbi9maXJlc3RvcmUnO1xuaW1wb3J0IHtcbiAgTG9hZFRyYW5zbGF0aW9uc09wdGlvbnMsXG4gIExvY2FsZVRyYW5zbGF0aW9ucyxcbiAgVHJhbnNsYXRpb24sXG4gIFRyYW5zbGF0aW9uc01hcCxcbiAgZ2V0Q21zUGx1Z2luLFxuICB0cmFuc2xhdGlvbnNGb3JMb2NhbGUsXG4gIHVubWFyc2hhbERhdGEsXG59IGZyb20gJy4vY2xpZW50LmpzJztcblxuLyoqXG4gKiBSZXRyaWV2ZXMgYSBkb2MgZnJvbSBSb290LmpzIENNUy5cbiAqIEBkZXByZWNhdGVkIFVzZSBSb290Q01TQ2xpZW50LmdldERvYygpIGluc3RlYWQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXREb2M8VD4oXG4gIHJvb3RDb25maWc6IFJvb3RDb25maWcsXG4gIGNvbGxlY3Rpb25JZDogc3RyaW5nLFxuICBzbHVnOiBzdHJpbmcsXG4gIG9wdGlvbnM6IHtcbiAgICBtb2RlOiAnZHJhZnQnIHwgJ3B1Ymxpc2hlZCc7XG4gIH1cbik6IFByb21pc2U8VCB8IG51bGw+IHtcbiAgY29uc3QgY21zUGx1Z2luID0gZ2V0Q21zUGx1Z2luKHJvb3RDb25maWcpO1xuICBjb25zdCBjbXNQbHVnaW5PcHRpb25zID0gY21zUGx1Z2luLmdldENvbmZpZygpO1xuICBjb25zdCBwcm9qZWN0SWQgPSBjbXNQbHVnaW5PcHRpb25zLmlkIHx8ICdkZWZhdWx0JztcbiAgY29uc3QgbW9kZSA9IG9wdGlvbnMubW9kZTtcbiAgY29uc3QgbW9kZUNvbGxlY3Rpb24gPSBtb2RlID09PSAnZHJhZnQnID8gJ0RyYWZ0cycgOiAnUHVibGlzaGVkJztcbiAgY29uc3QgZGIgPSBjbXNQbHVnaW4uZ2V0RmlyZXN0b3JlKCk7XG4gIC8vIFNsdWdzIHdpdGggc2xhc2hlcyBhcmUgZW5jb2RlZCBhcyBgLS1gIGluIHRoZSBEQi5cbiAgc2x1ZyA9IHNsdWcucmVwbGFjZUFsbCgnLycsICctLScpO1xuICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHtwcm9qZWN0SWR9L0NvbGxlY3Rpb25zLyR7Y29sbGVjdGlvbklkfS8ke21vZGVDb2xsZWN0aW9ufS8ke3NsdWd9YDtcbiAgY29uc3QgZG9jUmVmID0gZGIuZG9jKGRiUGF0aCk7XG4gIGNvbnN0IGRvYyA9IGF3YWl0IGRvY1JlZi5nZXQoKTtcbiAgaWYgKGRvYy5leGlzdHMpIHtcbiAgICBjb25zdCBkYXRhID0gZG9jLmRhdGEoKTtcbiAgICByZXR1cm4gdW5tYXJzaGFsRGF0YShkYXRhKSBhcyBUO1xuICB9XG4gIGNvbnNvbGUubG9nKGBkb2Mgbm90IGZvdW5kOiAke2RiUGF0aH1gKTtcbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogTGlzdHMgZG9jcyBmcm9tIGEgUm9vdC5qcyBDTVMgY29sbGVjdGlvbi5cbiAqIEBkZXByZWNhdGVkIFVzZSBSb290Q01TQ2xpZW50Lmxpc3REb2NzKCkgaW5zdGVhZC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxpc3REb2NzPFQ+KFxuICByb290Q29uZmlnOiBSb290Q29uZmlnLFxuICBjb2xsZWN0aW9uSWQ6IHN0cmluZyxcbiAgb3B0aW9uczoge1xuICAgIG1vZGU6ICdkcmFmdCcgfCAncHVibGlzaGVkJztcbiAgICBvZmZzZXQ/OiBudW1iZXI7XG4gICAgbGltaXQ/OiBudW1iZXI7XG4gICAgb3JkZXJCeT86IHN0cmluZztcbiAgICBvcmRlckJ5RGlyZWN0aW9uPzogJ2FzYycgfCAnZGVzYyc7XG4gICAgcXVlcnk/OiAocXVlcnk6IFF1ZXJ5KSA9PiBRdWVyeTtcbiAgfVxuKTogUHJvbWlzZTx7ZG9jczogVFtdfT4ge1xuICBjb25zdCBjbXNQbHVnaW4gPSBnZXRDbXNQbHVnaW4ocm9vdENvbmZpZyk7XG4gIGNvbnN0IGNtc1BsdWdpbk9wdGlvbnMgPSBjbXNQbHVnaW4uZ2V0Q29uZmlnKCk7XG4gIGNvbnN0IHByb2plY3RJZCA9IGNtc1BsdWdpbk9wdGlvbnMuaWQgfHwgJ2RlZmF1bHQnO1xuICBjb25zdCBtb2RlID0gb3B0aW9ucy5tb2RlO1xuICBjb25zdCBtb2RlQ29sbGVjdGlvbiA9IG1vZGUgPT09ICdkcmFmdCcgPyAnRHJhZnRzJyA6ICdQdWJsaXNoZWQnO1xuICBjb25zdCBkYiA9IGNtc1BsdWdpbi5nZXRGaXJlc3RvcmUoKTtcbiAgY29uc3QgZGJQYXRoID0gYFByb2plY3RzLyR7cHJvamVjdElkfS9Db2xsZWN0aW9ucy8ke2NvbGxlY3Rpb25JZH0vJHttb2RlQ29sbGVjdGlvbn1gO1xuICBsZXQgcXVlcnk6IFF1ZXJ5ID0gZGIuY29sbGVjdGlvbihkYlBhdGgpO1xuICBpZiAob3B0aW9ucy5saW1pdCkge1xuICAgIHF1ZXJ5ID0gcXVlcnkubGltaXQob3B0aW9ucy5saW1pdCk7XG4gIH1cbiAgaWYgKG9wdGlvbnMub2Zmc2V0KSB7XG4gICAgcXVlcnkgPSBxdWVyeS5vZmZzZXQob3B0aW9ucy5vZmZzZXQpO1xuICB9XG4gIGlmIChvcHRpb25zLm9yZGVyQnkpIHtcbiAgICBxdWVyeSA9IHF1ZXJ5Lm9yZGVyQnkob3B0aW9ucy5vcmRlckJ5LCBvcHRpb25zLm9yZGVyQnlEaXJlY3Rpb24pO1xuICB9XG4gIGlmIChvcHRpb25zLnF1ZXJ5KSB7XG4gICAgcXVlcnkgPSBvcHRpb25zLnF1ZXJ5KHF1ZXJ5KTtcbiAgfVxuICBjb25zdCByZXN1bHRzID0gYXdhaXQgcXVlcnkuZ2V0KCk7XG4gIGNvbnN0IGRvY3M6IFRbXSA9IFtdO1xuICByZXN1bHRzLmZvckVhY2goKHJlc3VsdCkgPT4ge1xuICAgIGNvbnN0IGRvYyA9IHVubWFyc2hhbERhdGEocmVzdWx0LmRhdGEoKSkgYXMgVDtcbiAgICBkb2NzLnB1c2goZG9jKTtcbiAgfSk7XG4gIHJldHVybiB7ZG9jc307XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGRvY3MgaW4gYSBSb290LmpzIENNUyBjb2xsZWN0aW9uLlxuICogQGRlcHJlY2F0ZWQgVXNlIFJvb3RDTVNDbGllbnQuZ2V0RG9jc0NvdW50KCkgaW5zdGVhZC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG51bURvY3MoXG4gIHJvb3RDb25maWc6IFJvb3RDb25maWcsXG4gIGNvbGxlY3Rpb25JZDogc3RyaW5nLFxuICBvcHRpb25zOiB7XG4gICAgbW9kZTogJ2RyYWZ0JyB8ICdwdWJsaXNoZWQnO1xuICAgIHF1ZXJ5PzogKHF1ZXJ5OiBRdWVyeSkgPT4gUXVlcnk7XG4gIH1cbikge1xuICBjb25zdCBjbXNQbHVnaW4gPSBnZXRDbXNQbHVnaW4ocm9vdENvbmZpZyk7XG4gIGNvbnN0IGNtc1BsdWdpbk9wdGlvbnMgPSBjbXNQbHVnaW4uZ2V0Q29uZmlnKCk7XG4gIGNvbnN0IHByb2plY3RJZCA9IGNtc1BsdWdpbk9wdGlvbnMuaWQgfHwgJ2RlZmF1bHQnO1xuICBjb25zdCBtb2RlID0gb3B0aW9ucy5tb2RlO1xuICBjb25zdCBtb2RlQ29sbGVjdGlvbiA9IG1vZGUgPT09ICdkcmFmdCcgPyAnRHJhZnRzJyA6ICdQdWJsaXNoZWQnO1xuICBjb25zdCBkYiA9IGNtc1BsdWdpbi5nZXRGaXJlc3RvcmUoKTtcbiAgY29uc3QgZGJQYXRoID0gYFByb2plY3RzLyR7cHJvamVjdElkfS9Db2xsZWN0aW9ucy8ke2NvbGxlY3Rpb25JZH0vJHttb2RlQ29sbGVjdGlvbn1gO1xuICBsZXQgcXVlcnk6IFF1ZXJ5ID0gZGIuY29sbGVjdGlvbihkYlBhdGgpO1xuICBpZiAob3B0aW9ucy5xdWVyeSkge1xuICAgIHF1ZXJ5ID0gb3B0aW9ucy5xdWVyeShxdWVyeSk7XG4gIH1cbiAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHF1ZXJ5LmNvdW50KCkuZ2V0KCk7XG4gIGNvbnN0IGNvdW50ID0gcmVzdWx0cy5kYXRhKCkuY291bnQ7XG4gIHJldHVybiBjb3VudDtcbn1cblxuLyoqXG4gKiBQdWJsaXNoZXMgc2NoZWR1bGVkIGRvY3MuXG4gKiBAZGVwcmVjYXRlZCBVc2UgUm9vdENNU0NsaWVudC5wdWJsaXNoU2NoZWR1bGVkRG9jcygpIGluc3RlYWQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwdWJsaXNoU2NoZWR1bGVkRG9jcyhyb290Q29uZmlnOiBSb290Q29uZmlnKSB7XG4gIGNvbnN0IGNtc1BsdWdpbiA9IGdldENtc1BsdWdpbihyb290Q29uZmlnKTtcbiAgY29uc3QgY21zUGx1Z2luT3B0aW9ucyA9IGNtc1BsdWdpbi5nZXRDb25maWcoKTtcbiAgY29uc3QgcHJvamVjdElkID0gY21zUGx1Z2luT3B0aW9ucy5pZCB8fCAnZGVmYXVsdCc7XG4gIGNvbnN0IGRiID0gY21zUGx1Z2luLmdldEZpcmVzdG9yZSgpO1xuXG4gIGNvbnN0IHByb2plY3RDb2xsZWN0aW9uc1BhdGggPSBgUHJvamVjdHMvJHtwcm9qZWN0SWR9L0NvbGxlY3Rpb25zYDtcbiAgY29uc3Qgbm93ID0gTWF0aC5jZWlsKG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcblxuICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IGRiLmNvbGxlY3Rpb25Hcm91cCgnU2NoZWR1bGVkJykuZ2V0KCk7XG4gIGNvbnN0IGRvY3MgPSBzbmFwc2hvdC5kb2NzXG4gICAgLmZpbHRlcigoZCkgPT4ge1xuICAgICAgLy8gRmlsdGVyIGRvY3MgYnkgcHJvamVjdC5cbiAgICAgIGlmICghZC5yZWYucGF0aC5zdGFydHNXaXRoKHByb2plY3RDb2xsZWN0aW9uc1BhdGgpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIC8vIEZpbHRlciBkb2NzIHdoZXJlIHNjaGVkdWxlZEF0IGlzIGluIHRoZSBwYXN0LlxuICAgICAgLy8gTk9URShzdGV2ZW5sZSk6IHRoZSBmaWx0ZXJpbmcgaXMgZG9uZSBtYW51YWxseSBpbnN0ZWFkIG9mIHVzaW5nIGEgcXVlcnlcbiAgICAgIC8vIHRvIGF2b2lkIGhhdmluZyB0byBjcmVhdGUgYW4gaW5kZXggaW4gZmlyZXN0b3JlLlxuICAgICAgY29uc3QgZGF0YSA9IGQuZGF0YSgpIHx8IHt9O1xuICAgICAgY29uc3Qgc2NoZWR1bGVkQXQ6IFRpbWVzdGFtcCB8IHVuZGVmaW5lZCA9IGRhdGEuc3lzPy5zY2hlZHVsZWRBdDtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIHNjaGVkdWxlZEF0ICYmIHNjaGVkdWxlZEF0LnRvTWlsbGlzICYmIHNjaGVkdWxlZEF0LnRvTWlsbGlzKCkgPD0gbm93XG4gICAgICApO1xuICAgIH0pXG4gICAgLm1hcCgoZCkgPT4ge1xuICAgICAgY29uc3QgZGJQYXRoID0gZC5yZWYucGF0aDtcbiAgICAgIGNvbnN0IHNlZ21lbnRzID0gZGJQYXRoLnNwbGl0KCcvJyk7XG4gICAgICBjb25zdCBzbHVnID0gc2VnbWVudHMuYXQoLTEpO1xuICAgICAgY29uc3QgY29sbGVjdGlvbiA9IHNlZ21lbnRzLmF0KC0zKTtcbiAgICAgIGNvbnN0IGlkID0gYCR7Y29sbGVjdGlvbn0vJHtzbHVnfWA7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBkYXRhOiBkLmRhdGEoKSxcbiAgICAgICAgaWQsXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIHNsdWcsXG4gICAgICB9O1xuICAgIH0pO1xuXG4gIGlmIChkb2NzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIC8vIEVhY2ggdHJhbnNhY3Rpb24gb3IgYmF0Y2ggY2FuIHdyaXRlIGEgbWF4IG9mIDUwMCBvcHMuXG4gIC8vIGh0dHBzOi8vZmlyZWJhc2UuZ29vZ2xlLmNvbS9kb2NzL2ZpcmVzdG9yZS9tYW5hZ2UtZGF0YS90cmFuc2FjdGlvbnNcbiAgbGV0IGJhdGNoQ291bnQgPSAwO1xuICBjb25zdCBiYXRjaCA9IGRiLmJhdGNoKCk7XG4gIGNvbnN0IHB1Ymxpc2hlZERvY3M6IGFueVtdID0gW107XG4gIGZvciAoY29uc3QgZG9jIG9mIGRvY3MpIHtcbiAgICBjb25zdCB7aWQsIGNvbGxlY3Rpb24sIHNsdWcsIGRhdGF9ID0gZG9jO1xuICAgIGNvbnN0IGRyYWZ0UmVmID0gZGIuZG9jKFxuICAgICAgYCR7cHJvamVjdENvbGxlY3Rpb25zUGF0aH0vJHtjb2xsZWN0aW9ufS9EcmFmdHMvJHtzbHVnfWBcbiAgICApO1xuICAgIGNvbnN0IHNjaGVkdWxlZFJlZiA9IGRiLmRvYyhcbiAgICAgIGAke3Byb2plY3RDb2xsZWN0aW9uc1BhdGh9LyR7Y29sbGVjdGlvbn0vU2NoZWR1bGVkLyR7c2x1Z31gXG4gICAgKTtcbiAgICBjb25zdCBwdWJsaXNoZWRSZWYgPSBkYi5kb2MoXG4gICAgICBgJHtwcm9qZWN0Q29sbGVjdGlvbnNQYXRofS8ke2NvbGxlY3Rpb259L1B1Ymxpc2hlZC8ke3NsdWd9YFxuICAgICk7XG4gICAgY29uc3Qge3NjaGVkdWxlZEF0LCBzY2hlZHVsZWRCeSwgLi4uc3lzfSA9IGRhdGEuc3lzIHx8IHt9O1xuXG4gICAgLy8gT25seSB1cGRhdGUgYGZpcnN0UHVibGlzaGVkYCBpZiBpdCBkb2Vzbid0IGFscmVhZHkgZXhpc3QuXG4gICAgY29uc3QgZmlyc3RQdWJsaXNoZWRBdCA9IHN5cy5maXJzdFB1Ymxpc2hlZEF0ID8/IHNjaGVkdWxlZEF0O1xuICAgIGNvbnN0IGZpcnN0UHVibGlzaGVkQnkgPSBzeXMuZmlyc3RQdWJsaXNoZWRCeSA/PyAoc2NoZWR1bGVkQnkgfHwgJycpO1xuXG4gICAgLy8gU2F2ZSBwdWJsaXNoZWQgZG9jLlxuICAgIGJhdGNoLnNldChwdWJsaXNoZWRSZWYsIHtcbiAgICAgIGlkLFxuICAgICAgY29sbGVjdGlvbixcbiAgICAgIHNsdWcsXG4gICAgICBmaWVsZHM6IGRhdGEuZmllbGRzIHx8IHt9LFxuICAgICAgc3lzOiB7XG4gICAgICAgIC4uLnN5cyxcbiAgICAgICAgZmlyc3RQdWJsaXNoZWRBdDogZmlyc3RQdWJsaXNoZWRBdCxcbiAgICAgICAgZmlyc3RQdWJsaXNoZWRCeTogZmlyc3RQdWJsaXNoZWRCeSxcbiAgICAgICAgcHVibGlzaGVkQXQ6IEZpZWxkVmFsdWUuc2VydmVyVGltZXN0YW1wKCksXG4gICAgICAgIHB1Ymxpc2hlZEJ5OiBzY2hlZHVsZWRCeSB8fCAnJyxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgYmF0Y2hDb3VudCArPSAxO1xuXG4gICAgLy8gUmVtb3ZlIHB1Ymxpc2hlZCBkb2MuXG4gICAgYmF0Y2guZGVsZXRlKHNjaGVkdWxlZFJlZik7XG4gICAgYmF0Y2hDb3VudCArPSAxO1xuXG4gICAgLy8gVXBkYXRlIHRoZSBkcmFmdCBkb2MgdG8gcmVtb3ZlIGBzY2hlZHVsZWRBdGAgYW5kIGBzY2hlZHVsZWRCeWAgZmllbGRzXG4gICAgLy8gYW5kIHVwZGF0ZSB0aGUgYHB1Ymxpc2hlZEF0YCBhbmQgYHB1Ymxpc2hlZEJ5YCBmaWVsZHMuXG4gICAgYmF0Y2gudXBkYXRlKGRyYWZ0UmVmLCB7XG4gICAgICAnc3lzLnNjaGVkdWxlZEF0JzogRmllbGRWYWx1ZS5kZWxldGUoKSxcbiAgICAgICdzeXMuc2NoZWR1bGVkQnknOiBGaWVsZFZhbHVlLmRlbGV0ZSgpLFxuICAgICAgJ3N5cy5maXJzdFB1Ymxpc2hlZEF0JzogZmlyc3RQdWJsaXNoZWRBdCxcbiAgICAgICdzeXMuZmlyc3RQdWJsaXNoZWRCeSc6IGZpcnN0UHVibGlzaGVkQnksXG4gICAgICAnc3lzLnB1Ymxpc2hlZEF0JzogRmllbGRWYWx1ZS5zZXJ2ZXJUaW1lc3RhbXAoKSxcbiAgICAgICdzeXMucHVibGlzaGVkQnknOiBzY2hlZHVsZWRCeSB8fCAnJyxcbiAgICB9KTtcbiAgICBiYXRjaENvdW50ICs9IDE7XG5cbiAgICBwdWJsaXNoZWREb2NzLnB1c2goZG9jKTtcblxuICAgIGlmIChiYXRjaENvdW50ID49IDQ5OCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgYXdhaXQgYmF0Y2guY29tbWl0KCk7XG4gIGNvbnNvbGUubG9nKGBwdWJsaXNoZWQgJHtwdWJsaXNoZWREb2NzLmxlbmd0aH0gZG9jcyFgKTtcbiAgcmV0dXJuIHB1Ymxpc2hlZERvY3M7XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWQgVXNlIGBSb290Q01TQ2xpZW50LmxvYWRUcmFuc2xhdGlvbnMoKWAuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsb2FkVHJhbnNsYXRpb25zKFxuICByb290Q29uZmlnOiBSb290Q29uZmlnLFxuICBvcHRpb25zPzogTG9hZFRyYW5zbGF0aW9uc09wdGlvbnNcbik6IFByb21pc2U8VHJhbnNsYXRpb25zTWFwPiB7XG4gIGNvbnN0IGNtc1BsdWdpbiA9IGdldENtc1BsdWdpbihyb290Q29uZmlnKTtcbiAgY29uc3QgY21zUGx1Z2luT3B0aW9ucyA9IGNtc1BsdWdpbi5nZXRDb25maWcoKTtcbiAgY29uc3QgcHJvamVjdElkID0gY21zUGx1Z2luT3B0aW9ucy5pZCB8fCAnZGVmYXVsdCc7XG4gIGNvbnN0IGRiID0gY21zUGx1Z2luLmdldEZpcmVzdG9yZSgpO1xuXG4gIGNvbnN0IGRiUGF0aCA9IGBQcm9qZWN0cy8ke3Byb2plY3RJZH0vVHJhbnNsYXRpb25zYDtcbiAgbGV0IHF1ZXJ5OiBRdWVyeSA9IGRiLmNvbGxlY3Rpb24oZGJQYXRoKTtcbiAgaWYgKG9wdGlvbnM/LnRhZ3MpIHtcbiAgICBxdWVyeSA9IHF1ZXJ5LndoZXJlKCd0YWdzJywgJ2FycmF5LWNvbnRhaW5zLWFueScsIG9wdGlvbnMudGFncyk7XG4gIH1cblxuICBjb25zdCBxdWVyeVNuYXBzaG90ID0gYXdhaXQgcXVlcnkuZ2V0KCk7XG4gIGNvbnN0IHRyYW5zbGF0aW9uc01hcDogVHJhbnNsYXRpb25zTWFwID0ge307XG4gIHF1ZXJ5U25hcHNob3QuZm9yRWFjaCgoZG9jKSA9PiB7XG4gICAgY29uc3QgaGFzaCA9IGRvYy5pZDtcbiAgICB0cmFuc2xhdGlvbnNNYXBbaGFzaF0gPSBkb2MuZGF0YSgpIGFzIFRyYW5zbGF0aW9uO1xuICB9KTtcbiAgcmV0dXJuIHRyYW5zbGF0aW9uc01hcDtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZCBVc2UgYFJvb3RDTVNDbGllbnQubG9hZFRyYW5zbGF0aW9uc0ZvckxvY2FsZSgpYC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxvYWRUcmFuc2xhdGlvbnNGb3JMb2NhbGUoXG4gIHJvb3RDb25maWc6IFJvb3RDb25maWcsXG4gIGxvY2FsZTogc3RyaW5nLFxuICBvcHRpb25zPzogTG9hZFRyYW5zbGF0aW9uc09wdGlvbnNcbik6IFByb21pc2U8TG9jYWxlVHJhbnNsYXRpb25zPiB7XG4gIGNvbnN0IHRyYW5zbGF0aW9uc01hcCA9IGF3YWl0IGxvYWRUcmFuc2xhdGlvbnMocm9vdENvbmZpZywgb3B0aW9ucyk7XG4gIHJldHVybiB0cmFuc2xhdGlvbnNGb3JMb2NhbGUodHJhbnNsYXRpb25zTWFwLCBsb2NhbGUpO1xufVxuIiwgImltcG9ydCB7RnVuY3Rpb25hbENvbXBvbmVudH0gZnJvbSAncHJlYWN0JztcblxuZXhwb3J0IGludGVyZmFjZSBDb21tb25GaWVsZFByb3BzIHtcbiAgdHlwZTogc3RyaW5nO1xuICBpZD86IHN0cmluZztcbiAgbGFiZWw/OiBzdHJpbmc7XG4gIGhlbHA/OiBzdHJpbmc7XG4gIHBsYWNlaG9sZGVyPzogc3RyaW5nO1xuICBkZWZhdWx0PzogYW55O1xuICBoaWRkZW4/OiBib29sZWFuO1xuICBkZXByZWNhdGVkPzogYm9vbGVhbjtcbiAgLyoqIEhpZGVzIHRoZSBmaWVsZCBsYWJlbCBpbiB0aGUgQ01TIFVJLiAqL1xuICBoaWRlTGFiZWw/OiBib29sZWFuO1xufVxuXG5leHBvcnQgdHlwZSBTdHJpbmdGaWVsZCA9IENvbW1vbkZpZWxkUHJvcHMgJiB7XG4gIHR5cGU6ICdzdHJpbmcnO1xuICBkZWZhdWx0Pzogc3RyaW5nO1xuICB0cmFuc2xhdGU/OiBib29sZWFuO1xuICB2YXJpYW50PzogJ2lucHV0JyB8ICd0ZXh0YXJlYSc7XG4gIC8qKiBGb3IgdGV4dGFyZWEgdmFyaWFudCwgdGhlIG1heGltdW0gbnVtYmVyIG9mIHJvd3Mgb2YgdGV4dCB0byBzaG93LiAqL1xuICBtYXhSb3dzPzogbnVtYmVyO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIHN0cmluZyhmaWVsZDogT21pdDxTdHJpbmdGaWVsZCwgJ3R5cGUnPik6IFN0cmluZ0ZpZWxkIHtcbiAgcmV0dXJuIHsuLi5maWVsZCwgdHlwZTogJ3N0cmluZyd9O1xufVxuXG5leHBvcnQgdHlwZSBOdW1iZXJGaWVsZCA9IENvbW1vbkZpZWxkUHJvcHMgJiB7XG4gIHR5cGU6ICdudW1iZXInO1xuICBkZWZhdWx0PzogbnVtYmVyO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIG51bWJlcihmaWVsZDogT21pdDxOdW1iZXJGaWVsZCwgJ3R5cGUnPik6IE51bWJlckZpZWxkIHtcbiAgcmV0dXJuIHsuLi5maWVsZCwgdHlwZTogJ251bWJlcid9O1xufVxuXG5leHBvcnQgdHlwZSBEYXRlRmllbGQgPSBDb21tb25GaWVsZFByb3BzICYge1xuICB0eXBlOiAnZGF0ZSc7XG4gIGRlZmF1bHQ/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZGF0ZShmaWVsZDogT21pdDxEYXRlRmllbGQsICd0eXBlJz4pOiBEYXRlRmllbGQge1xuICByZXR1cm4gey4uLmZpZWxkLCB0eXBlOiAnZGF0ZSd9O1xufVxuXG5leHBvcnQgdHlwZSBEYXRlVGltZUZpZWxkID0gQ29tbW9uRmllbGRQcm9wcyAmIHtcbiAgdHlwZTogJ2RhdGV0aW1lJztcbiAgZGVmYXVsdD86IHN0cmluZztcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBkYXRldGltZShmaWVsZDogT21pdDxEYXRlVGltZUZpZWxkLCAndHlwZSc+KTogRGF0ZVRpbWVGaWVsZCB7XG4gIHJldHVybiB7Li4uZmllbGQsIHR5cGU6ICdkYXRldGltZSd9O1xufVxuXG5leHBvcnQgdHlwZSBCb29sZWFuRmllbGQgPSBDb21tb25GaWVsZFByb3BzICYge1xuICB0eXBlOiAnYm9vbGVhbic7XG4gIGRlZmF1bHQ/OiBib29sZWFuO1xuICBjaGVja2JveExhYmVsPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGJvb2xlYW4oZmllbGQ6IE9taXQ8Qm9vbGVhbkZpZWxkLCAndHlwZSc+KTogQm9vbGVhbkZpZWxkIHtcbiAgcmV0dXJuIHsuLi5maWVsZCwgdHlwZTogJ2Jvb2xlYW4nfTtcbn1cblxuZXhwb3J0IHR5cGUgU2VsZWN0RmllbGQgPSBDb21tb25GaWVsZFByb3BzICYge1xuICB0eXBlOiAnc2VsZWN0JztcbiAgZGVmYXVsdD86IHN0cmluZztcbiAgb3B0aW9ucz86IEFycmF5PHt2YWx1ZTogc3RyaW5nOyBsYWJlbD86IHN0cmluZ30+IHwgc3RyaW5nW107XG4gIHRyYW5zbGF0ZT86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gc2VsZWN0KGZpZWxkOiBPbWl0PFNlbGVjdEZpZWxkLCAndHlwZSc+KTogU2VsZWN0RmllbGQge1xuICByZXR1cm4gey4uLmZpZWxkLCB0eXBlOiAnc2VsZWN0J307XG59XG5cbmV4cG9ydCB0eXBlIE11bHRpU2VsZWN0RmllbGQgPSBPbWl0PFNlbGVjdEZpZWxkLCAndHlwZSc+ICYge1xuICB0eXBlOiAnbXVsdGlzZWxlY3QnO1xuICAvKiogU2V0IHRvIGB0cnVlYCB0byBhbGxvdyB1c2VycyB0byBjcmVhdGUgYXJiaXRyYXJ5IHZhbHVlcy4gKi9cbiAgY3JlYXRhYmxlPzogYm9vbGVhbjtcbiAgdHJhbnNsYXRlPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBtdWx0aXNlbGVjdChcbiAgZmllbGQ6IE9taXQ8TXVsdGlTZWxlY3RGaWVsZCwgJ3R5cGUnPlxuKTogTXVsdGlTZWxlY3RGaWVsZCB7XG4gIHJldHVybiB7Li4uZmllbGQsIHR5cGU6ICdtdWx0aXNlbGVjdCd9O1xufVxuXG5leHBvcnQgdHlwZSBJbWFnZUZpZWxkID0gQ29tbW9uRmllbGRQcm9wcyAmIHtcbiAgdHlwZTogJ2ltYWdlJztcbiAgdHJhbnNsYXRlPzogYm9vbGVhbjtcbiAgLyoqIExpc3Qgb2Ygc3VwcG9ydGVkIGV4dHMsIGUuZy4gYFsnLm1wNCddYC4gKi9cbiAgZXh0cz86IHN0cmluZ1tdO1xuICAvKipcbiAgICogQ2FjaGUtY29udHJvbCBoZWFkZXIgdG8gc2V0IG9uIHRoZSBHQ1Mgb2JqZWN0LlxuICAgKi9cbiAgY2FjaGVDb250cm9sPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGltYWdlKGZpZWxkOiBPbWl0PEltYWdlRmllbGQsICd0eXBlJz4pOiBJbWFnZUZpZWxkIHtcbiAgcmV0dXJuIHsuLi5maWVsZCwgdHlwZTogJ2ltYWdlJ307XG59XG5cbmV4cG9ydCB0eXBlIEZpbGVGaWVsZCA9IENvbW1vbkZpZWxkUHJvcHMgJiB7XG4gIHR5cGU6ICdmaWxlJztcbiAgLyoqIExpc3Qgb2Ygc3VwcG9ydGVkIGV4dHMsIGUuZy4gYFsnLm1wNCddYC4gKi9cbiAgZXh0cz86IHN0cmluZ1tdO1xuICAvKipcbiAgICogV2hldGhlciB0byBwcmVzZXJ2ZSB0aGUgZmluYWwgc2VydmluZyBmaWxlbmFtZSB3aGVuIGEgdXNlciB1cGxvYWRzIGEgZmlsZS5cbiAgICogQnkgZGVmYXVsdCwgdGhlIGZpbGVuYW1lIGlzIGhhc2hlZCBmb3Igb2JmdXNjYXRpb24gcHVycG9zZXMuXG4gICAqL1xuICBwcmVzZXJ2ZUZpbGVuYW1lPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIENhY2hlLWNvbnRyb2wgaGVhZGVyIHRvIHNldCBvbiB0aGUgR0NTIG9iamVjdC5cbiAgICovXG4gIGNhY2hlQ29udHJvbD86IHN0cmluZztcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBmaWxlKGZpZWxkOiBPbWl0PEZpbGVGaWVsZCwgJ3R5cGUnPik6IEZpbGVGaWVsZCB7XG4gIHJldHVybiB7Li4uZmllbGQsIHR5cGU6ICdmaWxlJ307XG59XG5cbmV4cG9ydCB0eXBlIE9iamVjdEZpZWxkID0gQ29tbW9uRmllbGRQcm9wcyAmIHtcbiAgdHlwZTogJ29iamVjdCc7XG4gIGZpZWxkczogRmllbGRXaXRoSWRbXTtcbiAgLyoqIERlZmF1bHRzIHRvIFwiZHJhd2VyXCIuICovXG4gIHZhcmlhbnQ/OiAnZHJhd2VyJyB8ICdpbmxpbmUnO1xuICAvKiogT3B0aW9ucyBmb3IgdGhlIFwiZHJhd2VyXCIgdmFyaWFudC4gKi9cbiAgZHJhd2VyT3B0aW9ucz86IHtcbiAgICAvKiogV2hldGhlciB0aGUgZHJhd2VyIHNob3VsZCBpbml0aWFsaXplIHRvIHRoZSBcImNvbGxhcHNlZFwiIHN0YXRlLiAqL1xuICAgIGNvbGxhcHNlZD86IGJvb2xlYW47XG4gICAgLyoqXG4gICAgICogV2hldGhlciB0byByZW5kZXIgdGhlIGRyYXdlciBcImlubGluZVwiICh0aGlzIHJlbW92ZXMgYm9yZGVycyBmcm9tIHRoZVxuICAgICAqIHRvZ2dsZSBidXR0b24pLlxuICAgICAqL1xuICAgIGlubGluZT86IGJvb2xlYW47XG4gIH07XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gb2JqZWN0KGZpZWxkOiBPbWl0PE9iamVjdEZpZWxkLCAndHlwZSc+KTogT2JqZWN0RmllbGQge1xuICByZXR1cm4gey4uLmZpZWxkLCB0eXBlOiAnb2JqZWN0J307XG59XG5cbmV4cG9ydCB0eXBlIEFycmF5RmllbGQgPSBDb21tb25GaWVsZFByb3BzICYge1xuICB0eXBlOiAnYXJyYXknO1xuICBkZWZhdWx0PzogYW55W107XG4gIC8qKlxuICAgKiBTdHJpbmcgZm9ybWF0IGZvciB0aGUgcHJldmlldyBsaW5lIG9mIGFuIGl0ZW0gaW4gdGhlIGFycmF5LiBQbGFjZWhvbGRlclxuICAgKiB2YWx1ZXMgc2hvdWxkIHVzZSBicmFja2V0cywgZS5nLiBgbXtfaW5kZXg6MDJ9OiB7X3R5cGV9YC5cbiAgICpcbiAgICogTXVsdGlwbGUgdmFsdWVzIGNhbiBiZSBwcm92aWRlZCwgaW4gd2hpY2ggY2FzZSB0aGUgZmlyc3QgcHJldmlldyBsaW5lIHdpdGhcbiAgICogbm8gbWlzc2luZyBwbGFjZWhvbGRlciB2YWx1ZXMgd2lsbCBiZSB1c2VkLlxuICAgKlxuICAgKiBTeXN0ZW0gYWRkZWQgcGxhY2Vob2xkZXIgdmFsdWVzOlxuICAgKlxuICAgKiAtIF9pbmRleDogVGhlIDAtYmFzZWQgaW5kZXguXG4gICAqIC0gX2luZGV4OjAyOiBBIGxlZnQtcGFkZGVkIHZlcnNpb24gb2YgX2luZGV4IHRvIDIgZGlnaXRzLlxuICAgKiAtIF9pbmRleDowMzogQSBsZWZ0LXBhZGRlZCB2ZXJzaW9uIG9mIF9pbmRleCB0byAzIGRpZ2l0cy5cbiAgICogLSBfdHlwZTogRm9yIGFycmF5IG9mIG9uZS1vZiBmaWVsZHMsIHRoZSB0eXBlIG9mIHRoZSBzZWxlY3RlZCBmaWVsZC5cbiAgICovXG4gIHByZXZpZXc/OiBzdHJpbmcgfCBzdHJpbmdbXTtcbiAgLy8gTk9URShzdGV2ZW5sZSk6IHRoZSBhcnJheSBmaWVsZCBzaG91bGQgb25seSBhY2NlcHQgb2JqZWN0IHZhbHVlcyB0byBrZWVwXG4gIC8vIHRoZSBzY2hlbWFzIGZ1dHVyZS1mcmllbmRseS4gRm9yIGV4YW1wbGUsIGlmIHdlIHdlcmUgdG8gYWNjZXB0IHByaW1hdGl2ZXNcbiAgLy8gKGUuZy4gQXJyYXk8c3RyaW5nPikgYW5kIHRoZSBkZXZlbG9wZXIgZGVjaWRlcyBpbiB0aGUgZnV0dXJlIHRoYXQgdGhleVxuICAvLyBuZWVkIHRvIGFkZCBleHRyYSBmaWVsZHMgdG8gdGhhdCBhcnJheSB0eXBlLCB0aGV5IHdvdWxkIGhhdmUgdG8gY3JlYXRlIGFcbiAgLy8gbmV3IGZpZWxkLCBjcmVhdGUgYSBuZXcgc2NoZW1hIGZpZWxkLCBhbmQgdGhlbiBwZXJmb3JtIGEgZGIgbWlncmF0aW9uIHRvXG4gIC8vIHVwZGF0ZSBmcm9tIHRoZSBvbGQgZmllbGQgdHlwZSB0byB0aGUgbmV3IGZpZWxkIHR5cGUuIEJ1dCBpZiB3ZSBlbmZvcmNlXG4gIC8vIG9iamVjdHMgaGVyZSwgYSBkZXZlbG9wZXIgc2hvdWxkIHRlY2huaWNhbGx5IGJlIGFibGUgdG8gYWRkIGZpZWxkcyB0byB0aGVcbiAgLy8gbmVzdGVkIGZpZWxkIGRlZmluaXRpb24gd2l0aG91dCBicmVha2luZyBhbnkgZXhpc3RpbmcgZGIgZW50cmllcy5cbiAgb2Y6IE9iamVjdExpa2VGaWVsZDtcbiAgLyoqXG4gICAqIExhYmVsIHRvIHVzZSBmb3IgdGhlIFwiYWRkIGl0ZW1cIiBidXR0b24uIERlZmF1bHRzIHRvIGBBZGRgLlxuICAgKi9cbiAgYnV0dG9uTGFiZWw/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gYXJyYXkoZmllbGQ6IE9taXQ8QXJyYXlGaWVsZCwgJ3R5cGUnPik6IEFycmF5RmllbGQge1xuICByZXR1cm4gey4uLmZpZWxkLCB0eXBlOiAnYXJyYXknfTtcbn1cblxuZXhwb3J0IHR5cGUgT25lT2ZGaWVsZCA9IENvbW1vbkZpZWxkUHJvcHMgJiB7XG4gIHR5cGU6ICdvbmVvZic7XG4gIHR5cGVzOiBTY2hlbWFbXTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBvbmVPZihmaWVsZDogT21pdDxPbmVPZkZpZWxkLCAndHlwZSc+KTogT25lT2ZGaWVsZCB7XG4gIHJldHVybiB7Li4uZmllbGQsIHR5cGU6ICdvbmVvZid9O1xufVxuXG5leHBvcnQgdHlwZSBSaWNoVGV4dEZpZWxkID0gQ29tbW9uRmllbGRQcm9wcyAmIHtcbiAgdHlwZTogJ3JpY2h0ZXh0JztcbiAgdHJhbnNsYXRlPzogYm9vbGVhbjtcbiAgcGxhY2Vob2xkZXI/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gcmljaHRleHQoZmllbGQ6IE9taXQ8UmljaFRleHRGaWVsZCwgJ3R5cGUnPik6IFJpY2hUZXh0RmllbGQge1xuICByZXR1cm4gey4uLmZpZWxkLCB0eXBlOiAncmljaHRleHQnfTtcbn1cblxuZXhwb3J0IHR5cGUgUmVmZXJlbmNlRmllbGQgPSBDb21tb25GaWVsZFByb3BzICYge1xuICB0eXBlOiAncmVmZXJlbmNlJztcbiAgLyoqIExpc3Qgb2YgY29sbGVjdGlvbiBpZHMgdGhlIHJlZmVyZW5jZSBjYW4gYmUgY2hvc2VuIGZyb20uICovXG4gIGNvbGxlY3Rpb25zPzogc3RyaW5nW107XG4gIC8qKiBJbml0aWFsIGNvbGxlY3Rpb24gdG8gc2hvdyB3aGVuIHBpY2tpbmcgYSByZWZlcmVuY2UuICovXG4gIGluaXRpYWxDb2xsZWN0aW9uPzogc3RyaW5nO1xuICAvKiogTGFiZWwgZm9yIHRoZSBidXR0b24uIERlZmF1bHRzIHRvIFwiU2VsZWN0XCIuICovXG4gIGJ1dHRvbkxhYmVsPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIHJlZmVyZW5jZShmaWVsZDogT21pdDxSZWZlcmVuY2VGaWVsZCwgJ3R5cGUnPik6IFJlZmVyZW5jZUZpZWxkIHtcbiAgcmV0dXJuIHsuLi5maWVsZCwgdHlwZTogJ3JlZmVyZW5jZSd9O1xufVxuXG5leHBvcnQgdHlwZSBGaWVsZCA9XG4gIHwgU3RyaW5nRmllbGRcbiAgfCBOdW1iZXJGaWVsZFxuICB8IERhdGVGaWVsZFxuICB8IERhdGVUaW1lRmllbGRcbiAgfCBCb29sZWFuRmllbGRcbiAgfCBTZWxlY3RGaWVsZFxuICB8IE11bHRpU2VsZWN0RmllbGRcbiAgfCBJbWFnZUZpZWxkXG4gIHwgRmlsZUZpZWxkXG4gIHwgT2JqZWN0RmllbGRcbiAgfCBBcnJheUZpZWxkXG4gIHwgT25lT2ZGaWVsZFxuICB8IFJpY2hUZXh0RmllbGRcbiAgfCBSZWZlcmVuY2VGaWVsZDtcblxuLyoqXG4gKiBTaW1pbGFyIHRvIHtAbGluayBGaWVsZH0gYnV0IHdpdGggYSByZXF1aXJlZCBgaWRgLlxuICogVE9ETyhzdGV2ZW5sZSk6IGZpeCB0aGlzLlxuICovXG5leHBvcnQgdHlwZSBGaWVsZFdpdGhJZCA9IEZpZWxkO1xuXG5leHBvcnQgdHlwZSBPYmplY3RMaWtlRmllbGQgPVxuICB8IEltYWdlRmllbGRcbiAgfCBGaWxlRmllbGRcbiAgfCBPYmplY3RGaWVsZFxuICB8IE9uZU9mRmllbGRcbiAgfCBSZWZlcmVuY2VGaWVsZDtcblxuZXhwb3J0IGludGVyZmFjZSBTY2hlbWEge1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICBmaWVsZHM6IEZpZWxkV2l0aElkW107XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWZpbmVTY2hlbWEoc2NoZW1hOiBTY2hlbWEpOiBTY2hlbWEge1xuICByZXR1cm4gc2NoZW1hO1xufVxuXG4vKiogRGVmaW5lcyB0aGUgc2NoZW1hIGZvciBhIGNvbGxlY3Rpb24gb3IgcmV1c2FibGUgY29tcG9uZW50LiAqL1xuZXhwb3J0IGNvbnN0IGRlZmluZSA9IGRlZmluZVNjaGVtYTtcblxuZXhwb3J0IHR5cGUgQ29sbGVjdGlvbiA9IFNjaGVtYSAmIHtcbiAgLyoqXG4gICAqIERvbWFpbiB3aGVyZSB0aGUgY29sbGVjdGlvbiBzZXJ2ZXMgZnJvbS4gVXNlZCBmb3IgbXVsdGktZG9tYWluIHNpdGVzLFxuICAgKiBkZWZhdWx0cyB0byB0aGUgXCJkb21haW5cIiB2YWx1ZSBgZnJvbSByb290LmNvbmZpZy50c2AuXG4gICAqL1xuICBkb21haW4/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBVUkwgcGF0aCB3aGVyZSB0aGUgY29sbGVjdGlvbiBzZXJ2ZXMgZnJvbS4gVGhpcyBpcyB3aGF0J3MgZGlzcGxheWVkIGluIHRoZVxuICAgKiBwcmV2aWV3IHBhbmUgaW4gdGhlIENNUy5cbiAgICovXG4gIHVybD86IHN0cmluZztcbiAgLyoqXG4gICAqIFVSTCB0aGF0IGNhbiBiZSB1c2VkIHRvIHJlbmRlciBhIHByZXZpZXcgcGFnZS4gVXNlZCBieSB0aGUgc2lkZS1ieS1zaWRlXG4gICAqIGVkaXRvciB0byByZW5kZXIgaW5zdGFudCBwcmV2aWV3cy4gSWYgYmxhbmssIGRlZmF1bHRzIHRvIHRoZSBgdXJsYCBjb25maWcuXG4gICAqL1xuICBwcmV2aWV3VXJsPzogc3RyaW5nO1xuICAvKiogUGFnZSBjb21wb25lbnQgdG8gcmVuZGVyIHRoZSBjb2xsZWN0aW9uIGZvciBpbnN0YW50IHByZXZpZXdzICovXG4gIENvbXBvbmVudD86IEZ1bmN0aW9uYWxDb21wb25lbnQ7XG4gIC8qKlxuICAgKiBEZWZpbmVzIHRoZSBmaWVsZHMgdG8gdXNlIGZvciBkb2N1bWVudCBwcmV2aWV3LiBEZWZhdWx0cyB0byBcInRpdGxlXCIgYW5kXG4gICAqIFwiaW1hZ2VcIi4gVXNlIGRvdCBub3RhdGlvbiBmb3IgbmVzdGVkIGZpZWxkcywgZS5nLiBcIm1ldGEudGl0bGVcIi5cbiAgICovXG4gIHByZXZpZXc/OiB7XG4gICAgdGl0bGU/OiBzdHJpbmc7XG4gICAgaW1hZ2U/OiBzdHJpbmc7XG4gICAgZGVmYXVsdEltYWdlPzoge1xuICAgICAgc3JjOiBzdHJpbmc7XG4gICAgfTtcbiAgfTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWZpbmVDb2xsZWN0aW9uKGNvbGxlY3Rpb246IENvbGxlY3Rpb24pOiBDb2xsZWN0aW9uIHtcbiAgcmV0dXJuIGNvbGxlY3Rpb247XG59XG5cbmV4cG9ydCBjb25zdCBjb2xsZWN0aW9uID0gZGVmaW5lQ29sbGVjdGlvbjtcbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7QUFBQSxPQUFPQSxhQUFZO0FBR25CO0FBQUEsRUFDRTtBQUFBLEVBR0EsYUFBQUM7QUFBQSxPQUVLOzs7QUNUUCxTQUFRLFlBQVksVUFBUztBQUM3QixPQUFPQyxXQUFVO0FBQ2pCLFNBQVEscUJBQW9CO0FBVTVCLE9BQU8sZ0JBQWdCO0FBQ3ZCO0FBQUEsRUFFRTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsT0FDSztBQUNQLFNBQVEsZUFBOEI7QUFDdEMsU0FBbUIsb0JBQW1CO0FBQ3RDLFlBQVksa0JBQWtCO0FBQzlCLE9BQU8sVUFBVTs7O0FDckJqQixTQUFRLDJCQUEwQjs7O0FDRGxDLE9BQU8sWUFBWTtBQUNuQixTQUFRLGdCQUFlO0FBQ3ZCLFNBQVEsdUJBQXNCO0FBQzlCLFNBQVEsZ0JBQWU7QUFDdkIsU0FBUSxvQkFBb0IsNEJBQTJCO0FBQ3ZELFNBQVEsaUJBQWdCOzs7QUNleEIsT0FBTyxVQUFVO0FBRWpCLFNBQTBCLGFBQUFDLGtCQUFnQjtBQUMxQyxPQUFPLFVBQVU7QUFNakIsSUFBTSx1QkFBdUIsSUFBSSxLQUFLOzs7QUM3QnRDLFNBQVEsU0FBUyxnQkFBZTtBQUNoQyxTQUFRLGFBQWEsb0JBQW1COzs7QUNBeEMsU0FBUSxhQUFBQyxrQkFBZ0I7OztBTDBCeEIsSUFBTSxZQUFZQyxNQUFLLFFBQVEsY0FBYyxZQUFZLEdBQUcsQ0FBQztBQW1sQnRELFNBQVMsYUFBYSxZQUFtQztB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QU0sT0FBTTtBQUNoQztBQW1CTyxTQUFTLE9BQU8sT0FBK0M7QUFDcEUsU0FBTyxFQUFDLEdBQUcsT0FBTyxNQUFNLFNBQVE7QUFDbEM7QUFtQ08sU0FBUyxNQUFNLE9BQTZDO0FBQ2pFLFNBQU8sRUFBQyxHQUFHLE9BQU8sTUFBTSxRQUFPO0FBQ2pDO0FBT08sU0FBUyxNQUFNLE9BQTZDO0FBQ2pFLFNBQU8sRUFBQyxHQUFHLE9BQU8sTUFBTSxRQUFPO0FBQ2pDO0FBUU8sU0FBUyxTQUFTLE9BQW1EO0FBQzFFLFNBQU8sRUFBQyxHQUFHLE9BQU8sTUFBTSxXQUFVO0FBQ3BDO0FBWU8sU0FBUyxVQUFVLE9BQXFEO0FBQzdFLFNBQU8sRUFBQyxHQUFHLE9BQU8sTUFBTSxZQUFXO0FBQ3JDO0FBcUNPLFNBQVMsYUFBYSxRQUF3QjtBQUNuRCxTQUFPO0FBQ1Q7QUFHTyxJQUFNLFNBQVM7QUFpQ2YsU0FBUyxpQkFBaUJDLGFBQW9DO0FBQ25FLFNBQU9BO0FBQ1Q7QUFFTyxJQUFNLGFBQWE7IiwKICAibmFtZXMiOiBbImNyeXB0byIsICJUaW1lc3RhbXAiLCAicGF0aCIsICJUaW1lc3RhbXAiLCAiVGltZXN0YW1wIiwgInBhdGgiLCAicGx1Z2luIiwgImNvbGxlY3Rpb24iLCAiVGltZXN0YW1wIiwgImNyeXB0byIsICJzdHJpbmciLCAib2JqIiwgImxvY2FsZSIsICJGaWVsZFZhbHVlIiwgImNvbGxlY3Rpb24iLCAiRmllbGRWYWx1ZSIsICJjb2xsZWN0aW9uIl0KfQo=
|