@blinkk/root-cms 1.0.0-beta.8 → 1.0.0-rc.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/plugin.js CHANGED
@@ -1,34 +1,343 @@
1
1
  // core/plugin.ts
2
2
  import { promises as fs } from "node:fs";
3
- import path from "node:path";
3
+ import path2 from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import bodyParser from "body-parser";
6
- import cookieParser from "cookie-parser";
7
- import { applicationDefault, initializeApp } from "firebase-admin/app";
6
+ import {
7
+ applicationDefault,
8
+ getApp,
9
+ initializeApp
10
+ } from "firebase-admin/app";
8
11
  import { getAuth } from "firebase-admin/auth";
9
12
  import sirv from "sirv";
10
- var __dirname = path.dirname(fileURLToPath(import.meta.url));
11
- var SESSION_COOKIE = "_rootjs_cms";
12
- function generateSecret() {
13
- const result = [];
14
- const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
15
- for (let i = 0; i < 36; i++) {
16
- const rand = Math.floor(Math.random() * chars.length);
17
- result.push(chars.charAt(rand));
13
+
14
+ // core/api.ts
15
+ import { multipartMiddleware } from "@blinkk/root/middleware";
16
+
17
+ // core/runtime.ts
18
+ import {
19
+ FieldValue,
20
+ getFirestore
21
+ } from "firebase-admin/firestore";
22
+ async function publishScheduledDocs(rootConfig) {
23
+ const cmsPlugin2 = getCmsPlugin(rootConfig);
24
+ const cmsPluginOptions = cmsPlugin2.getConfig();
25
+ const projectId = cmsPluginOptions.id || "default";
26
+ const app = cmsPlugin2.getFirebaseApp();
27
+ const db = getFirestore(app);
28
+ const projectCollectionsPath = `Projects/${projectId}/Collections`;
29
+ const now = Math.ceil((/* @__PURE__ */ new Date()).getTime());
30
+ const snapshot = await db.collectionGroup("Scheduled").get();
31
+ const docs = snapshot.docs.filter((d) => {
32
+ var _a;
33
+ if (!d.ref.path.startsWith(projectCollectionsPath)) {
34
+ return false;
35
+ }
36
+ const data = d.data() || {};
37
+ const scheduledAt = (_a = data.sys) == null ? void 0 : _a.scheduledAt;
38
+ return scheduledAt && scheduledAt.toMillis && scheduledAt.toMillis() <= now;
39
+ }).map((d) => {
40
+ const dbPath = d.ref.path;
41
+ const segments = dbPath.split("/");
42
+ const slug = segments.at(-1);
43
+ const collection = segments.at(-3);
44
+ const id = `${collection}/${slug}`;
45
+ return {
46
+ data: d.data(),
47
+ id,
48
+ collection,
49
+ slug
50
+ };
51
+ });
52
+ if (docs.length === 0) {
53
+ return [];
54
+ }
55
+ let batchCount = 0;
56
+ const batch = db.batch();
57
+ const publishedDocs = [];
58
+ for (const doc of docs) {
59
+ const { id, collection, slug, data } = doc;
60
+ const draftRef = db.doc(
61
+ `${projectCollectionsPath}/${collection}/Drafts/${slug}`
62
+ );
63
+ const scheduledRef = db.doc(
64
+ `${projectCollectionsPath}/${collection}/Scheduled/${slug}`
65
+ );
66
+ const publishedRef = db.doc(
67
+ `${projectCollectionsPath}/${collection}/Published/${slug}`
68
+ );
69
+ const { scheduledAt, scheduledBy, ...sys } = data.sys || {};
70
+ const firstPublishedAt = sys.firstPublishedAt ?? scheduledAt;
71
+ const firstPublishedBy = sys.firstPublishedBy ?? (scheduledBy || "");
72
+ batch.set(publishedRef, {
73
+ id,
74
+ collection,
75
+ slug,
76
+ fields: data.fields || {},
77
+ sys: {
78
+ ...sys,
79
+ firstPublishedAt,
80
+ firstPublishedBy,
81
+ publishedAt: FieldValue.serverTimestamp(),
82
+ publishedBy: scheduledBy || ""
83
+ }
84
+ });
85
+ batchCount += 1;
86
+ batch.delete(scheduledRef);
87
+ batchCount += 1;
88
+ batch.update(draftRef, {
89
+ "sys.scheduledAt": FieldValue.delete(),
90
+ "sys.scheduledBy": FieldValue.delete(),
91
+ "sys.firstPublishedAt": firstPublishedAt,
92
+ "sys.firstPublishedBy": firstPublishedBy,
93
+ "sys.publishedAt": FieldValue.serverTimestamp(),
94
+ "sys.publishedBy": scheduledBy || ""
95
+ });
96
+ batchCount += 1;
97
+ publishedDocs.push(doc);
98
+ if (batchCount >= 498) {
99
+ break;
100
+ }
101
+ }
102
+ await batch.commit();
103
+ console.log(`published ${publishedDocs.length} docs!`);
104
+ return publishedDocs;
105
+ }
106
+ function getCmsPlugin(rootConfig) {
107
+ const plugins = rootConfig.plugins || [];
108
+ const plugin = plugins.find((plugin2) => plugin2.name === "root-cms");
109
+ if (!plugin) {
110
+ throw new Error("could not find root-cms plugin config in root.config.ts");
111
+ }
112
+ return plugin;
113
+ }
114
+
115
+ // core/versions.ts
116
+ import path from "node:path";
117
+ import {
118
+ Timestamp as Timestamp2,
119
+ getFirestore as getFirestore2
120
+ } from "firebase-admin/firestore";
121
+ import glob from "tiny-glob";
122
+ var DOCUMENT_SAVE_OFFSET = 5 * 60 * 1e3;
123
+ var VersionsService = class {
124
+ constructor(rootConfig) {
125
+ this.rootConfig = rootConfig;
126
+ const cmsPlugin2 = getCmsPlugin(rootConfig);
127
+ const cmsPluginOptions = cmsPlugin2.getConfig();
128
+ const projectId = cmsPluginOptions.id || "default";
129
+ this.projectId = projectId;
130
+ const app = cmsPlugin2.getFirebaseApp();
131
+ this.db = getFirestore2(app);
132
+ }
133
+ /**
134
+ * Saves a version of all documents that have been edited since the last run.
135
+ */
136
+ async saveVersions() {
137
+ const lastRun = await this.getLastRun();
138
+ const lastRunWithOffset = lastRun === 0 ? lastRun : lastRun - DOCUMENT_SAVE_OFFSET;
139
+ const changedDocs = await this.getDocsModifiedAfter(lastRunWithOffset);
140
+ const now = Timestamp2.now().toMillis();
141
+ const versions = changedDocs.filter((doc) => {
142
+ const modifiedAt = doc.sys.modifiedAt.toMillis();
143
+ return modifiedAt <= now - DOCUMENT_SAVE_OFFSET;
144
+ });
145
+ if (versions.length > 0) {
146
+ this.saveVersionsToFirestore(versions);
147
+ }
148
+ this.saveLastRun(now);
18
149
  }
19
- return result.join("");
150
+ async saveVersionsToFirestore(versions) {
151
+ const batch = this.db.batch();
152
+ versions.forEach((version) => {
153
+ var _a;
154
+ if (!version.collection || !version.slug || !((_a = version.sys) == null ? void 0 : _a.modifiedAt)) {
155
+ return;
156
+ }
157
+ const modifiedAtMillis = version.sys.modifiedAt.toMillis();
158
+ const versionPath = `Projects/${this.projectId}/Collections/${version.collection}/Drafts/${version.slug}/Versions/${modifiedAtMillis}`;
159
+ console.log(versionPath);
160
+ const versionRef = this.db.doc(versionPath);
161
+ batch.set(versionRef, version);
162
+ });
163
+ await batch.commit();
164
+ console.log(`versions: saved ${versions.length} versions`);
165
+ }
166
+ /**
167
+ * Returns the last time (in millis) saveVersions() was run, or 0 if has
168
+ * never been run.
169
+ */
170
+ async getLastRun() {
171
+ const projectDocRef = this.db.collection("Projects").doc(this.projectId);
172
+ const projectDoc = await projectDocRef.get();
173
+ if (projectDoc.exists) {
174
+ const data = projectDoc.data() || {};
175
+ const ts = data.versionsLastRun;
176
+ if (ts) {
177
+ return ts.toMillis();
178
+ }
179
+ }
180
+ return 0;
181
+ }
182
+ /**
183
+ * Saves {versionLastRun: <timestamp>} to the Projects/<projectId> doc.
184
+ */
185
+ async saveLastRun(millis) {
186
+ const ts = Timestamp2.fromMillis(millis);
187
+ const projectDocRef = this.db.collection("Projects").doc(this.projectId);
188
+ await projectDocRef.set({ versionsLastRun: ts }, { merge: true });
189
+ }
190
+ /**
191
+ * Returns a list of all docs that were edited after a certain time.
192
+ */
193
+ async getDocsModifiedAfter(millis) {
194
+ const ts = Timestamp2.fromMillis(millis);
195
+ const results = [];
196
+ const collectionIds = await this.listCollections();
197
+ for (const collectionId of collectionIds) {
198
+ const collectionPath = `Projects/${this.projectId}/Collections/${collectionId}/Drafts`;
199
+ const query = this.db.collection(collectionPath).where("sys.modifiedAt", ">=", ts);
200
+ const querySnapshot = await query.get();
201
+ querySnapshot.forEach((doc) => {
202
+ results.push(doc.data());
203
+ });
204
+ }
205
+ return results;
206
+ }
207
+ /**
208
+ * Returns a list of collection ids for the Root project.
209
+ */
210
+ async listCollections() {
211
+ const collectionIds = [];
212
+ const collectionFileNames = await glob("*.schema.ts", {
213
+ cwd: path.join(this.rootConfig.rootDir, "collections")
214
+ });
215
+ collectionFileNames.forEach((filename) => {
216
+ collectionIds.push(filename.slice(0, -10));
217
+ });
218
+ return collectionIds;
219
+ }
220
+ };
221
+
222
+ // core/cron.ts
223
+ async function runCronJobs(rootConfig) {
224
+ await Promise.all([
225
+ runCronJob("publishScheduledDocs", runPublishScheduledDocs, rootConfig),
226
+ runCronJob("saveVersions", runSaveVersions, rootConfig)
227
+ ]);
228
+ }
229
+ async function runCronJob(name, fn, ...args) {
230
+ try {
231
+ await fn(...args);
232
+ } catch (err) {
233
+ console.log(`cron failed: ${name}`);
234
+ console.error(String(err.stack || err));
235
+ throw err;
236
+ }
237
+ }
238
+ async function runPublishScheduledDocs(rootConfig) {
239
+ await publishScheduledDocs(rootConfig);
20
240
  }
241
+ async function runSaveVersions(rootConfig) {
242
+ const service = new VersionsService(rootConfig);
243
+ await service.saveVersions();
244
+ }
245
+
246
+ // core/csv.ts
247
+ import { parse as csvParse } from "csv-parse/sync";
248
+ import { stringify as csvStringify } from "csv-stringify/sync";
249
+ function arrayToCsv(req) {
250
+ const headers = req.headers || [];
251
+ const rows = req.rows || [];
252
+ return csvStringify(rows, {
253
+ header: true,
254
+ columns: headers
255
+ });
256
+ }
257
+ function csvToArray(csvString) {
258
+ const rows = csvParse(csvString, {
259
+ columns: true,
260
+ skip_empty_lines: true
261
+ });
262
+ return rows;
263
+ }
264
+
265
+ // core/api.ts
266
+ function api(server) {
267
+ server.use("/cms/api/cron.run", async (req, res) => {
268
+ try {
269
+ await runCronJobs(req.rootConfig);
270
+ res.status(200).json({ success: true });
271
+ } catch (err) {
272
+ console.error(err);
273
+ res.status(500).json({ success: false });
274
+ }
275
+ });
276
+ server.use("/cms/api/csv.download", (req, res) => {
277
+ if (req.method !== "POST" || !String(req.get("content-type")).startsWith("application/json")) {
278
+ res.status(400).json({ success: false, error: "BAD_REQUEST" });
279
+ }
280
+ try {
281
+ const body = req.body || {};
282
+ const headers = body.headers || [];
283
+ const rows = body.rows || [];
284
+ const csv = arrayToCsv({ headers, rows });
285
+ res.setHeader("Content-Type", "text/csv");
286
+ res.setHeader("Content-Disposition", 'attachment; filename="data.csv"');
287
+ res.status(200).end(csv);
288
+ } catch (err) {
289
+ console.error(err.stack || err);
290
+ res.status(500).json({ success: false, error: "UNKNOWN" });
291
+ }
292
+ });
293
+ server.use(
294
+ "/cms/api/csv.import",
295
+ multipartMiddleware(),
296
+ (req, res) => {
297
+ if (req.method !== "POST" || !req.files || !req.files.file) {
298
+ res.status(400).json({ success: false, error: "BAD_REQUEST" });
299
+ return;
300
+ }
301
+ try {
302
+ const file = req.files.file;
303
+ const csvString = file.buffer.toString("utf8");
304
+ const rows = csvToArray(csvString);
305
+ res.status(200).json({ success: true, data: rows });
306
+ } catch (err) {
307
+ console.error(err.stack || err);
308
+ res.status(500).json({ success: false, error: "UNKNOWN" });
309
+ }
310
+ }
311
+ );
312
+ }
313
+
314
+ // core/plugin.ts
315
+ var __dirname = path2.dirname(fileURLToPath(import.meta.url));
316
+ var SESSION_COOKIE_AUTH = "root-cms-auth";
21
317
  function isExpired(decodedIdToken) {
22
- const ts = new Date().getTime() / 1e3;
23
- return ts - decodedIdToken.auth_time > 5 * 60;
318
+ const ts = Math.floor((/* @__PURE__ */ new Date()).getTime() / 1e3);
319
+ return ts >= decodedIdToken.exp;
320
+ }
321
+ function getFirebaseApp(gcpProjectId) {
322
+ const appName = "root-cms";
323
+ try {
324
+ return getApp(appName);
325
+ } catch (err) {
326
+ if (err && err.code === "app/no-app") {
327
+ return initializeApp(
328
+ {
329
+ projectId: gcpProjectId,
330
+ credential: applicationDefault()
331
+ },
332
+ appName
333
+ );
334
+ }
335
+ throw err;
336
+ }
24
337
  }
25
338
  function cmsPlugin(options) {
26
339
  const firebaseConfig = options.firebaseConfig;
27
- const cookieSecret = options.cookieSecret || generateSecret();
28
- const app = initializeApp({
29
- projectId: firebaseConfig.projectId,
30
- credential: applicationDefault()
31
- });
340
+ const app = getFirebaseApp(firebaseConfig.projectId);
32
341
  const auth = getAuth(app);
33
342
  function loginRequired(req) {
34
343
  if (req.originalUrl.startsWith("/cms")) {
@@ -43,6 +352,7 @@ function cmsPlugin(options) {
43
352
  var _a;
44
353
  const idToken = (_a = req.body) == null ? void 0 : _a.idToken;
45
354
  if (!idToken) {
355
+ console.log("login failed: no id token");
46
356
  return false;
47
357
  }
48
358
  if (process.env.NODE_ENV === "development") {
@@ -51,13 +361,19 @@ function cmsPlugin(options) {
51
361
  try {
52
362
  const jwt = await auth.verifyIdToken(idToken, true);
53
363
  if (isExpired(jwt)) {
364
+ console.log("login failed: id token is expired");
54
365
  return false;
55
366
  }
56
367
  if (!jwt.email || !jwt.email_verified) {
368
+ console.log("login failed: email unverified");
57
369
  return false;
58
370
  }
59
371
  if (options.isUserAuthorized) {
60
- return await options.isUserAuthorized(req, jwt);
372
+ const authorized = await options.isUserAuthorized(req, jwt);
373
+ if (!authorized) {
374
+ console.log("login failed: user is not authorized");
375
+ }
376
+ return authorized;
61
377
  }
62
378
  } catch (err) {
63
379
  console.error("failed to verify jwt token");
@@ -67,8 +383,9 @@ function cmsPlugin(options) {
67
383
  return true;
68
384
  }
69
385
  async function verifyUserSession(req) {
70
- const sessionCookie = String(req.cookies[SESSION_COOKIE] || "");
386
+ const sessionCookie = req.session.getItem(SESSION_COOKIE_AUTH);
71
387
  if (!sessionCookie) {
388
+ console.log("session failed: no session cookie");
72
389
  return false;
73
390
  }
74
391
  if (process.env.NODE_ENV === "development") {
@@ -77,13 +394,19 @@ function cmsPlugin(options) {
77
394
  try {
78
395
  const jwt = await auth.verifySessionCookie(sessionCookie, true);
79
396
  if (isExpired(jwt)) {
397
+ console.log("session failed: token is expired");
80
398
  return false;
81
399
  }
82
400
  if (!jwt.email || !jwt.email_verified) {
401
+ console.log("session failed: email not verified");
83
402
  return false;
84
403
  }
85
404
  if (options.isUserAuthorized) {
86
- return await options.isUserAuthorized(req, jwt);
405
+ const authorized = await options.isUserAuthorized(req, jwt);
406
+ if (!authorized) {
407
+ console.log("session failed: not authorized");
408
+ }
409
+ return authorized;
87
410
  }
88
411
  return true;
89
412
  } catch (err) {
@@ -94,24 +417,38 @@ function cmsPlugin(options) {
94
417
  }
95
418
  return {
96
419
  name: "root-cms",
420
+ /**
421
+ * Returns the config options passed to the plugin.
422
+ */
97
423
  getConfig: () => {
98
424
  return options;
99
425
  },
426
+ /**
427
+ * Returns the Firebase App instance used by the plugin.
428
+ */
429
+ getFirebaseApp: () => {
430
+ return app;
431
+ },
432
+ /**
433
+ * A map of ssr files to include when running `root build`.
434
+ */
100
435
  ssrInput: () => ({
101
- cms: path.resolve(__dirname, "./app.js")
436
+ cms: path2.resolve(__dirname, "./app.js")
102
437
  }),
438
+ /**
439
+ * Attaches CMS-specific middleware to the Root.js server.
440
+ */
103
441
  configureServer: async (server, serverOptions) => {
104
- server.use(cookieParser(cookieSecret));
105
442
  server.use(bodyParser.json());
106
443
  async function getRenderer(req) {
107
444
  if (serverOptions.type === "dev") {
108
- const appFilePath = path.resolve(__dirname, "./app.js");
445
+ const appFilePath = path2.resolve(__dirname, "./app.js");
109
446
  const app3 = await req.viteServer.ssrLoadModule(
110
447
  appFilePath
111
448
  );
112
449
  return app3;
113
450
  }
114
- const appImportPath = path.resolve(
451
+ const appImportPath = path2.resolve(
115
452
  req.rootConfig.rootDir,
116
453
  "dist/server/cms.js"
117
454
  );
@@ -123,7 +460,7 @@ function cmsPlugin(options) {
123
460
  const app2 = await import(appImportPath);
124
461
  return app2;
125
462
  }
126
- const staticDir = path.resolve(__dirname, "ui");
463
+ const staticDir = path2.resolve(__dirname, "ui");
127
464
  server.use("/cms/static", sirv(staticDir, { dev: false }));
128
465
  server.use("/cms/login", async (req, res) => {
129
466
  if (req.method === "PUT" && req.headers["content-type"] === "application/json") {
@@ -143,11 +480,8 @@ function cmsPlugin(options) {
143
480
  expiresIn
144
481
  });
145
482
  }
146
- res.cookie(SESSION_COOKIE, sessionCookie, {
147
- maxAge: expiresIn,
148
- httpOnly: true,
149
- secure: true
150
- });
483
+ res.session.setItem(SESSION_COOKIE_AUTH, sessionCookie);
484
+ res.saveSession();
151
485
  res.json({ success: true });
152
486
  } catch (err) {
153
487
  console.error(err);
@@ -170,7 +504,8 @@ function cmsPlugin(options) {
170
504
  }
171
505
  });
172
506
  server.use("/cms/logout", async (req, res) => {
173
- res.clearCookie(SESSION_COOKIE);
507
+ res.session.removeItem(SESSION_COOKIE_AUTH);
508
+ res.saveSession();
174
509
  res.redirect("/cms/login");
175
510
  });
176
511
  server.use(async (req, res, next) => {
@@ -183,11 +518,17 @@ function cmsPlugin(options) {
183
518
  next();
184
519
  return;
185
520
  }
521
+ if (req.originalUrl.startsWith("/cms/api")) {
522
+ res.status(401).json({ success: false, error: "NOT_AUTHORIZED" });
523
+ return;
524
+ }
525
+ console.log("redirecting to login page");
186
526
  const params = new URLSearchParams({
187
527
  continue: req.originalUrl
188
528
  });
189
529
  res.redirect(`/cms/login?${params.toString()}`);
190
530
  });
531
+ api(server);
191
532
  server.use("/cms", async (req, res) => {
192
533
  try {
193
534
  const app2 = await getRenderer(req);
@@ -210,4 +551,4 @@ function fileExists(filepath) {
210
551
  export {
211
552
  cmsPlugin
212
553
  };
213
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vY29yZS9wbHVnaW4udHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7cHJvbWlzZXMgYXMgZnN9IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7ZmlsZVVSTFRvUGF0aH0gZnJvbSAnbm9kZTp1cmwnO1xuaW1wb3J0IHtcbiAgQ29uZmlndXJlU2VydmVyT3B0aW9ucyxcbiAgTmV4dEZ1bmN0aW9uLFxuICBQbHVnaW4sXG4gIFJlcXVlc3QsXG4gIFJlc3BvbnNlLFxuICBTZXJ2ZXIsXG59IGZyb20gJ0BibGlua2svcm9vdCc7XG5pbXBvcnQgYm9keVBhcnNlciBmcm9tICdib2R5LXBhcnNlcic7XG5pbXBvcnQgY29va2llUGFyc2VyIGZyb20gJ2Nvb2tpZS1wYXJzZXInO1xuaW1wb3J0IHthcHBsaWNhdGlvbkRlZmF1bHQsIGluaXRpYWxpemVBcHB9IGZyb20gJ2ZpcmViYXNlLWFkbWluL2FwcCc7XG5pbXBvcnQge2dldEF1dGgsIERlY29kZWRJZFRva2VufSBmcm9tICdmaXJlYmFzZS1hZG1pbi9hdXRoJztcbmltcG9ydCBzaXJ2IGZyb20gJ3NpcnYnO1xuXG5jb25zdCBfX2Rpcm5hbWUgPSBwYXRoLmRpcm5hbWUoZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpKTtcblxudHlwZSBBcHBNb2R1bGUgPSB0eXBlb2YgaW1wb3J0KCcuL2FwcC5qcycpO1xuXG5jb25zdCBTRVNTSU9OX0NPT0tJRSA9ICdfcm9vdGpzX2Ntcyc7XG5cbmV4cG9ydCB0eXBlIENNU1VzZXIgPSBEZWNvZGVkSWRUb2tlbjtcblxuZXhwb3J0IHR5cGUgQ01TUGx1Z2luT3B0aW9ucyA9IHtcbiAgLyoqXG4gICAqIFRoZSBJRCBvZiB0aGUgcHJvamVjdC4gRGF0YSB3aWxsIGJlIHN0b3JlZCB1bmRlciB0aGUgbmFtZXNwYWNlXG4gICAqIGBQcm9qZWN0cy8ke2lkfWAgaW4gZmlyZXN0b3JlLlxuICAgKi9cbiAgaWQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9qZWN0LiBVc2VkIGluIHRoZSBoZWFkZXIgb2YgdGhlIENNUyB0byBoZWxwIGlkZW50aWZ5XG4gICAqIHRoZSBwcm9qZWN0LlxuICAgKi9cbiAgbmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogRmlyZWJhc2UgY29uZmlnIG9iamVjdCwgd2hpY2ggY2FuIGJlIG9idGFpbmVkIGluIHRoZSBGaXJlYmFzZSBDb25zb2xlIGJ5XG4gICAqIGdvaW5nIHRvIFwiUHJvamVjdCBTZXR0aW5nc1wiLlxuICAgKi9cbiAgZmlyZWJhc2VDb25maWc6IHtcbiAgICBba2V5OiBzdHJpbmddOiBzdHJpbmc7XG4gICAgYXBpS2V5OiBzdHJpbmc7XG4gICAgYXV0aERvbWFpbjogc3RyaW5nO1xuICAgIHByb2plY3RJZDogc3RyaW5nO1xuICAgIHN0b3JhZ2VCdWNrZXQ6IHN0cmluZztcbiAgICBtZXNzYWdpbmdTZW5kZXJJZDogc3RyaW5nO1xuICAgIGFwcElkOiBzdHJpbmc7XG4gIH07XG5cbiAgLyoqIFNlY3JldCB2YWx1ZShzKSB1c2VkIGZvciBzaWduaW5nIHRoZSB1c2VyIGF1dGhlbnRpY2F0aW9uIGNvb2tpZS4gKi9cbiAgY29va2llU2VjcmV0Pzogc3RyaW5nIHwgc3RyaW5nW107XG5cbiAgLyoqIEZ1bmN0aW9uIGNhbGxlZCB0byBjaGVjayBpZiBhIHVzZXIgc2hvdWxkIGhhdmUgYWNjZXNzIHRvIHRoZSBDTVMuICovXG4gIGlzVXNlckF1dGhvcml6ZWQ/OiAoXG4gICAgcmVxOiBSZXF1ZXN0LFxuICAgIHVzZXI6IENNU1VzZXJcbiAgKSA9PiBib29sZWFuIHwgUHJvbWlzZTxib29sZWFuPjtcblxuICAvKipcbiAgICogVVJMIHRvIEdDSSBzZXJ2aWNlIGZvciB0cmFuc2Zvcm1pbmcgdXBsb2FkZWQgR0NTIGltYWdlcyB0byBhIEdvb2dsZSBBcHBcbiAgICogRW5naW5lIEltYWdlcyBBUEkgc2VydmluZyBVUkwuIERlZmF1bHRzIHRvIFwiaHR0cHM6Ly9nY2kucm9vdGpzLmRldlwiLiBUb1xuICAgKiBkaXNhYmxlLCBzZXQgdGhpcyB2YWx1ZSB0byBgZmFsc2VgLlxuICAgKi9cbiAgZ2NpPzogc3RyaW5nIHwgYm9vbGVhbjtcbn07XG5cbmV4cG9ydCB0eXBlIENNU1BsdWdpbiA9IFBsdWdpbiAmIHtcbiAgbmFtZTogJ3Jvb3QtY21zJztcbiAgZ2V0Q29uZmlnOiAoKSA9PiBDTVNQbHVnaW5PcHRpb25zO1xufTtcblxuZnVuY3Rpb24gZ2VuZXJhdGVTZWNyZXQoKTogc3RyaW5nIHtcbiAgY29uc3QgcmVzdWx0ID0gW107XG4gIGNvbnN0IGNoYXJzID1cbiAgICAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODknO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IDM2OyBpKyspIHtcbiAgICBjb25zdCByYW5kID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogY2hhcnMubGVuZ3RoKTtcbiAgICByZXN1bHQucHVzaChjaGFycy5jaGFyQXQocmFuZCkpO1xuICB9XG4gIHJldHVybiByZXN1bHQuam9pbignJyk7XG59XG5cbmZ1bmN0aW9uIGlzRXhwaXJlZChkZWNvZGVkSWRUb2tlbjogRGVjb2RlZElkVG9rZW4pIHtcbiAgY29uc3QgdHMgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKSAvIDEwMDA7XG4gIHJldHVybiB0cyAtIGRlY29kZWRJZFRva2VuLmF1dGhfdGltZSA+IDUgKiA2MDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNtc1BsdWdpbihvcHRpb25zOiBDTVNQbHVnaW5PcHRpb25zKTogQ01TUGx1Z2luIHtcbiAgY29uc3QgZmlyZWJhc2VDb25maWcgPSBvcHRpb25zLmZpcmViYXNlQ29uZmlnO1xuICBjb25zdCBjb29raWVTZWNyZXQgPSBvcHRpb25zLmNvb2tpZVNlY3JldCB8fCBnZW5lcmF0ZVNlY3JldCgpO1xuICBjb25zdCBhcHAgPSBpbml0aWFsaXplQXBwKHtcbiAgICBwcm9qZWN0SWQ6IGZpcmViYXNlQ29uZmlnLnByb2plY3RJZCxcbiAgICBjcmVkZW50aWFsOiBhcHBsaWNhdGlvbkRlZmF1bHQoKSxcbiAgfSk7XG4gIGNvbnN0IGF1dGggPSBnZXRBdXRoKGFwcCk7XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBsb2dpbiBpcyByZXF1aXJlZCBmb3IgdGhlIHJlcXVlc3QuIEN1cnJlbnRseSByZXR1cm5zIGB0cnVlYCBpZlxuICAgKiB0aGUgVVJMIHBhdGggc3RhcnRzIHdpdGggL2NtcyBvciBpZiA/cHJldmlldz10cnVlIGlzIGluIHRoZSBVUkwuXG4gICAqL1xuICBmdW5jdGlvbiBsb2dpblJlcXVpcmVkKHJlcTogUmVxdWVzdCk6IGJvb2xlYW4ge1xuICAgIGlmIChyZXEub3JpZ2luYWxVcmwuc3RhcnRzV2l0aCgnL2NtcycpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKFN0cmluZyhyZXEucXVlcnkucHJldmlldykgPT09ICd0cnVlJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZmllcyBhIG5ldyBsb2dpbiByZXF1ZXN0IGZvciBhIHVzZXIuIFRoZSByZXF1ZXN0IGJvZHkgc2hvdWxkIGNvbnRhaW5cbiAgICogYW4gaWRUb2tlbiwgd2hpY2ggaXMgdmVyaWZpZWQgb24gcHJvZCB1c2luZyBGaXJlYmFzZSBBZG1pbiBhbmQgSWRlbnRpdHlcbiAgICogVG9vbGtpdC4gSWYgYSBgaXNVc2VyQXV0aG9yaXplZCgpYCBjb25maWcgaXMgc2V0LCB0aGlzIGZ1bmN0aW9uIHdpbGwgYWxzb1xuICAgKiB2ZXJpZnkgdmlhIHRoYXQgZnVuY3Rpb24uIFJldHVybnMgdHJ1ZSBpZiB0aGUgbG9naW4gdmVyaWZpY2F0aW9uIHN1Y2NlZWRzLlxuICAgKi9cbiAgYXN5bmMgZnVuY3Rpb24gdmVyaWZ5VXNlckxvZ2luKHJlcTogUmVxdWVzdCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGlkVG9rZW4gPSByZXEuYm9keT8uaWRUb2tlbjtcbiAgICBpZiAoIWlkVG9rZW4pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBPbiBsb2NhbCBkZXYsIHNpbXBseSB2ZXJpZnkgdGhhdCBhbiBpZFRva2VuIGlzIHNldC4gVGhlIGlkZW50aXR5IHRvb2xraXRcbiAgICAvLyB0aGF0IHZlcmlmaWVzIGlkIHRva2VucyByZXF1aXJlcyBhIHNlcnZpY2UgYWNjb3VudCwgd2hpY2ggd2Ugd2FudCB0b1xuICAgIC8vIGF2b2lkIGhhdmluZyB0byBzZXQgdXAgd2hlbiB1c2VycyBhcmUgZG9pbmcgbG9jYWwgZGV2ZWxvcG1lbnQuXG4gICAgLy8gQXV0aGVudGljYXRpb24gaXMgc3RpbGwgcmVxdWlyZWQgYnkgdGhlIGZyb250ZW5kIHVzaW5nIEZpcmViYXNlIEF1dGgsXG4gICAgLy8gdGhpcyBqdXN0IGJ5cGFzc2VzIHRoZSBpbml0aWFsIHNlcnZlciBjaGVjayBiZWZvcmUgdGhlIHVpIGlzIHJlbmRlcmVkLlxuICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50Jykge1xuICAgICAgcmV0dXJuIEJvb2xlYW4oaWRUb2tlbik7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGp3dCA9IGF3YWl0IGF1dGgudmVyaWZ5SWRUb2tlbihpZFRva2VuLCB0cnVlKTtcbiAgICAgIGlmIChpc0V4cGlyZWQoand0KSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAoIWp3dC5lbWFpbCB8fCAhand0LmVtYWlsX3ZlcmlmaWVkKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmIChvcHRpb25zLmlzVXNlckF1dGhvcml6ZWQpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IG9wdGlvbnMuaXNVc2VyQXV0aG9yaXplZChyZXEsIGp3dCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdmYWlsZWQgdG8gdmVyaWZ5IGp3dCB0b2tlbicpO1xuICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvLyBUT0RPKHN0ZXZlbmxlKTogZGVjaWRlIHdoZXRoZXIgd2Ugd2FudCB0byBlbmZvcmNlIGBpc1VzZXJBdXRob3JpemVkKClgLlxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWVzIHdoZXRoZXIgdGhlIGN1cnJlbnQgdXNlciBzZXNzaW9uIHNob3VsZCBiZSBhbGxvd2VkIHRvIGFjY2VzcyB0aGVcbiAgICogQ01TLiBSZXR1cm5zIHRydWUgaWYgYWNjZXNzIGlzIGdyYW50ZWQuXG4gICAqL1xuICBhc3luYyBmdW5jdGlvbiB2ZXJpZnlVc2VyU2Vzc2lvbihyZXE6IFJlcXVlc3QpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBzZXNzaW9uQ29va2llID0gU3RyaW5nKHJlcS5jb29raWVzW1NFU1NJT05fQ09PS0lFXSB8fCAnJyk7XG4gICAgaWYgKCFzZXNzaW9uQ29va2llKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gT24gbG9jYWwgZGV2LCBzaW1wbHkgdmVyaWZ5IHRoYXQgYW4gc2Vzc2lvbiBjb29raWUgaXMgc2V0LiBTZWUgbm90ZVxuICAgIC8vIGFib3ZlIGluIGB2ZXJpZnlVc2VyTG9naW4oKWAgZm9yIG1vcmUgaW5mb3JtYXRpb24uXG4gICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAnZGV2ZWxvcG1lbnQnKSB7XG4gICAgICByZXR1cm4gQm9vbGVhbihzZXNzaW9uQ29va2llKTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgand0ID0gYXdhaXQgYXV0aC52ZXJpZnlTZXNzaW9uQ29va2llKHNlc3Npb25Db29raWUsIHRydWUpO1xuICAgICAgaWYgKGlzRXhwaXJlZChqd3QpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmICghand0LmVtYWlsIHx8ICFqd3QuZW1haWxfdmVyaWZpZWQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgaWYgKG9wdGlvbnMuaXNVc2VyQXV0aG9yaXplZCkge1xuICAgICAgICByZXR1cm4gYXdhaXQgb3B0aW9ucy5pc1VzZXJBdXRob3JpemVkKHJlcSwgand0KTtcbiAgICAgIH1cbiAgICAgIC8vIFRPRE8oc3RldmVubGUpOiBkZWNpZGUgd2hldGhlciB3ZSB3YW50IHRvIGVuZm9yY2UgYGlzVXNlckF1dGhvcml6ZWQoKWAuXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ2ZhaWxlZCB0byB2ZXJpZnkgand0IHRva2VuJyk7XG4gICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAncm9vdC1jbXMnLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY29uZmlnIG9wdGlvbnMgcGFzc2VkIHRvIHRoZSBwbHVnaW4uXG4gICAgICovXG4gICAgZ2V0Q29uZmlnOiAoKSA9PiB7XG4gICAgICByZXR1cm4gb3B0aW9ucztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQSBtYXAgb2Ygc3NyIGZpbGVzIHRvIGluY2x1ZGUgd2hlbiBydW5uaW5nIGByb290IGJ1aWxkYC5cbiAgICAgKi9cbiAgICBzc3JJbnB1dDogKCkgPT4gKHtcbiAgICAgIGNtczogcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4vYXBwLmpzJyksXG4gICAgfSksXG5cbiAgICAvKipcbiAgICAgKiBBdHRhY2hlcyBDTVMtc3BlY2lmaWMgbWlkZGxld2FyZSB0byB0aGUgUm9vdC5qcyBzZXJ2ZXIuXG4gICAgICovXG4gICAgY29uZmlndXJlU2VydmVyOiBhc3luYyAoXG4gICAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICAgIHNlcnZlck9wdGlvbnM6IENvbmZpZ3VyZVNlcnZlck9wdGlvbnNcbiAgICApID0+IHtcbiAgICAgIHNlcnZlci51c2UoY29va2llUGFyc2VyKGNvb2tpZVNlY3JldCkpO1xuICAgICAgc2VydmVyLnVzZShib2R5UGFyc2VyLmpzb24oKSk7XG5cbiAgICAgIGFzeW5jIGZ1bmN0aW9uIGdldFJlbmRlcmVyKHJlcTogUmVxdWVzdCk6IFByb21pc2U8QXBwTW9kdWxlPiB7XG4gICAgICAgIGlmIChzZXJ2ZXJPcHRpb25zLnR5cGUgPT09ICdkZXYnKSB7XG4gICAgICAgICAgY29uc3QgYXBwRmlsZVBhdGggPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi9hcHAuanMnKTtcbiAgICAgICAgICBjb25zdCBhcHAgPSAoYXdhaXQgcmVxLnZpdGVTZXJ2ZXIhLnNzckxvYWRNb2R1bGUoXG4gICAgICAgICAgICBhcHBGaWxlUGF0aFxuICAgICAgICAgICkpIGFzIEFwcE1vZHVsZTtcbiAgICAgICAgICByZXR1cm4gYXBwO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYXBwSW1wb3J0UGF0aCA9IHBhdGgucmVzb2x2ZShcbiAgICAgICAgICByZXEucm9vdENvbmZpZyEucm9vdERpcixcbiAgICAgICAgICAnZGlzdC9zZXJ2ZXIvY21zLmpzJ1xuICAgICAgICApO1xuICAgICAgICBpZiAoIShhd2FpdCBmaWxlRXhpc3RzKGFwcEltcG9ydFBhdGgpKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICdkaXN0L3NlcnZlci9jbXMuanMgbm90IGZvdW5kLiBydW4gYHJvb3QgYnVpbGRgIHRvIGNyZWF0ZSBpdC4nXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhcHAgPSAoYXdhaXQgaW1wb3J0KGFwcEltcG9ydFBhdGgpKSBhcyBBcHBNb2R1bGU7XG4gICAgICAgIHJldHVybiBhcHA7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN0YXRpY0RpciA9IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICd1aScpO1xuICAgICAgc2VydmVyLnVzZSgnL2Ntcy9zdGF0aWMnLCBzaXJ2KHN0YXRpY0Rpciwge2RldjogZmFsc2V9KSk7XG5cbiAgICAgIC8vIExvZ2luIGhhbmRsZXIuXG4gICAgICBzZXJ2ZXIudXNlKCcvY21zL2xvZ2luJywgYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgcmVxLm1ldGhvZCA9PT0gJ1BVVCcgJiZcbiAgICAgICAgICByZXEuaGVhZGVyc1snY29udGVudC10eXBlJ10gPT09ICdhcHBsaWNhdGlvbi9qc29uJ1xuICAgICAgICApIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgaXNBdXRob3JpemVkID0gYXdhaXQgdmVyaWZ5VXNlckxvZ2luKHJlcSk7XG4gICAgICAgICAgICBpZiAoIWlzQXV0aG9yaXplZCkge1xuICAgICAgICAgICAgICByZXMuc3RhdHVzKDQwMSkuanNvbih7c3VjY2VzczogZmFsc2UsIGVycm9yOiAnTk9UX0FVVEhPUklaRUQnfSk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHNlc3Npb24gZXhwaXJhdGlvbiB0byA1IGRheXMuXG4gICAgICAgICAgICBjb25zdCBleHBpcmVzSW4gPSA2MCAqIDYwICogMjQgKiA1ICogMTAwMDtcbiAgICAgICAgICAgIGNvbnN0IGlkVG9rZW4gPSByZXEuYm9keS5pZFRva2VuITtcblxuICAgICAgICAgICAgbGV0IHNlc3Npb25Db29raWU6IHN0cmluZztcbiAgICAgICAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50Jykge1xuICAgICAgICAgICAgICBzZXNzaW9uQ29va2llID0gaWRUb2tlbjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHNlc3Npb25Db29raWUgPSBhd2FpdCBhdXRoLmNyZWF0ZVNlc3Npb25Db29raWUoaWRUb2tlbiwge1xuICAgICAgICAgICAgICAgIGV4cGlyZXNJbixcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMuY29va2llKFNFU1NJT05fQ09PS0lFLCBzZXNzaW9uQ29va2llLCB7XG4gICAgICAgICAgICAgIG1heEFnZTogZXhwaXJlc0luLFxuICAgICAgICAgICAgICBodHRwT25seTogdHJ1ZSxcbiAgICAgICAgICAgICAgc2VjdXJlOiB0cnVlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXMuanNvbih7c3VjY2VzczogdHJ1ZX0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgICAgICAgaWYgKGVyci5zdGFjaykge1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVyci5zdGFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXNcbiAgICAgICAgICAgICAgLnN0YXR1cyg1MDApXG4gICAgICAgICAgICAgIC5qc29uKHtzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdVTktOT1dOX1NFUlZFUl9FUlJPUid9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBhcHAgPSBhd2FpdCBnZXRSZW5kZXJlcihyZXEpO1xuICAgICAgICAgIGFwcC5yZW5kZXJTaWduSW4ocmVxLCByZXMsIG9wdGlvbnMpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICAgICAgaWYgKGVyci5zdGFjaykge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2spO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXMuc3RhdHVzKDUwMCkuc2VuZCgnVU5LTk9XTiBTRVJWRVIgRVJST1InKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIExvZ291dCBoYW5kbGVyLlxuICAgICAgc2VydmVyLnVzZSgnL2Ntcy9sb2dvdXQnLCBhc3luYyAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgICAgIHJlcy5jbGVhckNvb2tpZShTRVNTSU9OX0NPT0tJRSk7XG4gICAgICAgIHJlcy5yZWRpcmVjdCgnL2Ntcy9sb2dpbicpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIFNhZmVndWFyZCB0byB2ZXJpZnkgdXNlciBsb2dpbiBiZWZvcmUgcmVuZGVyaW5nIGFueSBDTVMgcGFnZS5cbiAgICAgIHNlcnZlci51c2UoYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKSA9PiB7XG4gICAgICAgIGlmICghbG9naW5SZXF1aXJlZChyZXEpKSB7XG4gICAgICAgICAgbmV4dCgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB1c2VySXNMb2dnZWRJbiA9IGF3YWl0IHZlcmlmeVVzZXJTZXNzaW9uKHJlcSk7XG4gICAgICAgIGlmICh1c2VySXNMb2dnZWRJbikge1xuICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh7XG4gICAgICAgICAgY29udGludWU6IHJlcS5vcmlnaW5hbFVybCxcbiAgICAgICAgfSk7XG4gICAgICAgIHJlcy5yZWRpcmVjdChgL2Ntcy9sb2dpbj8ke3BhcmFtcy50b1N0cmluZygpfWApO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIFJlbmRlciB0aGUgQ01TIFNQQS5cbiAgICAgIHNlcnZlci51c2UoJy9jbXMnLCBhc3luYyAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgYXBwID0gYXdhaXQgZ2V0UmVuZGVyZXIocmVxKTtcbiAgICAgICAgICBhd2FpdCBhcHAucmVuZGVyQXBwKHJlcSwgcmVzLCB7XG4gICAgICAgICAgICByb290Q29uZmlnOiByZXEucm9vdENvbmZpZyxcbiAgICAgICAgICAgIGNtc0NvbmZpZzogb3B0aW9ucyxcbiAgICAgICAgICAgIGZpcmViYXNlQ29uZmlnOiBvcHRpb25zLmZpcmViYXNlQ29uZmlnLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAvLyBUT0RPKHN0ZXZlbmxlKTogcmVuZGVyIGEgY3VzdG9tIGVycm9yIHBhZ2UuXG4gICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgICAgIHJlcy5zdGF0dXMoNTAwKS5zZW5kKCdVTktOT1dOIFNFUlZFUiBFUlJPUicpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9LFxuICB9O1xufVxuXG5mdW5jdGlvbiBmaWxlRXhpc3RzKGZpbGVwYXRoOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgcmV0dXJuIGZzXG4gICAgLmFjY2VzcyhmaWxlcGF0aClcbiAgICAudGhlbigoKSA9PiB0cnVlKVxuICAgIC5jYXRjaCgoKSA9PiBmYWxzZSk7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQUEsU0FBUSxZQUFZLFVBQVM7QUFDN0IsT0FBTyxVQUFVO0FBQ2pCLFNBQVEscUJBQW9CO0FBUzVCLE9BQU8sZ0JBQWdCO0FBQ3ZCLE9BQU8sa0JBQWtCO0FBQ3pCLFNBQVEsb0JBQW9CLHFCQUFvQjtBQUNoRCxTQUFRLGVBQThCO0FBQ3RDLE9BQU8sVUFBVTtBQUVqQixJQUFNLFlBQVksS0FBSyxRQUFRLGNBQWMsWUFBWSxHQUFHLENBQUM7QUFJN0QsSUFBTSxpQkFBaUI7QUFxRHZCLFNBQVMsaUJBQXlCO0FBQ2hD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
554
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vY29yZS9wbHVnaW4udHMiLCAiLi4vY29yZS9hcGkudHMiLCAiLi4vY29yZS9ydW50aW1lLnRzIiwgIi4uL2NvcmUvdmVyc2lvbnMudHMiLCAiLi4vY29yZS9jcm9uLnRzIiwgIi4uL2NvcmUvY3N2LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQge3Byb21pc2VzIGFzIGZzfSBmcm9tICdub2RlOmZzJztcbmltcG9ydCBwYXRoIGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQge2ZpbGVVUkxUb1BhdGh9IGZyb20gJ25vZGU6dXJsJztcblxuaW1wb3J0IHtcbiAgQ29uZmlndXJlU2VydmVyT3B0aW9ucyxcbiAgTmV4dEZ1bmN0aW9uLFxuICBQbHVnaW4sXG4gIFJlcXVlc3QsXG4gIFJlc3BvbnNlLFxuICBTZXJ2ZXIsXG59IGZyb20gJ0BibGlua2svcm9vdCc7XG5pbXBvcnQgYm9keVBhcnNlciBmcm9tICdib2R5LXBhcnNlcic7XG5pbXBvcnQge1xuICBBcHAsXG4gIGFwcGxpY2F0aW9uRGVmYXVsdCxcbiAgZ2V0QXBwLFxuICBpbml0aWFsaXplQXBwLFxufSBmcm9tICdmaXJlYmFzZS1hZG1pbi9hcHAnO1xuaW1wb3J0IHtnZXRBdXRoLCBEZWNvZGVkSWRUb2tlbn0gZnJvbSAnZmlyZWJhc2UtYWRtaW4vYXV0aCc7XG5pbXBvcnQgc2lydiBmcm9tICdzaXJ2JztcbmltcG9ydCB7YXBpfSBmcm9tICcuL2FwaS5qcyc7XG5cbmNvbnN0IF9fZGlybmFtZSA9IHBhdGguZGlybmFtZShmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpO1xuXG50eXBlIEFwcE1vZHVsZSA9IHR5cGVvZiBpbXBvcnQoJy4vYXBwLmpzJyk7XG5cbi8vIFRoZSBzZXNzaW9uIGtleSBuYW1lIHVzZWQgZm9yIFJvb3QgQ01TIGF1dGhlbnRpY2F0aW9uLlxuY29uc3QgU0VTU0lPTl9DT09LSUVfQVVUSCA9ICdyb290LWNtcy1hdXRoJztcblxuZXhwb3J0IHR5cGUgQ01TVXNlciA9IERlY29kZWRJZFRva2VuO1xuXG5leHBvcnQgdHlwZSBDTVNQbHVnaW5PcHRpb25zID0ge1xuICAvKipcbiAgICogVGhlIElEIG9mIHRoZSBwcm9qZWN0LiBEYXRhIHdpbGwgYmUgc3RvcmVkIHVuZGVyIHRoZSBuYW1lc3BhY2VcbiAgICogYFByb2plY3RzLyR7aWR9YCBpbiBmaXJlc3RvcmUuXG4gICAqL1xuICBpZD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIHByb2plY3QuIFVzZWQgaW4gdGhlIGhlYWRlciBvZiB0aGUgQ01TIHRvIGhlbHAgaWRlbnRpZnlcbiAgICogdGhlIHByb2plY3QuXG4gICAqL1xuICBuYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBGaXJlYmFzZSBjb25maWcgb2JqZWN0LCB3aGljaCBjYW4gYmUgb2J0YWluZWQgaW4gdGhlIEZpcmViYXNlIENvbnNvbGUgYnlcbiAgICogZ29pbmcgdG8gXCJQcm9qZWN0IFNldHRpbmdzXCIuXG4gICAqL1xuICBmaXJlYmFzZUNvbmZpZzoge1xuICAgIFtrZXk6IHN0cmluZ106IHN0cmluZztcbiAgICBhcGlLZXk6IHN0cmluZztcbiAgICBhdXRoRG9tYWluOiBzdHJpbmc7XG4gICAgcHJvamVjdElkOiBzdHJpbmc7XG4gICAgc3RvcmFnZUJ1Y2tldDogc3RyaW5nO1xuICAgIG1lc3NhZ2luZ1NlbmRlcklkOiBzdHJpbmc7XG4gICAgYXBwSWQ6IHN0cmluZztcbiAgfTtcblxuICAvKipcbiAgICogU2VjcmV0IHZhbHVlKHMpIHVzZWQgZm9yIHNpZ25pbmcgdGhlIHVzZXIgYXV0aGVudGljYXRpb24gY29va2llLlxuICAgKiBAZGVwcmVjYXRlZCBUaGlzIGlzIG5vdyBoYW5kbGVkIGRpcmVjdGx5IGJ5IHJvb3QncyBzZXNzaW9uTWlkZGxld2FyZSB1bmRlclxuICAgKiBgc2VydmVyLnNlc3Npb25Db29raWVTZWNyZXRgIGluIHJvb3QuY29uZmlnLnRzLlxuICAgKi9cbiAgY29va2llU2VjcmV0Pzogc3RyaW5nIHwgc3RyaW5nW107XG5cbiAgLyoqIEZ1bmN0aW9uIGNhbGxlZCB0byBjaGVjayBpZiBhIHVzZXIgc2hvdWxkIGhhdmUgYWNjZXNzIHRvIHRoZSBDTVMuICovXG4gIGlzVXNlckF1dGhvcml6ZWQ/OiAoXG4gICAgcmVxOiBSZXF1ZXN0LFxuICAgIHVzZXI6IENNU1VzZXJcbiAgKSA9PiBib29sZWFuIHwgUHJvbWlzZTxib29sZWFuPjtcblxuICAvKipcbiAgICogVVJMIHRvIEdDSSBzZXJ2aWNlIGZvciB0cmFuc2Zvcm1pbmcgdXBsb2FkZWQgR0NTIGltYWdlcyB0byBhIEdvb2dsZSBBcHBcbiAgICogRW5naW5lIEltYWdlcyBBUEkgc2VydmluZyBVUkwuXG4gICAqXG4gICAqIFNldHRpbmcgdGhpcyB0byBgdHJ1ZWAgdXNlcyB0aGUgZGVmYXVsdCBob3N0ZWQgc2VydmljZSBhdFxuICAgKiBodHRwczovL2djaS5yb290anMuZGV2LlxuICAgKlxuICAgKiBUbyBzZXQgdXAgR0NJOlxuICAgKlxuICAgKiAtIENyZWF0ZSBhIEdDUyBidWNrZXQgd2l0aCBmaW5lLWdyYWluZWQgcGVybWlzc2lvbnNcbiAgICogLSBTaGFyZSBvd25lciBhY2Nlc3MgdG8gdGhlIGJ1Y2tldCB3aXRoIHRoZSBzZXJ2aWNlIGFjY291bnQgcmV0dXJuZWQgaW5cbiAgICogICBodHRwczovL2djaS5yb290anMuZGV2L18vc2VydmljZV9hY2NvdW50XG4gICAqXG4gICAqIFRvIGRpc2FibGUgR0NJLCBsZWF2ZSB0aGlzIHZhbHVlIGVtcHR5IG9yIHNldCB0byBgZmFsc2VgLCB3aGljaCB3aGljaCB3aWxsXG4gICAqIHNlcnZlIGltYWdlcyBkaXJlY3RseSBmcm9tIEdDUyBpbnN0ZWFkLlxuICAgKi9cbiAgZ2NpPzogc3RyaW5nIHwgYm9vbGVhbjtcbn07XG5cbmV4cG9ydCB0eXBlIENNU1BsdWdpbiA9IFBsdWdpbiAmIHtcbiAgbmFtZTogJ3Jvb3QtY21zJztcbiAgZ2V0Q29uZmlnOiAoKSA9PiBDTVNQbHVnaW5PcHRpb25zO1xuICBnZXRGaXJlYmFzZUFwcDogKCkgPT4gQXBwO1xufTtcblxuZnVuY3Rpb24gaXNFeHBpcmVkKGRlY29kZWRJZFRva2VuOiBEZWNvZGVkSWRUb2tlbikge1xuICBjb25zdCB0cyA9IE1hdGguZmxvb3IobmV3IERhdGUoKS5nZXRUaW1lKCkgLyAxMDAwKTtcbiAgcmV0dXJuIHRzID49IGRlY29kZWRJZFRva2VuLmV4cDtcbn1cblxuZnVuY3Rpb24gZ2V0RmlyZWJhc2VBcHAoZ2NwUHJvamVjdElkOiBzdHJpbmcpOiBBcHAge1xuICBjb25zdCBhcHBOYW1lID0gJ3Jvb3QtY21zJztcbiAgdHJ5IHtcbiAgICByZXR1cm4gZ2V0QXBwKGFwcE5hbWUpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBpZiAoZXJyICYmIGVyci5jb2RlID09PSAnYXBwL25vLWFwcCcpIHtcbiAgICAgIHJldHVybiBpbml0aWFsaXplQXBwKFxuICAgICAgICB7XG4gICAgICAgICAgcHJvamVjdElkOiBnY3BQcm9qZWN0SWQsXG4gICAgICAgICAgY3JlZGVudGlhbDogYXBwbGljYXRpb25EZWZhdWx0KCksXG4gICAgICAgIH0sXG4gICAgICAgIGFwcE5hbWVcbiAgICAgICk7XG4gICAgfVxuICAgIHRocm93IGVycjtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY21zUGx1Z2luKG9wdGlvbnM6IENNU1BsdWdpbk9wdGlvbnMpOiBDTVNQbHVnaW4ge1xuICBjb25zdCBmaXJlYmFzZUNvbmZpZyA9IG9wdGlvbnMuZmlyZWJhc2VDb25maWc7XG4gIGNvbnN0IGFwcCA9IGdldEZpcmViYXNlQXBwKGZpcmViYXNlQ29uZmlnLnByb2plY3RJZCk7XG4gIGNvbnN0IGF1dGggPSBnZXRBdXRoKGFwcCk7XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBsb2dpbiBpcyByZXF1aXJlZCBmb3IgdGhlIHJlcXVlc3QuIEN1cnJlbnRseSByZXR1cm5zIGB0cnVlYCBpZlxuICAgKiB0aGUgVVJMIHBhdGggc3RhcnRzIHdpdGggL2NtcyBvciBpZiA/cHJldmlldz10cnVlIGlzIGluIHRoZSBVUkwuXG4gICAqL1xuICBmdW5jdGlvbiBsb2dpblJlcXVpcmVkKHJlcTogUmVxdWVzdCk6IGJvb2xlYW4ge1xuICAgIGlmIChyZXEub3JpZ2luYWxVcmwuc3RhcnRzV2l0aCgnL2NtcycpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKFN0cmluZyhyZXEucXVlcnkucHJldmlldykgPT09ICd0cnVlJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZmllcyBhIG5ldyBsb2dpbiByZXF1ZXN0IGZvciBhIHVzZXIuIFRoZSByZXF1ZXN0IGJvZHkgc2hvdWxkIGNvbnRhaW5cbiAgICogYW4gaWRUb2tlbiwgd2hpY2ggaXMgdmVyaWZpZWQgb24gcHJvZCB1c2luZyBGaXJlYmFzZSBBZG1pbiBhbmQgSWRlbnRpdHlcbiAgICogVG9vbGtpdC4gSWYgYSBgaXNVc2VyQXV0aG9yaXplZCgpYCBjb25maWcgaXMgc2V0LCB0aGlzIGZ1bmN0aW9uIHdpbGwgYWxzb1xuICAgKiB2ZXJpZnkgdmlhIHRoYXQgZnVuY3Rpb24uIFJldHVybnMgdHJ1ZSBpZiB0aGUgbG9naW4gdmVyaWZpY2F0aW9uIHN1Y2NlZWRzLlxuICAgKi9cbiAgYXN5bmMgZnVuY3Rpb24gdmVyaWZ5VXNlckxvZ2luKHJlcTogUmVxdWVzdCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGlkVG9rZW4gPSByZXEuYm9keT8uaWRUb2tlbjtcbiAgICBpZiAoIWlkVG9rZW4pIHtcbiAgICAgIGNvbnNvbGUubG9nKCdsb2dpbiBmYWlsZWQ6IG5vIGlkIHRva2VuJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gT24gbG9jYWwgZGV2LCBzaW1wbHkgdmVyaWZ5IHRoYXQgYW4gaWRUb2tlbiBpcyBzZXQuIFRoZSBpZGVudGl0eSB0b29sa2l0XG4gICAgLy8gdGhhdCB2ZXJpZmllcyBpZCB0b2tlbnMgcmVxdWlyZXMgYSBzZXJ2aWNlIGFjY291bnQsIHdoaWNoIHdlIHdhbnQgdG9cbiAgICAvLyBhdm9pZCBoYXZpbmcgdG8gc2V0IHVwIHdoZW4gdXNlcnMgYXJlIGRvaW5nIGxvY2FsIGRldmVsb3BtZW50LlxuICAgIC8vIEF1dGhlbnRpY2F0aW9uIGlzIHN0aWxsIHJlcXVpcmVkIGJ5IHRoZSBmcm9udGVuZCB1c2luZyBGaXJlYmFzZSBBdXRoLFxuICAgIC8vIHRoaXMganVzdCBieXBhc3NlcyB0aGUgaW5pdGlhbCBzZXJ2ZXIgY2hlY2sgYmVmb3JlIHRoZSB1aSBpcyByZW5kZXJlZC5cbiAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdkZXZlbG9wbWVudCcpIHtcbiAgICAgIHJldHVybiBCb29sZWFuKGlkVG9rZW4pO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBqd3QgPSBhd2FpdCBhdXRoLnZlcmlmeUlkVG9rZW4oaWRUb2tlbiwgdHJ1ZSk7XG4gICAgICBpZiAoaXNFeHBpcmVkKGp3dCkpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2xvZ2luIGZhaWxlZDogaWQgdG9rZW4gaXMgZXhwaXJlZCcpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAoIWp3dC5lbWFpbCB8fCAhand0LmVtYWlsX3ZlcmlmaWVkKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdsb2dpbiBmYWlsZWQ6IGVtYWlsIHVudmVyaWZpZWQnKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgaWYgKG9wdGlvbnMuaXNVc2VyQXV0aG9yaXplZCkge1xuICAgICAgICBjb25zdCBhdXRob3JpemVkID0gYXdhaXQgb3B0aW9ucy5pc1VzZXJBdXRob3JpemVkKHJlcSwgand0KTtcbiAgICAgICAgaWYgKCFhdXRob3JpemVkKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJ2xvZ2luIGZhaWxlZDogdXNlciBpcyBub3QgYXV0aG9yaXplZCcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhdXRob3JpemVkO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcignZmFpbGVkIHRvIHZlcmlmeSBqd3QgdG9rZW4nKTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLy8gVE9ETyhzdGV2ZW5sZSk6IGRlY2lkZSB3aGV0aGVyIHdlIHdhbnQgdG8gZW5mb3JjZSBgaXNVc2VyQXV0aG9yaXplZCgpYC5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZmllcyB3aGV0aGVyIHRoZSBjdXJyZW50IHVzZXIgc2Vzc2lvbiBzaG91bGQgYmUgYWxsb3dlZCB0byBhY2Nlc3MgdGhlXG4gICAqIENNUy4gUmV0dXJucyB0cnVlIGlmIGFjY2VzcyBpcyBncmFudGVkLlxuICAgKi9cbiAgYXN5bmMgZnVuY3Rpb24gdmVyaWZ5VXNlclNlc3Npb24ocmVxOiBSZXF1ZXN0KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3Qgc2Vzc2lvbkNvb2tpZSA9IHJlcS5zZXNzaW9uLmdldEl0ZW0oU0VTU0lPTl9DT09LSUVfQVVUSCk7XG4gICAgaWYgKCFzZXNzaW9uQ29va2llKSB7XG4gICAgICBjb25zb2xlLmxvZygnc2Vzc2lvbiBmYWlsZWQ6IG5vIHNlc3Npb24gY29va2llJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gT24gbG9jYWwgZGV2LCBzaW1wbHkgdmVyaWZ5IHRoYXQgYW4gc2Vzc2lvbiBjb29raWUgaXMgc2V0LiBTZWUgbm90ZVxuICAgIC8vIGFib3ZlIGluIGB2ZXJpZnlVc2VyTG9naW4oKWAgZm9yIG1vcmUgaW5mb3JtYXRpb24uXG4gICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAnZGV2ZWxvcG1lbnQnKSB7XG4gICAgICByZXR1cm4gQm9vbGVhbihzZXNzaW9uQ29va2llKTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgand0ID0gYXdhaXQgYXV0aC52ZXJpZnlTZXNzaW9uQ29va2llKHNlc3Npb25Db29raWUsIHRydWUpO1xuICAgICAgaWYgKGlzRXhwaXJlZChqd3QpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdzZXNzaW9uIGZhaWxlZDogdG9rZW4gaXMgZXhwaXJlZCcpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAoIWp3dC5lbWFpbCB8fCAhand0LmVtYWlsX3ZlcmlmaWVkKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdzZXNzaW9uIGZhaWxlZDogZW1haWwgbm90IHZlcmlmaWVkJyk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmIChvcHRpb25zLmlzVXNlckF1dGhvcml6ZWQpIHtcbiAgICAgICAgY29uc3QgYXV0aG9yaXplZCA9IGF3YWl0IG9wdGlvbnMuaXNVc2VyQXV0aG9yaXplZChyZXEsIGp3dCk7XG4gICAgICAgIGlmICghYXV0aG9yaXplZCkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdzZXNzaW9uIGZhaWxlZDogbm90IGF1dGhvcml6ZWQnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXV0aG9yaXplZDtcbiAgICAgIH1cbiAgICAgIC8vIFRPRE8oc3RldmVubGUpOiBkZWNpZGUgd2hldGhlciB3ZSB3YW50IHRvIGVuZm9yY2UgYGlzVXNlckF1dGhvcml6ZWQoKWAuXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ2ZhaWxlZCB0byB2ZXJpZnkgand0IHRva2VuJyk7XG4gICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAncm9vdC1jbXMnLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY29uZmlnIG9wdGlvbnMgcGFzc2VkIHRvIHRoZSBwbHVnaW4uXG4gICAgICovXG4gICAgZ2V0Q29uZmlnOiAoKSA9PiB7XG4gICAgICByZXR1cm4gb3B0aW9ucztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgRmlyZWJhc2UgQXBwIGluc3RhbmNlIHVzZWQgYnkgdGhlIHBsdWdpbi5cbiAgICAgKi9cbiAgICBnZXRGaXJlYmFzZUFwcDogKCkgPT4ge1xuICAgICAgcmV0dXJuIGFwcDtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQSBtYXAgb2Ygc3NyIGZpbGVzIHRvIGluY2x1ZGUgd2hlbiBydW5uaW5nIGByb290IGJ1aWxkYC5cbiAgICAgKi9cbiAgICBzc3JJbnB1dDogKCkgPT4gKHtcbiAgICAgIGNtczogcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4vYXBwLmpzJyksXG4gICAgfSksXG5cbiAgICAvKipcbiAgICAgKiBBdHRhY2hlcyBDTVMtc3BlY2lmaWMgbWlkZGxld2FyZSB0byB0aGUgUm9vdC5qcyBzZXJ2ZXIuXG4gICAgICovXG4gICAgY29uZmlndXJlU2VydmVyOiBhc3luYyAoXG4gICAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICAgIHNlcnZlck9wdGlvbnM6IENvbmZpZ3VyZVNlcnZlck9wdGlvbnNcbiAgICApID0+IHtcbiAgICAgIHNlcnZlci51c2UoYm9keVBhcnNlci5qc29uKCkpO1xuXG4gICAgICBhc3luYyBmdW5jdGlvbiBnZXRSZW5kZXJlcihyZXE6IFJlcXVlc3QpOiBQcm9taXNlPEFwcE1vZHVsZT4ge1xuICAgICAgICBpZiAoc2VydmVyT3B0aW9ucy50eXBlID09PSAnZGV2Jykge1xuICAgICAgICAgIGNvbnN0IGFwcEZpbGVQYXRoID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4vYXBwLmpzJyk7XG4gICAgICAgICAgY29uc3QgYXBwID0gKGF3YWl0IHJlcS52aXRlU2VydmVyIS5zc3JMb2FkTW9kdWxlKFxuICAgICAgICAgICAgYXBwRmlsZVBhdGhcbiAgICAgICAgICApKSBhcyBBcHBNb2R1bGU7XG4gICAgICAgICAgcmV0dXJuIGFwcDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFwcEltcG9ydFBhdGggPSBwYXRoLnJlc29sdmUoXG4gICAgICAgICAgcmVxLnJvb3RDb25maWchLnJvb3REaXIsXG4gICAgICAgICAgJ2Rpc3Qvc2VydmVyL2Ntcy5qcydcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCEoYXdhaXQgZmlsZUV4aXN0cyhhcHBJbXBvcnRQYXRoKSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnZGlzdC9zZXJ2ZXIvY21zLmpzIG5vdCBmb3VuZC4gcnVuIGByb290IGJ1aWxkYCB0byBjcmVhdGUgaXQuJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYXBwID0gKGF3YWl0IGltcG9ydChhcHBJbXBvcnRQYXRoKSkgYXMgQXBwTW9kdWxlO1xuICAgICAgICByZXR1cm4gYXBwO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdGF0aWNEaXIgPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAndWknKTtcbiAgICAgIHNlcnZlci51c2UoJy9jbXMvc3RhdGljJywgc2lydihzdGF0aWNEaXIsIHtkZXY6IGZhbHNlfSkpO1xuXG4gICAgICAvLyBMb2dpbiBoYW5kbGVyLlxuICAgICAgc2VydmVyLnVzZSgnL2Ntcy9sb2dpbicsIGFzeW5jIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHJlcS5tZXRob2QgPT09ICdQVVQnICYmXG4gICAgICAgICAgcmVxLmhlYWRlcnNbJ2NvbnRlbnQtdHlwZSddID09PSAnYXBwbGljYXRpb24vanNvbidcbiAgICAgICAgKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGlzQXV0aG9yaXplZCA9IGF3YWl0IHZlcmlmeVVzZXJMb2dpbihyZXEpO1xuICAgICAgICAgICAgaWYgKCFpc0F1dGhvcml6ZWQpIHtcbiAgICAgICAgICAgICAgcmVzLnN0YXR1cyg0MDEpLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogJ05PVF9BVVRIT1JJWkVEJ30pO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCBzZXNzaW9uIGV4cGlyYXRpb24gdG8gNSBkYXlzLlxuICAgICAgICAgICAgY29uc3QgZXhwaXJlc0luID0gNjAgKiA2MCAqIDI0ICogNSAqIDEwMDA7XG4gICAgICAgICAgICBjb25zdCBpZFRva2VuID0gcmVxLmJvZHkuaWRUb2tlbiE7XG5cbiAgICAgICAgICAgIGxldCBzZXNzaW9uQ29va2llOiBzdHJpbmc7XG4gICAgICAgICAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdkZXZlbG9wbWVudCcpIHtcbiAgICAgICAgICAgICAgc2Vzc2lvbkNvb2tpZSA9IGlkVG9rZW47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzZXNzaW9uQ29va2llID0gYXdhaXQgYXV0aC5jcmVhdGVTZXNzaW9uQ29va2llKGlkVG9rZW4sIHtcbiAgICAgICAgICAgICAgICBleHBpcmVzSW4sXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzLnNlc3Npb24uc2V0SXRlbShTRVNTSU9OX0NPT0tJRV9BVVRILCBzZXNzaW9uQ29va2llKTtcbiAgICAgICAgICAgIHJlcy5zYXZlU2Vzc2lvbigpO1xuICAgICAgICAgICAgcmVzLmpzb24oe3N1Y2Nlc3M6IHRydWV9KTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIGlmIChlcnIuc3RhY2spIHtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzXG4gICAgICAgICAgICAgIC5zdGF0dXMoNTAwKVxuICAgICAgICAgICAgICAuanNvbih7c3VjY2VzczogZmFsc2UsIGVycm9yOiAnVU5LTk9XTl9TRVJWRVJfRVJST1InfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgYXBwID0gYXdhaXQgZ2V0UmVuZGVyZXIocmVxKTtcbiAgICAgICAgICBhcHAucmVuZGVyU2lnbkluKHJlcSwgcmVzLCBvcHRpb25zKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgICAgIGlmIChlcnIuc3RhY2spIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyLnN0YWNrKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzLnN0YXR1cyg1MDApLnNlbmQoJ1VOS05PV04gU0VSVkVSIEVSUk9SJyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBMb2dvdXQgaGFuZGxlci5cbiAgICAgIHNlcnZlci51c2UoJy9jbXMvbG9nb3V0JywgYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgICByZXMuc2Vzc2lvbi5yZW1vdmVJdGVtKFNFU1NJT05fQ09PS0lFX0FVVEgpO1xuICAgICAgICByZXMuc2F2ZVNlc3Npb24oKTtcbiAgICAgICAgcmVzLnJlZGlyZWN0KCcvY21zL2xvZ2luJyk7XG4gICAgICB9KTtcblxuICAgICAgLy8gU2FmZWd1YXJkIHRvIHZlcmlmeSB1c2VyIGxvZ2luIGJlZm9yZSByZW5kZXJpbmcgYW55IENNUyBwYWdlLlxuICAgICAgc2VydmVyLnVzZShhc3luYyAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHtcbiAgICAgICAgaWYgKCFsb2dpblJlcXVpcmVkKHJlcSkpIHtcbiAgICAgICAgICBuZXh0KCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHVzZXJJc0xvZ2dlZEluID0gYXdhaXQgdmVyaWZ5VXNlclNlc3Npb24ocmVxKTtcbiAgICAgICAgaWYgKHVzZXJJc0xvZ2dlZEluKSB7XG4gICAgICAgICAgbmV4dCgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVxLm9yaWdpbmFsVXJsLnN0YXJ0c1dpdGgoJy9jbXMvYXBpJykpIHtcbiAgICAgICAgICByZXMuc3RhdHVzKDQwMSkuanNvbih7c3VjY2VzczogZmFsc2UsIGVycm9yOiAnTk9UX0FVVEhPUklaRUQnfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUubG9nKCdyZWRpcmVjdGluZyB0byBsb2dpbiBwYWdlJyk7XG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoe1xuICAgICAgICAgIGNvbnRpbnVlOiByZXEub3JpZ2luYWxVcmwsXG4gICAgICAgIH0pO1xuICAgICAgICByZXMucmVkaXJlY3QoYC9jbXMvbG9naW4/JHtwYXJhbXMudG9TdHJpbmcoKX1gKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBSZWdpc3RlciBBUEkgaGFuZGxlcnMuXG4gICAgICBhcGkoc2VydmVyKTtcblxuICAgICAgLy8gUmVuZGVyIHRoZSBDTVMgU1BBLlxuICAgICAgc2VydmVyLnVzZSgnL2NtcycsIGFzeW5jIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBhcHAgPSBhd2FpdCBnZXRSZW5kZXJlcihyZXEpO1xuICAgICAgICAgIGF3YWl0IGFwcC5yZW5kZXJBcHAocmVxLCByZXMsIHtcbiAgICAgICAgICAgIHJvb3RDb25maWc6IHJlcS5yb290Q29uZmlnLFxuICAgICAgICAgICAgY21zQ29uZmlnOiBvcHRpb25zLFxuICAgICAgICAgICAgZmlyZWJhc2VDb25maWc6IG9wdGlvbnMuZmlyZWJhc2VDb25maWcsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIC8vIFRPRE8oc3RldmVubGUpOiByZW5kZXIgYSBjdXN0b20gZXJyb3IgcGFnZS5cbiAgICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICAgICAgcmVzLnN0YXR1cyg1MDApLnNlbmQoJ1VOS05PV04gU0VSVkVSIEVSUk9SJyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0sXG4gIH07XG59XG5cbmZ1bmN0aW9uIGZpbGVFeGlzdHMoZmlsZXBhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICByZXR1cm4gZnNcbiAgICAuYWNjZXNzKGZpbGVwYXRoKVxuICAgIC50aGVuKCgpID0+IHRydWUpXG4gICAgLmNhdGNoKCgpID0+IGZhbHNlKTtcbn1cbiIsICJpbXBvcnQge1NlcnZlciwgUmVxdWVzdCwgUmVzcG9uc2V9IGZyb20gJ0BibGlua2svcm9vdCc7XG5pbXBvcnQge211bHRpcGFydE1pZGRsZXdhcmV9IGZyb20gJ0BibGlua2svcm9vdC9taWRkbGV3YXJlJztcbmltcG9ydCB7cnVuQ3JvbkpvYnN9IGZyb20gJy4vY3Jvbi5qcyc7XG5pbXBvcnQge2FycmF5VG9Dc3YsIGNzdlRvQXJyYXl9IGZyb20gJy4vY3N2LmpzJztcblxuLyoqXG4gKiBSZWdpc3RlcnMgQVBJIG1pZGRsZXdhcmUgaGFuZGxlcnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcGkoc2VydmVyOiBTZXJ2ZXIpIHtcbiAgLyoqXG4gICAqIFJ1bnMgQ01TIGNyb24gam9icy5cbiAgICovXG4gIHNlcnZlci51c2UoJy9jbXMvYXBpL2Nyb24ucnVuJywgYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBydW5Dcm9uSm9icyhyZXEucm9vdENvbmZpZyEpO1xuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oe3N1Y2Nlc3M6IHRydWV9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZX0pO1xuICAgIH1cbiAgfSk7XG5cbiAgLyoqXG4gICAqIEFjY2VwdHMgYSBKU09OIG9iamVjdCBjb250YWluaW5nIHtoZWFkZXJzOiBbLi4uXSwgcm93czogWy4uLl19IGFuZCBzZW5kc1xuICAgKiBhbiBIVFRQIHJlc3BvbnNlIHdpdGggYSBjb3JyZXNwb25kaW5nIENTViBmaWxlIGFzIGFuIGF0dGFjaG1lbnQuXG4gICAqXG4gICAqIFNhbXBsZSByZXF1ZXN0OlxuICAgKlxuICAgKiBgYGBqc29uXG4gICAqIHtcbiAgICogICBcImhlYWRlcnNcIjogW1wiZm9vXCJdLFxuICAgKiAgIFwicm93c1wiOiBbXG4gICAqICAgICB7XCJmb29cIjogXCJiYXJcIn0sXG4gICAqICAgICB7XCJmb29cIjogXCJiYXpcIn0sXG4gICAqICAgXVxuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgc2VydmVyLnVzZSgnL2Ntcy9hcGkvY3N2LmRvd25sb2FkJywgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIGlmIChcbiAgICAgIHJlcS5tZXRob2QgIT09ICdQT1NUJyB8fFxuICAgICAgIVN0cmluZyhyZXEuZ2V0KCdjb250ZW50LXR5cGUnKSkuc3RhcnRzV2l0aCgnYXBwbGljYXRpb24vanNvbicpXG4gICAgKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7c3VjY2VzczogZmFsc2UsIGVycm9yOiAnQkFEX1JFUVVFU1QnfSk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGJvZHkgPSByZXEuYm9keSB8fCB7fTtcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSBib2R5LmhlYWRlcnMgfHwgW107XG4gICAgICBjb25zdCByb3dzID0gYm9keS5yb3dzIHx8IFtdO1xuICAgICAgY29uc3QgY3N2ID0gYXJyYXlUb0Nzdih7aGVhZGVycywgcm93c30pO1xuICAgICAgcmVzLnNldEhlYWRlcignQ29udGVudC1UeXBlJywgJ3RleHQvY3N2Jyk7XG4gICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LURpc3Bvc2l0aW9uJywgJ2F0dGFjaG1lbnQ7IGZpbGVuYW1lPVwiZGF0YS5jc3ZcIicpO1xuICAgICAgcmVzLnN0YXR1cygyMDApLmVuZChjc3YpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2sgfHwgZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdVTktOT1dOJ30pO1xuICAgIH1cbiAgfSk7XG5cbiAgLyoqXG4gICAqIEltcG9ydHMgYSBDU1YgZmlsZSBhbmQgcmV0dXJucyBhIEpTT04gYXJyYXkgb2Ygb2JqZWN0cyByZXByZXNlbnRpbmcgdGhlXG4gICAqIENTVi5cbiAgICpcbiAgICogU2FtcGxlIHJlc3BvbnNlOlxuICAgKlxuICAgKiBgYGBqc29uXG4gICAqIHtcbiAgICogICBcInN1Y2Nlc3NcIjogdHJ1ZSxcbiAgICogICBcImRhdGFcIjogW1xuICAgKiAgICAge1wiZm9vXCI6IFwiYmFyXCJ9LFxuICAgKiAgICAge1wiZm9vXCI6IFwiYmF6XCJ9LFxuICAgKiAgIF1cbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIHNlcnZlci51c2UoXG4gICAgJy9jbXMvYXBpL2Nzdi5pbXBvcnQnLFxuICAgIG11bHRpcGFydE1pZGRsZXdhcmUoKSxcbiAgICAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgICBpZiAocmVxLm1ldGhvZCAhPT0gJ1BPU1QnIHx8ICFyZXEuZmlsZXMgfHwgIXJlcS5maWxlcy5maWxlKSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgZXJyb3I6ICdCQURfUkVRVUVTVCd9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBmaWxlID0gcmVxLmZpbGVzLmZpbGU7XG4gICAgICAgIGNvbnN0IGNzdlN0cmluZyA9IGZpbGUuYnVmZmVyLnRvU3RyaW5nKCd1dGY4Jyk7XG4gICAgICAgIGNvbnN0IHJvd3MgPSBjc3ZUb0FycmF5KGNzdlN0cmluZyk7XG4gICAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtzdWNjZXNzOiB0cnVlLCBkYXRhOiByb3dzfSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2sgfHwgZXJyKTtcbiAgICAgICAgcmVzLnN0YXR1cyg1MDApLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogJ1VOS05PV04nfSk7XG4gICAgICB9XG4gICAgfVxuICApO1xufVxuIiwgImltcG9ydCB7UGx1Z2luLCBSb290Q29uZmlnfSBmcm9tICdAYmxpbmtrL3Jvb3QnO1xuaW1wb3J0IHtcbiAgRmllbGRWYWx1ZSxcbiAgUXVlcnksXG4gIFRpbWVzdGFtcCxcbiAgZ2V0RmlyZXN0b3JlLFxufSBmcm9tICdmaXJlYmFzZS1hZG1pbi9maXJlc3RvcmUnO1xuXG5pbXBvcnQge0NNU1BsdWdpbn0gZnJvbSAnLi9wbHVnaW4uanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdldERvY09wdGlvbnMge1xuICBtb2RlOiAnZHJhZnQnIHwgJ3B1Ymxpc2hlZCc7XG59XG5cbi8qKlxuICogUmV0cmlldmVzIGEgZG9jIGZyb20gUm9vdC5qcyBDTVMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXREb2M8VD4oXG4gIHJvb3RDb25maWc6IFJvb3RDb25maWcsXG4gIGNvbGxlY3Rpb25JZDogc3RyaW5nLFxuICBzbHVnOiBzdHJpbmcsXG4gIG9wdGlvbnM6IEdldERvY09wdGlvbnNcbik6IFByb21pc2U8VCB8IG51bGw+IHtcbiAgY29uc3QgY21zUGx1Z2luID0gZ2V0Q21zUGx1Z2luKHJvb3RDb25maWcpO1xuICBjb25zdCBjbXNQbHVnaW5PcHRpb25zID0gY21zUGx1Z2luLmdldENvbmZpZygpO1xuICBjb25zdCBwcm9qZWN0SWQgPSBjbXNQbHVnaW5PcHRpb25zLmlkIHx8ICdkZWZhdWx0JztcbiAgY29uc3QgbW9kZSA9IG9wdGlvbnMubW9kZTtcbiAgY29uc3QgbW9kZUNvbGxlY3Rpb24gPSBtb2RlID09PSAnZHJhZnQnID8gJ0RyYWZ0cycgOiAnUHVibGlzaGVkJztcbiAgY29uc3QgYXBwID0gY21zUGx1Z2luLmdldEZpcmViYXNlQXBwKCk7XG4gIGNvbnN0IGRiID0gZ2V0RmlyZXN0b3JlKGFwcCk7XG4gIC8vIFNsdWdzIHdpdGggc2xhc2hlcyBhcmUgZW5jb2RlZCBhcyBgLS1gIGluIHRoZSBEQi5cbiAgc2x1ZyA9IHNsdWcucmVwbGFjZUFsbCgnLycsICctLScpO1xuICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHtwcm9qZWN0SWR9L0NvbGxlY3Rpb25zLyR7Y29sbGVjdGlvbklkfS8ke21vZGVDb2xsZWN0aW9ufS8ke3NsdWd9YDtcbiAgY29uc3QgZG9jUmVmID0gZGIuZG9jKGRiUGF0aCk7XG4gIGNvbnN0IGRvYyA9IGF3YWl0IGRvY1JlZi5nZXQoKTtcbiAgaWYgKGRvYy5leGlzdHMpIHtcbiAgICBjb25zdCBkYXRhID0gZG9jLmRhdGEoKTtcbiAgICByZXR1cm4gbm9ybWFsaXplRGF0YShkYXRhKSBhcyBUO1xuICB9XG4gIGNvbnNvbGUubG9nKGBkb2Mgbm90IGZvdW5kOiAke2RiUGF0aH1gKTtcbiAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGlzdERvY3NPcHRpb25zIHtcbiAgbW9kZTogJ2RyYWZ0JyB8ICdwdWJsaXNoZWQnO1xuICBvZmZzZXQ/OiBudW1iZXI7XG4gIGxpbWl0PzogbnVtYmVyO1xuICBvcmRlckJ5Pzogc3RyaW5nO1xuICBvcmRlckJ5RGlyZWN0aW9uPzogJ2FzYycgfCAnZGVzYyc7XG4gIHF1ZXJ5PzogKHF1ZXJ5OiBRdWVyeSkgPT4gUXVlcnk7XG59XG5cbi8qKlxuICogTGlzdHMgZG9jcyBmcm9tIGEgUm9vdC5qcyBDTVMgY29sbGVjdGlvbi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxpc3REb2NzPFQ+KFxuICByb290Q29uZmlnOiBSb290Q29uZmlnLFxuICBjb2xsZWN0aW9uSWQ6IHN0cmluZyxcbiAgb3B0aW9uczogTGlzdERvY3NPcHRpb25zXG4pOiBQcm9taXNlPHtkb2NzOiBUW119PiB7XG4gIGNvbnN0IGNtc1BsdWdpbiA9IGdldENtc1BsdWdpbihyb290Q29uZmlnKTtcbiAgY29uc3QgY21zUGx1Z2luT3B0aW9ucyA9IGNtc1BsdWdpbi5nZXRDb25maWcoKTtcbiAgY29uc3QgcHJvamVjdElkID0gY21zUGx1Z2luT3B0aW9ucy5pZCB8fCAnZGVmYXVsdCc7XG4gIGNvbnN0IG1vZGUgPSBvcHRpb25zLm1vZGU7XG4gIGNvbnN0IG1vZGVDb2xsZWN0aW9uID0gbW9kZSA9PT0gJ2RyYWZ0JyA/ICdEcmFmdHMnIDogJ1B1Ymxpc2hlZCc7XG4gIGNvbnN0IGFwcCA9IGNtc1BsdWdpbi5nZXRGaXJlYmFzZUFwcCgpO1xuICBjb25zdCBkYiA9IGdldEZpcmVzdG9yZShhcHApO1xuICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHtwcm9qZWN0SWR9L0NvbGxlY3Rpb25zLyR7Y29sbGVjdGlvbklkfS8ke21vZGVDb2xsZWN0aW9ufWA7XG4gIGxldCBxdWVyeTogUXVlcnkgPSBkYi5jb2xsZWN0aW9uKGRiUGF0aCk7XG4gIGlmIChvcHRpb25zLmxpbWl0KSB7XG4gICAgcXVlcnkgPSBxdWVyeS5saW1pdChvcHRpb25zLmxpbWl0KTtcbiAgfVxuICBpZiAob3B0aW9ucy5vZmZzZXQpIHtcbiAgICBxdWVyeSA9IHF1ZXJ5Lm9mZnNldChvcHRpb25zLm9mZnNldCk7XG4gIH1cbiAgaWYgKG9wdGlvbnMub3JkZXJCeSkge1xuICAgIHF1ZXJ5ID0gcXVlcnkub3JkZXJCeShvcHRpb25zLm9yZGVyQnksIG9wdGlvbnMub3JkZXJCeURpcmVjdGlvbik7XG4gIH1cbiAgaWYgKG9wdGlvbnMucXVlcnkpIHtcbiAgICBxdWVyeSA9IG9wdGlvbnMucXVlcnkocXVlcnkpO1xuICB9XG4gIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBxdWVyeS5nZXQoKTtcbiAgY29uc3QgZG9jczogVFtdID0gW107XG4gIHJlc3VsdHMuZm9yRWFjaCgocmVzdWx0KSA9PiB7XG4gICAgY29uc3QgZG9jID0gbm9ybWFsaXplRGF0YShyZXN1bHQuZGF0YSgpKSBhcyBUO1xuICAgIGRvY3MucHVzaChkb2MpO1xuICB9KTtcbiAgcmV0dXJuIHtkb2NzfTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBOdW1Eb2NzT3B0aW9ucyB7XG4gIG1vZGU6ICdkcmFmdCcgfCAncHVibGlzaGVkJztcbiAgcXVlcnk/OiAocXVlcnk6IFF1ZXJ5KSA9PiBRdWVyeTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZG9jcyBpbiBhIFJvb3QuanMgQ01TIGNvbGxlY3Rpb24uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBudW1Eb2NzKFxuICByb290Q29uZmlnOiBSb290Q29uZmlnLFxuICBjb2xsZWN0aW9uSWQ6IHN0cmluZyxcbiAgb3B0aW9uczogTnVtRG9jc09wdGlvbnNcbikge1xuICBjb25zdCBjbXNQbHVnaW4gPSBnZXRDbXNQbHVnaW4ocm9vdENvbmZpZyk7XG4gIGNvbnN0IGNtc1BsdWdpbk9wdGlvbnMgPSBjbXNQbHVnaW4uZ2V0Q29uZmlnKCk7XG4gIGNvbnN0IHByb2plY3RJZCA9IGNtc1BsdWdpbk9wdGlvbnMuaWQgfHwgJ2RlZmF1bHQnO1xuICBjb25zdCBtb2RlID0gb3B0aW9ucy5tb2RlO1xuICBjb25zdCBtb2RlQ29sbGVjdGlvbiA9IG1vZGUgPT09ICdkcmFmdCcgPyAnRHJhZnRzJyA6ICdQdWJsaXNoZWQnO1xuICBjb25zdCBhcHAgPSBjbXNQbHVnaW4uZ2V0RmlyZWJhc2VBcHAoKTtcbiAgY29uc3QgZGIgPSBnZXRGaXJlc3RvcmUoYXBwKTtcbiAgY29uc3QgZGJQYXRoID0gYFByb2plY3RzLyR7cHJvamVjdElkfS9Db2xsZWN0aW9ucy8ke2NvbGxlY3Rpb25JZH0vJHttb2RlQ29sbGVjdGlvbn1gO1xuICBsZXQgcXVlcnk6IFF1ZXJ5ID0gZGIuY29sbGVjdGlvbihkYlBhdGgpO1xuICBpZiAob3B0aW9ucy5xdWVyeSkge1xuICAgIHF1ZXJ5ID0gb3B0aW9ucy5xdWVyeShxdWVyeSk7XG4gIH1cbiAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHF1ZXJ5LmNvdW50KCkuZ2V0KCk7XG4gIGNvbnN0IGNvdW50ID0gcmVzdWx0cy5kYXRhKCkuY291bnQ7XG4gIHJldHVybiBjb3VudDtcbn1cblxuLyoqXG4gKiBQdWJsaXNoZXMgc2NoZWR1bGVkIGRvY3MuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwdWJsaXNoU2NoZWR1bGVkRG9jcyhyb290Q29uZmlnOiBSb290Q29uZmlnKSB7XG4gIGNvbnN0IGNtc1BsdWdpbiA9IGdldENtc1BsdWdpbihyb290Q29uZmlnKTtcbiAgY29uc3QgY21zUGx1Z2luT3B0aW9ucyA9IGNtc1BsdWdpbi5nZXRDb25maWcoKTtcbiAgY29uc3QgcHJvamVjdElkID0gY21zUGx1Z2luT3B0aW9ucy5pZCB8fCAnZGVmYXVsdCc7XG4gIGNvbnN0IGFwcCA9IGNtc1BsdWdpbi5nZXRGaXJlYmFzZUFwcCgpO1xuICBjb25zdCBkYiA9IGdldEZpcmVzdG9yZShhcHApO1xuXG4gIGNvbnN0IHByb2plY3RDb2xsZWN0aW9uc1BhdGggPSBgUHJvamVjdHMvJHtwcm9qZWN0SWR9L0NvbGxlY3Rpb25zYDtcbiAgY29uc3Qgbm93ID0gTWF0aC5jZWlsKG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcblxuICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IGRiLmNvbGxlY3Rpb25Hcm91cCgnU2NoZWR1bGVkJykuZ2V0KCk7XG4gIGNvbnN0IGRvY3MgPSBzbmFwc2hvdC5kb2NzXG4gICAgLmZpbHRlcigoZCkgPT4ge1xuICAgICAgLy8gRmlsdGVyIGRvY3MgYnkgcHJvamVjdC5cbiAgICAgIGlmICghZC5yZWYucGF0aC5zdGFydHNXaXRoKHByb2plY3RDb2xsZWN0aW9uc1BhdGgpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIC8vIEZpbHRlciBkb2NzIHdoZXJlIHNjaGVkdWxlZEF0IGlzIGluIHRoZSBwYXN0LlxuICAgICAgLy8gTk9URShzdGV2ZW5sZSk6IHRoZSBmaWx0ZXJpbmcgaXMgZG9uZSBtYW51YWxseSBpbnN0ZWFkIG9mIHVzaW5nIGEgcXVlcnlcbiAgICAgIC8vIHRvIGF2b2lkIGhhdmluZyB0byBjcmVhdGUgYW4gaW5kZXggaW4gZmlyZXN0b3JlLlxuICAgICAgY29uc3QgZGF0YSA9IGQuZGF0YSgpIHx8IHt9O1xuICAgICAgY29uc3Qgc2NoZWR1bGVkQXQ6IFRpbWVzdGFtcCB8IHVuZGVmaW5lZCA9IGRhdGEuc3lzPy5zY2hlZHVsZWRBdDtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIHNjaGVkdWxlZEF0ICYmIHNjaGVkdWxlZEF0LnRvTWlsbGlzICYmIHNjaGVkdWxlZEF0LnRvTWlsbGlzKCkgPD0gbm93XG4gICAgICApO1xuICAgIH0pXG4gICAgLm1hcCgoZCkgPT4ge1xuICAgICAgY29uc3QgZGJQYXRoID0gZC5yZWYucGF0aDtcbiAgICAgIGNvbnN0IHNlZ21lbnRzID0gZGJQYXRoLnNwbGl0KCcvJyk7XG4gICAgICBjb25zdCBzbHVnID0gc2VnbWVudHMuYXQoLTEpO1xuICAgICAgY29uc3QgY29sbGVjdGlvbiA9IHNlZ21lbnRzLmF0KC0zKTtcbiAgICAgIGNvbnN0IGlkID0gYCR7Y29sbGVjdGlvbn0vJHtzbHVnfWA7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBkYXRhOiBkLmRhdGEoKSxcbiAgICAgICAgaWQsXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIHNsdWcsXG4gICAgICB9O1xuICAgIH0pO1xuXG4gIGlmIChkb2NzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIC8vIEVhY2ggdHJhbnNhY3Rpb24gb3IgYmF0Y2ggY2FuIHdyaXRlIGEgbWF4IG9mIDUwMCBvcHMuXG4gIC8vIGh0dHBzOi8vZmlyZWJhc2UuZ29vZ2xlLmNvbS9kb2NzL2ZpcmVzdG9yZS9tYW5hZ2UtZGF0YS90cmFuc2FjdGlvbnNcbiAgbGV0IGJhdGNoQ291bnQgPSAwO1xuICBjb25zdCBiYXRjaCA9IGRiLmJhdGNoKCk7XG4gIGNvbnN0IHB1Ymxpc2hlZERvY3M6IGFueVtdID0gW107XG4gIGZvciAoY29uc3QgZG9jIG9mIGRvY3MpIHtcbiAgICBjb25zdCB7aWQsIGNvbGxlY3Rpb24sIHNsdWcsIGRhdGF9ID0gZG9jO1xuICAgIGNvbnN0IGRyYWZ0UmVmID0gZGIuZG9jKFxuICAgICAgYCR7cHJvamVjdENvbGxlY3Rpb25zUGF0aH0vJHtjb2xsZWN0aW9ufS9EcmFmdHMvJHtzbHVnfWBcbiAgICApO1xuICAgIGNvbnN0IHNjaGVkdWxlZFJlZiA9IGRiLmRvYyhcbiAgICAgIGAke3Byb2plY3RDb2xsZWN0aW9uc1BhdGh9LyR7Y29sbGVjdGlvbn0vU2NoZWR1bGVkLyR7c2x1Z31gXG4gICAgKTtcbiAgICBjb25zdCBwdWJsaXNoZWRSZWYgPSBkYi5kb2MoXG4gICAgICBgJHtwcm9qZWN0Q29sbGVjdGlvbnNQYXRofS8ke2NvbGxlY3Rpb259L1B1Ymxpc2hlZC8ke3NsdWd9YFxuICAgICk7XG4gICAgY29uc3Qge3NjaGVkdWxlZEF0LCBzY2hlZHVsZWRCeSwgLi4uc3lzfSA9IGRhdGEuc3lzIHx8IHt9O1xuXG4gICAgLy8gT25seSB1cGRhdGUgYGZpcnN0UHVibGlzaGVkYCBpZiBpdCBkb2Vzbid0IGFscmVhZHkgZXhpc3QuXG4gICAgY29uc3QgZmlyc3RQdWJsaXNoZWRBdCA9IHN5cy5maXJzdFB1Ymxpc2hlZEF0ID8/IHNjaGVkdWxlZEF0O1xuICAgIGNvbnN0IGZpcnN0UHVibGlzaGVkQnkgPSBzeXMuZmlyc3RQdWJsaXNoZWRCeSA/PyAoc2NoZWR1bGVkQnkgfHwgJycpO1xuXG4gICAgLy8gU2F2ZSBwdWJsaXNoZWQgZG9jLlxuICAgIGJhdGNoLnNldChwdWJsaXNoZWRSZWYsIHtcbiAgICAgIGlkLFxuICAgICAgY29sbGVjdGlvbixcbiAgICAgIHNsdWcsXG4gICAgICBmaWVsZHM6IGRhdGEuZmllbGRzIHx8IHt9LFxuICAgICAgc3lzOiB7XG4gICAgICAgIC4uLnN5cyxcbiAgICAgICAgZmlyc3RQdWJsaXNoZWRBdDogZmlyc3RQdWJsaXNoZWRBdCxcbiAgICAgICAgZmlyc3RQdWJsaXNoZWRCeTogZmlyc3RQdWJsaXNoZWRCeSxcbiAgICAgICAgcHVibGlzaGVkQXQ6IEZpZWxkVmFsdWUuc2VydmVyVGltZXN0YW1wKCksXG4gICAgICAgIHB1Ymxpc2hlZEJ5OiBzY2hlZHVsZWRCeSB8fCAnJyxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgYmF0Y2hDb3VudCArPSAxO1xuXG4gICAgLy8gUmVtb3ZlIHB1Ymxpc2hlZCBkb2MuXG4gICAgYmF0Y2guZGVsZXRlKHNjaGVkdWxlZFJlZik7XG4gICAgYmF0Y2hDb3VudCArPSAxO1xuXG4gICAgLy8gVXBkYXRlIHRoZSBkcmFmdCBkb2MgdG8gcmVtb3ZlIGBzY2hlZHVsZWRBdGAgYW5kIGBzY2hlZHVsZWRCeWAgZmllbGRzXG4gICAgLy8gYW5kIHVwZGF0ZSB0aGUgYHB1Ymxpc2hlZEF0YCBhbmQgYHB1Ymxpc2hlZEJ5YCBmaWVsZHMuXG4gICAgYmF0Y2gudXBkYXRlKGRyYWZ0UmVmLCB7XG4gICAgICAnc3lzLnNjaGVkdWxlZEF0JzogRmllbGRWYWx1ZS5kZWxldGUoKSxcbiAgICAgICdzeXMuc2NoZWR1bGVkQnknOiBGaWVsZFZhbHVlLmRlbGV0ZSgpLFxuICAgICAgJ3N5cy5maXJzdFB1Ymxpc2hlZEF0JzogZmlyc3RQdWJsaXNoZWRBdCxcbiAgICAgICdzeXMuZmlyc3RQdWJsaXNoZWRCeSc6IGZpcnN0UHVibGlzaGVkQnksXG4gICAgICAnc3lzLnB1Ymxpc2hlZEF0JzogRmllbGRWYWx1ZS5zZXJ2ZXJUaW1lc3RhbXAoKSxcbiAgICAgICdzeXMucHVibGlzaGVkQnknOiBzY2hlZHVsZWRCeSB8fCAnJyxcbiAgICB9KTtcbiAgICBiYXRjaENvdW50ICs9IDE7XG5cbiAgICBwdWJsaXNoZWREb2NzLnB1c2goZG9jKTtcblxuICAgIGlmIChiYXRjaENvdW50ID49IDQ5OCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgYXdhaXQgYmF0Y2guY29tbWl0KCk7XG4gIGNvbnNvbGUubG9nKGBwdWJsaXNoZWQgJHtwdWJsaXNoZWREb2NzLmxlbmd0aH0gZG9jcyFgKTtcbiAgcmV0dXJuIHB1Ymxpc2hlZERvY3M7XG59XG5cbi8qKlxuICogV2Fsa3MgdGhlIGRhdGEgdHJlZSBhbmQgY29udmVydHMgYW55IFRpbWVzdGFtcCBvYmplY3RzIHRvIG1pbGxpcyBhbmQgYW55XG4gKiBfYXJyYXkgbWFwcyB0byBub3JtYWwgYXJyYXlzLlxuICpcbiAqIEUuZy46XG4gKlxuICogbm9ybWFsaXplRGF0YSh7XG4gKiAgIHN5czoge21vZGlmaWVkQXQ6IFRpbWVzdGFtcCgxMjMpfSxcbiAqICAgZmllbGRzOiB7XG4gKiAgICAgX2FycmF5OiBbJ2FzZGYnXSxcbiAqICAgICBhc2RmOiB7dGl0bGU6ICdoZWxsbyd9XG4gKiAgIH1cbiAqIH0pXG4gKiAvLyA9PiB7c3lzOiB7bW9kaWZpZWRBdDogMTIzfSwgZmllbGRzOiB7Zm9vOiBbe3RpdGxlOiAnaGVsbG8nfV19fVxuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplRGF0YShkYXRhOiBhbnkpOiBhbnkge1xuICBjb25zdCByZXN1bHQ6IGFueSA9IHt9O1xuICBmb3IgKGNvbnN0IGtleSBpbiBkYXRhKSB7XG4gICAgY29uc3QgdmFsID0gZGF0YVtrZXldO1xuICAgIGlmIChpc09iamVjdCh2YWwpKSB7XG4gICAgICBpZiAodmFsLnRvTWlsbGlzKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gdmFsLnRvTWlsbGlzKCk7XG4gICAgICB9IGVsc2UgaWYgKE9iamVjdC5oYXNPd24odmFsLCAnX2FycmF5JykgJiYgQXJyYXkuaXNBcnJheSh2YWwuX2FycmF5KSkge1xuICAgICAgICBjb25zdCBhcnIgPSB2YWwuX2FycmF5Lm1hcCgoazogc3RyaW5nKSA9PiBub3JtYWxpemVEYXRhKHZhbFtrXSB8fCB7fSkpO1xuICAgICAgICByZXN1bHRba2V5XSA9IGFycjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gbm9ybWFsaXplRGF0YSh2YWwpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHRba2V5XSA9IHZhbDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gaXNPYmplY3QoZGF0YTogYW55KTogYm9vbGVhbiB7XG4gIHJldHVybiB0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkoZGF0YSkgJiYgZGF0YSAhPT0gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENtc1BsdWdpbihyb290Q29uZmlnOiBSb290Q29uZmlnKTogQ01TUGx1Z2luIHtcbiAgY29uc3QgcGx1Z2luczogUGx1Z2luW10gPSByb290Q29uZmlnLnBsdWdpbnMgfHwgW107XG4gIGNvbnN0IHBsdWdpbiA9IHBsdWdpbnMuZmluZCgocGx1Z2luKSA9PiBwbHVnaW4ubmFtZSA9PT0gJ3Jvb3QtY21zJyk7XG4gIGlmICghcGx1Z2luKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb3VsZCBub3QgZmluZCByb290LWNtcyBwbHVnaW4gY29uZmlnIGluIHJvb3QuY29uZmlnLnRzJyk7XG4gIH1cbiAgcmV0dXJuIHBsdWdpbiBhcyBDTVNQbHVnaW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNsYXRpb24ge1xuICBbbG9jYWxlOiBzdHJpbmddOiBzdHJpbmc7XG4gIHNvdXJjZTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRyYW5zbGF0aW9uc01hcCB7XG4gIFtoYXNoOiBzdHJpbmddOiBUcmFuc2xhdGlvbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBMb2NhbGVUcmFuc2xhdGlvbnMge1xuICBbc291cmNlOiBzdHJpbmddOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9hZFRyYW5zbGF0aW9uc09wdGlvbnMge1xuICB0YWdzPzogc3RyaW5nW107XG59XG5cbi8qKlxuICogTG9hZHMgdHJhbnNsYXRpb25zIHNhdmVkIGluIHRoZSB0cmFzbmxhdGlvbnMgY29sbGVjdGlvbiwgb3B0aW9uYWxseSBmaWx0ZXJlZFxuICogYnkgdGFnLlxuICpcbiAqIFJldHVybnMgYSBtYXAgbGlrZTpcbiAqIGBgYFxuICoge1xuICogICBcIjxoYXNoPlwiOiB7XCJzb3VyY2VcIjogXCJIZWxsb1wiLCBcImVzXCI6IFwiSG9sYVwiLCBcImZyXCI6IFwiQm9uam91clwifSxcbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbG9hZFRyYW5zbGF0aW9ucyhcbiAgcm9vdENvbmZpZzogUm9vdENvbmZpZyxcbiAgb3B0aW9ucz86IExvYWRUcmFuc2xhdGlvbnNPcHRpb25zXG4pOiBQcm9taXNlPFRyYW5zbGF0aW9uc01hcD4ge1xuICBjb25zdCBjbXNQbHVnaW4gPSBnZXRDbXNQbHVnaW4ocm9vdENvbmZpZyk7XG4gIGNvbnN0IGNtc1BsdWdpbk9wdGlvbnMgPSBjbXNQbHVnaW4uZ2V0Q29uZmlnKCk7XG4gIGNvbnN0IHByb2plY3RJZCA9IGNtc1BsdWdpbk9wdGlvbnMuaWQgfHwgJ2RlZmF1bHQnO1xuICBjb25zdCBhcHAgPSBjbXNQbHVnaW4uZ2V0RmlyZWJhc2VBcHAoKTtcbiAgY29uc3QgZGIgPSBnZXRGaXJlc3RvcmUoYXBwKTtcblxuICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHtwcm9qZWN0SWR9L1RyYW5zbGF0aW9uc2A7XG4gIGxldCBxdWVyeTogUXVlcnkgPSBkYi5jb2xsZWN0aW9uKGRiUGF0aCk7XG4gIGlmIChvcHRpb25zPy50YWdzKSB7XG4gICAgcXVlcnkgPSBxdWVyeS53aGVyZSgndGFncycsICdhcnJheS1jb250YWlucy1hbnknLCBvcHRpb25zLnRhZ3MpO1xuICB9XG5cbiAgY29uc3QgcXVlcnlTbmFwc2hvdCA9IGF3YWl0IHF1ZXJ5LmdldCgpO1xuICBjb25zdCB0cmFuc2xhdGlvbnNNYXA6IFRyYW5zbGF0aW9uc01hcCA9IHt9O1xuICBxdWVyeVNuYXBzaG90LmZvckVhY2goKGRvYykgPT4ge1xuICAgIGNvbnN0IGhhc2ggPSBkb2MuaWQ7XG4gICAgdHJhbnNsYXRpb25zTWFwW2hhc2hdID0gZG9jLmRhdGEoKSBhcyBUcmFuc2xhdGlvbjtcbiAgfSk7XG4gIHJldHVybiB0cmFuc2xhdGlvbnNNYXA7XG59XG5cbi8qKlxuICogTG9hZHMgdHJhbnNsYXRpb25zIGZvciBhIHBhcnRpY3VsYXIgbG9jYWxlLlxuICpcbiAqIFJldHVybnMgYSBtYXAgbGlrZTpcbiAqIGBgYFxuICoge1xuICogICBcIkhlbGxvXCI6IFwiQm9uam91clwiLFxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsb2FkVHJhbnNsYXRpb25zRm9yTG9jYWxlKFxuICByb290Q29uZmlnOiBSb290Q29uZmlnLFxuICBsb2NhbGU6IHN0cmluZyxcbiAgb3B0aW9ucz86IExvYWRUcmFuc2xhdGlvbnNPcHRpb25zXG4pOiBQcm9taXNlPExvY2FsZVRyYW5zbGF0aW9ucz4ge1xuICBjb25zdCB0cmFuc2xhdGlvbnNNYXAgPSBhd2FpdCBsb2FkVHJhbnNsYXRpb25zKHJvb3RDb25maWcsIG9wdGlvbnMpO1xuICByZXR1cm4gdHJhbnNsYXRpb25zRm9yTG9jYWxlKHRyYW5zbGF0aW9uc01hcCwgbG9jYWxlKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHRyYW5zbGF0aW9ucyBtYXAgZnJvbSBgbG9hZFRyYW5zbGF0aW9ucygpYCB0byBhIG1hcCBvZiBzb3VyY2UgdG9cbiAqIHRyYW5zbGF0ZWQgc3RyaW5nIGZvciBhIHBhcnRpY3VsYXIgbG9jYWxlLlxuICpcbiAqIFJldHVybnMgYSBtYXAgbGlrZTpcbiAqIGBgYFxuICoge1xuICogICBcIkhlbGxvXCI6IFwiQm9uam91clwiLFxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2xhdGlvbnNGb3JMb2NhbGUoXG4gIHRyYW5zbGF0aW9uc01hcDogVHJhbnNsYXRpb25zTWFwLFxuICBsb2NhbGU6IHN0cmluZ1xuKSB7XG4gIGNvbnN0IGxvY2FsZVRyYW5zbGF0aW9uczogTG9jYWxlVHJhbnNsYXRpb25zID0ge307XG4gIE9iamVjdC52YWx1ZXModHJhbnNsYXRpb25zTWFwKS5mb3JFYWNoKChzdHJpbmcpID0+IHtcbiAgICBjb25zdCBzb3VyY2UgPSBzdHJpbmcuc291cmNlO1xuICAgIGNvbnN0IHRyYW5zbGF0aW9uID0gc3RyaW5nW2xvY2FsZV0gfHwgc3RyaW5nLmVuIHx8IHN0cmluZy5zb3VyY2U7XG4gICAgbG9jYWxlVHJhbnNsYXRpb25zW3NvdXJjZV0gPSB0cmFuc2xhdGlvbjtcbiAgfSk7XG4gIHJldHVybiBsb2NhbGVUcmFuc2xhdGlvbnM7XG59XG4iLCAiLyoqXG4gKiBEb2N1bWVudCB2ZXJpb24gaGlzdG9yeS5cbiAqXG4gKiBWZXJpb25zIHNhdmUgdGhlIHN0YXRlIG9mIGEgZG9jdW1lbnQgYXQgZGlmZmVyZW50IG1vbWVudHMgaW4gdGltZSwgYWxsb3dpbmdcbiAqIHVzZXJzIHRvIHJldmVydCBiYWNrIHRvIGEgdmVyc2lvbiBpZi93aGVuIG5lZWRlZC5cbiAqXG4gKiBUaGUgc2F2ZVZlcnNpb25zKCkgZnVuY3Rpb24gaXMgbWVhbnQgdG8gYmUgcnVuIHdpdGhpbiBhIGNyb24gam9iIChlLmcgdXNpbmdcbiAqIGZpcmViYXNlIGZ1bmN0aW9ucykuIEV2ZXJ5IG1pbnV0ZSwgdGhlIHJ1bm5lciBjaGVja3MgZm9yIGFsbCBkb2N1bWVudHMgdGhhdFxuICogaGF2ZSBiZWVuIGVkaXRlZCBzaW5jZSB0aGUgbGFzdCBydW4uIFRvIGF2b2lkIHNhdmluZyBcInBhcnRpYWxcIiB2ZXJzaW9uc1xuICogKHdoZW4gdGhlIHVzZXIgbWlnaHQgYmUgaW4gdGhlIG1pZGRsZSBvZiBlZGl0aW5nIGEgZG9jdW1lbnQpLCB2ZXJzaW9ucyBvbmx5XG4gKiBydW4gb24gZG9jdW1lbnRzIHRoYXQgaGF2ZW4ndCBiZWVuIGVkaXRlZCB3aXRoaW4gdGhlIGxhc3QgNSBtaW5zIHRvIGVuc3VyZVxuICogdGhhdCB2ZXJzaW9uIGlzIFwic3RhYmxlXCIuXG4gKlxuICogSW4gdGhlIGRhdGFiYXNlLCB2ZXJzaW9ucyBhcmUgc3RvcmVkIGFzOlxuICogL1Byb2plY3RzLzxwcm9qZWN0SWQ+L0NvbGxlY3Rpb25zLzxjb2xsZWN0aW9uSWQ+L0RyYWZ0cy88ZG9jSWQ+L1ZlcnNpb25zLzx0aW1lc3RhbXA+XG4gKlxuICogV2hlcmUgPHRpbWVzdGFtcD4gaXMgdGhlIHVuaXggdGltZXN0YW1wIChtaWxsaXMpIHRoYXQgdGhlIGRvY3VtZW50IHdhcyBsYXN0XG4gKiBlZGl0ZWQuXG4gKi9cblxuaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7Um9vdENvbmZpZ30gZnJvbSAnQGJsaW5ray9yb290JztcbmltcG9ydCB7XG4gIEZpcmVzdG9yZSxcbiAgUXVlcnksXG4gIFRpbWVzdGFtcCxcbiAgZ2V0RmlyZXN0b3JlLFxufSBmcm9tICdmaXJlYmFzZS1hZG1pbi9maXJlc3RvcmUnO1xuaW1wb3J0IGdsb2IgZnJvbSAndGlueS1nbG9iJztcbmltcG9ydCB7Z2V0Q21zUGx1Z2lufSBmcm9tICcuL3J1bnRpbWUuanMnO1xuXG4vLyBUbyBhdm9pZCBzYXZpbmcgXCJwYXJ0aWFsXCIgdmVyc2lvbnMgKHdoZW4gdGhlIHVzZXIgbWlnaHQgYmUgaW4gdGhlIG1pZGRsZSBvZlxuLy8gZWRpdGluZyBhIGRvY3VtZW50KSwgdmVyc2lvbnMgb25seSBydW4gb24gZG9jdW1lbnRzIHRoYXQgaGF2ZW4ndCBiZWVuIGVkaXRlZFxuLy8gd2l0aGluIHRoZSBsYXN0IDUgbWlucyB0byBlbnN1cmUgdGhhdCB2ZXJzaW9uIGlzIFwic3RhYmxlXCIuXG5jb25zdCBET0NVTUVOVF9TQVZFX09GRlNFVCA9IDUgKiA2MCAqIDEwMDA7XG5cbmludGVyZmFjZSBQYXJ0aWFsQ01TRG9jIHtcbiAgW2tleTogc3RyaW5nXTogYW55O1xuICBpZDogc3RyaW5nO1xuICBjb2xsZWN0aW9uOiBzdHJpbmc7XG4gIHNsdWc6IHN0cmluZztcbiAgc3lzOiB7XG4gICAgbW9kaWZpZWRBdDogVGltZXN0YW1wO1xuICAgIG1vZGlmaWVkQnk6IHN0cmluZztcbiAgfTtcbn1cblxuZXhwb3J0IGNsYXNzIFZlcnNpb25zU2VydmljZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcm9vdENvbmZpZzogUm9vdENvbmZpZztcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9qZWN0SWQ6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBkYjogRmlyZXN0b3JlO1xuXG4gIGNvbnN0cnVjdG9yKHJvb3RDb25maWc6IFJvb3RDb25maWcpIHtcbiAgICB0aGlzLnJvb3RDb25maWcgPSByb290Q29uZmlnO1xuICAgIGNvbnN0IGNtc1BsdWdpbiA9IGdldENtc1BsdWdpbihyb290Q29uZmlnKTtcbiAgICBjb25zdCBjbXNQbHVnaW5PcHRpb25zID0gY21zUGx1Z2luLmdldENvbmZpZygpO1xuICAgIGNvbnN0IHByb2plY3RJZCA9IGNtc1BsdWdpbk9wdGlvbnMuaWQgfHwgJ2RlZmF1bHQnO1xuICAgIHRoaXMucHJvamVjdElkID0gcHJvamVjdElkO1xuICAgIGNvbnN0IGFwcCA9IGNtc1BsdWdpbi5nZXRGaXJlYmFzZUFwcCgpO1xuICAgIHRoaXMuZGIgPSBnZXRGaXJlc3RvcmUoYXBwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTYXZlcyBhIHZlcnNpb24gb2YgYWxsIGRvY3VtZW50cyB0aGF0IGhhdmUgYmVlbiBlZGl0ZWQgc2luY2UgdGhlIGxhc3QgcnVuLlxuICAgKi9cbiAgYXN5bmMgc2F2ZVZlcnNpb25zKCkge1xuICAgIC8vIE9mZnNldCB0aGUgXCJsYXN0IHJ1blwiIHRpbWUgYnkgNSBtaW5zLiBWZXJzaW9ucyBpZ25vcmUgZG9jcyB0aGF0IHdlcmVcbiAgICAvLyBlZGl0ZWQgd2l0aGluIHRoZSBsYXN0IDUgbWlucyB0byBhdm9pZCBwb3RlbnRpYWwgXCJwYXJ0aWFsXCIgdmVyc2lvbnMgd2hlblxuICAgIC8vIHVzZXIgaXMgaW4gdGhlIG1pZGRsZSBvZiBlZGl0aW5nIGEgZG9jdW1lbnQuXG4gICAgY29uc3QgbGFzdFJ1biA9IGF3YWl0IHRoaXMuZ2V0TGFzdFJ1bigpO1xuICAgIGNvbnN0IGxhc3RSdW5XaXRoT2Zmc2V0ID1cbiAgICAgIGxhc3RSdW4gPT09IDAgPyBsYXN0UnVuIDogbGFzdFJ1biAtIERPQ1VNRU5UX1NBVkVfT0ZGU0VUO1xuICAgIGNvbnN0IGNoYW5nZWREb2NzID0gYXdhaXQgdGhpcy5nZXREb2NzTW9kaWZpZWRBZnRlcihsYXN0UnVuV2l0aE9mZnNldCk7XG4gICAgY29uc3Qgbm93ID0gVGltZXN0YW1wLm5vdygpLnRvTWlsbGlzKCk7XG4gICAgY29uc3QgdmVyc2lvbnMgPSBjaGFuZ2VkRG9jcy5maWx0ZXIoKGRvYykgPT4ge1xuICAgICAgY29uc3QgbW9kaWZpZWRBdCA9IGRvYy5zeXMubW9kaWZpZWRBdC50b01pbGxpcygpO1xuICAgICAgcmV0dXJuIG1vZGlmaWVkQXQgPD0gbm93IC0gRE9DVU1FTlRfU0FWRV9PRkZTRVQ7XG4gICAgfSk7XG4gICAgaWYgKHZlcnNpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuc2F2ZVZlcnNpb25zVG9GaXJlc3RvcmUodmVyc2lvbnMpO1xuICAgIH1cbiAgICB0aGlzLnNhdmVMYXN0UnVuKG5vdyk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHNhdmVWZXJzaW9uc1RvRmlyZXN0b3JlKHZlcnNpb25zOiBQYXJ0aWFsQ01TRG9jW10pIHtcbiAgICBjb25zdCBiYXRjaCA9IHRoaXMuZGIuYmF0Y2goKTtcbiAgICB2ZXJzaW9ucy5mb3JFYWNoKCh2ZXJzaW9uKSA9PiB7XG4gICAgICBpZiAoIXZlcnNpb24uY29sbGVjdGlvbiB8fCAhdmVyc2lvbi5zbHVnIHx8ICF2ZXJzaW9uLnN5cz8ubW9kaWZpZWRBdCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCBtb2RpZmllZEF0TWlsbGlzID0gdmVyc2lvbi5zeXMubW9kaWZpZWRBdC50b01pbGxpcygpO1xuICAgICAgY29uc3QgdmVyc2lvblBhdGggPSBgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH0vQ29sbGVjdGlvbnMvJHt2ZXJzaW9uLmNvbGxlY3Rpb259L0RyYWZ0cy8ke3ZlcnNpb24uc2x1Z30vVmVyc2lvbnMvJHttb2RpZmllZEF0TWlsbGlzfWA7XG4gICAgICBjb25zb2xlLmxvZyh2ZXJzaW9uUGF0aCk7XG4gICAgICBjb25zdCB2ZXJzaW9uUmVmID0gdGhpcy5kYi5kb2ModmVyc2lvblBhdGgpO1xuICAgICAgYmF0Y2guc2V0KHZlcnNpb25SZWYsIHZlcnNpb24pO1xuICAgIH0pO1xuICAgIGF3YWl0IGJhdGNoLmNvbW1pdCgpO1xuICAgIGNvbnNvbGUubG9nKGB2ZXJzaW9uczogc2F2ZWQgJHt2ZXJzaW9ucy5sZW5ndGh9IHZlcnNpb25zYCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbGFzdCB0aW1lIChpbiBtaWxsaXMpIHNhdmVWZXJzaW9ucygpIHdhcyBydW4sIG9yIDAgaWYgaGFzXG4gICAqIG5ldmVyIGJlZW4gcnVuLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBnZXRMYXN0UnVuKCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgcHJvamVjdERvY1JlZiA9IHRoaXMuZGIuY29sbGVjdGlvbignUHJvamVjdHMnKS5kb2ModGhpcy5wcm9qZWN0SWQpO1xuICAgIGNvbnN0IHByb2plY3REb2MgPSBhd2FpdCBwcm9qZWN0RG9jUmVmLmdldCgpO1xuICAgIGlmIChwcm9qZWN0RG9jLmV4aXN0cykge1xuICAgICAgY29uc3QgZGF0YSA9IHByb2plY3REb2MuZGF0YSgpIHx8IHt9O1xuICAgICAgY29uc3QgdHMgPSBkYXRhLnZlcnNpb25zTGFzdFJ1biBhcyBUaW1lc3RhbXA7XG4gICAgICBpZiAodHMpIHtcbiAgICAgICAgcmV0dXJuIHRzLnRvTWlsbGlzKCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAwO1xuICB9XG5cbiAgLyoqXG4gICAqIFNhdmVzIHt2ZXJzaW9uTGFzdFJ1bjogPHRpbWVzdGFtcD59IHRvIHRoZSBQcm9qZWN0cy88cHJvamVjdElkPiBkb2MuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHNhdmVMYXN0UnVuKG1pbGxpczogbnVtYmVyKSB7XG4gICAgY29uc3QgdHMgPSBUaW1lc3RhbXAuZnJvbU1pbGxpcyhtaWxsaXMpO1xuICAgIGNvbnN0IHByb2plY3REb2NSZWYgPSB0aGlzLmRiLmNvbGxlY3Rpb24oJ1Byb2plY3RzJykuZG9jKHRoaXMucHJvamVjdElkKTtcbiAgICBhd2FpdCBwcm9qZWN0RG9jUmVmLnNldCh7dmVyc2lvbnNMYXN0UnVuOiB0c30sIHttZXJnZTogdHJ1ZX0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBsaXN0IG9mIGFsbCBkb2NzIHRoYXQgd2VyZSBlZGl0ZWQgYWZ0ZXIgYSBjZXJ0YWluIHRpbWUuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldERvY3NNb2RpZmllZEFmdGVyKG1pbGxpczogbnVtYmVyKTogUHJvbWlzZTxQYXJ0aWFsQ01TRG9jW10+IHtcbiAgICBjb25zdCB0cyA9IFRpbWVzdGFtcC5mcm9tTWlsbGlzKG1pbGxpcyk7XG4gICAgY29uc3QgcmVzdWx0czogUGFydGlhbENNU0RvY1tdID0gW107XG4gICAgY29uc3QgY29sbGVjdGlvbklkcyA9IGF3YWl0IHRoaXMubGlzdENvbGxlY3Rpb25zKCk7XG4gICAgLy8gTk9URTogSW5kaXZpZHVhbCBjb2xsZWN0aW9ucyBhcmUgcXVlcmllZCBpbnN0ZWFkIG9mIHVzaW5nIGFcbiAgICAvLyBjb2xsZWN0aW9uR3JvdXAgcXVlcnkgYmVjYXVzZSB0aGUgbGF0dGVyIHJlcXVpcmVzIGEgZmlyZXN0b3JlIGluZGV4IHRvIGJlXG4gICAgLy8gc2V0IHVwLlxuICAgIGZvciAoY29uc3QgY29sbGVjdGlvbklkIG9mIGNvbGxlY3Rpb25JZHMpIHtcbiAgICAgIGNvbnN0IGNvbGxlY3Rpb25QYXRoID0gYFByb2plY3RzLyR7dGhpcy5wcm9qZWN0SWR9L0NvbGxlY3Rpb25zLyR7Y29sbGVjdGlvbklkfS9EcmFmdHNgO1xuICAgICAgY29uc3QgcXVlcnk6IFF1ZXJ5ID0gdGhpcy5kYlxuICAgICAgICAuY29sbGVjdGlvbihjb2xsZWN0aW9uUGF0aClcbiAgICAgICAgLndoZXJlKCdzeXMubW9kaWZpZWRBdCcsICc+PScsIHRzKTtcbiAgICAgIGNvbnN0IHF1ZXJ5U25hcHNob3QgPSBhd2FpdCBxdWVyeS5nZXQoKTtcbiAgICAgIHF1ZXJ5U25hcHNob3QuZm9yRWFjaCgoZG9jKSA9PiB7XG4gICAgICAgIHJlc3VsdHMucHVzaChkb2MuZGF0YSgpIGFzIFBhcnRpYWxDTVNEb2MpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBsaXN0IG9mIGNvbGxlY3Rpb24gaWRzIGZvciB0aGUgUm9vdCBwcm9qZWN0LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBsaXN0Q29sbGVjdGlvbnMoKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGNvbnN0IGNvbGxlY3Rpb25JZHM6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgY29sbGVjdGlvbkZpbGVOYW1lcyA9IGF3YWl0IGdsb2IoJyouc2NoZW1hLnRzJywge1xuICAgICAgY3dkOiBwYXRoLmpvaW4odGhpcy5yb290Q29uZmlnLnJvb3REaXIsICdjb2xsZWN0aW9ucycpLFxuICAgIH0pO1xuICAgIGNvbGxlY3Rpb25GaWxlTmFtZXMuZm9yRWFjaCgoZmlsZW5hbWUpID0+IHtcbiAgICAgIGNvbGxlY3Rpb25JZHMucHVzaChmaWxlbmFtZS5zbGljZSgwLCAtMTApKTtcbiAgICB9KTtcbiAgICByZXR1cm4gY29sbGVjdGlvbklkcztcbiAgfVxufVxuIiwgImltcG9ydCB7Um9vdENvbmZpZ30gZnJvbSAnQGJsaW5ray9yb290JztcbmltcG9ydCB7cHVibGlzaFNjaGVkdWxlZERvY3N9IGZyb20gJy4vcnVudGltZS5qcyc7XG5pbXBvcnQge1ZlcnNpb25zU2VydmljZX0gZnJvbSAnLi92ZXJzaW9ucy5qcyc7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBydW5Dcm9uSm9icyhyb290Q29uZmlnOiBSb290Q29uZmlnKSB7XG4gIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICBydW5Dcm9uSm9iKCdwdWJsaXNoU2NoZWR1bGVkRG9jcycsIHJ1blB1Ymxpc2hTY2hlZHVsZWREb2NzLCByb290Q29uZmlnKSxcbiAgICBydW5Dcm9uSm9iKCdzYXZlVmVyc2lvbnMnLCBydW5TYXZlVmVyc2lvbnMsIHJvb3RDb25maWcpLFxuICBdKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcnVuQ3JvbkpvYihcbiAgbmFtZTogc3RyaW5nLFxuICBmbjogKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnksXG4gIC4uLmFyZ3M6IGFueVtdXG4pIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCBmbiguLi5hcmdzKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgY29uc29sZS5sb2coYGNyb24gZmFpbGVkOiAke25hbWV9YCk7XG4gICAgY29uc29sZS5lcnJvcihTdHJpbmcoZXJyLnN0YWNrIHx8IGVycikpO1xuICAgIHRocm93IGVycjtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBydW5QdWJsaXNoU2NoZWR1bGVkRG9jcyhyb290Q29uZmlnOiBSb290Q29uZmlnKSB7XG4gIGF3YWl0IHB1Ymxpc2hTY2hlZHVsZWREb2NzKHJvb3RDb25maWcpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBydW5TYXZlVmVyc2lvbnMocm9vdENvbmZpZzogUm9vdENvbmZpZykge1xuICBjb25zdCBzZXJ2aWNlID0gbmV3IFZlcnNpb25zU2VydmljZShyb290Q29uZmlnKTtcbiAgYXdhaXQgc2VydmljZS5zYXZlVmVyc2lvbnMoKTtcbn1cbiIsICJpbXBvcnQge3BhcnNlIGFzIGNzdlBhcnNlfSBmcm9tICdjc3YtcGFyc2Uvc3luYyc7XG5pbXBvcnQge3N0cmluZ2lmeSBhcyBjc3ZTdHJpbmdpZnl9IGZyb20gJ2Nzdi1zdHJpbmdpZnkvc3luYyc7XG5cbmV4cG9ydCBmdW5jdGlvbiBhcnJheVRvQ3N2KHJlcToge1xuICBoZWFkZXJzOiBzdHJpbmdbXTtcbiAgcm93czogQXJyYXk8UmVjb3JkPHN0cmluZywgYW55Pj47XG59KTogc3RyaW5nIHtcbiAgY29uc3QgaGVhZGVycyA9IHJlcS5oZWFkZXJzIHx8IFtdO1xuICBjb25zdCByb3dzID0gcmVxLnJvd3MgfHwgW107XG4gIHJldHVybiBjc3ZTdHJpbmdpZnkocm93cywge1xuICAgIGhlYWRlcjogdHJ1ZSxcbiAgICBjb2x1bW5zOiBoZWFkZXJzLFxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNzdlRvQXJyYXkoY3N2U3RyaW5nOiBzdHJpbmcpIHtcbiAgY29uc3Qgcm93cyA9IGNzdlBhcnNlKGNzdlN0cmluZywge1xuICAgIGNvbHVtbnM6IHRydWUsXG4gICAgc2tpcF9lbXB0eV9saW5lczogdHJ1ZSxcbiAgfSk7XG4gIHJldHVybiByb3dzO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUFBLFNBQVEsWUFBWSxVQUFTO0FBQzdCLE9BQU9BLFdBQVU7QUFDakIsU0FBUSxxQkFBb0I7QUFVNUIsT0FBTyxnQkFBZ0I7QUFDdkI7QUFBQSxFQUVFO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1AsU0FBUSxlQUE4QjtBQUN0QyxPQUFPLFVBQVU7OztBQ25CakIsU0FBUSwyQkFBMEI7OztBQ0FsQztBQUFBLEVBQ0U7QUFBQSxFQUdBO0FBQUEsT0FDSztBQXFI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Q0YsZ0JBQU1BLE9BQU0sTUFBTSxZQUFZLEdBQUc7QUFDakMsZ0JBQU1BLEtBQUksVUFBVSxLQUFLLEtBQUs7QUFBQSxZQUM1QixZQUFZLElBQUk7QUFBQSxZQUNoQixXQUFXO0FBQUEsWUFDWCxnQkFBZ0IsUUFBUTtBQUFBLFVBQzFCLENBQUM7QUFBQSxRQUNILFNBQVMsS0FBSztBQUVaLGtCQUFRLE1BQU0sR0FBRztBQUNqQixjQUFJLE9BQU8sR0FBRyxFQUFFLEtBQUssc0JBQXNCO0FBQUEsUUFDN0M7QUFBQSxNQUNGLENBQUM7QUFBQSxJQUNIO0FBQUEsRUFDRjtBQUNGO0FBRUEsU0FBUyxXQUFXLFVBQW9DO0FBQ3RELFNBQU8sR0FDSixPQUFPLFFBQVEsRUFDZixLQUFLLE1BQU0sSUFBSSxFQUNmLE1BQU0sTUFBTSxLQUFLO0FBQ3RCOyIsCiAgIm5hbWVzIjogWyJwYXRoIiwgImNtc1BsdWdpbiIsICJwbHVnaW4iLCAiVGltZXN0YW1wIiwgImdldEZpcmVzdG9yZSIsICJjbXNQbHVnaW4iLCAiZ2V0RmlyZXN0b3JlIiwgIlRpbWVzdGFtcCIsICJwYXRoIiwgImFwcCJdCn0K