@workflow/next 5.0.0-beta.0 → 5.0.0-beta.10

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.
@@ -7,11 +7,12 @@ exports.getNextBuilderDeferred = getNextBuilderDeferred;
7
7
  const node_crypto_1 = require("node:crypto");
8
8
  const node_fs_1 = require("node:fs");
9
9
  const promises_1 = require("node:fs/promises");
10
+ const node_module_1 = require("node:module");
10
11
  const node_os_1 = __importDefault(require("node:os"));
11
12
  const node_path_1 = require("node:path");
12
13
  const socket_server_js_1 = require("./socket-server.js");
13
- const step_copy_utils_js_1 = require("./step-copy-utils.js");
14
14
  const ROUTE_STUB_FILE_MARKER = 'WORKFLOW_ROUTE_STUB_FILE';
15
+ const ROUTE_STUB_MARKER_SCAN_BYTES = 4 * 1024;
15
16
  let CachedNextBuilderDeferred;
16
17
  // Create the deferred Next builder dynamically by extending the ESM BaseBuilder.
17
18
  // Exported as getNextBuilderDeferred() to allow CommonJS modules to import from
@@ -20,7 +21,13 @@ async function getNextBuilderDeferred() {
20
21
  if (CachedNextBuilderDeferred) {
21
22
  return CachedNextBuilderDeferred;
22
23
  }
23
- const { BaseBuilder: BaseBuilderClass, STEP_QUEUE_TRIGGER, WORKFLOW_QUEUE_TRIGGER, applySwcTransform, detectWorkflowPatterns, getImportPath, isWorkflowSdkFile, resolveWorkflowAliasRelativePath,
24
+ // V2: STEP_QUEUE_TRIGGER, getImportPath, and enhanced-resolve infrastructure
25
+ // were removed because the V2 combined handler eliminates the separate step
26
+ // route/topic. The step copy import rewriting (getRelativeImportSpecifier,
27
+ // getStepCopyFileName, rewriteRelativeImportsForCopiedStep) from main was also
28
+ // removed — V2 doesn't use step copies. If step copy support is needed, it
29
+ // should land as a complete feature set.
30
+ const { BaseBuilder: BaseBuilderClass, WORKFLOW_QUEUE_TRIGGER, detectWorkflowPatterns, applySwcTransform, resolveWorkflowAliasRelativePath,
24
31
  // biome-ignore lint/security/noGlobalEval: Need to use eval here to avoid TypeScript from transpiling the import statement into `require()`
25
32
  } = (await eval('import("@workflow/builders")'));
26
33
  class NextDeferredBuilder extends BaseBuilderClass {
@@ -70,7 +77,9 @@ async function getNextBuilderDeferred() {
70
77
  for (let buildPass = 0; buildPass < maxBuildPasses; buildPass++) {
71
78
  const inputFiles = this.getCurrentInputFiles(implicitStepFiles);
72
79
  const buildSignature = await this.createDeferredBuildSignature(inputFiles);
73
- if (buildSignature === this.lastDeferredBuildSignature) {
80
+ const shouldForceBuildForGeneratedRoutes = await this.shouldForceBuildForGeneratedRoutes();
81
+ if (buildSignature === this.lastDeferredBuildSignature &&
82
+ !shouldForceBuildForGeneratedRoutes) {
74
83
  return;
75
84
  }
76
85
  try {
@@ -95,6 +104,14 @@ async function getNextBuilderDeferred() {
95
104
  }
96
105
  }
97
106
  this.lastDeferredBuildSignature = buildSignature;
107
+ if (!this.config.watch) {
108
+ // Production builds can persist newly discovered deferred-entry files to
109
+ // the cache after the first pass completes. Reload that cache before we
110
+ // decide whether the input signature stabilized so staged tarball builds
111
+ // can immediately replay with the expanded step set.
112
+ await new Promise((resolve) => setTimeout(resolve, 250));
113
+ await this.loadWorkflowsCache();
114
+ }
98
115
  const postBuildInputFiles = this.getCurrentInputFiles(implicitStepFiles);
99
116
  const postBuildSignature = await this.createDeferredBuildSignature(postBuildInputFiles);
100
117
  if (postBuildSignature === buildSignature) {
@@ -107,6 +124,49 @@ async function getNextBuilderDeferred() {
107
124
  const workflowStdlibPath = this.resolveWorkflowStdlibStepFilePath();
108
125
  return workflowStdlibPath ? [workflowStdlibPath] : [];
109
126
  }
127
+ async shouldForceBuildForGeneratedRoutes() {
128
+ const outputDir = await this.findAppDirectory();
129
+ const generatedRouteFiles = [
130
+ (0, node_path_1.join)(outputDir, '.well-known/workflow/v1/flow/route.js'),
131
+ (0, node_path_1.join)(outputDir, '.well-known/workflow/v1/webhook/[token]/route.js'),
132
+ ];
133
+ for (const routeFilePath of generatedRouteFiles) {
134
+ const routeState = await this.getGeneratedRouteState(routeFilePath);
135
+ if (routeState === 'missing' || routeState === 'stub') {
136
+ return true;
137
+ }
138
+ }
139
+ return false;
140
+ }
141
+ async getGeneratedRouteState(routeFilePath) {
142
+ let routeStats;
143
+ try {
144
+ routeStats = await (0, promises_1.stat)(routeFilePath);
145
+ }
146
+ catch {
147
+ return 'missing';
148
+ }
149
+ if (!routeStats.isFile()) {
150
+ return 'missing';
151
+ }
152
+ try {
153
+ const routeFileHandle = await (0, promises_1.open)(routeFilePath, 'r');
154
+ try {
155
+ const markerScanBuffer = Buffer.alloc(ROUTE_STUB_MARKER_SCAN_BYTES);
156
+ const { bytesRead } = await routeFileHandle.read(markerScanBuffer, 0, ROUTE_STUB_MARKER_SCAN_BYTES, 0);
157
+ const markerScanSource = markerScanBuffer.toString('utf8', 0, bytesRead);
158
+ return markerScanSource.includes(ROUTE_STUB_FILE_MARKER)
159
+ ? 'stub'
160
+ : 'generated';
161
+ }
162
+ finally {
163
+ await routeFileHandle.close();
164
+ }
165
+ }
166
+ catch {
167
+ return 'missing';
168
+ }
169
+ }
110
170
  resolveWorkflowStdlibStepFilePath() {
111
171
  let workflowCjsEntry;
112
172
  try {
@@ -175,22 +235,20 @@ async function getNextBuilderDeferred() {
175
235
  return null;
176
236
  }
177
237
  if (!validatePatterns) {
178
- const isSdkFile = isWorkflowSdkFile(filePath);
179
238
  return {
180
239
  filePath,
181
240
  hasUseWorkflow: candidates.hasWorkflowCandidate,
182
241
  hasUseStep: candidates.hasStepCandidate,
183
- hasSerde: candidates.hasSerdeCandidate && !isSdkFile,
242
+ hasSerde: candidates.hasSerdeCandidate,
184
243
  };
185
244
  }
186
245
  const source = await (0, promises_1.readFile)(filePath, 'utf-8');
187
246
  const patterns = detectWorkflowPatterns(source);
188
- const isSdkFile = isWorkflowSdkFile(filePath);
189
247
  return {
190
248
  filePath,
191
249
  hasUseWorkflow: patterns.hasUseWorkflow,
192
250
  hasUseStep: patterns.hasUseStep,
193
- hasSerde: patterns.hasSerde && !isSdkFile,
251
+ hasSerde: patterns.hasSerde,
194
252
  };
195
253
  }
196
254
  catch {
@@ -292,18 +350,17 @@ async function getNextBuilderDeferred() {
292
350
  ...this.discoveredSerdeFiles,
293
351
  ...trackedDiscoveredEntries.discoveredSerdeFiles,
294
352
  ])).sort();
295
- const discoveredStepFiles = await this.filterExistingFiles(discoveredStepFileCandidates);
296
353
  const discoveredWorkflowFiles = await this.filterExistingFiles(discoveredWorkflowFileCandidates);
354
+ const existingStepFileCandidates = await this.filterExistingFiles(discoveredStepFileCandidates);
355
+ const discoveredStepFiles = await this.collectTransitiveStepFiles({
356
+ entryFiles: [...existingStepFileCandidates, ...discoveredWorkflowFiles],
357
+ stepFiles: existingStepFileCandidates,
358
+ });
297
359
  const existingSerdeFileCandidates = await this.filterExistingFiles(discoveredSerdeFileCandidates);
298
360
  const discoveredSerdeFiles = await this.collectTransitiveSerdeFiles({
299
361
  entryFiles: [...discoveredStepFiles, ...discoveredWorkflowFiles],
300
362
  serdeFiles: existingSerdeFileCandidates,
301
363
  });
302
- const discoveredEntries = {
303
- discoveredSteps: new Set(discoveredStepFiles),
304
- discoveredWorkflows: new Set(discoveredWorkflowFiles),
305
- discoveredSerdeFiles: new Set(discoveredSerdeFiles),
306
- };
307
364
  const existingInputFiles = await this.filterExistingFiles(inputFiles);
308
365
  const buildInputFiles = Array.from(new Set([
309
366
  ...existingInputFiles,
@@ -311,35 +368,42 @@ async function getNextBuilderDeferred() {
311
368
  ...discoveredWorkflowFiles,
312
369
  ...discoveredSerdeFiles,
313
370
  ])).sort();
371
+ const discoveredEntries = {
372
+ discoveredSteps: new Set(discoveredStepFiles),
373
+ discoveredWorkflows: new Set(discoveredWorkflowFiles),
374
+ discoveredSerdeFiles: new Set(discoveredSerdeFiles),
375
+ };
314
376
  // Ensure output directories exist
315
377
  await (0, promises_1.mkdir)(workflowGeneratedDir, { recursive: true });
316
378
  await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, '.gitignore'), '*');
317
379
  const tsconfigPath = await this.findTsConfigPath();
318
- const options = {
380
+ // V2: Build combined route (replaces separate step + flow routes)
381
+ const flowRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'flow');
382
+ await (0, promises_1.mkdir)(flowRouteDir, { recursive: true });
383
+ // Write step registrations to final name directly (not temp) so the
384
+ // import path in the flow route is correct. The flow route uses temp
385
+ // naming to avoid HMR churn via copyFileIfChanged, but the step
386
+ // registrations file is a side-effect import and doesn't need that.
387
+ const stepsOutfile = (0, node_path_1.join)(flowRouteDir, '__step_registrations.js');
388
+ const combinedResult = await this.createCombinedBundle({
389
+ format: 'esm',
319
390
  inputFiles: buildInputFiles,
320
- workflowGeneratedDir,
391
+ stepsOutfile,
392
+ flowOutfile: (0, node_path_1.join)(flowRouteDir, tempRouteFileName),
393
+ bundleFinalOutput: false,
394
+ externalizeNonSteps: true,
321
395
  tsconfigPath,
322
- routeFileName: tempRouteFileName,
323
396
  discoveredEntries,
324
- };
325
- const { manifest: stepsManifest } = await this.buildStepsFunction(options);
326
- const workflowsBundle = await this.buildWorkflowsFunction(options);
397
+ });
327
398
  await this.buildWebhookRoute({
328
399
  workflowGeneratedDir,
329
400
  routeFileName: tempRouteFileName,
330
401
  });
331
402
  await this.refreshTrackedDependencyFiles(workflowGeneratedDir, tempRouteFileName);
332
- // Merge manifests from both bundles
333
403
  const manifest = {
334
- steps: { ...stepsManifest.steps, ...workflowsBundle?.manifest?.steps },
335
- workflows: {
336
- ...stepsManifest.workflows,
337
- ...workflowsBundle?.manifest?.workflows,
338
- },
339
- classes: {
340
- ...stepsManifest.classes,
341
- ...workflowsBundle?.manifest?.classes,
342
- },
404
+ steps: { ...combinedResult?.manifest?.steps },
405
+ workflows: { ...combinedResult?.manifest?.workflows },
406
+ classes: { ...combinedResult?.manifest?.classes },
343
407
  };
344
408
  const manifestFilePath = (0, node_path_1.join)(workflowGeneratedDir, 'manifest.json');
345
409
  const manifestBuildPath = (0, node_path_1.join)(manifestBuildDir, 'manifest.json');
@@ -358,14 +422,17 @@ async function getNextBuilderDeferred() {
358
422
  await (0, promises_1.rm)(manifestFilePath, { force: true });
359
423
  }
360
424
  await this.writeFunctionsConfig(outputDir);
425
+ // V2: Combined route (flow) — step registrations already at final path
361
426
  await this.copyFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, `flow/${tempRouteFileName}`), (0, node_path_1.join)(workflowGeneratedDir, 'flow/route.js'));
362
- await this.copyFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, `step/${tempRouteFileName}`), (0, node_path_1.join)(workflowGeneratedDir, 'step/route.js'));
363
427
  await this.copyFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, `webhook/[token]/${tempRouteFileName}`), (0, node_path_1.join)(workflowGeneratedDir, 'webhook/[token]/route.js'));
364
428
  // Expose manifest as a static file when WORKFLOW_PUBLIC_MANIFEST=1.
365
429
  // Next.js serves files from public/ at the root URL.
366
430
  if (this.shouldExposePublicManifest && manifestJson) {
367
431
  const publicManifestDir = (0, node_path_1.join)(this.config.workingDir, 'public/.well-known/workflow/v1');
368
432
  await (0, promises_1.mkdir)(publicManifestDir, { recursive: true });
433
+ if (process.env.VERCEL_DEPLOYMENT_ID === undefined) {
434
+ await this.writeFileIfChanged((0, node_path_1.join)(publicManifestDir, '.gitignore'), '*');
435
+ }
369
436
  await this.copyFileIfChanged(manifestFilePath, (0, node_path_1.join)(publicManifestDir, 'manifest.json'));
370
437
  }
371
438
  // Notify deferred entry loaders waiting on route.js stubs.
@@ -380,17 +447,17 @@ async function getNextBuilderDeferred() {
380
447
  (0, node_path_1.join)(flowRouteDir, 'route.js.temp'),
381
448
  (0, node_path_1.join)(flowRouteDir, 'route.js.temp.debug.json'),
382
449
  (0, node_path_1.join)(flowRouteDir, 'route.js.debug.json'),
383
- (0, node_path_1.join)(stepRouteDir, 'route.js.temp'),
384
- (0, node_path_1.join)(stepRouteDir, 'route.js.temp.debug.json'),
385
- (0, node_path_1.join)(stepRouteDir, 'route.js.debug.json'),
386
- (0, node_path_1.join)(stepRouteDir, step_copy_utils_js_1.DEFERRED_STEP_COPY_DIR_NAME),
450
+ (0, node_path_1.join)(flowRouteDir, '__step_registrations.route.js.temp'),
451
+ (0, node_path_1.join)(flowRouteDir, '__step_registrations.route.js.temp.debug.json'),
452
+ // V2: clean up stale V1 step route directory
453
+ stepRouteDir,
387
454
  (0, node_path_1.join)(webhookRouteDir, 'route.js.temp'),
388
455
  (0, node_path_1.join)(workflowGeneratedDir, 'manifest.json'),
389
456
  ];
390
- await Promise.all(staleArtifactPaths.map((stalePath) => (0, promises_1.rm)(stalePath, { recursive: true, force: true })));
391
457
  await Promise.all([
458
+ ...staleArtifactPaths.map((stalePath) => (0, promises_1.rm)(stalePath, { recursive: true, force: true })),
459
+ (0, socket_server_js_1.cleanupStaleSocketInfoFiles)((0, node_path_1.join)(this.config.workingDir, this.getDistDir())),
392
460
  this.removeStaleDeferredTempFiles(flowRouteDir),
393
- this.removeStaleDeferredTempFiles(stepRouteDir),
394
461
  this.removeStaleDeferredTempFiles(webhookRouteDir),
395
462
  ]);
396
463
  }
@@ -470,7 +537,8 @@ async function getNextBuilderDeferred() {
470
537
  return;
471
538
  }
472
539
  await this.loadWorkflowsCache();
473
- await this.loadDiscoveredEntriesFromInputGraph();
540
+ // Deferred mode must not run eager input-graph discovery; entries are
541
+ // discovered via loader->socket notifications during Next's build.
474
542
  this.cacheInitialized = true;
475
543
  }
476
544
  getDistDir() {
@@ -480,12 +548,68 @@ async function getNextBuilderDeferred() {
480
548
  return (0, node_path_1.join)(this.config.workingDir, this.getDistDir(), 'cache', 'workflows.json');
481
549
  }
482
550
  getSocketInfoFilePath() {
483
- return (0, node_path_1.join)(this.config.workingDir, this.getDistDir(), 'cache', 'workflow-socket.json');
551
+ return (0, node_path_1.join)(this.config.workingDir, this.getDistDir(), socket_server_js_1.SOCKET_INFO_FILENAME);
552
+ }
553
+ findPackageJsonPath(filePath) {
554
+ let currentDir = (0, node_path_1.dirname)(filePath);
555
+ let previousDir = '';
556
+ while (currentDir !== previousDir) {
557
+ const packageJsonPath = (0, node_path_1.join)(currentDir, 'package.json');
558
+ if ((0, node_fs_1.existsSync)(packageJsonPath)) {
559
+ return packageJsonPath;
560
+ }
561
+ previousDir = currentDir;
562
+ currentDir = (0, node_path_1.dirname)(currentDir);
563
+ }
564
+ return null;
565
+ }
566
+ shouldPreferSourceBackedPackagePath(filePath) {
567
+ const normalizedPath = filePath.replace(/\\/g, '/');
568
+ // Only prefer source for workspace packages (not in node_modules).
569
+ // For tarball-installed packages, using source-backed paths causes
570
+ // esbuild to bundle the full source tree (including world.ts with
571
+ // process.cwd()) instead of externalizing properly.
572
+ if (normalizedPath.includes('/packages/') &&
573
+ !normalizedPath.includes('/node_modules/')) {
574
+ return true;
575
+ }
576
+ if (!normalizedPath.includes('/node_modules/')) {
577
+ return false;
578
+ }
579
+ const packageJsonPath = this.findPackageJsonPath(filePath);
580
+ if (!packageJsonPath) {
581
+ return false;
582
+ }
583
+ try {
584
+ const packageJson = JSON.parse((0, node_fs_1.readFileSync)(packageJsonPath, 'utf-8'));
585
+ return (packageJson.name === 'workflow' ||
586
+ (typeof packageJson.name === 'string' &&
587
+ packageJson.name.startsWith('@workflow/')));
588
+ }
589
+ catch {
590
+ return false;
591
+ }
592
+ }
593
+ resolveSourceBackedPackagePath(filePath) {
594
+ const normalizedPath = filePath.replace(/\\/g, '/');
595
+ if (!normalizedPath.includes('/dist/')) {
596
+ return filePath;
597
+ }
598
+ const sourceCandidate = normalizedPath.replace('/dist/', '/src/');
599
+ const resolvedSourceCandidate = this.resolveCopiedStepImportTargetPath(sourceCandidate);
600
+ if (!(0, node_fs_1.existsSync)(resolvedSourceCandidate) ||
601
+ !this.shouldPreferSourceBackedPackagePath(filePath)) {
602
+ return filePath;
603
+ }
604
+ return (0, node_fs_1.existsSync)(resolvedSourceCandidate)
605
+ ? resolvedSourceCandidate
606
+ : filePath;
484
607
  }
485
608
  normalizeDiscoveredFilePath(filePath) {
486
- return (0, node_path_1.isAbsolute)(filePath)
609
+ const absolutePath = (0, node_path_1.isAbsolute)(filePath)
487
610
  ? filePath
488
611
  : (0, node_path_1.resolve)(this.config.workingDir, filePath);
612
+ return this.resolveSourceBackedPackagePath(absolutePath);
489
613
  }
490
614
  async filterExistingFiles(filePaths) {
491
615
  const normalizedFilePaths = Array.from(new Set(filePaths.map((filePath) => this.normalizeDiscoveredFilePath(filePath)))).sort();
@@ -567,9 +691,62 @@ async function getNextBuilderDeferred() {
567
691
  }
568
692
  const baseDirectory = (0, node_path_1.dirname)(bundleFilePath);
569
693
  const localSourceFiles = new Set();
570
- const sourceMapMatches = bundleContents.matchAll(/\/\/# sourceMappingURL=data:application\/json[^,]*;base64,([A-Za-z0-9+/=]+)/g);
694
+ // Extract inline base64 sourcemaps via string scanning. A previous
695
+ // implementation used `bundleContents.matchAll(/...[A-Za-z0-9+/=]+.../g)`
696
+ // which overflows V8's regex stack
697
+ // (`RangeError: Maximum call stack size exceeded at RegExpStringIterator.next`)
698
+ // on bundles with large inline sourcemaps — V8's irregexp uses
699
+ // recursion for greedy character-class quantifiers and certain long
700
+ // base64 inputs exhaust the call stack.
701
+ const sourceMapPrefix = '//# sourceMappingURL=data:application/json';
702
+ const base64Marker = ';base64,';
703
+ const sourceMapMatches = [];
704
+ let scanFrom = 0;
705
+ while (scanFrom < bundleContents.length) {
706
+ const prefixIdx = bundleContents.indexOf(sourceMapPrefix, scanFrom);
707
+ if (prefixIdx === -1)
708
+ break;
709
+ const base64Start = bundleContents.indexOf(base64Marker, prefixIdx + sourceMapPrefix.length);
710
+ if (base64Start === -1) {
711
+ scanFrom = prefixIdx + sourceMapPrefix.length;
712
+ continue;
713
+ }
714
+ // Bail if a comma appears before `;base64,` — that means this
715
+ // wasn't a `data:application/json[;params];base64,...` URL after
716
+ // all (the comma would terminate the data URL parameters).
717
+ const commaBefore = bundleContents.indexOf(',', prefixIdx);
718
+ if (commaBefore !== -1 && commaBefore < base64Start) {
719
+ scanFrom = base64Start;
720
+ continue;
721
+ }
722
+ const valueStart = base64Start + base64Marker.length;
723
+ // Base64 payload terminates at first non-base64 char (newline,
724
+ // closing `*/`, etc.). Scanning a small alphabet by char is far
725
+ // cheaper than backtracking a regex over a multi-MB capture.
726
+ let valueEnd = valueStart;
727
+ while (valueEnd < bundleContents.length) {
728
+ const code = bundleContents.charCodeAt(valueEnd);
729
+ // A-Z 0x41-0x5A, a-z 0x61-0x7A, 0-9 0x30-0x39, '+' 0x2B,
730
+ // '/' 0x2F, '=' 0x3D
731
+ if (!((code >= 0x41 && code <= 0x5a) ||
732
+ (code >= 0x61 && code <= 0x7a) ||
733
+ (code >= 0x30 && code <= 0x39) ||
734
+ code === 0x2b ||
735
+ code === 0x2f ||
736
+ code === 0x3d)) {
737
+ break;
738
+ }
739
+ valueEnd++;
740
+ }
741
+ if (valueEnd > valueStart) {
742
+ sourceMapMatches.push({
743
+ base64Value: bundleContents.slice(valueStart, valueEnd),
744
+ });
745
+ }
746
+ scanFrom = valueEnd;
747
+ }
571
748
  for (const match of sourceMapMatches) {
572
- const base64Value = match[1];
749
+ const base64Value = match.base64Value;
573
750
  if (!base64Value) {
574
751
  continue;
575
752
  }
@@ -605,9 +782,12 @@ async function getNextBuilderDeferred() {
605
782
  }
606
783
  const normalizedSourcePath = this.normalizeDiscoveredFilePath(resolvedSourcePath);
607
784
  const normalizedSourcePathForCheck = normalizedSourcePath.replace(/\\/g, '/');
785
+ const isSourceBackedPackagePath = this.shouldPreferSourceBackedPackagePath(normalizedSourcePath);
608
786
  if (normalizedSourcePathForCheck.includes('/.well-known/workflow/') ||
609
- normalizedSourcePathForCheck.includes('/node_modules/') ||
610
- normalizedSourcePathForCheck.includes('/.pnpm/') ||
787
+ (!isSourceBackedPackagePath &&
788
+ normalizedSourcePathForCheck.includes('/node_modules/')) ||
789
+ (!isSourceBackedPackagePath &&
790
+ normalizedSourcePathForCheck.includes('/.pnpm/')) ||
611
791
  normalizedSourcePathForCheck.includes('/.next/') ||
612
792
  normalizedSourcePathForCheck.endsWith('/virtual-entry.js')) {
613
793
  continue;
@@ -629,9 +809,6 @@ async function getNextBuilderDeferred() {
629
809
  }, 50);
630
810
  }
631
811
  scheduleDeferredRebuild() {
632
- if (!this.config.watch) {
633
- return;
634
- }
635
812
  if (this.deferredRebuildTimer) {
636
813
  clearTimeout(this.deferredRebuildTimer);
637
814
  }
@@ -683,41 +860,6 @@ async function getNextBuilderDeferred() {
683
860
  this.discoveredSerdeFiles.add(filePath);
684
861
  }
685
862
  }
686
- async loadDiscoveredEntriesFromInputGraph() {
687
- const inputFiles = await this.getInputFiles();
688
- if (inputFiles.length === 0) {
689
- return;
690
- }
691
- const { discoveredWorkflows, discoveredSteps, discoveredSerdeFiles } = await this.discoverEntries(inputFiles, this.config.workingDir);
692
- const { workflowFiles, stepFiles, serdeFiles } = await this.reconcileDiscoveredEntries({
693
- workflowCandidates: discoveredWorkflows,
694
- stepCandidates: discoveredSteps,
695
- serdeCandidates: discoveredSerdeFiles,
696
- validatePatterns: true,
697
- });
698
- let hasChanges = false;
699
- for (const filePath of workflowFiles) {
700
- if (!this.discoveredWorkflowFiles.has(filePath)) {
701
- this.discoveredWorkflowFiles.add(filePath);
702
- hasChanges = true;
703
- }
704
- }
705
- for (const filePath of stepFiles) {
706
- if (!this.discoveredStepFiles.has(filePath)) {
707
- this.discoveredStepFiles.add(filePath);
708
- hasChanges = true;
709
- }
710
- }
711
- for (const filePath of serdeFiles) {
712
- if (!this.discoveredSerdeFiles.has(filePath)) {
713
- this.discoveredSerdeFiles.add(filePath);
714
- hasChanges = true;
715
- }
716
- }
717
- if (hasChanges) {
718
- this.scheduleWorkflowsCacheWrite();
719
- }
720
- }
721
863
  async writeWorkflowsCache() {
722
864
  const cacheFilePath = this.getWorkflowsCacheFilePath();
723
865
  const cacheDir = (0, node_path_1.join)(this.config.workingDir, this.getDistDir(), 'cache');
@@ -741,50 +883,61 @@ async function getNextBuilderDeferred() {
741
883
  ].join('\n');
742
884
  const workflowGeneratedDir = (0, node_path_1.join)(outputDir, '.well-known/workflow/v1');
743
885
  await (0, promises_1.mkdir)((0, node_path_1.join)(workflowGeneratedDir, 'flow'), { recursive: true });
744
- await (0, promises_1.mkdir)((0, node_path_1.join)(workflowGeneratedDir, 'step'), { recursive: true });
745
886
  await (0, promises_1.mkdir)((0, node_path_1.join)(workflowGeneratedDir, 'webhook/[token]'), {
746
887
  recursive: true,
747
888
  });
748
889
  await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, '.gitignore'), '*');
749
- // route.js stubs are replaced by generated route.js output once discovery
750
- // finishes and a deferred build completes.
890
+ // V2: Only flow + webhook stubs needed (no separate step route).
891
+ // Stubs are replaced by generated output once discovery finishes.
751
892
  await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, 'flow/route.js'), routeStubContent);
752
- await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, 'step/route.js'), routeStubContent);
753
893
  await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, 'webhook/[token]/route.js'), routeStubContent);
754
894
  }
755
895
  async getInputFiles() {
756
- const inputFiles = await super.getInputFiles();
757
- return inputFiles.filter((item) => {
758
- // Match App Router entrypoints: route.ts, page.ts, layout.ts in app/ or src/app/ directories
759
- // Matches: /app/page.ts, /app/dashboard/page.ts, /src/app/route.ts, etc.
760
- if (item.match(/(^|.*[/\\])(app|src[/\\]app)([/\\](route|page|layout)\.|[/\\].*[/\\](route|page|layout)\.)/)) {
761
- return true;
762
- }
763
- // Match Pages Router entrypoints: files in pages/ or src/pages/
764
- if (item.match(/[/\\](pages|src[/\\]pages)[/\\]/)) {
765
- return true;
766
- }
767
- return false;
768
- });
896
+ // Read Next.js's app-paths-manifest.json from a previous build to
897
+ // determine which files are actual route entrypoints. This avoids
898
+ // predicting Next.js conventions with regexes and instead reads
899
+ // from Next.js's own output.
900
+ const nextDir = (0, node_path_1.join)(this.config.workingDir, '.next');
901
+ const manifestPath = (0, node_path_1.join)(nextDir, 'app-paths-manifest.json');
902
+ try {
903
+ const manifestContent = (0, node_fs_1.readFileSync)(manifestPath, 'utf-8');
904
+ const manifest = JSON.parse(manifestContent);
905
+ // The manifest maps route paths to their source files.
906
+ // Extract the source file paths and resolve them.
907
+ const manifestFiles = new Set();
908
+ for (const sourcePath of Object.values(manifest)) {
909
+ const resolved = (0, node_path_1.resolve)(nextDir, 'server', sourcePath);
910
+ // The manifest points to built output; find the source file
911
+ // by matching against the base builder's full file list.
912
+ manifestFiles.add(resolved);
913
+ }
914
+ // Use the manifest route paths to filter the input files.
915
+ // A file is included if it matches a known route segment from
916
+ // the manifest (e.g., app/api/route contains 'app/api/route').
917
+ const inputFiles = await super.getInputFiles();
918
+ const routeSegments = Object.keys(manifest).map((route) => route.replace(/^\//, '').replace(/\/route$/, ''));
919
+ return inputFiles.filter((item) => routeSegments.some((segment) => item.includes(segment)));
920
+ }
921
+ catch {
922
+ // No manifest from a previous build — fall back to the base
923
+ // builder's full file scan. This is safe but slower; subsequent
924
+ // builds will use the manifest.
925
+ return super.getInputFiles();
926
+ }
769
927
  }
770
928
  async writeFunctionsConfig(outputDir) {
771
929
  // we don't run this in development mode as it's not needed
772
930
  if (process.env.NODE_ENV === 'development') {
773
931
  return;
774
932
  }
933
+ // V2: Single combined trigger handles both workflow and step execution
775
934
  const generatedConfig = {
776
935
  version: '0',
777
- steps: {
778
- maxDuration: 'max',
779
- experimentalTriggers: [STEP_QUEUE_TRIGGER],
780
- },
781
936
  workflows: {
782
937
  maxDuration: 'max',
783
938
  experimentalTriggers: [WORKFLOW_QUEUE_TRIGGER],
784
939
  },
785
940
  };
786
- // We write this file to the generated directory for
787
- // the Next.js builder to consume
788
941
  await this.writeFileIfChanged((0, node_path_1.join)(outputDir, '.well-known/workflow/v1/config.json'), JSON.stringify(generatedConfig, null, 2));
789
942
  }
790
943
  async writeFileIfChanged(filePath, contents) {
@@ -831,16 +984,56 @@ async function getNextBuilderDeferred() {
831
984
  // Manifest may not exist (e.g. manifest generation failed); ignore.
832
985
  }
833
986
  }
834
- mergeWorkflowManifest(target, source) {
835
- if (source.steps) {
836
- target.steps = Object.assign(target.steps || {}, source.steps);
987
+ resolveCopiedStepImportTargetPath(targetPath) {
988
+ if ((0, node_fs_1.existsSync)(targetPath)) {
989
+ return targetPath;
837
990
  }
838
- if (source.workflows) {
839
- target.workflows = Object.assign(target.workflows || {}, source.workflows);
991
+ const extensionMatch = targetPath.match(/(\.[^./\\]+)$/);
992
+ const extension = extensionMatch?.[1]?.toLowerCase();
993
+ if (!extension) {
994
+ return targetPath;
840
995
  }
841
- if (source.classes) {
842
- target.classes = Object.assign(target.classes || {}, source.classes);
996
+ const extensionFallbacks = extension === '.js'
997
+ ? ['.ts', '.tsx', '.mts', '.cts']
998
+ : extension === '.mjs'
999
+ ? ['.mts']
1000
+ : extension === '.cjs'
1001
+ ? ['.cts']
1002
+ : extension === '.jsx'
1003
+ ? ['.tsx']
1004
+ : [];
1005
+ if (extensionFallbacks.length === 0) {
1006
+ return targetPath;
843
1007
  }
1008
+ const targetWithoutExtension = targetPath.slice(0, -extension.length);
1009
+ for (const fallbackExtension of extensionFallbacks) {
1010
+ const fallbackPath = `${targetWithoutExtension}${fallbackExtension}`;
1011
+ if ((0, node_fs_1.existsSync)(fallbackPath)) {
1012
+ return fallbackPath;
1013
+ }
1014
+ }
1015
+ return targetPath;
1016
+ }
1017
+ extractRelativeImportSpecifiers(source) {
1018
+ return this.extractImportSpecifiers(source).filter((specifier) => specifier.startsWith('.'));
1019
+ }
1020
+ extractImportSpecifiers(source) {
1021
+ const relativeSpecifiers = new Set();
1022
+ const importPatterns = [
1023
+ /from\s+['"]([^'"]+)['"]/g,
1024
+ /import\s+['"]([^'"]+)['"]/g,
1025
+ /import\(\s*['"]([^'"]+)['"]\s*\)/g,
1026
+ /require\(\s*['"]([^'"]+)['"]\s*\)/g,
1027
+ ];
1028
+ for (const importPattern of importPatterns) {
1029
+ for (const match of source.matchAll(importPattern)) {
1030
+ const specifier = match[1];
1031
+ if (specifier) {
1032
+ relativeSpecifiers.add(specifier);
1033
+ }
1034
+ }
1035
+ }
1036
+ return Array.from(relativeSpecifiers);
844
1037
  }
845
1038
  async getRelativeFilenameForSwc(filePath) {
846
1039
  const workingDir = this.config.workingDir;
@@ -878,46 +1071,7 @@ async function getNextBuilderDeferred() {
878
1071
  }
879
1072
  return relativeFilename;
880
1073
  }
881
- getRelativeImportSpecifier(fromFilePath, toFilePath) {
882
- let relativePath = (0, node_path_1.relative)((0, node_path_1.dirname)(fromFilePath), toFilePath).replace(/\\/g, '/');
883
- if (!relativePath.startsWith('.')) {
884
- relativePath = `./${relativePath}`;
885
- }
886
- return relativePath;
887
- }
888
- getStepCopyFileName(filePath) {
889
- const normalizedPath = filePath.replace(/\\/g, '/');
890
- const hash = (0, node_crypto_1.createHash)('sha256').update(normalizedPath).digest('hex');
891
- const extension = (0, node_path_1.extname)(normalizedPath);
892
- return `${hash.slice(0, 16)}${extension || '.js'}`;
893
- }
894
- rewriteCopiedStepImportSpecifier(specifier, sourceFilePath, copiedFilePath, copiedStepFileBySourcePath) {
895
- if (!specifier.startsWith('.')) {
896
- return specifier;
897
- }
898
- const specifierMatch = specifier.match(/^([^?#]+)(.*)$/);
899
- const importPath = specifierMatch?.[1] ?? specifier;
900
- const suffix = specifierMatch?.[2] ?? '';
901
- const absoluteTargetPath = (0, node_path_1.resolve)((0, node_path_1.dirname)(sourceFilePath), importPath);
902
- const resolvedTargetPath = this.resolveCopiedStepImportTargetPath(absoluteTargetPath);
903
- const normalizedTargetPath = resolvedTargetPath.replace(/\\/g, '/');
904
- const copiedTargetPath = copiedStepFileBySourcePath.get(normalizedTargetPath) ||
905
- (() => {
906
- try {
907
- const realTargetPath = (0, node_fs_1.realpathSync)(resolvedTargetPath).replace(/\\/g, '/');
908
- return copiedStepFileBySourcePath.get(realTargetPath);
909
- }
910
- catch {
911
- return undefined;
912
- }
913
- })();
914
- let rewrittenPath = (0, node_path_1.relative)((0, node_path_1.dirname)(copiedFilePath), copiedTargetPath || resolvedTargetPath).replace(/\\/g, '/');
915
- if (!rewrittenPath.startsWith('.')) {
916
- rewrittenPath = `./${rewrittenPath}`;
917
- }
918
- return `${rewrittenPath}${suffix}`;
919
- }
920
- resolveCopiedStepImportTargetPath(targetPath) {
1074
+ resolveImportTargetWithExtensionFallbacks(targetPath) {
921
1075
  if ((0, node_fs_1.existsSync)(targetPath)) {
922
1076
  return targetPath;
923
1077
  }
@@ -947,47 +1101,38 @@ async function getNextBuilderDeferred() {
947
1101
  }
948
1102
  return targetPath;
949
1103
  }
950
- rewriteRelativeImportsForCopiedStep(source, sourceFilePath, copiedFilePath, copiedStepFileBySourcePath) {
951
- const rewriteSpecifier = (specifier) => this.rewriteCopiedStepImportSpecifier(specifier, sourceFilePath, copiedFilePath, copiedStepFileBySourcePath);
952
- const rewritePattern = (currentSource, pattern) => currentSource.replace(pattern, (_match, prefix, specifier, suffix) => `${prefix}${rewriteSpecifier(specifier)}${suffix}`);
953
- let rewrittenSource = source;
954
- rewrittenSource = rewritePattern(rewrittenSource, /(from\s+['"])([^'"]+)(['"])/g);
955
- rewrittenSource = rewritePattern(rewrittenSource, /(import\s+['"])([^'"]+)(['"])/g);
956
- rewrittenSource = rewritePattern(rewrittenSource, /(import\(\s*['"])([^'"]+)(['"]\s*\))/g);
957
- rewrittenSource = rewritePattern(rewrittenSource, /(require\(\s*['"])([^'"]+)(['"]\s*\))/g);
958
- return rewrittenSource;
959
- }
960
- extractRelativeImportSpecifiers(source) {
961
- const relativeSpecifiers = new Set();
962
- const importPatterns = [
963
- /from\s+['"]([^'"]+)['"]/g,
964
- /import\s+['"]([^'"]+)['"]/g,
965
- /import\(\s*['"]([^'"]+)['"]\s*\)/g,
966
- /require\(\s*['"]([^'"]+)['"]\s*\)/g,
967
- ];
968
- for (const importPattern of importPatterns) {
969
- for (const match of source.matchAll(importPattern)) {
970
- const specifier = match[1];
971
- if (specifier?.startsWith('.')) {
972
- relativeSpecifiers.add(specifier);
973
- }
974
- }
975
- }
976
- return Array.from(relativeSpecifiers);
977
- }
978
1104
  shouldSkipTransitiveStepFile(filePath) {
979
1105
  const normalizedPath = filePath.replace(/\\/g, '/');
1106
+ const isSourceBackedPackagePath = this.shouldPreferSourceBackedPackagePath(filePath);
980
1107
  return (normalizedPath.includes('/.well-known/workflow/') ||
981
1108
  normalizedPath.includes('/.next/') ||
982
- normalizedPath.includes('/node_modules/') ||
983
- normalizedPath.includes('/.pnpm/'));
1109
+ (!isSourceBackedPackagePath &&
1110
+ (normalizedPath.includes('/node_modules/') ||
1111
+ normalizedPath.includes('/.pnpm/'))));
984
1112
  }
985
1113
  async resolveTransitiveStepImportTargetPath(sourceFilePath, specifier) {
986
1114
  const specifierMatch = specifier.match(/^([^?#]+)(.*)$/);
987
1115
  const importPath = specifierMatch?.[1] ?? specifier;
1116
+ if (!importPath.startsWith('.')) {
1117
+ if (importPath !== 'workflow' && !importPath.startsWith('@workflow/')) {
1118
+ return null;
1119
+ }
1120
+ try {
1121
+ const resolvedPath = (0, node_module_1.createRequire)(sourceFilePath).resolve(importPath);
1122
+ const normalizedResolvedPath = this.normalizeDiscoveredFilePath(resolvedPath);
1123
+ if (this.shouldSkipTransitiveStepFile(normalizedResolvedPath)) {
1124
+ return null;
1125
+ }
1126
+ const fileStats = await (0, promises_1.stat)(normalizedResolvedPath);
1127
+ return fileStats.isFile() ? normalizedResolvedPath : null;
1128
+ }
1129
+ catch {
1130
+ return null;
1131
+ }
1132
+ }
988
1133
  const absoluteTargetPath = (0, node_path_1.resolve)((0, node_path_1.dirname)(sourceFilePath), importPath);
989
1134
  const candidatePaths = new Set([
990
- this.resolveCopiedStepImportTargetPath(absoluteTargetPath),
1135
+ this.resolveImportTargetWithExtensionFallbacks(absoluteTargetPath),
991
1136
  ]);
992
1137
  if (!(0, node_path_1.extname)(absoluteTargetPath)) {
993
1138
  const extensionCandidates = [
@@ -1006,7 +1151,7 @@ async function getNextBuilderDeferred() {
1006
1151
  }
1007
1152
  }
1008
1153
  for (const candidatePath of candidatePaths) {
1009
- const resolvedPath = this.resolveCopiedStepImportTargetPath(candidatePath);
1154
+ const resolvedPath = this.resolveImportTargetWithExtensionFallbacks(candidatePath);
1010
1155
  const normalizedResolvedPath = this.normalizeDiscoveredFilePath(resolvedPath);
1011
1156
  if (this.shouldSkipTransitiveStepFile(normalizedResolvedPath)) {
1012
1157
  continue;
@@ -1023,13 +1168,11 @@ async function getNextBuilderDeferred() {
1023
1168
  }
1024
1169
  return null;
1025
1170
  }
1026
- async collectTransitiveStepFiles({ stepFiles, seedFiles = [], }) {
1027
- const normalizedSeedFiles = Array.from(new Set([...stepFiles, ...seedFiles].map((stepFile) => this.normalizeDiscoveredFilePath(stepFile)))).sort();
1028
- // Intentionally re-validate step seeds against current file contents
1029
- // instead of blindly trusting callers. This prevents stale/manual seed
1030
- // paths from persisting when files no longer contain "use step".
1031
- const discoveredStepFiles = new Set();
1032
- const queuedFiles = [...normalizedSeedFiles];
1171
+ async collectTransitiveStepFiles({ entryFiles, stepFiles, }) {
1172
+ const normalizedEntryFiles = Array.from(new Set(entryFiles.map((entryFile) => this.normalizeDiscoveredFilePath(entryFile)))).sort();
1173
+ const normalizedStepSeedFiles = Array.from(new Set(stepFiles.map((stepFile) => this.normalizeDiscoveredFilePath(stepFile)))).sort();
1174
+ const discoveredStepFiles = new Set(normalizedStepSeedFiles);
1175
+ const queuedFiles = Array.from(new Set([...normalizedEntryFiles, ...normalizedStepSeedFiles]));
1033
1176
  const visitedFiles = new Set();
1034
1177
  const sourceCache = new Map();
1035
1178
  const patternCache = new Map();
@@ -1070,12 +1213,8 @@ async function getNextBuilderDeferred() {
1070
1213
  if (currentSource === null) {
1071
1214
  continue;
1072
1215
  }
1073
- const currentPatterns = await getPatterns(currentFile);
1074
- if (currentPatterns?.hasUseStep) {
1075
- discoveredStepFiles.add(currentFile);
1076
- }
1077
- const relativeImportSpecifiers = this.extractRelativeImportSpecifiers(currentSource);
1078
- for (const specifier of relativeImportSpecifiers) {
1216
+ const importSpecifiers = this.extractImportSpecifiers(currentSource);
1217
+ for (const specifier of importSpecifiers) {
1079
1218
  const resolvedImportPath = await this.resolveTransitiveStepImportTargetPath(currentFile, specifier);
1080
1219
  if (!resolvedImportPath) {
1081
1220
  continue;
@@ -1094,9 +1233,9 @@ async function getNextBuilderDeferred() {
1094
1233
  async collectTransitiveSerdeFiles({ entryFiles, serdeFiles, }) {
1095
1234
  const normalizedEntryFiles = Array.from(new Set(entryFiles.map((entryFile) => this.normalizeDiscoveredFilePath(entryFile)))).sort();
1096
1235
  const normalizedSerdeSeedFiles = Array.from(new Set(serdeFiles.map((serdeFile) => this.normalizeDiscoveredFilePath(serdeFile)))).sort();
1097
- // Intentionally re-validate serde seeds against source + SDK filtering.
1236
+ // Intentionally re-validate serde seeds against source patterns.
1098
1237
  // This keeps previously discovered/manual seed entries from sticking when
1099
- // files no longer match serde patterns or resolve to SDK internals.
1238
+ // files no longer match serde patterns.
1100
1239
  const discoveredSerdeFiles = new Set();
1101
1240
  const queuedFiles = Array.from(new Set([...normalizedEntryFiles, ...normalizedSerdeSeedFiles]));
1102
1241
  const visitedFiles = new Set();
@@ -1131,7 +1270,7 @@ async function getNextBuilderDeferred() {
1131
1270
  };
1132
1271
  for (const serdeSeedFile of normalizedSerdeSeedFiles) {
1133
1272
  const seedPatterns = await getPatterns(serdeSeedFile);
1134
- if (seedPatterns?.hasSerde && !isWorkflowSdkFile(serdeSeedFile)) {
1273
+ if (seedPatterns?.hasSerde) {
1135
1274
  discoveredSerdeFiles.add(serdeSeedFile);
1136
1275
  }
1137
1276
  }
@@ -1155,206 +1294,37 @@ async function getNextBuilderDeferred() {
1155
1294
  queuedFiles.push(resolvedImportPath);
1156
1295
  }
1157
1296
  const importPatterns = await getPatterns(resolvedImportPath);
1158
- if (importPatterns?.hasSerde &&
1159
- !isWorkflowSdkFile(resolvedImportPath)) {
1297
+ if (importPatterns?.hasSerde) {
1160
1298
  discoveredSerdeFiles.add(resolvedImportPath);
1161
1299
  }
1162
1300
  }
1163
1301
  }
1164
- return Array.from(discoveredSerdeFiles).sort();
1165
- }
1166
- async createResponseBuiltinsStepFile({ stepsRouteDir, }) {
1167
- const copiedStepsDir = (0, node_path_1.join)(stepsRouteDir, step_copy_utils_js_1.DEFERRED_STEP_COPY_DIR_NAME);
1168
- await (0, promises_1.mkdir)(copiedStepsDir, { recursive: true });
1169
- const responseBuiltinsFilePath = (0, node_path_1.join)(copiedStepsDir, 'workflow-response-builtins.ts');
1170
- const source = [
1171
- 'export async function __builtin_response_array_buffer(this: Request | Response) {',
1172
- " 'use step';",
1173
- ' return this.arrayBuffer();',
1174
- '}',
1175
- '',
1176
- 'export async function __builtin_response_json(this: Request | Response) {',
1177
- " 'use step';",
1178
- ' return this.json();',
1179
- '}',
1180
- '',
1181
- 'export async function __builtin_response_text(this: Request | Response) {',
1182
- " 'use step';",
1183
- ' return this.text();',
1184
- '}',
1185
- ].join('\n');
1186
- const sourceMapComment = (0, step_copy_utils_js_1.createDeferredStepCopyInlineSourceMapComment)({
1187
- sourcePath: responseBuiltinsFilePath,
1188
- sourceContent: source,
1189
- });
1190
- await this.writeFileIfChanged(responseBuiltinsFilePath, `${source}\n${sourceMapComment}\n`);
1191
- return responseBuiltinsFilePath;
1192
- }
1193
- async copyDiscoveredStepFiles({ stepFiles, stepsRouteDir, }) {
1194
- const copiedStepsDir = (0, node_path_1.join)(stepsRouteDir, step_copy_utils_js_1.DEFERRED_STEP_COPY_DIR_NAME);
1195
- await (0, promises_1.mkdir)(copiedStepsDir, { recursive: true });
1196
- const normalizedStepFiles = Array.from(new Set(stepFiles.map((stepFile) => this.normalizeDiscoveredFilePath(stepFile)))).sort();
1197
- const copiedStepFileBySourcePath = new Map();
1198
- const expectedFileNames = new Set();
1199
- const copiedStepFiles = [];
1200
- for (const normalizedStepFile of normalizedStepFiles) {
1201
- const copiedFileName = this.getStepCopyFileName(normalizedStepFile);
1202
- const copiedFilePath = (0, node_path_1.join)(copiedStepsDir, copiedFileName);
1203
- const normalizedPathKey = normalizedStepFile.replace(/\\/g, '/');
1204
- copiedStepFileBySourcePath.set(normalizedPathKey, copiedFilePath);
1302
+ // AST-level verification: run SWC detect mode on regex-matched candidates
1303
+ // to confirm they actually define serde classes. This prevents SDK internal
1304
+ // files (which match serde regex patterns but define no classes) from being
1305
+ // bundled into the workflow sandbox.
1306
+ const projectRoot = this.config.projectRoot || this.config.workingDir;
1307
+ const verifiedSerdeFiles = [];
1308
+ await Promise.all(Array.from(discoveredSerdeFiles).map(async (filePath) => {
1309
+ const source = await getSource(filePath);
1310
+ if (!source)
1311
+ return;
1205
1312
  try {
1206
- const realPathKey = (0, node_fs_1.realpathSync)(normalizedStepFile).replace(/\\/g, '/');
1207
- copiedStepFileBySourcePath.set(realPathKey, copiedFilePath);
1313
+ const relativeFilename = await this.getRelativeFilenameForSwc(filePath);
1314
+ const { workflowManifest } = await applySwcTransform(relativeFilename, source, 'detect', filePath, projectRoot);
1315
+ // Only include files that actually define serde classes
1316
+ const hasClasses = workflowManifest.classes &&
1317
+ Object.values(workflowManifest.classes).some((entries) => Object.keys(entries).length > 0);
1318
+ if (hasClasses) {
1319
+ verifiedSerdeFiles.push(filePath);
1320
+ }
1208
1321
  }
1209
1322
  catch {
1210
- // Keep best-effort mapping when source cannot be realpath-resolved.
1211
- }
1212
- expectedFileNames.add(copiedFileName);
1213
- copiedStepFiles.push(copiedFilePath);
1214
- }
1215
- for (const normalizedStepFile of normalizedStepFiles) {
1216
- const source = await (0, promises_1.readFile)(normalizedStepFile, 'utf-8');
1217
- const copiedFilePath = copiedStepFileBySourcePath.get(normalizedStepFile.replace(/\\/g, '/'));
1218
- if (!copiedFilePath) {
1219
- continue;
1220
- }
1221
- const rewrittenSource = this.rewriteRelativeImportsForCopiedStep(source, normalizedStepFile, copiedFilePath, copiedStepFileBySourcePath);
1222
- const metadataComment = (0, step_copy_utils_js_1.createDeferredStepSourceMetadataComment)({
1223
- relativeFilename: await this.getRelativeFilenameForSwc(normalizedStepFile),
1224
- absolutePath: normalizedStepFile.replace(/\\/g, '/'),
1225
- });
1226
- const sourceMapComment = (0, step_copy_utils_js_1.createDeferredStepCopyInlineSourceMapComment)({
1227
- sourcePath: normalizedStepFile,
1228
- sourceContent: source,
1229
- generatedContent: rewrittenSource,
1230
- });
1231
- const copiedSource = `${metadataComment}\n${rewrittenSource}\n${sourceMapComment}`;
1232
- await this.writeFileIfChanged(copiedFilePath, copiedSource);
1233
- }
1234
- const existingEntries = await (0, promises_1.readdir)(copiedStepsDir, {
1235
- withFileTypes: true,
1236
- }).catch(() => []);
1237
- await Promise.all(existingEntries
1238
- .filter((entry) => !expectedFileNames.has(entry.name))
1239
- .map((entry) => (0, promises_1.rm)((0, node_path_1.join)(copiedStepsDir, entry.name), {
1240
- recursive: true,
1241
- force: true,
1242
- })));
1243
- return copiedStepFiles;
1244
- }
1245
- async createDeferredStepsManifest({ stepFiles, workflowFiles, serdeOnlyFiles, }) {
1246
- const workflowManifest = {};
1247
- const filesForStepTransform = Array.from(new Set([...stepFiles, ...serdeOnlyFiles])).sort();
1248
- await Promise.all(filesForStepTransform.map(async (stepFile) => {
1249
- const source = await (0, promises_1.readFile)(stepFile, 'utf-8');
1250
- const relativeFilename = await this.getRelativeFilenameForSwc(stepFile);
1251
- const { workflowManifest: fileManifest } = await applySwcTransform(relativeFilename, source, 'step', stepFile, this.config.projectRoot || this.config.workingDir);
1252
- this.mergeWorkflowManifest(workflowManifest, fileManifest);
1253
- }));
1254
- const stepFileSet = new Set(stepFiles);
1255
- const workflowOnlyFiles = workflowFiles
1256
- .filter((workflowFile) => !stepFileSet.has(workflowFile))
1257
- .sort();
1258
- await Promise.all(workflowOnlyFiles.map(async (workflowFile) => {
1259
- try {
1260
- const source = await (0, promises_1.readFile)(workflowFile, 'utf-8');
1261
- const relativeFilename = await this.getRelativeFilenameForSwc(workflowFile);
1262
- const { workflowManifest: fileManifest } = await applySwcTransform(relativeFilename, source, 'workflow', workflowFile, this.config.projectRoot || this.config.workingDir);
1263
- this.mergeWorkflowManifest(workflowManifest, {
1264
- workflows: fileManifest.workflows,
1265
- classes: fileManifest.classes,
1266
- });
1267
- }
1268
- catch (error) {
1269
- console.log(`Warning: Failed to extract workflow metadata from ${workflowFile}:`, error instanceof Error ? error.message : String(error));
1323
+ // If detect fails, include the file to be safe
1324
+ verifiedSerdeFiles.push(filePath);
1270
1325
  }
1271
1326
  }));
1272
- return workflowManifest;
1273
- }
1274
- async buildStepsFunction({ workflowGeneratedDir, routeFileName = 'route.js', discoveredEntries, }) {
1275
- const stepsRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'step');
1276
- await (0, promises_1.mkdir)(stepsRouteDir, { recursive: true });
1277
- const discovered = discoveredEntries;
1278
- const workflowFiles = [...discovered.discoveredWorkflows].sort();
1279
- const stepFiles = await this.collectTransitiveStepFiles({
1280
- stepFiles: [...discovered.discoveredSteps].sort(),
1281
- // Workflow transforms can inline step IDs and remove runtime imports,
1282
- // so seed transitive traversal with workflow files too.
1283
- seedFiles: workflowFiles,
1284
- });
1285
- const serdeFiles = [...discovered.discoveredSerdeFiles].sort();
1286
- const stepFileSet = new Set(stepFiles);
1287
- const serdeOnlyFiles = serdeFiles.filter((file) => !stepFileSet.has(file));
1288
- // Copy all discovered step sources so they are transformed in step mode.
1289
- // Importing raw node_modules files directly can bypass loader transforms,
1290
- // which prevents step registrars from being emitted.
1291
- const copiedStepSourceFiles = stepFiles;
1292
- const copiedDiscoveredStepFiles = await this.copyDiscoveredStepFiles({
1293
- stepFiles: copiedStepSourceFiles,
1294
- stepsRouteDir,
1295
- });
1296
- const responseBuiltinsStepFilePath = await this.createResponseBuiltinsStepFile({
1297
- stepsRouteDir,
1298
- });
1299
- const copiedStepFiles = [
1300
- responseBuiltinsStepFilePath,
1301
- ...copiedDiscoveredStepFiles,
1302
- ];
1303
- const manifestStepFiles = Array.from(new Set([...stepFiles, responseBuiltinsStepFilePath])).sort();
1304
- const stepRouteFile = (0, node_path_1.join)(stepsRouteDir, routeFileName);
1305
- const copiedStepImports = copiedStepFiles
1306
- .map((copiedStepFile) => {
1307
- const importSpecifier = this.getRelativeImportSpecifier(stepRouteFile, copiedStepFile);
1308
- return `import '${importSpecifier}';`;
1309
- })
1310
- .join('\n');
1311
- const serdeImports = serdeOnlyFiles
1312
- .map((serdeFile) => {
1313
- const normalizedSerdeFile = this.normalizeDiscoveredFilePath(serdeFile);
1314
- const { importPath, isPackage } = getImportPath(normalizedSerdeFile, this.config.workingDir);
1315
- if (isPackage) {
1316
- return `import '${importPath}';`;
1317
- }
1318
- const importSpecifier = this.getRelativeImportSpecifier(stepRouteFile, normalizedSerdeFile);
1319
- return `import '${importSpecifier}';`;
1320
- })
1321
- .join('\n');
1322
- const routeContents = [
1323
- '// biome-ignore-all lint: generated file',
1324
- '/* eslint-disable */',
1325
- copiedStepImports,
1326
- serdeImports
1327
- ? `// Serde files for cross-context class registration\n${serdeImports}`
1328
- : '',
1329
- "export { stepEntrypoint as POST } from 'workflow/runtime';",
1330
- ]
1331
- .filter(Boolean)
1332
- .join('\n');
1333
- await this.writeFileIfChanged(stepRouteFile, routeContents);
1334
- const manifest = await this.createDeferredStepsManifest({
1335
- stepFiles: manifestStepFiles,
1336
- workflowFiles,
1337
- serdeOnlyFiles,
1338
- });
1339
- return {
1340
- context: undefined,
1341
- manifest,
1342
- };
1343
- }
1344
- async buildWorkflowsFunction({ inputFiles, workflowGeneratedDir, tsconfigPath, routeFileName = 'route.js', discoveredEntries, }) {
1345
- const workflowsRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'flow');
1346
- await (0, promises_1.mkdir)(workflowsRouteDir, { recursive: true });
1347
- return await this.createWorkflowsBundle({
1348
- format: 'esm',
1349
- outfile: (0, node_path_1.join)(workflowsRouteDir, routeFileName),
1350
- bundleFinalOutput: false,
1351
- // Deferred builds do not reuse the interim esbuild context. Dispose it
1352
- // after each pass to avoid leaking contexts during watch-mode rebuilds.
1353
- keepInterimBundleContext: false,
1354
- inputFiles,
1355
- tsconfigPath,
1356
- discoveredEntries,
1357
- });
1327
+ return verifiedSerdeFiles.sort();
1358
1328
  }
1359
1329
  async buildWebhookRoute({ workflowGeneratedDir, routeFileName = 'route.js', }) {
1360
1330
  const webhookRouteFile = (0, node_path_1.join)(workflowGeneratedDir, `webhook/[token]/${routeFileName}`);
@@ -1410,4 +1380,4 @@ async function getNextBuilderDeferred() {
1410
1380
  CachedNextBuilderDeferred = NextDeferredBuilder;
1411
1381
  return NextDeferredBuilder;
1412
1382
  }
1413
- //# sourceMappingURL=builder-deferred.js.map
1383
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGRlci1kZWZlcnJlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9idWlsZGVyLWRlZmVycmVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBdUNBLHdEQXUwREM7QUE5MkRELDZDQUF5QztBQUN6QyxxQ0FBOEQ7QUFDOUQsK0NBUzBCO0FBQzFCLDZDQUE0QztBQUM1QyxzREFBeUI7QUFDekIseUNBUW1CO0FBQ25CLHlEQU00QjtBQUU1QixNQUFNLHNCQUFzQixHQUFHLDBCQUEwQixDQUFDO0FBQzFELE1BQU0sNEJBQTRCLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztBQUU5QyxJQUFJLHlCQUE4QixDQUFDO0FBRW5DLGlGQUFpRjtBQUNqRixnRkFBZ0Y7QUFDaEYsb0VBQW9FO0FBQzdELEtBQUssVUFBVSxzQkFBc0I7SUFDMUMsSUFBSSx5QkFBeUIsRUFBRSxDQUFDO1FBQzlCLE9BQU8seUJBQXlCLENBQUM7SUFDbkMsQ0FBQztJQUVELDZFQUE2RTtJQUM3RSw0RUFBNEU7SUFDNUUsMkVBQTJFO0lBQzNFLCtFQUErRTtJQUMvRSwyRUFBMkU7SUFDM0UseUNBQXlDO0lBQ3pDLE1BQU0sRUFDSixXQUFXLEVBQUUsZ0JBQWdCLEVBQzdCLHNCQUFzQixFQUN0QixzQkFBc0IsRUFDdEIsaUJBQWlCLEVBQ2pCLGdDQUFnQztJQUNoQyw0SUFBNEk7TUFDN0ksR0FBRyxDQUFDLE1BQU0sSUFBSSxDQUNiLDhCQUE4QixDQUMvQixDQUF3QyxDQUFDO0lBRTFDLE1BQU0sbUJBQW9CLFNBQVEsZ0JBQWdCO1FBQ3hDLFFBQVEsQ0FBWTtRQUNYLHVCQUF1QixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDNUMsbUJBQW1CLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUN4QyxvQkFBb0IsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQ2xELHNCQUFzQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDM0Msa0JBQWtCLEdB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QUFDO2dCQUNoQywrQ0FBK0M7Z0JBQy9DLE1BQU0sSUFBQSxnQkFBSyxFQUFDLE1BQU0sRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUN6QyxPQUFPLE1BQU0sQ0FBQztZQUNoQixDQUFDO1lBRUQsSUFBSSxNQUFNLFdBQVcsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO2dCQUNuQyx1REFBdUQ7Z0JBQ3ZELE1BQU0sSUFBQSxnQkFBSyxFQUFDLFNBQVMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUM1QyxPQUFPLFNBQVMsQ0FBQztZQUNuQixDQUFDO1lBRUQsTUFBTSxJQUFJLEtBQUssQ0FDYixxSEFBcUgsQ0FDdEgsQ0FBQztRQUNKLENBQUM7S0FDRjtJQUVELHlCQUF5QixHQUFHLG1CQUFtQixDQUFDO0lBQ2hELE9BQU8sbUJBQW1CLENBQUM7QUFDN0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tICdub2RlOmNyeXB0byc7XG5pbXBvcnQgeyBjb25zdGFudHMsIGV4aXN0c1N5bmMsIHJlYWRGaWxlU3luYyB9IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHtcbiAgYWNjZXNzLFxuICBta2RpcixcbiAgb3BlbixcbiAgcmVhZGRpcixcbiAgcmVhZEZpbGUsXG4gIHJtLFxuICBzdGF0LFxuICB3cml0ZUZpbGUsXG59IGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnO1xuaW1wb3J0IHsgY3JlYXRlUmVxdWlyZSB9IGZyb20gJ25vZGU6bW9kdWxlJztcbmltcG9ydCBvcyBmcm9tICdub2RlOm9zJztcbmltcG9ydCB7XG4gIGJhc2VuYW1lLFxuICBkaXJuYW1lLFxuICBleHRuYW1lLFxuICBpc0Fic29sdXRlLFxuICBqb2luLFxuICByZWxhdGl2ZSxcbiAgcmVzb2x2ZSxcbn0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7XG4gIGNsZWFudXBTdGFsZVNvY2tldEluZm9GaWxlcyxcbiAgY3JlYXRlU29ja2V0U2VydmVyLFxuICBTT0NLRVRfSU5GT19GSUxFTkFNRSxcbiAgdHlwZSBTb2NrZXRJTyxcbiAgdHlwZSBTb2NrZXRTZXJ2ZXJDb25maWcsXG59IGZyb20gJy4vc29ja2V0LXNlcnZlci5qcyc7XG5cbmNvbnN0IFJPVVRFX1NUVUJfRklMRV9NQVJLRVIgPSAnV09SS0ZMT1dfUk9VVEVfU1RVQl9GSUxFJztcbmNvbnN0IFJPVVRFX1NUVUJfTUFSS0VSX1NDQU5fQllURVMgPSA0ICogMTAyNDtcblxubGV0IENhY2hlZE5leHRCdWlsZGVyRGVmZXJyZWQ6IGFueTtcblxuLy8gQ3JlYXRlIHRoZSBkZWZlcnJlZCBOZXh0IGJ1aWxkZXIgZHluYW1pY2FsbHkgYnkgZXh0ZW5kaW5nIHRoZSBFU00gQmFzZUJ1aWxkZXIuXG4vLyBFeHBvcnRlZCBhcyBnZXROZXh0QnVpbGRlckRlZmVycmVkKCkgdG8gYWxsb3cgQ29tbW9uSlMgbW9kdWxlcyB0byBpbXBvcnQgZnJvbVxuLy8gdGhlIEVTTSBAd29ya2Zsb3cvYnVpbGRlcnMgcGFja2FnZSB2aWEgZHluYW1pYyBpbXBvcnQgYXQgcnVudGltZS5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXROZXh0QnVpbGRlckRlZmVycmVkKCkge1xuICBpZiAoQ2FjaGVkTmV4dEJ1aWxkZXJEZWZlcnJlZCkge1xuICAgIHJldHVybiBDYWNoZWROZXh0QnVpbGRlckRlZmVycmVkO1xuICB9XG5cbiAgLy8gVjI6IFNURVBfUVVFVUVfVFJJR0dFUiwgZ2V0SW1wb3J0UGF0aCwgYW5kIGVuaGFuY2VkLXJlc29sdmUgaW5mcmFzdHJ1Y3R1cmVcbiAgLy8gd2VyZSByZW1vdmVkIGJlY2F1c2UgdGhlIFYyIGNvbWJpbmVkIGhhbmRsZXIgZWxpbWluYXRlcyB0aGUgc2VwYXJhdGUgc3RlcFxuICAvLyByb3V0ZS90b3BpYy4gVGhlIHN0ZXAgY29weSBpbXBvcnQgcmV3cml0aW5nIChnZXRSZWxhdGl2ZUltcG9ydFNwZWNpZmllcixcbiAgLy8gZ2V0U3RlcENvcHlGaWxlTmFtZSwgcmV3cml0ZVJlbGF0aXZlSW1wb3J0c0ZvckNvcGllZFN0ZXApIGZyb20gbWFpbiB3YXMgYWxzb1xuICAvLyByZW1vdmVkIOKAlCBWMiBkb2Vzbid0IHVzZSBzdGVwIGNvcGllcy4gSWYgc3RlcCBjb3B5IHN1cHBvcnQgaXMgbmVlZGVkLCBpdFxuICAvLyBzaG91bGQgbGFuZCBhcyBhIGNvbXBsZXRlIGZlYXR1cmUgc2V0LlxuICBjb25zdCB7XG4gICAgQmFzZUJ1aWxkZXI6IEJhc2VCdWlsZGVyQ2xhc3MsXG4gICAgV09SS0ZMT1dfUVVFVUVfVFJJR0dFUixcbiAgICBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zLFxuICAgIGFwcGx5U3djVHJhbnNmb3JtLFxuICAgIHJlc29sdmVXb3JrZmxvd0FsaWFzUmVsYXRpdmVQYXRoLFxuICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L3NlY3VyaXR5L25vR2xvYmFsRXZhbDogTmVlZCB0byB1c2UgZXZhbCBoZXJlIHRvIGF2b2lkIFR5cGVTY3JpcHQgZnJvbSB0cmFuc3BpbGluZyB0aGUgaW1wb3J0IHN0YXRlbWVudCBpbnRvIGByZXF1aXJlKClgXG4gIH0gPSAoYXdhaXQgZXZhbChcbiAgICAnaW1wb3J0KFwiQHdvcmtmbG93L2J1aWxkZXJzXCIpJ1xuICApKSBhcyB0eXBlb2YgaW1wb3J0KCdAd29ya2Zsb3cvYnVpbGRlcnMnKTtcblxuICBjbGFzcyBOZXh0RGVmZXJyZWRCdWlsZGVyIGV4dGVuZHMgQmFzZUJ1aWxkZXJDbGFzcyB7XG4gICAgcHJpdmF0ZSBzb2NrZXRJTz86IFNvY2tldElPO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZGlzY292ZXJlZFdvcmtmbG93RmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGRpc2NvdmVyZWRTdGVwRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGRpc2NvdmVyZWRTZXJkZUZpbGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgcHJpdmF0ZSB0cmFja2VkRGVwZW5kZW5jeUZpbGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgcHJpdmF0ZSBkZWZlcnJlZEJ1aWxkUXVldWUgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICBwcml2YXRlIGNhY2hlSW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIGNhY2hlV3JpdGVUaW1lcjogTm9kZUpTLlRpbWVvdXQgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIGRlZmVycmVkUmVidWlsZFRpbWVyOiBOb2RlSlMuVGltZW91dCB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgbGFzdERlZmVycmVkQnVpbGRTaWduYXR1cmU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gICAgYXN5bmMgYnVpbGQoKSB7XG4gICAgICBjb25zdCBvdXRwdXREaXIgPSBhd2FpdCB0aGlzLmZpbmRBcHBEaXJlY3RvcnkoKTtcblxuICAgICAgYXdhaXQgdGhpcy5pbml0aWFsaXplRGlzY292ZXJ5U3RhdGUoKTtcbiAgICAgIGF3YWl0IHRoaXMuY2xlYW51cEdlbmVyYXRlZEFydGlmYWN0c09uQm9vdChvdXRwdXREaXIpO1xuXG4gICAgICBhd2FpdCB0aGlzLndyaXRlU3R1YkZpbGVzKG91dHB1dERpcik7XG4gICAgICBhd2FpdCB0aGlzLmNyZWF0ZURpc2NvdmVyeVNvY2tldFNlcnZlcigpO1xuICAgIH1cblxuICAgIGFzeW5jIG9uQmVmb3JlRGVmZXJyZWRFbnRyaWVzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgYXdhaXQgdGhpcy5pbml0aWFsaXplRGlzY292ZXJ5U3RhdGUoKTtcbiAgICAgIGF3YWl0IHRoaXMudmFsaWRhdGVEaXNjb3ZlcmVkRW50cnlGaWxlcygpO1xuICAgICAgY29uc3QgaW1wbGljaXRTdGVwRmlsZXMgPSBhd2FpdCB0aGlzLnJlc29sdmVJbXBsaWNpdFN0ZXBGaWxlcygpO1xuXG4gICAgICBjb25zdCBwZW5kaW5nQnVpbGQgPSB0aGlzLmRlZmVycmVkQnVpbGRRdWV1ZS50aGVuKCgpID0+XG4gICAgICAgIHRoaXMuYnVpbGREZWZlcnJlZEVudHJpZXNVbnRpbFN0YWJsZShpbXBsaWNpdFN0ZXBGaWxlcylcbiAgICAgICk7XG5cbiAgICAgIC8vIEtlZXAgdGhlIHF1ZXVlIGNoYWluIGFsaXZlIGV2ZW4gd2hlbiB0aGUgY3VycmVudCBidWlsZCBmYWlscyBzbyBmdXR1cmVcbiAgICAgIC8vIGNhbGxiYWNrcyBjYW4gZW5xdWV1ZSBhbm90aGVyIGF0dGVtcHQgd2l0aG91dCB0cmlnZ2VyaW5nIHVuaGFuZGxlZFxuICAgICAgLy8gcmVqZWN0aW9uIHdhcm5pbmdzLlxuICAgICAgdGhpcy5kZWZlcnJlZEJ1aWxkUXVldWUgPSBwZW5kaW5nQnVpbGQuY2F0Y2goKCkgPT4ge1xuICAgICAgICAvLyBFcnJvciBpcyBzdXJmYWNlZCB0aHJvdWdoIGBwZW5kaW5nQnVpbGRgIGJlbG93LlxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHBlbmRpbmdCdWlsZDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEN1cnJlbnRJbnB1dEZpbGVzKGltcGxpY2l0U3RlcEZpbGVzOiBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgICAgIHJldHVybiBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFtcbiAgICAgICAgICAuLi50aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzLFxuICAgICAgICAgIC4uLnRoaXMuZGlzY292ZXJlZFN0ZXBGaWxlcyxcbiAgICAgICAgICAuLi50aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLFxuICAgICAgICAgIC4uLmltcGxpY2l0U3RlcEZpbGVzLFxuICAgICAgICBdKVxuICAgICAgKS5zb3J0KCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBidWlsZERlZmVycmVkRW50cmllc1VudGlsU3RhYmxlKFxuICAgICAgaW1wbGljaXRTdGVwRmlsZXM6IHN0cmluZ1tdXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAvLyBBIHN1Y2Nlc3NmdWwgYnVpbGQgY2FuIGRpc2NvdmVyIGFkZGl0aW9uYWwgdHJhbnNpdGl2ZSBkZXBlbmRlbmN5IGZpbGVzXG4gICAgICAvLyAodmlhIHNvdXJjZSBtYXBzKSwgd2hpY2ggY2hhbmdlcyB0aGUgc2lnbmF0dXJlIGFuZCBtYXkgcmVxdWlyZSBvbmUgbW9yZVxuICAgICAgLy8gYnVpbGQgcGFzcyB0byBpbmNsdWRlIG5ld2x5IGRpc2NvdmVyZWQgc2VyZGUgZmlsZXMuXG4gICAgICBjb25zdCBtYXhCdWlsZFBhc3NlcyA9IDM7XG5cbiAgICAgIGZvciAobGV0IGJ1aWxkUGFzcyA9IDA7IGJ1aWxkUGFzcyA8IG1heEJ1aWxkUGFzc2VzOyBidWlsZFBhc3MrKykge1xuICAgICAgICBjb25zdCBpbnB1dEZpbGVzID0gdGhpcy5nZXRDdXJyZW50SW5wdXRGaWxlcyhpbXBsaWNpdFN0ZXBGaWxlcyk7XG4gICAgICAgIGNvbnN0IGJ1aWxkU2lnbmF0dXJlID1cbiAgICAgICAgICBhd2FpdCB0aGlzLmNyZWF0ZURlZmVycmVkQnVpbGRTaWduYXR1cmUoaW5wdXRGaWxlcyk7XG4gICAgICAgIGNvbnN0IHNob3VsZEZvcmNlQnVpbGRGb3JHZW5lcmF0ZWRSb3V0ZXMgPVxuICAgICAgICAgIGF3YWl0IHRoaXMuc2hvdWxkRm9yY2VCdWlsZEZvckdlbmVyYXRlZFJvdXRlcygpO1xuICAgICAgICBpZiAoXG4gICAgICAgICAgYnVpbGRTaWduYXR1cmUgPT09IHRoaXMubGFzdERlZmVycmVkQnVpbGRTaWduYXR1cmUgJiZcbiAgICAgICAgICAhc2hvdWxkRm9yY2VCdWlsZEZvckdlbmVyYXRlZFJvdXRlc1xuICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuYnVpbGREaXNjb3ZlcmVkRmlsZXMoaW5wdXRGaWxlcywgaW1wbGljaXRTdGVwRmlsZXMpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy53YXRjaCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy52YWxpZGF0ZURpc2NvdmVyZWRFbnRyeUZpbGVzKCk7XG4gICAgICAgICAgICBjb25zdCByZWNvdmVyZWRJbnB1dEZpbGVzID1cbiAgICAgICAgICAgICAgdGhpcy5nZXRDdXJyZW50SW5wdXRGaWxlcyhpbXBsaWNpdFN0ZXBGaWxlcyk7XG4gICAgICAgICAgICBjb25zdCByZWNvdmVyZWRTaWduYXR1cmUgPVxuICAgICAgICAgICAgICBhd2FpdCB0aGlzLmNyZWF0ZURlZmVycmVkQnVpbGRTaWduYXR1cmUocmVjb3ZlcmVkSW5wdXRGaWxlcyk7XG4gICAgICAgICAgICBpZiAocmVjb3ZlcmVkU2lnbmF0dXJlICE9PSBidWlsZFNpZ25hdHVyZSkge1xuICAgICAgICAgICAgICAvLyBBIGZpbGUgd2FzIGFkZGVkL3JlbW92ZWQgd2hpbGUgdGhpcyBidWlsZCB3YXMgcnVubmluZzsgcmV0cnlcbiAgICAgICAgICAgICAgLy8gaW1tZWRpYXRlbHkgd2l0aCB0aGUgcmVmcmVzaGVkIGRpc2NvdmVyZWQtZW50cnkgc3RhdGUuXG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICAnW3dvcmtmbG93XSBEZWZlcnJlZCBlbnRyaWVzIGJ1aWxkIGZhaWxlZC4gV2lsbCByZXRyeSBvbmx5IGFmdGVyIGlucHV0cyBjaGFuZ2UuJyxcbiAgICAgICAgICAgICAgZXJyb3JcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLmxhc3REZWZlcnJlZEJ1aWxkU2lnbmF0dXJlID0gYnVpbGRTaWduYXR1cmU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxhc3REZWZlcnJlZEJ1aWxkU2lnbmF0dXJlID0gYnVpbGRTaWduYXR1cmU7XG5cbiAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy53YXRjaCkge1xuICAgICAgICAgIC8vIFByb2R1Y3Rpb24gYnVpbGRzIGNhbiBwZXJzaXN0IG5ld2x5IGRpc2NvdmVyZWQgZGVmZXJyZWQtZW50cnkgZmlsZXMgdG9cbiAgICAgICAgICAvLyB0aGUgY2FjaGUgYWZ0ZXIgdGhlIGZpcnN0IHBhc3MgY29tcGxldGVzLiBSZWxvYWQgdGhhdCBjYWNoZSBiZWZvcmUgd2VcbiAgICAgICAgICAvLyBkZWNpZGUgd2hldGhlciB0aGUgaW5wdXQgc2lnbmF0dXJlIHN0YWJpbGl6ZWQgc28gc3RhZ2VkIHRhcmJhbGwgYnVpbGRzXG4gICAgICAgICAgLy8gY2FuIGltbWVkaWF0ZWx5IHJlcGxheSB3aXRoIHRoZSBleHBhbmRlZCBzdGVwIHNldC5cbiAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAyNTApKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLmxvYWRXb3JrZmxvd3NDYWNoZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcG9zdEJ1aWxkSW5wdXRGaWxlcyA9XG4gICAgICAgICAgdGhpcy5nZXRDdXJyZW50SW5wdXRGaWxlcyhpbXBsaWNpdFN0ZXBGaWxlcyk7XG4gICAgICAgIGNvbnN0IHBvc3RCdWlsZFNpZ25hdHVyZSA9XG4gICAgICAgICAgYXdhaXQgdGhpcy5jcmVhdGVEZWZlcnJlZEJ1aWxkU2lnbmF0dXJlKHBvc3RCdWlsZElucHV0RmlsZXMpO1xuICAgICAgICBpZiAocG9zdEJ1aWxkU2lnbmF0dXJlID09PSBidWlsZFNpZ25hdHVyZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICdbd29ya2Zsb3ddIERlZmVycmVkIGVudHJpZXMgYnVpbGQgc2lnbmF0dXJlIGRpZCBub3Qgc3RhYmlsaXplIGFmdGVyIDMgcGFzc2VzLidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZXNvbHZlSW1wbGljaXRTdGVwRmlsZXMoKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgICAgY29uc3Qgd29ya2Zsb3dTdGRsaWJQYXRoID0gdGhpcy5yZXNvbHZlV29ya2Zsb3dTdGRsaWJTdGVwRmlsZVBhdGgoKTtcbiAgICAgIHJldHVybiB3b3JrZmxvd1N0ZGxpYlBhdGggPyBbd29ya2Zsb3dTdGRsaWJQYXRoXSA6IFtdO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgc2hvdWxkRm9yY2VCdWlsZEZvckdlbmVyYXRlZFJvdXRlcygpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgIGNvbnN0IG91dHB1dERpciA9IGF3YWl0IHRoaXMuZmluZEFwcERpcmVjdG9yeSgpO1xuICAgICAgY29uc3QgZ2VuZXJhdGVkUm91dGVGaWxlcyA9IFtcbiAgICAgICAgam9pbihvdXRwdXREaXIsICcud2VsbC1rbm93bi93b3JrZmxvdy92MS9mbG93L3JvdXRlLmpzJyksXG4gICAgICAgIGpvaW4ob3V0cHV0RGlyLCAnLndlbGwta25vd24vd29ya2Zsb3cvdjEvd2ViaG9vay9bdG9rZW5dL3JvdXRlLmpzJyksXG4gICAgICBdO1xuXG4gICAgICBmb3IgKGNvbnN0IHJvdXRlRmlsZVBhdGggb2YgZ2VuZXJhdGVkUm91dGVGaWxlcykge1xuICAgICAgICBjb25zdCByb3V0ZVN0YXRlID0gYXdhaXQgdGhpcy5nZXRHZW5lcmF0ZWRSb3V0ZVN0YXRlKHJvdXRlRmlsZVBhdGgpO1xuICAgICAgICBpZiAocm91dGVTdGF0ZSA9PT0gJ21pc3NpbmcnIHx8IHJvdXRlU3RhdGUgPT09ICdzdHViJykge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGdldEdlbmVyYXRlZFJvdXRlU3RhdGUoXG4gICAgICByb3V0ZUZpbGVQYXRoOiBzdHJpbmdcbiAgICApOiBQcm9taXNlPCdtaXNzaW5nJyB8ICdzdHViJyB8ICdnZW5lcmF0ZWQnPiB7XG4gICAgICBsZXQgcm91dGVTdGF0cztcbiAgICAgIHRyeSB7XG4gICAgICAgIHJvdXRlU3RhdHMgPSBhd2FpdCBzdGF0KHJvdXRlRmlsZVBhdGgpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiAnbWlzc2luZyc7XG4gICAgICB9XG4gICAgICBpZiAoIXJvdXRlU3RhdHMuaXNGaWxlKCkpIHtcbiAgICAgICAgcmV0dXJuICdtaXNzaW5nJztcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3Qgcm91dGVGaWxlSGFuZGxlID0gYXdhaXQgb3Blbihyb3V0ZUZpbGVQYXRoLCAncicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IG1hcmtlclNjYW5CdWZmZXIgPSBCdWZmZXIuYWxsb2MoUk9VVEVfU1RVQl9NQVJLRVJfU0NBTl9CWVRFUyk7XG4gICAgICAgICAgY29uc3QgeyBieXRlc1JlYWQgfSA9IGF3YWl0IHJvdXRlRmlsZUhhbmRsZS5yZWFkKFxuICAgICAgICAgICAgbWFya2VyU2NhbkJ1ZmZlcixcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICBST1VURV9TVFVCX01BUktFUl9TQ0FOX0JZVEVTLFxuICAgICAgICAgICAgMFxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgbWFya2VyU2NhblNvdXJjZSA9IG1hcmtlclNjYW5CdWZmZXIudG9TdHJpbmcoXG4gICAgICAgICAgICAndXRmOCcsXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgYnl0ZXNSZWFkXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4gbWFya2VyU2NhblNvdXJjZS5pbmNsdWRlcyhST1VURV9TVFVCX0ZJTEVfTUFSS0VSKVxuICAgICAgICAgICAgPyAnc3R1YidcbiAgICAgICAgICAgIDogJ2dlbmVyYXRlZCc7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgYXdhaXQgcm91dGVGaWxlSGFuZGxlLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gJ21pc3NpbmcnO1xuICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcmVzb2x2ZVdvcmtmbG93U3RkbGliU3RlcEZpbGVQYXRoKCk6IHN0cmluZyB8IG51bGwge1xuICAgICAgbGV0IHdvcmtmbG93Q2pzRW50cnk6IHN0cmluZztcbiAgICAgIHRyeSB7XG4gICAgICAgIHdvcmtmbG93Q2pzRW50cnkgPSByZXF1aXJlLnJlc29sdmUoJ3dvcmtmbG93Jywge1xuICAgICAgICAgIHBhdGhzOiBbdGhpcy5jb25maWcud29ya2luZ0Rpcl0sXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB3b3JrZmxvd0Rpc3REaXIgPSBkaXJuYW1lKHdvcmtmbG93Q2pzRW50cnkpO1xuICAgICAgY29uc3Qgd29ya2Zsb3dTdGRsaWJQYXRoID0gdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoXG4gICAgICAgIGpvaW4od29ya2Zsb3dEaXN0RGlyLCAnc3RkbGliLmpzJylcbiAgICAgICk7XG4gICAgICByZXR1cm4gZXhpc3RzU3luYyh3b3JrZmxvd1N0ZGxpYlBhdGgpID8gd29ya2Zsb3dTdGRsaWJQYXRoIDogbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJlY29uY2lsZURpc2NvdmVyZWRFbnRyaWVzKHtcbiAgICAgIHdvcmtmbG93Q2FuZGlkYXRlcyxcbiAgICAgIHN0ZXBDYW5kaWRhdGVzLFxuICAgICAgc2VyZGVDYW5kaWRhdGVzLFxuICAgICAgdmFsaWRhdGVQYXR0ZXJucyxcbiAgICB9OiB7XG4gICAgICB3b3JrZmxvd0NhbmRpZGF0ZXM6IEl0ZXJhYmxlPHN0cmluZz47XG4gICAgICBzdGVwQ2FuZGlkYXRlczogSXRlcmFibGU8c3RyaW5nPjtcbiAgICAgIHNlcmRlQ2FuZGlkYXRlcz86IEl0ZXJhYmxlPHN0cmluZz47XG4gICAgICB2YWxpZGF0ZVBhdHRlcm5zOiBib29sZWFuO1xuICAgIH0pOiBQcm9taXNlPHtcbiAgICAgIHdvcmtmbG93RmlsZXM6IFNldDxzdHJpbmc+O1xuICAgICAgc3RlcEZpbGVzOiBTZXQ8c3RyaW5nPjtcbiAgICAgIHNlcmRlRmlsZXM6IFNldDxzdHJpbmc+O1xuICAgIH0+IHtcbiAgICAgIGNvbnN0IGNhbmRpZGF0ZXNCeUZpbGUgPSBuZXcgTWFwPFxuICAgICAgICBzdHJpbmcsXG4gICAgICAgIHtcbiAgICAgICAgICBoYXNXb3JrZmxvd0NhbmRpZGF0ZTogYm9vbGVhbjtcbiAgICAgICAgICBoYXNTdGVwQ2FuZGlkYXRlOiBib29sZWFuO1xuICAgICAgICAgIGhhc1NlcmRlQ2FuZGlkYXRlOiBib29sZWFuO1xuICAgICAgICB9XG4gICAgICA+KCk7XG5cbiAgICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2Ygd29ya2Zsb3dDYW5kaWRhdGVzKSB7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoZmlsZVBhdGgpO1xuICAgICAgICBjb25zdCBleGlzdGluZyA9IGNhbmRpZGF0ZXNCeUZpbGUuZ2V0KG5vcm1hbGl6ZWRQYXRoKTtcbiAgICAgICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICAgICAgZXhpc3RpbmcuaGFzV29ya2Zsb3dDYW5kaWRhdGUgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbmRpZGF0ZXNCeUZpbGUuc2V0KG5vcm1hbGl6ZWRQYXRoLCB7XG4gICAgICAgICAgICBoYXNXb3JrZmxvd0NhbmRpZGF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIGhhc1N0ZXBDYW5kaWRhdGU6IGZhbHNlLFxuICAgICAgICAgICAgaGFzU2VyZGVDYW5kaWRhdGU6IGZhbHNlLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2Ygc3RlcENhbmRpZGF0ZXMpIHtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFBhdGggPSB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChmaWxlUGF0aCk7XG4gICAgICAgIGNvbnN0IGV4aXN0aW5nID0gY2FuZGlkYXRlc0J5RmlsZS5nZXQobm9ybWFsaXplZFBhdGgpO1xuICAgICAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgICAgICBleGlzdGluZy5oYXNTdGVwQ2FuZGlkYXRlID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjYW5kaWRhdGVzQnlGaWxlLnNldChub3JtYWxpemVkUGF0aCwge1xuICAgICAgICAgICAgaGFzV29ya2Zsb3dDYW5kaWRhdGU6IGZhbHNlLFxuICAgICAgICAgICAgaGFzU3RlcENhbmRpZGF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIGhhc1NlcmRlQ2FuZGlkYXRlOiBmYWxzZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoc2VyZGVDYW5kaWRhdGVzKSB7XG4gICAgICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2Ygc2VyZGVDYW5kaWRhdGVzKSB7XG4gICAgICAgICAgY29uc3Qgbm9ybWFsaXplZFBhdGggPSB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChmaWxlUGF0aCk7XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBjYW5kaWRhdGVzQnlGaWxlLmdldChub3JtYWxpemVkUGF0aCk7XG4gICAgICAgICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICAgICAgICBleGlzdGluZy5oYXNTZXJkZUNhbmRpZGF0ZSA9IHRydWU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbmRpZGF0ZXNCeUZpbGUuc2V0KG5vcm1hbGl6ZWRQYXRoLCB7XG4gICAgICAgICAgICAgIGhhc1dvcmtmbG93Q2FuZGlkYXRlOiBmYWxzZSxcbiAgICAgICAgICAgICAgaGFzU3RlcENhbmRpZGF0ZTogZmFsc2UsXG4gICAgICAgICAgICAgIGhhc1NlcmRlQ2FuZGlkYXRlOiB0cnVlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGZpbGVFbnRyaWVzID0gQXJyYXkuZnJvbShjYW5kaWRhdGVzQnlGaWxlLmVudHJpZXMoKSkuc29ydChcbiAgICAgICAgKFthXSwgW2JdKSA9PiBhLmxvY2FsZUNvbXBhcmUoYilcbiAgICAgICk7XG4gICAgICBjb25zdCB2YWxpZGF0ZWRFbnRyaWVzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGZpbGVFbnRyaWVzLm1hcChhc3luYyAoW2ZpbGVQYXRoLCBjYW5kaWRhdGVzXSkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBmaWxlU3RhdHMgPSBhd2FpdCBzdGF0KGZpbGVQYXRoKTtcbiAgICAgICAgICAgIGlmICghZmlsZVN0YXRzLmlzRmlsZSgpKSB7XG4gICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIXZhbGlkYXRlUGF0dGVybnMpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBmaWxlUGF0aCxcbiAgICAgICAgICAgICAgICBoYXNVc2VXb3JrZmxvdzogY2FuZGlkYXRlcy5oYXNXb3JrZmxvd0NhbmRpZGF0ZSxcbiAgICAgICAgICAgICAgICBoYXNVc2VTdGVwOiBjYW5kaWRhdGVzLmhhc1N0ZXBDYW5kaWRhdGUsXG4gICAgICAgICAgICAgICAgaGFzU2VyZGU6IGNhbmRpZGF0ZXMuaGFzU2VyZGVDYW5kaWRhdGUsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IGF3YWl0IHJlYWRGaWxlKGZpbGVQYXRoLCAndXRmLTgnKTtcbiAgICAgICAgICAgIGNvbnN0IHBhdHRlcm5zID0gZGV0ZWN0V29ya2Zsb3dQYXR0ZXJucyhzb3VyY2UpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZmlsZVBhdGgsXG4gICAgICAgICAgICAgIGhhc1VzZVdvcmtmbG93OiBwYXR0ZXJucy5oYXNVc2VXb3JrZmxvdyxcbiAgICAgICAgICAgICAgaGFzVXNlU3RlcDogcGF0dGVybnMuaGFzVXNlU3RlcCxcbiAgICAgICAgICAgICAgaGFzU2VyZGU6IHBhdHRlcm5zLmhhc1NlcmRlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHdvcmtmbG93RmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgIGNvbnN0IHN0ZXBGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgY29uc3Qgc2VyZGVGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiB2YWxpZGF0ZWRFbnRyaWVzKSB7XG4gICAgICAgIGlmICghZW50cnkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW50cnkuaGFzVXNlV29ya2Zsb3cpIHtcbiAgICAgICAgICB3b3JrZmxvd0ZpbGVzLmFkZChlbnRyeS5maWxlUGF0aCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVudHJ5Lmhhc1VzZVN0ZXApIHtcbiAgICAgICAgICBzdGVwRmlsZXMuYWRkKGVudHJ5LmZpbGVQYXRoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW50cnkuaGFzU2VyZGUpIHtcbiAgICAgICAgICBzZXJkZUZpbGVzLmFkZChlbnRyeS5maWxlUGF0aCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHsgd29ya2Zsb3dGaWxlcywgc3RlcEZpbGVzLCBzZXJkZUZpbGVzIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyB2YWxpZGF0ZURpc2NvdmVyZWRFbnRyeUZpbGVzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgY29uc3Qgd29ya2Zsb3dDYW5kaWRhdGVzID0gbmV3IFNldCh0aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzKTtcbiAgICAgIGNvbnN0IHN0ZXBDYW5kaWRhdGVzID0gbmV3IFNldCh0aGlzLmRpc2NvdmVyZWRTdGVwRmlsZXMpO1xuICAgICAgY29uc3Qgc2VyZGVDYW5kaWRhdGVzID0gbmV3IFNldCh0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzKTtcbiAgICAgIGNvbnN0IHsgd29ya2Zsb3dGaWxlcywgc3RlcEZpbGVzLCBzZXJkZUZpbGVzIH0gPVxuICAgICAgICBhd2FpdCB0aGlzLnJlY29uY2lsZURpc2NvdmVyZWRFbnRyaWVzKHtcbiAgICAgICAgICB3b3JrZmxvd0NhbmRpZGF0ZXMsXG4gICAgICAgICAgc3RlcENhbmRpZGF0ZXMsXG4gICAgICAgICAgc2VyZGVDYW5kaWRhdGVzLFxuICAgICAgICAgIHZhbGlkYXRlUGF0dGVybnM6IHRydWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAvLyBSZWNvbmNpbGUgdmFsaWRhdGVkIGVudHJpZXMgYWdhaW5zdCB0aGUgc25hcHNob3Qgd2Ugc3RhcnRlZCB3aXRoIHNvXG4gICAgICAvLyBmaWxlIGRpc2NvdmVyaWVzIHRoYXQgYXJyaXZlIGR1cmluZyB2YWxpZGF0aW9uIGFyZSBwcmVzZXJ2ZWQuXG4gICAgICBsZXQgd29ya2Zsb3dzQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgbGV0IHN0ZXBzQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgbGV0IHNlcmRlQ2hhbmdlZCA9IGZhbHNlO1xuXG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHdvcmtmbG93Q2FuZGlkYXRlcykge1xuICAgICAgICBpZiAoIXdvcmtmbG93RmlsZXMuaGFzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHdvcmtmbG93c0NoYW5nZWQgPVxuICAgICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcy5kZWxldGUoZmlsZVBhdGgpIHx8IHdvcmtmbG93c0NoYW5nZWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2Ygd29ya2Zsb3dGaWxlcykge1xuICAgICAgICBpZiAoIXRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMuaGFzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMuYWRkKGZpbGVQYXRoKTtcbiAgICAgICAgICB3b3JrZmxvd3NDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHN0ZXBDYW5kaWRhdGVzKSB7XG4gICAgICAgIGlmICghc3RlcEZpbGVzLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICBzdGVwc0NoYW5nZWQgPVxuICAgICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLmRlbGV0ZShmaWxlUGF0aCkgfHwgc3RlcHNDaGFuZ2VkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHN0ZXBGaWxlcykge1xuICAgICAgICBpZiAoIXRoaXMuZGlzY292ZXJlZFN0ZXBGaWxlcy5oYXMoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLmFkZChmaWxlUGF0aCk7XG4gICAgICAgICAgc3RlcHNDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHNlcmRlQ2FuZGlkYXRlcykge1xuICAgICAgICBpZiAoIXNlcmRlRmlsZXMuaGFzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHNlcmRlQ2hhbmdlZCA9XG4gICAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmRlbGV0ZShmaWxlUGF0aCkgfHwgc2VyZGVDaGFuZ2VkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHNlcmRlRmlsZXMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmFkZChmaWxlUGF0aCk7XG4gICAgICAgICAgc2VyZGVDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAod29ya2Zsb3dzQ2hhbmdlZCB8fCBzdGVwc0NoYW5nZWQpIHtcbiAgICAgICAgdGhpcy5zY2hlZHVsZVdvcmtmbG93c0NhY2hlV3JpdGUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGJ1aWxkRGlzY292ZXJlZEZpbGVzKFxuICAgICAgaW5wdXRGaWxlczogc3RyaW5nW10sXG4gICAgICBpbXBsaWNpdFN0ZXBGaWxlczogc3RyaW5nW11cbiAgICApIHtcbiAgICAgIGNvbnN0IG91dHB1dERpciA9IGF3YWl0IHRoaXMuZmluZEFwcERpcmVjdG9yeSgpO1xuICAgICAgY29uc3Qgd29ya2Zsb3dHZW5lcmF0ZWREaXIgPSBqb2luKG91dHB1dERpciwgJy53ZWxsLWtub3duL3dvcmtmbG93L3YxJyk7XG4gICAgICBjb25zdCBjYWNoZURpciA9IGpvaW4odGhpcy5jb25maWcud29ya2luZ0RpciwgdGhpcy5nZXREaXN0RGlyKCksICdjYWNoZScpO1xuICAgICAgYXdhaXQgbWtkaXIoY2FjaGVEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgY29uc3QgbWFuaWZlc3RCdWlsZERpciA9IGpvaW4oY2FjaGVEaXIsICd3b3JrZmxvdy1nZW5lcmF0ZWQtbWFuaWZlc3QnKTtcbiAgICAgIGNvbnN0IHRlbXBSb3V0ZUZpbGVOYW1lID0gJ3JvdXRlLmpzLnRlbXAnO1xuICAgICAgY29uc3QgdHJhY2tlZERpc2NvdmVyZWRFbnRyaWVzID1cbiAgICAgICAgYXdhaXQgdGhpcy5jb2xsZWN0VHJhY2tlZERpc2NvdmVyZWRFbnRyaWVzKCk7XG4gICAgICBjb25zdCBkaXNjb3ZlcmVkU3RlcEZpbGVDYW5kaWRhdGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbXG4gICAgICAgICAgLi4udGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLFxuICAgICAgICAgIC4uLnRyYWNrZWREaXNjb3ZlcmVkRW50cmllcy5kaXNjb3ZlcmVkU3RlcHMsXG4gICAgICAgICAgLi4uaW1wbGljaXRTdGVwRmlsZXMsXG4gICAgICAgIF0pXG4gICAgICApLnNvcnQoKTtcbiAgICAgIGNvbnN0IGRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVDYW5kaWRhdGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbXG4gICAgICAgICAgLi4udGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcyxcbiAgICAgICAgICAuLi50cmFja2VkRGlzY292ZXJlZEVudHJpZXMuZGlzY292ZXJlZFdvcmtmbG93cyxcbiAgICAgICAgXSlcbiAgICAgICkuc29ydCgpO1xuICAgICAgY29uc3QgZGlzY292ZXJlZFNlcmRlRmlsZUNhbmRpZGF0ZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFtcbiAgICAgICAgICAuLi50aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLFxuICAgICAgICAgIC4uLnRyYWNrZWREaXNjb3ZlcmVkRW50cmllcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcyxcbiAgICAgICAgXSlcbiAgICAgICkuc29ydCgpO1xuICAgICAgY29uc3QgZGlzY292ZXJlZFdvcmtmbG93RmlsZXMgPSBhd2FpdCB0aGlzLmZpbHRlckV4aXN0aW5nRmlsZXMoXG4gICAgICAgIGRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVDYW5kaWRhdGVzXG4gICAgICApO1xuICAgICAgY29uc3QgZXhpc3RpbmdTdGVwRmlsZUNhbmRpZGF0ZXMgPSBhd2FpdCB0aGlzLmZpbHRlckV4aXN0aW5nRmlsZXMoXG4gICAgICAgIGRpc2NvdmVyZWRTdGVwRmlsZUNhbmRpZGF0ZXNcbiAgICAgICk7XG4gICAgICBjb25zdCBkaXNjb3ZlcmVkU3RlcEZpbGVzID0gYXdhaXQgdGhpcy5jb2xsZWN0VHJhbnNpdGl2ZVN0ZXBGaWxlcyh7XG4gICAgICAgIGVudHJ5RmlsZXM6IFsuLi5leGlzdGluZ1N0ZXBGaWxlQ2FuZGlkYXRlcywgLi4uZGlzY292ZXJlZFdvcmtmbG93RmlsZXNdLFxuICAgICAgICBzdGVwRmlsZXM6IGV4aXN0aW5nU3RlcEZpbGVDYW5kaWRhdGVzLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBleGlzdGluZ1NlcmRlRmlsZUNhbmRpZGF0ZXMgPSBhd2FpdCB0aGlzLmZpbHRlckV4aXN0aW5nRmlsZXMoXG4gICAgICAgIGRpc2NvdmVyZWRTZXJkZUZpbGVDYW5kaWRhdGVzXG4gICAgICApO1xuICAgICAgY29uc3QgZGlzY292ZXJlZFNlcmRlRmlsZXMgPSBhd2FpdCB0aGlzLmNvbGxlY3RUcmFuc2l0aXZlU2VyZGVGaWxlcyh7XG4gICAgICAgIGVudHJ5RmlsZXM6IFsuLi5kaXNjb3ZlcmVkU3RlcEZpbGVzLCAuLi5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlc10sXG4gICAgICAgIHNlcmRlRmlsZXM6IGV4aXN0aW5nU2VyZGVGaWxlQ2FuZGlkYXRlcyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgZXhpc3RpbmdJbnB1dEZpbGVzID0gYXdhaXQgdGhpcy5maWx0ZXJFeGlzdGluZ0ZpbGVzKGlucHV0RmlsZXMpO1xuICAgICAgY29uc3QgYnVpbGRJbnB1dEZpbGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbXG4gICAgICAgICAgLi4uZXhpc3RpbmdJbnB1dEZpbGVzLFxuICAgICAgICAgIC4uLmRpc2NvdmVyZWRTdGVwRmlsZXMsXG4gICAgICAgICAgLi4uZGlzY292ZXJlZFdvcmtmbG93RmlsZXMsXG4gICAgICAgICAgLi4uZGlzY292ZXJlZFNlcmRlRmlsZXMsXG4gICAgICAgIF0pXG4gICAgICApLnNvcnQoKTtcbiAgICAgIGNvbnN0IGRpc2NvdmVyZWRFbnRyaWVzID0ge1xuICAgICAgICBkaXNjb3ZlcmVkU3RlcHM6IG5ldyBTZXQoZGlzY292ZXJlZFN0ZXBGaWxlcyksXG4gICAgICAgIGRpc2NvdmVyZWRXb3JrZmxvd3M6IG5ldyBTZXQoZGlzY292ZXJlZFdvcmtmbG93RmlsZXMpLFxuICAgICAgICBkaXNjb3ZlcmVkU2VyZGVGaWxlczogbmV3IFNldChkaXNjb3ZlcmVkU2VyZGVGaWxlcyksXG4gICAgICB9O1xuXG4gICAgICAvLyBFbnN1cmUgb3V0cHV0IGRpcmVjdG9yaWVzIGV4aXN0XG4gICAgICBhd2FpdCBta2Rpcih3b3JrZmxvd0dlbmVyYXRlZERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgICAgIGF3YWl0IHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnLmdpdGlnbm9yZScpLFxuICAgICAgICAnKidcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHRzY29uZmlnUGF0aCA9IGF3YWl0IHRoaXMuZmluZFRzQ29uZmlnUGF0aCgpO1xuXG4gICAgICAvLyBWMjogQnVpbGQgY29tYmluZWQgcm91dGUgKHJlcGxhY2VzIHNlcGFyYXRlIHN0ZXAgKyBmbG93IHJvdXRlcylcbiAgICAgIGNvbnN0IGZsb3dSb3V0ZURpciA9IGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdmbG93Jyk7XG4gICAgICBhd2FpdCBta2RpcihmbG93Um91dGVEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgLy8gV3JpdGUgc3RlcCByZWdpc3RyYXRpb25zIHRvIGZpbmFsIG5hbWUgZGlyZWN0bHkgKG5vdCB0ZW1wKSBzbyB0aGVcbiAgICAgIC8vIGltcG9ydCBwYXRoIGluIHRoZSBmbG93IHJvdXRlIGlzIGNvcnJlY3QuIFRoZSBmbG93IHJvdXRlIHVzZXMgdGVtcFxuICAgICAgLy8gbmFtaW5nIHRvIGF2b2lkIEhNUiBjaHVybiB2aWEgY29weUZpbGVJZkNoYW5nZWQsIGJ1dCB0aGUgc3RlcFxuICAgICAgLy8gcmVnaXN0cmF0aW9ucyBmaWxlIGlzIGEgc2lkZS1lZmZlY3QgaW1wb3J0IGFuZCBkb2Vzbid0IG5lZWQgdGhhdC5cbiAgICAgIGNvbnN0IHN0ZXBzT3V0ZmlsZSA9IGpvaW4oZmxvd1JvdXRlRGlyLCAnX19zdGVwX3JlZ2lzdHJhdGlvbnMuanMnKTtcbiAgICAgIGNvbnN0IGNvbWJpbmVkUmVzdWx0ID0gYXdhaXQgdGhpcy5jcmVhdGVDb21iaW5lZEJ1bmRsZSh7XG4gICAgICAgIGZvcm1hdDogJ2VzbScsXG4gICAgICAgIGlucHV0RmlsZXM6IGJ1aWxkSW5wdXRGaWxlcyxcbiAgICAgICAgc3RlcHNPdXRmaWxlLFxuICAgICAgICBmbG93T3V0ZmlsZTogam9pbihmbG93Um91dGVEaXIsIHRlbXBSb3V0ZUZpbGVOYW1lKSxcbiAgICAgICAgYnVuZGxlRmluYWxPdXRwdXQ6IGZhbHNlLFxuICAgICAgICBleHRlcm5hbGl6ZU5vblN0ZXBzOiB0cnVlLFxuICAgICAgICB0c2NvbmZpZ1BhdGgsXG4gICAgICAgIGRpc2NvdmVyZWRFbnRyaWVzLFxuICAgICAgfSk7XG4gICAgICBhd2FpdCB0aGlzLmJ1aWxkV2ViaG9va1JvdXRlKHtcbiAgICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXIsXG4gICAgICAgIHJvdXRlRmlsZU5hbWU6IHRlbXBSb3V0ZUZpbGVOYW1lLFxuICAgICAgfSk7XG4gICAgICBhd2FpdCB0aGlzLnJlZnJlc2hUcmFja2VkRGVwZW5kZW5jeUZpbGVzKFxuICAgICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcixcbiAgICAgICAgdGVtcFJvdXRlRmlsZU5hbWVcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IG1hbmlmZXN0ID0ge1xuICAgICAgICBzdGVwczogeyAuLi5jb21iaW5lZFJlc3VsdD8ubWFuaWZlc3Q/LnN0ZXBzIH0sXG4gICAgICAgIHdvcmtmbG93czogeyAuLi5jb21iaW5lZFJlc3VsdD8ubWFuaWZlc3Q/LndvcmtmbG93cyB9LFxuICAgICAgICBjbGFzc2VzOiB7IC4uLmNvbWJpbmVkUmVzdWx0Py5tYW5pZmVzdD8uY2xhc3NlcyB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgbWFuaWZlc3RGaWxlUGF0aCA9IGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdtYW5pZmVzdC5qc29uJyk7XG4gICAgICBjb25zdCBtYW5pZmVzdEJ1aWxkUGF0aCA9IGpvaW4obWFuaWZlc3RCdWlsZERpciwgJ21hbmlmZXN0Lmpzb24nKTtcbiAgICAgIGNvbnN0IHdvcmtmbG93QnVuZGxlUGF0aCA9IGpvaW4oXG4gICAgICAgIHdvcmtmbG93R2VuZXJhdGVkRGlyLFxuICAgICAgICBgZmxvdy8ke3RlbXBSb3V0ZUZpbGVOYW1lfWBcbiAgICAgICk7XG4gICAgICBjb25zdCBtYW5pZmVzdEpzb24gPSBhd2FpdCB0aGlzLmNyZWF0ZU1hbmlmZXN0KHtcbiAgICAgICAgd29ya2Zsb3dCdW5kbGVQYXRoLFxuICAgICAgICBtYW5pZmVzdERpcjogbWFuaWZlc3RCdWlsZERpcixcbiAgICAgICAgbWFuaWZlc3QsXG4gICAgICB9KTtcbiAgICAgIGlmIChtYW5pZmVzdEpzb24pIHtcbiAgICAgICAgYXdhaXQgdGhpcy5yZXdyaXRlSnNvbkZpbGVXaXRoU3RhYmxlS2V5T3JkZXIobWFuaWZlc3RCdWlsZFBhdGgpO1xuICAgICAgICBhd2FpdCB0aGlzLmNvcHlGaWxlSWZDaGFuZ2VkKG1hbmlmZXN0QnVpbGRQYXRoLCBtYW5pZmVzdEZpbGVQYXRoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHJtKG1hbmlmZXN0QnVpbGRQYXRoLCB7IGZvcmNlOiB0cnVlIH0pO1xuICAgICAgICBhd2FpdCBybShtYW5pZmVzdEZpbGVQYXRoLCB7IGZvcmNlOiB0cnVlIH0pO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCB0aGlzLndyaXRlRnVuY3Rpb25zQ29uZmlnKG91dHB1dERpcik7XG5cbiAgICAgIC8vIFYyOiBDb21iaW5lZCByb3V0ZSAoZmxvdykg4oCUIHN0ZXAgcmVnaXN0cmF0aW9ucyBhbHJlYWR5IGF0IGZpbmFsIHBhdGhcbiAgICAgIGF3YWl0IHRoaXMuY29weUZpbGVJZkNoYW5nZWQoXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsIGBmbG93LyR7dGVtcFJvdXRlRmlsZU5hbWV9YCksXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdmbG93L3JvdXRlLmpzJylcbiAgICAgICk7XG4gICAgICBhd2FpdCB0aGlzLmNvcHlGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCBgd2ViaG9vay9bdG9rZW5dLyR7dGVtcFJvdXRlRmlsZU5hbWV9YCksXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICd3ZWJob29rL1t0b2tlbl0vcm91dGUuanMnKVxuICAgICAgKTtcblxuICAgICAgLy8gRXhwb3NlIG1hbmlmZXN0IGFzIGEgc3RhdGljIGZpbGUgd2hlbiBXT1JLRkxPV19QVUJMSUNfTUFOSUZFU1Q9MS5cbiAgICAgIC8vIE5leHQuanMgc2VydmVzIGZpbGVzIGZyb20gcHVibGljLyBhdCB0aGUgcm9vdCBVUkwuXG4gICAgICBpZiAodGhpcy5zaG91bGRFeHBvc2VQdWJsaWNNYW5pZmVzdCAmJiBtYW5pZmVzdEpzb24pIHtcbiAgICAgICAgY29uc3QgcHVibGljTWFuaWZlc3REaXIgPSBqb2luKFxuICAgICAgICAgIHRoaXMuY29uZmlnLndvcmtpbmdEaXIsXG4gICAgICAgICAgJ3B1YmxpYy8ud2VsbC1rbm93bi93b3JrZmxvdy92MSdcbiAgICAgICAgKTtcbiAgICAgICAgYXdhaXQgbWtkaXIocHVibGljTWFuaWZlc3REaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgICBpZiAocHJvY2Vzcy5lbnYuVkVSQ0VMX0RFUExPWU1FTlRfSUQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGF3YWl0IHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKFxuICAgICAgICAgICAgam9pbihwdWJsaWNNYW5pZmVzdERpciwgJy5naXRpZ25vcmUnKSxcbiAgICAgICAgICAgICcqJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgdGhpcy5jb3B5RmlsZUlmQ2hhbmdlZChcbiAgICAgICAgICBtYW5pZmVzdEZpbGVQYXRoLFxuICAgICAgICAgIGpvaW4ocHVibGljTWFuaWZlc3REaXIsICdtYW5pZmVzdC5qc29uJylcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gTm90aWZ5IGRlZmVycmVkIGVudHJ5IGxvYWRlcnMgd2FpdGluZyBvbiByb3V0ZS5qcyBzdHVicy5cbiAgICAgIHRoaXMuc29ja2V0SU8/LmVtaXQoJ2J1aWxkLWNvbXBsZXRlJyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjbGVhbnVwR2VuZXJhdGVkQXJ0aWZhY3RzT25Cb290KFxuICAgICAgb3V0cHV0RGlyOiBzdHJpbmdcbiAgICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IHdvcmtmbG93R2VuZXJhdGVkRGlyID0gam9pbihvdXRwdXREaXIsICcud2VsbC1rbm93bi93b3JrZmxvdy92MScpO1xuICAgICAgY29uc3QgZmxvd1JvdXRlRGlyID0gam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgJ2Zsb3cnKTtcbiAgICAgIGNvbnN0IHN0ZXBSb3V0ZURpciA9IGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdzdGVwJyk7XG4gICAgICBjb25zdCB3ZWJob29rUm91dGVEaXIgPSBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnd2ViaG9vay9bdG9rZW5dJyk7XG5cbiAgICAgIGNvbnN0IHN0YWxlQXJ0aWZhY3RQYXRocyA9IFtcbiAgICAgICAgam9pbihmbG93Um91dGVEaXIsICdyb3V0ZS5qcy50ZW1wJyksXG4gICAgICAgIGpvaW4oZmxvd1JvdXRlRGlyLCAncm91dGUuanMudGVtcC5kZWJ1Zy5qc29uJyksXG4gICAgICAgIGpvaW4oZmxvd1JvdXRlRGlyLCAncm91dGUuanMuZGVidWcuanNvbicpLFxuICAgICAgICBqb2luKGZsb3dSb3V0ZURpciwgJ19fc3RlcF9yZWdpc3RyYXRpb25zLnJvdXRlLmpzLnRlbXAnKSxcbiAgICAgICAgam9pbihmbG93Um91dGVEaXIsICdfX3N0ZXBfcmVnaXN0cmF0aW9ucy5yb3V0ZS5qcy50ZW1wLmRlYnVnLmpzb24nKSxcbiAgICAgICAgLy8gVjI6IGNsZWFuIHVwIHN0YWxlIFYxIHN0ZXAgcm91dGUgZGlyZWN0b3J5XG4gICAgICAgIHN0ZXBSb3V0ZURpcixcbiAgICAgICAgam9pbih3ZWJob29rUm91dGVEaXIsICdyb3V0ZS5qcy50ZW1wJyksXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdtYW5pZmVzdC5qc29uJyksXG4gICAgICBdO1xuXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgIC4uLnN0YWxlQXJ0aWZhY3RQYXRocy5tYXAoKHN0YWxlUGF0aCkgPT5cbiAgICAgICAgICBybShzdGFsZVBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KVxuICAgICAgICApLFxuICAgICAgICBjbGVhbnVwU3RhbGVTb2NrZXRJbmZvRmlsZXMoXG4gICAgICAgICAgam9pbih0aGlzLmNvbmZpZy53b3JraW5nRGlyLCB0aGlzLmdldERpc3REaXIoKSlcbiAgICAgICAgKSxcbiAgICAgICAgdGhpcy5yZW1vdmVTdGFsZURlZmVycmVkVGVtcEZpbGVzKGZsb3dSb3V0ZURpciksXG4gICAgICAgIHRoaXMucmVtb3ZlU3RhbGVEZWZlcnJlZFRlbXBGaWxlcyh3ZWJob29rUm91dGVEaXIpLFxuICAgICAgXSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZW1vdmVTdGFsZURlZmVycmVkVGVtcEZpbGVzKFxuICAgICAgcm91dGVEaXI6IHN0cmluZ1xuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgY29uc3Qgcm91dGVFbnRyaWVzID0gYXdhaXQgcmVhZGRpcihyb3V0ZURpciwge1xuICAgICAgICB3aXRoRmlsZVR5cGVzOiB0cnVlLFxuICAgICAgfSkuY2F0Y2goKCkgPT4gW10pO1xuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIHJvdXRlRW50cmllc1xuICAgICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgICAoZW50cnkpID0+XG4gICAgICAgICAgICAgIGVudHJ5LmlzRmlsZSgpICYmXG4gICAgICAgICAgICAgIGVudHJ5Lm5hbWUuc3RhcnRzV2l0aCgncm91dGUuanMuJykgJiZcbiAgICAgICAgICAgICAgZW50cnkubmFtZS5lbmRzV2l0aCgnLnRtcCcpXG4gICAgICAgICAgKVxuICAgICAgICAgIC5tYXAoKGVudHJ5KSA9PlxuICAgICAgICAgICAgcm0oam9pbihyb3V0ZURpciwgZW50cnkubmFtZSksIHtcbiAgICAgICAgICAgICAgZm9yY2U6IHRydWUsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjcmVhdGVEaXNjb3ZlcnlTb2NrZXRTZXJ2ZXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBpZiAodGhpcy5zb2NrZXRJTyB8fCBwcm9jZXNzLmVudi5XT1JLRkxPV19TT0NLRVRfUE9SVCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3MuZW52LldPUktGTE9XX1NPQ0tFVF9JTkZPX1BBVEggPSB0aGlzLmdldFNvY2tldEluZm9GaWxlUGF0aCgpO1xuICAgICAgY29uc3QgY29uZmlnOiBTb2NrZXRTZXJ2ZXJDb25maWcgPSB7XG4gICAgICAgIGlzRGV2U2VydmVyOiBCb29sZWFuKHRoaXMuY29uZmlnLndhdGNoKSxcbiAgICAgICAgc29ja2V0SW5mb0ZpbGVQYXRoOiB0aGlzLmdldFNvY2tldEluZm9GaWxlUGF0aCgpLFxuICAgICAgICBvbkZpbGVEaXNjb3ZlcmVkOiAoXG4gICAgICAgICAgZmlsZVBhdGg6IHN0cmluZyxcbiAgICAgICAgICBoYXNXb3JrZmxvdzogYm9vbGVhbixcbiAgICAgICAgICBoYXNTdGVwOiBib29sZWFuLFxuICAgICAgICAgIGhhc1NlcmRlOiBib29sZWFuXG4gICAgICAgICkgPT4ge1xuICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRGaWxlUGF0aCA9IHRoaXMubm9ybWFsaXplRGlzY292ZXJlZEZpbGVQYXRoKGZpbGVQYXRoKTtcbiAgICAgICAgICBsZXQgaGFzQ2FjaGVUcmFja2luZ0NoYW5nZSA9IGZhbHNlO1xuICAgICAgICAgIGNvbnN0IHdhc1RyYWNrZWREZXBlbmRlbmN5ID1cbiAgICAgICAgICAgIHRoaXMudHJhY2tlZERlcGVuZGVuY3lGaWxlcy5oYXMobm9ybWFsaXplZEZpbGVQYXRoKTtcblxuICAgICAgICAgIGlmIChoYXNXb3JrZmxvdykge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzLmhhcyhub3JtYWxpemVkRmlsZVBhdGgpKSB7XG4gICAgICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMuYWRkKG5vcm1hbGl6ZWRGaWxlUGF0aCk7XG4gICAgICAgICAgICAgIGhhc0NhY2hlVHJhY2tpbmdDaGFuZ2UgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCB3YXNEZWxldGVkID1cbiAgICAgICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcy5kZWxldGUobm9ybWFsaXplZEZpbGVQYXRoKTtcbiAgICAgICAgICAgIGhhc0NhY2hlVHJhY2tpbmdDaGFuZ2UgPSB3YXNEZWxldGVkIHx8IGhhc0NhY2hlVHJhY2tpbmdDaGFuZ2U7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGhhc1N0ZXApIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLmhhcyhub3JtYWxpemVkRmlsZVBhdGgpKSB7XG4gICAgICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFN0ZXBGaWxlcy5hZGQobm9ybWFsaXplZEZpbGVQYXRoKTtcbiAgICAgICAgICAgICAgaGFzQ2FjaGVUcmFja2luZ0NoYW5nZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHdhc0RlbGV0ZWQgPVxuICAgICAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRTdGVwRmlsZXMuZGVsZXRlKG5vcm1hbGl6ZWRGaWxlUGF0aCk7XG4gICAgICAgICAgICBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlID0gd2FzRGVsZXRlZCB8fCBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChoYXNTZXJkZSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmhhcyhub3JtYWxpemVkRmlsZVBhdGgpKSB7XG4gICAgICAgICAgICAgIGhhc0NhY2hlVHJhY2tpbmdDaGFuZ2UgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcy5hZGQobm9ybWFsaXplZEZpbGVQYXRoKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3Qgd2FzRGVsZXRlZCA9XG4gICAgICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFNlcmRlRmlsZXMuZGVsZXRlKG5vcm1hbGl6ZWRGaWxlUGF0aCk7XG4gICAgICAgICAgICBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlID0gd2FzRGVsZXRlZCB8fCBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChoYXNDYWNoZVRyYWNraW5nQ2hhbmdlKSB7XG4gICAgICAgICAgICB0aGlzLnNjaGVkdWxlV29ya2Zsb3dzQ2FjaGVXcml0ZSgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGhhc1dvcmtmbG93IHx8XG4gICAgICAgICAgICBoYXNTdGVwIHx8XG4gICAgICAgICAgICBoYXNTZXJkZSB8fFxuICAgICAgICAgICAgaGFzQ2FjaGVUcmFja2luZ0NoYW5nZSB8fFxuICAgICAgICAgICAgd2FzVHJhY2tlZERlcGVuZGVuY3lcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMuc2NoZWR1bGVEZWZlcnJlZFJlYnVpbGQoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG9uVHJpZ2dlckJ1aWxkOiAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5zY2hlZHVsZURlZmVycmVkUmVidWlsZCgpO1xuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgdGhpcy5zb2NrZXRJTyA9IGF3YWl0IGNyZWF0ZVNvY2tldFNlcnZlcihjb25maWcpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgaW5pdGlhbGl6ZURpc2NvdmVyeVN0YXRlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgaWYgKHRoaXMuY2FjaGVJbml0aWFsaXplZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IHRoaXMubG9hZFdvcmtmbG93c0NhY2hlKCk7XG4gICAgICAvLyBEZWZlcnJlZCBtb2RlIG11c3Qgbm90IHJ1biBlYWdlciBpbnB1dC1ncmFwaCBkaXNjb3Zlcnk7IGVudHJpZXMgYXJlXG4gICAgICAvLyBkaXNjb3ZlcmVkIHZpYSBsb2FkZXItPnNvY2tldCBub3RpZmljYXRpb25zIGR1cmluZyBOZXh0J3MgYnVpbGQuXG4gICAgICB0aGlzLmNhY2hlSW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0RGlzdERpcigpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuICh0aGlzLmNvbmZpZyBhcyB7IGRpc3REaXI/OiBzdHJpbmcgfSkuZGlzdERpciB8fCAnLm5leHQnO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0V29ya2Zsb3dzQ2FjaGVGaWxlUGF0aCgpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIGpvaW4oXG4gICAgICAgIHRoaXMuY29uZmlnLndvcmtpbmdEaXIsXG4gICAgICAgIHRoaXMuZ2V0RGlzdERpcigpLFxuICAgICAgICAnY2FjaGUnLFxuICAgICAgICAnd29ya2Zsb3dzLmpzb24nXG4gICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0U29ja2V0SW5mb0ZpbGVQYXRoKCk6IHN0cmluZyB7XG4gICAgICByZXR1cm4gam9pbihcbiAgICAgICAgdGhpcy5jb25maWcud29ya2luZ0RpcixcbiAgICAgICAgdGhpcy5nZXREaXN0RGlyKCksXG4gICAgICAgIFNPQ0tFVF9JTkZPX0ZJTEVOQU1FXG4gICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgZmluZFBhY2thZ2VKc29uUGF0aChmaWxlUGF0aDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICBsZXQgY3VycmVudERpciA9IGRpcm5hbWUoZmlsZVBhdGgpO1xuICAgICAgbGV0IHByZXZpb3VzRGlyID0gJyc7XG5cbiAgICAgIHdoaWxlIChjdXJyZW50RGlyICE9PSBwcmV2aW91c0Rpcikge1xuICAgICAgICBjb25zdCBwYWNrYWdlSnNvblBhdGggPSBqb2luKGN1cnJlbnREaXIsICdwYWNrYWdlLmpzb24nKTtcbiAgICAgICAgaWYgKGV4aXN0c1N5bmMocGFja2FnZUpzb25QYXRoKSkge1xuICAgICAgICAgIHJldHVybiBwYWNrYWdlSnNvblBhdGg7XG4gICAgICAgIH1cbiAgICAgICAgcHJldmlvdXNEaXIgPSBjdXJyZW50RGlyO1xuICAgICAgICBjdXJyZW50RGlyID0gZGlybmFtZShjdXJyZW50RGlyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzaG91bGRQcmVmZXJTb3VyY2VCYWNrZWRQYWNrYWdlUGF0aChmaWxlUGF0aDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICBjb25zdCBub3JtYWxpemVkUGF0aCA9IGZpbGVQYXRoLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgIC8vIE9ubHkgcHJlZmVyIHNvdXJjZSBmb3Igd29ya3NwYWNlIHBhY2thZ2VzIChub3QgaW4gbm9kZV9tb2R1bGVzKS5cbiAgICAgIC8vIEZvciB0YXJiYWxsLWluc3RhbGxlZCBwYWNrYWdlcywgdXNpbmcgc291cmNlLWJhY2tlZCBwYXRocyBjYXVzZXNcbiAgICAgIC8vIGVzYnVpbGQgdG8gYnVuZGxlIHRoZSBmdWxsIHNvdXJjZSB0cmVlIChpbmNsdWRpbmcgd29ybGQudHMgd2l0aFxuICAgICAgLy8gcHJvY2Vzcy5jd2QoKSkgaW5zdGVhZCBvZiBleHRlcm5hbGl6aW5nIHByb3Blcmx5LlxuICAgICAgaWYgKFxuICAgICAgICBub3JtYWxpemVkUGF0aC5pbmNsdWRlcygnL3BhY2thZ2VzLycpICYmXG4gICAgICAgICFub3JtYWxpemVkUGF0aC5pbmNsdWRlcygnL25vZGVfbW9kdWxlcy8nKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoIW5vcm1hbGl6ZWRQYXRoLmluY2x1ZGVzKCcvbm9kZV9tb2R1bGVzLycpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcGFja2FnZUpzb25QYXRoID0gdGhpcy5maW5kUGFja2FnZUpzb25QYXRoKGZpbGVQYXRoKTtcbiAgICAgIGlmICghcGFja2FnZUpzb25QYXRoKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcGFja2FnZUpzb24gPSBKU09OLnBhcnNlKFxuICAgICAgICAgIHJlYWRGaWxlU3luYyhwYWNrYWdlSnNvblBhdGgsICd1dGYtOCcpXG4gICAgICAgICkgYXMgeyBuYW1lPzogdW5rbm93biB9O1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIHBhY2thZ2VKc29uLm5hbWUgPT09ICd3b3JrZmxvdycgfHxcbiAgICAgICAgICAodHlwZW9mIHBhY2thZ2VKc29uLm5hbWUgPT09ICdzdHJpbmcnICYmXG4gICAgICAgICAgICBwYWNrYWdlSnNvbi5uYW1lLnN0YXJ0c1dpdGgoJ0B3b3JrZmxvdy8nKSlcbiAgICAgICAgKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZXNvbHZlU291cmNlQmFja2VkUGFja2FnZVBhdGgoZmlsZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICBjb25zdCBub3JtYWxpemVkUGF0aCA9IGZpbGVQYXRoLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgIGlmICghbm9ybWFsaXplZFBhdGguaW5jbHVkZXMoJy9kaXN0LycpKSB7XG4gICAgICAgIHJldHVybiBmaWxlUGF0aDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc291cmNlQ2FuZGlkYXRlID0gbm9ybWFsaXplZFBhdGgucmVwbGFjZSgnL2Rpc3QvJywgJy9zcmMvJyk7XG4gICAgICBjb25zdCByZXNvbHZlZFNvdXJjZUNhbmRpZGF0ZSA9XG4gICAgICAgIHRoaXMucmVzb2x2ZUNvcGllZFN0ZXBJbXBvcnRUYXJnZXRQYXRoKHNvdXJjZUNhbmRpZGF0ZSk7XG4gICAgICBpZiAoXG4gICAgICAgICFleGlzdHNTeW5jKHJlc29sdmVkU291cmNlQ2FuZGlkYXRlKSB8fFxuICAgICAgICAhdGhpcy5zaG91bGRQcmVmZXJTb3VyY2VCYWNrZWRQYWNrYWdlUGF0aChmaWxlUGF0aClcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gZmlsZVBhdGg7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBleGlzdHNTeW5jKHJlc29sdmVkU291cmNlQ2FuZGlkYXRlKVxuICAgICAgICA/IHJlc29sdmVkU291cmNlQ2FuZGlkYXRlXG4gICAgICAgIDogZmlsZVBhdGg7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoZmlsZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICBjb25zdCBhYnNvbHV0ZVBhdGggPSBpc0Fic29sdXRlKGZpbGVQYXRoKVxuICAgICAgICA/IGZpbGVQYXRoXG4gICAgICAgIDogcmVzb2x2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCBmaWxlUGF0aCk7XG4gICAgICByZXR1cm4gdGhpcy5yZXNvbHZlU291cmNlQmFja2VkUGFja2FnZVBhdGgoYWJzb2x1dGVQYXRoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGZpbHRlckV4aXN0aW5nRmlsZXMoZmlsZVBhdGhzOiBzdHJpbmdbXSk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRGaWxlUGF0aHMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFxuICAgICAgICAgIGZpbGVQYXRocy5tYXAoKGZpbGVQYXRoKSA9PlxuICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoZmlsZVBhdGgpXG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgICApLnNvcnQoKTtcblxuICAgICAgY29uc3QgZXhpc3RpbmdGaWxlcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBub3JtYWxpemVkRmlsZVBhdGhzLm1hcChhc3luYyAoZmlsZVBhdGgpID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgZmlsZVN0YXRzID0gYXdhaXQgc3RhdChmaWxlUGF0aCk7XG4gICAgICAgICAgICByZXR1cm4gZmlsZVN0YXRzLmlzRmlsZSgpID8gZmlsZVBhdGggOiBudWxsO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgKTtcblxuICAgICAgcmV0dXJuIGV4aXN0aW5nRmlsZXMuZmlsdGVyKChmaWxlUGF0aCk6IGZpbGVQYXRoIGlzIHN0cmluZyA9PlxuICAgICAgICBCb29sZWFuKGZpbGVQYXRoKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGNyZWF0ZURlZmVycmVkQnVpbGRTaWduYXR1cmUoXG4gICAgICBpbnB1dEZpbGVzOiBzdHJpbmdbXVxuICAgICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICBjb25zdCBub3JtYWxpemVkRmlsZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFtcbiAgICAgICAgICAuLi5pbnB1dEZpbGVzLm1hcCgoZmlsZVBhdGgpID0+XG4gICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChmaWxlUGF0aClcbiAgICAgICAgICApLFxuICAgICAgICAgIC4uLnRoaXMudHJhY2tlZERlcGVuZGVuY3lGaWxlcyxcbiAgICAgICAgXSlcbiAgICAgICkuc29ydCgpO1xuXG4gICAgICBjb25zdCBzaWduYXR1cmVQYXJ0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBub3JtYWxpemVkRmlsZXMubWFwKGFzeW5jIChmaWxlUGF0aCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBmaWxlU3RhdHMgPSBhd2FpdCBzdGF0KGZpbGVQYXRoKTtcbiAgICAgICAgICAgIHJldHVybiBgJHtmaWxlUGF0aH06JHtmaWxlU3RhdHMuc2l6ZX06JHtNYXRoLnRydW5jKGZpbGVTdGF0cy5tdGltZU1zKX1gO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcmV0dXJuIGAke2ZpbGVQYXRofTptaXNzaW5nYDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgICBjb25zdCBzaWduYXR1cmVIYXNoID0gY3JlYXRlSGFzaCgnc2hhMjU2Jyk7XG4gICAgICBmb3IgKGNvbnN0IHNpZ25hdHVyZVBhcnQgb2Ygc2lnbmF0dXJlUGFydHMpIHtcbiAgICAgICAgc2lnbmF0dXJlSGFzaC51cGRhdGUoc2lnbmF0dXJlUGFydCk7XG4gICAgICAgIHNpZ25hdHVyZUhhc2gudXBkYXRlKCdcXG4nKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHNpZ25hdHVyZUhhc2guZGlnZXN0KCdoZXgnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGNvbGxlY3RUcmFja2VkRGlzY292ZXJlZEVudHJpZXMoKTogUHJvbWlzZTx7XG4gICAgICBkaXNjb3ZlcmVkU3RlcHM6IHN0cmluZ1tdO1xuICAgICAgZGlzY292ZXJlZFdvcmtmbG93czogc3RyaW5nW107XG4gICAgICBkaXNjb3ZlcmVkU2VyZGVGaWxlczogc3RyaW5nW107XG4gICAgfT4ge1xuICAgICAgaWYgKHRoaXMudHJhY2tlZERlcGVuZGVuY3lGaWxlcy5zaXplID09PSAwKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZGlzY292ZXJlZFN0ZXBzOiBbXSxcbiAgICAgICAgICBkaXNjb3ZlcmVkV29ya2Zsb3dzOiBbXSxcbiAgICAgICAgICBkaXNjb3ZlcmVkU2VyZGVGaWxlczogW10sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgd29ya2Zsb3dGaWxlcywgc3RlcEZpbGVzLCBzZXJkZUZpbGVzIH0gPVxuICAgICAgICBhd2FpdCB0aGlzLnJlY29uY2lsZURpc2NvdmVyZWRFbnRyaWVzKHtcbiAgICAgICAgICB3b3JrZmxvd0NhbmRpZGF0ZXM6IHRoaXMudHJhY2tlZERlcGVuZGVuY3lGaWxlcyxcbiAgICAgICAgICBzdGVwQ2FuZGlkYXRlczogdGhpcy50cmFja2VkRGVwZW5kZW5jeUZpbGVzLFxuICAgICAgICAgIHNlcmRlQ2FuZGlkYXRlczogdGhpcy50cmFja2VkRGVwZW5kZW5jeUZpbGVzLFxuICAgICAgICAgIHZhbGlkYXRlUGF0dGVybnM6IHRydWUsXG4gICAgICAgIH0pO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBkaXNjb3ZlcmVkU3RlcHM6IEFycmF5LmZyb20oc3RlcEZpbGVzKS5zb3J0KCksXG4gICAgICAgIGRpc2NvdmVyZWRXb3JrZmxvd3M6IEFycmF5LmZyb20od29ya2Zsb3dGaWxlcykuc29ydCgpLFxuICAgICAgICBkaXNjb3ZlcmVkU2VyZGVGaWxlczogQXJyYXkuZnJvbShzZXJkZUZpbGVzKS5zb3J0KCksXG4gICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcmVmcmVzaFRyYWNrZWREZXBlbmRlbmN5RmlsZXMoXG4gICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcjogc3RyaW5nLFxuICAgICAgcm91dGVGaWxlTmFtZTogc3RyaW5nXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBjb25zdCBidW5kbGVGaWxlcyA9IFtcbiAgICAgICAgam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgYHN0ZXAvJHtyb3V0ZUZpbGVOYW1lfWApLFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCBgZmxvdy8ke3JvdXRlRmlsZU5hbWV9YCksXG4gICAgICBdO1xuICAgICAgY29uc3QgdHJhY2tlZEZpbGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICAgIGZvciAoY29uc3QgYnVuZGxlRmlsZSBvZiBidW5kbGVGaWxlcykge1xuICAgICAgICBjb25zdCBidW5kbGVTb3VyY2VzID0gYXdhaXQgdGhpcy5leHRyYWN0QnVuZGxlU291cmNlRmlsZXMoYnVuZGxlRmlsZSk7XG4gICAgICAgIGZvciAoY29uc3Qgc291cmNlRmlsZSBvZiBidW5kbGVTb3VyY2VzKSB7XG4gICAgICAgICAgdHJhY2tlZEZpbGVzLmFkZChzb3VyY2VGaWxlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodHJhY2tlZEZpbGVzLnNpemUgPiAwKSB7XG4gICAgICAgIHRoaXMudHJhY2tlZERlcGVuZGVuY3lGaWxlcyA9IHRyYWNrZWRGaWxlcztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGV4dHJhY3RCdW5kbGVTb3VyY2VGaWxlcyhcbiAgICAgIGJ1bmRsZUZpbGVQYXRoOiBzdHJpbmdcbiAgICApOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICBsZXQgYnVuZGxlQ29udGVudHM6IHN0cmluZztcbiAgICAgIHRyeSB7XG4gICAgICAgIGJ1bmRsZUNvbnRlbnRzID0gYXdhaXQgcmVhZEZpbGUoYnVuZGxlRmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYmFzZURpcmVjdG9yeSA9IGRpcm5hbWUoYnVuZGxlRmlsZVBhdGgpO1xuICAgICAgY29uc3QgbG9jYWxTb3VyY2VGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgICAvLyBFeHRyYWN0IGlubGluZSBiYXNlNjQgc291cmNlbWFwcyB2aWEgc3RyaW5nIHNjYW5uaW5nLiBBIHByZXZpb3VzXG4gICAgICAvLyBpbXBsZW1lbnRhdGlvbiB1c2VkIGBidW5kbGVDb250ZW50cy5tYXRjaEFsbCgvLi4uW0EtWmEtejAtOSsvPV0rLi4uL2cpYFxuICAgICAgLy8gd2hpY2ggb3ZlcmZsb3dzIFY4J3MgcmVnZXggc3RhY2tcbiAgICAgIC8vIChgUmFuZ2VFcnJvcjogTWF4aW11bSBjYWxsIHN0YWNrIHNpemUgZXhjZWVkZWQgYXQgUmVnRXhwU3RyaW5nSXRlcmF0b3IubmV4dGApXG4gICAgICAvLyBvbiBidW5kbGVzIHdpdGggbGFyZ2UgaW5saW5lIHNvdXJjZW1hcHMg4oCUIFY4J3MgaXJyZWdleHAgdXNlc1xuICAgICAgLy8gcmVjdXJzaW9uIGZvciBncmVlZHkgY2hhcmFjdGVyLWNsYXNzIHF1YW50aWZpZXJzIGFuZCBjZXJ0YWluIGxvbmdcbiAgICAgIC8vIGJhc2U2NCBpbnB1dHMgZXhoYXVzdCB0aGUgY2FsbCBzdGFjay5cbiAgICAgIGNvbnN0IHNvdXJjZU1hcFByZWZpeCA9ICcvLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb24nO1xuICAgICAgY29uc3QgYmFzZTY0TWFya2VyID0gJztiYXNlNjQsJztcbiAgICAgIGNvbnN0IHNvdXJjZU1hcE1hdGNoZXM6IEFycmF5PHsgYmFzZTY0VmFsdWU6IHN0cmluZyB9PiA9IFtdO1xuICAgICAgbGV0IHNjYW5Gcm9tID0gMDtcbiAgICAgIHdoaWxlIChzY2FuRnJvbSA8IGJ1bmRsZUNvbnRlbnRzLmxlbmd0aCkge1xuICAgICAgICBjb25zdCBwcmVmaXhJZHggPSBidW5kbGVDb250ZW50cy5pbmRleE9mKHNvdXJjZU1hcFByZWZpeCwgc2NhbkZyb20pO1xuICAgICAgICBpZiAocHJlZml4SWR4ID09PSAtMSkgYnJlYWs7XG4gICAgICAgIGNvbnN0IGJhc2U2NFN0YXJ0ID0gYnVuZGxlQ29udGVudHMuaW5kZXhPZihcbiAgICAgICAgICBiYXNlNjRNYXJrZXIsXG4gICAgICAgICAgcHJlZml4SWR4ICsgc291cmNlTWFwUHJlZml4Lmxlbmd0aFxuICAgICAgICApO1xuICAgICAgICBpZiAoYmFzZTY0U3RhcnQgPT09IC0xKSB7XG4gICAgICAgICAgc2NhbkZyb20gPSBwcmVmaXhJZHggKyBzb3VyY2VNYXBQcmVmaXgubGVuZ3RoO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIEJhaWwgaWYgYSBjb21tYSBhcHBlYXJzIGJlZm9yZSBgO2Jhc2U2NCxgIOKAlCB0aGF0IG1lYW5zIHRoaXNcbiAgICAgICAgLy8gd2Fzbid0IGEgYGRhdGE6YXBwbGljYXRpb24vanNvbls7cGFyYW1zXTtiYXNlNjQsLi4uYCBVUkwgYWZ0ZXJcbiAgICAgICAgLy8gYWxsICh0aGUgY29tbWEgd291bGQgdGVybWluYXRlIHRoZSBkYXRhIFVSTCBwYXJhbWV0ZXJzKS5cbiAgICAgICAgY29uc3QgY29tbWFCZWZvcmUgPSBidW5kbGVDb250ZW50cy5pbmRleE9mKCcsJywgcHJlZml4SWR4KTtcbiAgICAgICAgaWYgKGNvbW1hQmVmb3JlICE9PSAtMSAmJiBjb21tYUJlZm9yZSA8IGJhc2U2NFN0YXJ0KSB7XG4gICAgICAgICAgc2NhbkZyb20gPSBiYXNlNjRTdGFydDtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2YWx1ZVN0YXJ0ID0gYmFzZTY0U3RhcnQgKyBiYXNlNjRNYXJrZXIubGVuZ3RoO1xuICAgICAgICAvLyBCYXNlNjQgcGF5bG9hZCB0ZXJtaW5hdGVzIGF0IGZpcnN0IG5vbi1iYXNlNjQgY2hhciAobmV3bGluZSxcbiAgICAgICAgLy8gY2xvc2luZyBgKi9gLCBldGMuKS4gU2Nhbm5pbmcgYSBzbWFsbCBhbHBoYWJldCBieSBjaGFyIGlzIGZhclxuICAgICAgICAvLyBjaGVhcGVyIHRoYW4gYmFja3RyYWNraW5nIGEgcmVnZXggb3ZlciBhIG11bHRpLU1CIGNhcHR1cmUuXG4gICAgICAgIGxldCB2YWx1ZUVuZCA9IHZhbHVlU3RhcnQ7XG4gICAgICAgIHdoaWxlICh2YWx1ZUVuZCA8IGJ1bmRsZUNvbnRlbnRzLmxlbmd0aCkge1xuICAgICAgICAgIGNvbnN0IGNvZGUgPSBidW5kbGVDb250ZW50cy5jaGFyQ29kZUF0KHZhbHVlRW5kKTtcbiAgICAgICAgICAvLyBBLVogMHg0MS0weDVBLCBhLXogMHg2MS0weDdBLCAwLTkgMHgzMC0weDM5LCAnKycgMHgyQixcbiAgICAgICAgICAvLyAnLycgMHgyRiwgJz0nIDB4M0RcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhKFxuICAgICAgICAgICAgICAoY29kZSA+PSAweDQxICYmIGNvZGUgPD0gMHg1YSkgfHxcbiAgICAgICAgICAgICAgKGNvZGUgPj0gMHg2MSAmJiBjb2RlIDw9IDB4N2EpIHx8XG4gICAgICAgICAgICAgIChjb2RlID49IDB4MzAgJiYgY29kZSA8PSAweDM5KSB8fFxuICAgICAgICAgICAgICBjb2RlID09PSAweDJiIHx8XG4gICAgICAgICAgICAgIGNvZGUgPT09IDB4MmYgfHxcbiAgICAgICAgICAgICAgY29kZSA9PT0gMHgzZFxuICAgICAgICAgICAgKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhbHVlRW5kKys7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlRW5kID4gdmFsdWVTdGFydCkge1xuICAgICAgICAgIHNvdXJjZU1hcE1hdGNoZXMucHVzaCh7XG4gICAgICAgICAgICBiYXNlNjRWYWx1ZTogYnVuZGxlQ29udGVudHMuc2xpY2UodmFsdWVTdGFydCwgdmFsdWVFbmQpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHNjYW5Gcm9tID0gdmFsdWVFbmQ7XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgbWF0Y2ggb2Ygc291cmNlTWFwTWF0Y2hlcykge1xuICAgICAgICBjb25zdCBiYXNlNjRWYWx1ZSA9IG1hdGNoLmJhc2U2NFZhbHVlO1xuICAgICAgICBpZiAoIWJhc2U2NFZhbHVlKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgc291cmNlTWFwOiB7IHNvdXJjZVJvb3Q/OiB1bmtub3duOyBzb3VyY2VzPzogdW5rbm93biB9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHNvdXJjZU1hcCA9IEpTT04ucGFyc2UoXG4gICAgICAgICAgICBCdWZmZXIuZnJvbShiYXNlNjRWYWx1ZSwgJ2Jhc2U2NCcpLnRvU3RyaW5nKCd1dGYtOCcpXG4gICAgICAgICAgKSBhcyB7IHNvdXJjZVJvb3Q/OiB1bmtub3duOyBzb3VyY2VzPzogdW5rbm93biB9O1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNvdXJjZVJvb3QgPVxuICAgICAgICAgIHR5cGVvZiBzb3VyY2VNYXAuc291cmNlUm9vdCA9PT0gJ3N0cmluZycgPyBzb3VyY2VNYXAuc291cmNlUm9vdCA6ICcnO1xuICAgICAgICBjb25zdCBzb3VyY2VzID0gQXJyYXkuaXNBcnJheShzb3VyY2VNYXAuc291cmNlcylcbiAgICAgICAgICA/IHNvdXJjZU1hcC5zb3VyY2VzLmZpbHRlcihcbiAgICAgICAgICAgICAgKHNvdXJjZSk6IHNvdXJjZSBpcyBzdHJpbmcgPT4gdHlwZW9mIHNvdXJjZSA9PT0gJ3N0cmluZydcbiAgICAgICAgICAgIClcbiAgICAgICAgICA6IFtdO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc291cmNlIG9mIHNvdXJjZXMpIHtcbiAgICAgICAgICBpZiAoc291cmNlLnN0YXJ0c1dpdGgoJ3dlYnBhY2s6Ly8nKSB8fCBzb3VyY2Uuc3RhcnRzV2l0aCgnPCcpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsZXQgcmVzb2x2ZWRTb3VyY2VQYXRoOiBzdHJpbmc7XG4gICAgICAgICAgaWYgKHNvdXJjZS5zdGFydHNXaXRoKCdmaWxlOi8vJykpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIHJlc29sdmVkU291cmNlUGF0aCA9IGRlY29kZVVSSUNvbXBvbmVudChuZXcgVVJMKHNvdXJjZSkucGF0aG5hbWUpO1xuICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAoaXNBYnNvbHV0ZShzb3VyY2UpKSB7XG4gICAgICAgICAgICByZXNvbHZlZFNvdXJjZVBhdGggPSBzb3VyY2U7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc29sdmVkU291cmNlUGF0aCA9IHJlc29sdmUoYmFzZURpcmVjdG9yeSwgc291cmNlUm9vdCwgc291cmNlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBub3JtYWxpemVkU291cmNlUGF0aCA9XG4gICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChyZXNvbHZlZFNvdXJjZVBhdGgpO1xuICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRTb3VyY2VQYXRoRm9yQ2hlY2sgPSBub3JtYWxpemVkU291cmNlUGF0aC5yZXBsYWNlKFxuICAgICAgICAgICAgL1xcXFwvZyxcbiAgICAgICAgICAgICcvJ1xuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgaXNTb3VyY2VCYWNrZWRQYWNrYWdlUGF0aCA9XG4gICAgICAgICAgICB0aGlzLnNob3VsZFByZWZlclNvdXJjZUJhY2tlZFBhY2thZ2VQYXRoKG5vcm1hbGl6ZWRTb3VyY2VQYXRoKTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBub3JtYWxpemVkU291cmNlUGF0aEZvckNoZWNrLmluY2x1ZGVzKCcvLndlbGwta25vd24vd29ya2Zsb3cvJykgfHxcbiAgICAgICAgICAgICghaXNTb3VyY2VCYWNrZWRQYWNrYWdlUGF0aCAmJlxuICAgICAgICAgICAgICBub3JtYWxpemVkU291cmNlUGF0aEZvckNoZWNrLmluY2x1ZGVzKCcvbm9kZV9tb2R1bGVzLycpKSB8fFxuICAgICAgICAgICAgKCFpc1NvdXJjZUJhY2tlZFBhY2thZ2VQYXRoICYmXG4gICAgICAgICAgICAgIG5vcm1hbGl6ZWRTb3VyY2VQYXRoRm9yQ2hlY2suaW5jbHVkZXMoJy8ucG5wbS8nKSkgfHxcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRTb3VyY2VQYXRoRm9yQ2hlY2suaW5jbHVkZXMoJy8ubmV4dC8nKSB8fFxuICAgICAgICAgICAgbm9ybWFsaXplZFNvdXJjZVBhdGhGb3JDaGVjay5lbmRzV2l0aCgnL3ZpcnR1YWwtZW50cnkuanMnKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbG9jYWxTb3VyY2VGaWxlcy5hZGQobm9ybWFsaXplZFNvdXJjZVBhdGgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBBcnJheS5mcm9tKGxvY2FsU291cmNlRmlsZXMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2NoZWR1bGVXb3JrZmxvd3NDYWNoZVdyaXRlKCk6IHZvaWQge1xuICAgICAgaWYgKHRoaXMuY2FjaGVXcml0ZVRpbWVyKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmNhY2hlV3JpdGVUaW1lcik7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY2FjaGVXcml0ZVRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMuY2FjaGVXcml0ZVRpbWVyID0gbnVsbDtcbiAgICAgICAgdm9pZCB0aGlzLndyaXRlV29ya2Zsb3dzQ2FjaGUoKS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ0ZhaWxlZCB0byB3cml0ZSB3b3JrZmxvdyBkaXNjb3ZlcnkgY2FjaGUnLCBlcnJvcik7XG4gICAgICAgIH0pO1xuICAgICAgfSwgNTApO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2NoZWR1bGVEZWZlcnJlZFJlYnVpbGQoKTogdm9pZCB7XG4gICAgICBpZiAodGhpcy5kZWZlcnJlZFJlYnVpbGRUaW1lcikge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5kZWZlcnJlZFJlYnVpbGRUaW1lcik7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZGVmZXJyZWRSZWJ1aWxkVGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdGhpcy5kZWZlcnJlZFJlYnVpbGRUaW1lciA9IG51bGw7XG4gICAgICAgIHZvaWQgdGhpcy5vbkJlZm9yZURlZmVycmVkRW50cmllcygpLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICdbd29ya2Zsb3ddIERlZmVycmVkIHJlYnVpbGQgYWZ0ZXIgc291cmNlIHVwZGF0ZSBmYWlsZWQuJyxcbiAgICAgICAgICAgIGVycm9yXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9LCA3NSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZWFkV29ya2Zsb3dzQ2FjaGUoKTogUHJvbWlzZTx7XG4gICAgICB3b3JrZmxvd0ZpbGVzOiBzdHJpbmdbXTtcbiAgICAgIHN0ZXBGaWxlczogc3RyaW5nW107XG4gICAgfSB8IG51bGw+IHtcbiAgICAgIGNvbnN0IGNhY2hlRmlsZVBhdGggPSB0aGlzLmdldFdvcmtmbG93c0NhY2hlRmlsZVBhdGgoKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY2FjaGVDb250ZW50cyA9IGF3YWl0IHJlYWRGaWxlKGNhY2hlRmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGNhY2hlQ29udGVudHMpIGFzIHtcbiAgICAgICAgICB3b3JrZmxvd0ZpbGVzPzogdW5rbm93bjtcbiAgICAgICAgICBzdGVwRmlsZXM/OiB1bmtub3duO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHdvcmtmbG93RmlsZXMgPSBBcnJheS5pc0FycmF5KHBhcnNlZC53b3JrZmxvd0ZpbGVzKVxuICAgICAgICAgID8gcGFyc2VkLndvcmtmbG93RmlsZXMuZmlsdGVyKFxuICAgICAgICAgICAgICAoaXRlbSk6IGl0ZW0gaXMgc3RyaW5nID0+IHR5cGVvZiBpdGVtID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgKVxuICAgICAgICAgIDogW107XG4gICAgICAgIGNvbnN0IHN0ZXBGaWxlcyA9IEFycmF5LmlzQXJyYXkocGFyc2VkLnN0ZXBGaWxlcylcbiAgICAgICAgICA/IHBhcnNlZC5zdGVwRmlsZXMuZmlsdGVyKFxuICAgICAgICAgICAgICAoaXRlbSk6IGl0ZW0gaXMgc3RyaW5nID0+IHR5cGVvZiBpdGVtID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgKVxuICAgICAgICAgIDogW107XG5cbiAgICAgICAgcmV0dXJuIHsgd29ya2Zsb3dGaWxlcywgc3RlcEZpbGVzIH07XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBsb2FkV29ya2Zsb3dzQ2FjaGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBjb25zdCBjYWNoZWREYXRhID0gYXdhaXQgdGhpcy5yZWFkV29ya2Zsb3dzQ2FjaGUoKTtcbiAgICAgIGlmICghY2FjaGVkRGF0YSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCB7IHdvcmtmbG93RmlsZXMsIHN0ZXBGaWxlcywgc2VyZGVGaWxlcyB9ID1cbiAgICAgICAgYXdhaXQgdGhpcy5yZWNvbmNpbGVEaXNjb3ZlcmVkRW50cmllcyh7XG4gICAgICAgICAgd29ya2Zsb3dDYW5kaWRhdGVzOiBjYWNoZWREYXRhLndvcmtmbG93RmlsZXMsXG4gICAgICAgICAgc3RlcENhbmRpZGF0ZXM6IGNhY2hlZERhdGEuc3RlcEZpbGVzLFxuICAgICAgICAgIHNlcmRlQ2FuZGlkYXRlczogdGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcyxcbiAgICAgICAgICB2YWxpZGF0ZVBhdHRlcm5zOiB0cnVlLFxuICAgICAgICB9KTtcblxuICAgICAgdGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcy5jbGVhcigpO1xuICAgICAgdGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLmNsZWFyKCk7XG4gICAgICB0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmNsZWFyKCk7XG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHdvcmtmbG93RmlsZXMpIHtcbiAgICAgICAgdGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcy5hZGQoZmlsZVBhdGgpO1xuICAgICAgfVxuICAgICAgZm9yIChjb25zdCBmaWxlUGF0aCBvZiBzdGVwRmlsZXMpIHtcbiAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLmFkZChmaWxlUGF0aCk7XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHNlcmRlRmlsZXMpIHtcbiAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcy5hZGQoZmlsZVBhdGgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgd3JpdGVXb3JrZmxvd3NDYWNoZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IGNhY2hlRmlsZVBhdGggPSB0aGlzLmdldFdvcmtmbG93c0NhY2hlRmlsZVBhdGgoKTtcbiAgICAgIGNvbnN0IGNhY2hlRGlyID0gam9pbih0aGlzLmNvbmZpZy53b3JraW5nRGlyLCB0aGlzLmdldERpc3REaXIoKSwgJ2NhY2hlJyk7XG4gICAgICBhd2FpdCBta2RpcihjYWNoZURpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgICAgIGNvbnN0IGNhY2hlRGF0YSA9IHtcbiAgICAgICAgd29ya2Zsb3dGaWxlczogQXJyYXkuZnJvbSh0aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzKS5zb3J0KCksXG4gICAgICAgIHN0ZXBGaWxlczogQXJyYXkuZnJvbSh0aGlzLmRpc2NvdmVyZWRTdGVwRmlsZXMpLnNvcnQoKSxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IHdyaXRlRmlsZShjYWNoZUZpbGVQYXRoLCBKU09OLnN0cmluZ2lmeShjYWNoZURhdGEsIG51bGwsIDIpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHdyaXRlU3R1YkZpbGVzKG91dHB1dERpcjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAvLyBUdXJib3BhY2sgY3VycmVudGx5IGhhcyBhIHdvcmtlci1jb25jdXJyZW5jeSBsaW1pdGF0aW9uIGZvciBwZW5kaW5nXG4gICAgICAvLyB2aXJ0dWFsIGVudHJpZXMuIFdhcm4gaWYgcGFyYWxsZWxpc20gaXMgdG9vIGxvdyB0byByZWxpYWJseSBkaXNjb3Zlci5cbiAgICAgIGNvbnN0IHBhcmFsbGVsaXNtQ291bnQgPSBvcy5hdmFpbGFibGVQYXJhbGxlbGlzbSgpO1xuICAgICAgaWYgKHByb2Nlc3MuZW52LlRVUkJPUEFDSyAmJiBwYXJhbGxlbGlzbUNvdW50IDwgNCkge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgYEF2YWlsYWJsZSBwYXJhbGxlbGlzbSBvZiAke3BhcmFsbGVsaXNtQ291bnR9IGlzIGxlc3MgdGhhbiBuZWVkZWQgNC4gVGhpcyBjYW4gY2F1c2Ugd29ya2Zsb3dzL3N0ZXBzIHRvIGZhaWwgdG8gZGlzY292ZXIgcHJvcGVybHkgaW4gdHVyYm9wYWNrYFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByb3V0ZVN0dWJDb250ZW50ID0gW1xuICAgICAgICBgLy8gJHtST1VURV9TVFVCX0ZJTEVfTUFSS0VSfWAsXG4gICAgICAgICdleHBvcnQgY29uc3QgX193b3JrZmxvd1JvdXRlU3R1YiA9IHRydWU7JyxcbiAgICAgIF0uam9pbignXFxuJyk7XG4gICAgICBjb25zdCB3b3JrZmxvd0dlbmVyYXRlZERpciA9IGpvaW4ob3V0cHV0RGlyLCAnLndlbGwta25vd24vd29ya2Zsb3cvdjEnKTtcblxuICAgICAgYXdhaXQgbWtkaXIoam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgJ2Zsb3cnKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBhd2FpdCBta2Rpcihqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnd2ViaG9vay9bdG9rZW5dJyksIHtcbiAgICAgICAgcmVjdXJzaXZlOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnLmdpdGlnbm9yZScpLFxuICAgICAgICAnKidcbiAgICAgICk7XG5cbiAgICAgIC8vIFYyOiBPbmx5IGZsb3cgKyB3ZWJob29rIHN0dWJzIG5lZWRlZCAobm8gc2VwYXJhdGUgc3RlcCByb3V0ZSkuXG4gICAgICAvLyBTdHVicyBhcmUgcmVwbGFjZWQgYnkgZ2VuZXJhdGVkIG91dHB1dCBvbmNlIGRpc2NvdmVyeSBmaW5pc2hlcy5cbiAgICAgIGF3YWl0IHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnZmxvdy9yb3V0ZS5qcycpLFxuICAgICAgICByb3V0ZVN0dWJDb250ZW50XG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQoXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICd3ZWJob29rL1t0b2tlbl0vcm91dGUuanMnKSxcbiAgICAgICAgcm91dGVTdHViQ29udGVudFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYXN5bmMgZ2V0SW5wdXRGaWxlcygpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICAvLyBSZWFkIE5leHQuanMncyBhcHAtcGF0aHMtbWFuaWZlc3QuanNvbiBmcm9tIGEgcHJldmlvdXMgYnVpbGQgdG9cbiAgICAgIC8vIGRldGVybWluZSB3aGljaCBmaWxlcyBhcmUgYWN0dWFsIHJvdXRlIGVudHJ5cG9pbnRzLiBUaGlzIGF2b2lkc1xuICAgICAgLy8gcHJlZGljdGluZyBOZXh0LmpzIGNvbnZlbnRpb25zIHdpdGggcmVnZXhlcyBhbmQgaW5zdGVhZCByZWFkc1xuICAgICAgLy8gZnJvbSBOZXh0LmpzJ3Mgb3duIG91dHB1dC5cbiAgICAgIGNvbnN0IG5leHREaXIgPSBqb2luKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsICcubmV4dCcpO1xuICAgICAgY29uc3QgbWFuaWZlc3RQYXRoID0gam9pbihuZXh0RGlyLCAnYXBwLXBhdGhzLW1hbmlmZXN0Lmpzb24nKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IG1hbmlmZXN0Q29udGVudCA9IHJlYWRGaWxlU3luYyhtYW5pZmVzdFBhdGgsICd1dGYtOCcpO1xuICAgICAgICBjb25zdCBtYW5pZmVzdCA9IEpTT04ucGFyc2UobWFuaWZlc3RDb250ZW50KSBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAgICAgICAvLyBUaGUgbWFuaWZlc3QgbWFwcyByb3V0ZSBwYXRocyB0byB0aGVpciBzb3VyY2UgZmlsZXMuXG4gICAgICAgIC8vIEV4dHJhY3QgdGhlIHNvdXJjZSBmaWxlIHBhdGhzIGFuZCByZXNvbHZlIHRoZW0uXG4gICAgICAgIGNvbnN0IG1hbmlmZXN0RmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgICAgZm9yIChjb25zdCBzb3VyY2VQYXRoIG9mIE9iamVjdC52YWx1ZXMobWFuaWZlc3QpKSB7XG4gICAgICAgICAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlKG5leHREaXIsICdzZXJ2ZXInLCBzb3VyY2VQYXRoKTtcbiAgICAgICAgICAvLyBUaGUgbWFuaWZlc3QgcG9pbnRzIHRvIGJ1aWx0IG91dHB1dDsgZmluZCB0aGUgc291cmNlIGZpbGVcbiAgICAgICAgICAvLyBieSBtYXRjaGluZyBhZ2FpbnN0IHRoZSBiYXNlIGJ1aWxkZXIncyBmdWxsIGZpbGUgbGlzdC5cbiAgICAgICAgICBtYW5pZmVzdEZpbGVzLmFkZChyZXNvbHZlZCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVc2UgdGhlIG1hbmlmZXN0IHJvdXRlIHBhdGhzIHRvIGZpbHRlciB0aGUgaW5wdXQgZmlsZXMuXG4gICAgICAgIC8vIEEgZmlsZSBpcyBpbmNsdWRlZCBpZiBpdCBtYXRjaGVzIGEga25vd24gcm91dGUgc2VnbWVudCBmcm9tXG4gICAgICAgIC8vIHRoZSBtYW5pZmVzdCAoZS5nLiwgYXBwL2FwaS9yb3V0ZSBjb250YWlucyAnYXBwL2FwaS9yb3V0ZScpLlxuICAgICAgICBjb25zdCBpbnB1dEZpbGVzID0gYXdhaXQgc3VwZXIuZ2V0SW5wdXRGaWxlcygpO1xuICAgICAgICBjb25zdCByb3V0ZVNlZ21lbnRzID0gT2JqZWN0LmtleXMobWFuaWZlc3QpLm1hcCgocm91dGUpID0+XG4gICAgICAgICAgcm91dGUucmVwbGFjZSgvXlxcLy8sICcnKS5yZXBsYWNlKC9cXC9yb3V0ZSQvLCAnJylcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIGlucHV0RmlsZXMuZmlsdGVyKChpdGVtKSA9PlxuICAgICAgICAgIHJvdXRlU2VnbWVudHMuc29tZSgoc2VnbWVudCkgPT4gaXRlbS5pbmNsdWRlcyhzZWdtZW50KSlcbiAgICAgICAgKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBObyBtYW5pZmVzdCBmcm9tIGEgcHJldmlvdXMgYnVpbGQg4oCUIGZhbGwgYmFjayB0byB0aGUgYmFzZVxuICAgICAgICAvLyBidWlsZGVyJ3MgZnVsbCBmaWxlIHNjYW4uIFRoaXMgaXMgc2FmZSBidXQgc2xvd2VyOyBzdWJzZXF1ZW50XG4gICAgICAgIC8vIGJ1aWxkcyB3aWxsIHVzZSB0aGUgbWFuaWZlc3QuXG4gICAgICAgIHJldHVybiBzdXBlci5nZXRJbnB1dEZpbGVzKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyB3cml0ZUZ1bmN0aW9uc0NvbmZpZyhvdXRwdXREaXI6IHN0cmluZykge1xuICAgICAgLy8gd2UgZG9uJ3QgcnVuIHRoaXMgaW4gZGV2ZWxvcG1lbnQgbW9kZSBhcyBpdCdzIG5vdCBuZWVkZWRcbiAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50Jykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICAvLyBWMjogU2luZ2xlIGNvbWJpbmVkIHRyaWdnZXIgaGFuZGxlcyBib3RoIHdvcmtmbG93IGFuZCBzdGVwIGV4ZWN1dGlvblxuICAgICAgY29uc3QgZ2VuZXJhdGVkQ29uZmlnID0ge1xuICAgICAgICB2ZXJzaW9uOiAnMCcsXG4gICAgICAgIHdvcmtmbG93czoge1xuICAgICAgICAgIG1heER1cmF0aW9uOiAnbWF4JyxcbiAgICAgICAgICBleHBlcmltZW50YWxUcmlnZ2VyczogW1dPUktGTE9XX1FVRVVFX1RSSUdHRVJdLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQoXG4gICAgICAgIGpvaW4ob3V0cHV0RGlyLCAnLndlbGwta25vd24vd29ya2Zsb3cvdjEvY29uZmlnLmpzb24nKSxcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoZ2VuZXJhdGVkQ29uZmlnLCBudWxsLCAyKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHdyaXRlRmlsZUlmQ2hhbmdlZChcbiAgICAgIGZpbGVQYXRoOiBzdHJpbmcsXG4gICAgICBjb250ZW50czogc3RyaW5nIHwgQnVmZmVyXG4gICAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICBjb25zdCBuZXh0QnVmZmVyID0gQnVmZmVyLmlzQnVmZmVyKGNvbnRlbnRzKVxuICAgICAgICA/IGNvbnRlbnRzXG4gICAgICAgIDogQnVmZmVyLmZyb20oY29udGVudHMpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjdXJyZW50QnVmZmVyID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgpO1xuICAgICAgICBpZiAoY3VycmVudEJ1ZmZlci5lcXVhbHMobmV4dEJ1ZmZlcikpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBGaWxlIGRvZXMgbm90IGV4aXN0IHlldCBvciBjYW5ub3QgYmUgcmVhZDsgd3JpdGUgYSBmcmVzaCBjb3B5LlxuICAgICAgfVxuXG4gICAgICBhd2FpdCBta2RpcihkaXJuYW1lKGZpbGVQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBhd2FpdCB3cml0ZUZpbGUoZmlsZVBhdGgsIG5leHRCdWZmZXIpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjb3B5RmlsZUlmQ2hhbmdlZChcbiAgICAgIHNvdXJjZVBhdGg6IHN0cmluZyxcbiAgICAgIGRlc3RpbmF0aW9uUGF0aDogc3RyaW5nXG4gICAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICBjb25zdCBzb3VyY2VDb250ZW50cyA9IGF3YWl0IHJlYWRGaWxlKHNvdXJjZVBhdGgpO1xuICAgICAgcmV0dXJuIHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKGRlc3RpbmF0aW9uUGF0aCwgc291cmNlQ29udGVudHMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc29ydEpzb25WYWx1ZSh2YWx1ZTogdW5rbm93bik6IHVua25vd24ge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZS5tYXAoKGl0ZW0pID0+IHRoaXMuc29ydEpzb25WYWx1ZShpdGVtKSk7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgICBjb25zdCBzb3J0ZWRFbnRyaWVzID0gT2JqZWN0LmVudHJpZXModmFsdWUgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pXG4gICAgICAgICAgLnNvcnQoKFthXSwgW2JdKSA9PiBhLmxvY2FsZUNvbXBhcmUoYikpXG4gICAgICAgICAgLm1hcCgoW2tleSwgZW50cnlWYWx1ZV0pID0+IFtrZXksIHRoaXMuc29ydEpzb25WYWx1ZShlbnRyeVZhbHVlKV0pO1xuICAgICAgICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKHNvcnRlZEVudHJpZXMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcmV3cml0ZUpzb25GaWxlV2l0aFN0YWJsZUtleU9yZGVyKFxuICAgICAgZmlsZVBhdGg6IHN0cmluZ1xuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY29udGVudHMgPSBhd2FpdCByZWFkRmlsZShmaWxlUGF0aCwgJ3V0Zi04Jyk7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UoY29udGVudHMpIGFzIHVua25vd247XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSB0aGlzLnNvcnRKc29uVmFsdWUocGFyc2VkKTtcbiAgICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQoXG4gICAgICAgICAgZmlsZVBhdGgsXG4gICAgICAgICAgYCR7SlNPTi5zdHJpbmdpZnkobm9ybWFsaXplZCwgbnVsbCwgMil9XFxuYFxuICAgICAgICApO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIE1hbmlmZXN0IG1heSBub3QgZXhpc3QgKGUuZy4gbWFuaWZlc3QgZ2VuZXJhdGlvbiBmYWlsZWQpOyBpZ25vcmUuXG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZXNvbHZlQ29waWVkU3RlcEltcG9ydFRhcmdldFBhdGgodGFyZ2V0UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgIGlmIChleGlzdHNTeW5jKHRhcmdldFBhdGgpKSB7XG4gICAgICAgIHJldHVybiB0YXJnZXRQYXRoO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBleHRlbnNpb25NYXRjaCA9IHRhcmdldFBhdGgubWF0Y2goLyhcXC5bXi4vXFxcXF0rKSQvKTtcbiAgICAgIGNvbnN0IGV4dGVuc2lvbiA9IGV4dGVuc2lvbk1hdGNoPy5bMV0/LnRvTG93ZXJDYXNlKCk7XG4gICAgICBpZiAoIWV4dGVuc2lvbikge1xuICAgICAgICByZXR1cm4gdGFyZ2V0UGF0aDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXh0ZW5zaW9uRmFsbGJhY2tzID1cbiAgICAgICAgZXh0ZW5zaW9uID09PSAnLmpzJ1xuICAgICAgICAgID8gWycudHMnLCAnLnRzeCcsICcubXRzJywgJy5jdHMnXVxuICAgICAgICAgIDogZXh0ZW5zaW9uID09PSAnLm1qcydcbiAgICAgICAgICAgID8gWycubXRzJ11cbiAgICAgICAgICAgIDogZXh0ZW5zaW9uID09PSAnLmNqcydcbiAgICAgICAgICAgICAgPyBbJy5jdHMnXVxuICAgICAgICAgICAgICA6IGV4dGVuc2lvbiA9PT0gJy5qc3gnXG4gICAgICAgICAgICAgICAgPyBbJy50c3gnXVxuICAgICAgICAgICAgICAgIDogW107XG5cbiAgICAgIGlmIChleHRlbnNpb25GYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0YXJnZXRQYXRoO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0YXJnZXRXaXRob3V0RXh0ZW5zaW9uID0gdGFyZ2V0UGF0aC5zbGljZSgwLCAtZXh0ZW5zaW9uLmxlbmd0aCk7XG4gICAgICBmb3IgKGNvbnN0IGZhbGxiYWNrRXh0ZW5zaW9uIG9mIGV4dGVuc2lvbkZhbGxiYWNrcykge1xuICAgICAgICBjb25zdCBmYWxsYmFja1BhdGggPSBgJHt0YXJnZXRXaXRob3V0RXh0ZW5zaW9ufSR7ZmFsbGJhY2tFeHRlbnNpb259YDtcbiAgICAgICAgaWYgKGV4aXN0c1N5bmMoZmFsbGJhY2tQYXRoKSkge1xuICAgICAgICAgIHJldHVybiBmYWxsYmFja1BhdGg7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRhcmdldFBhdGg7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBleHRyYWN0UmVsYXRpdmVJbXBvcnRTcGVjaWZpZXJzKHNvdXJjZTogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgICAgcmV0dXJuIHRoaXMuZXh0cmFjdEltcG9ydFNwZWNpZmllcnMoc291cmNlKS5maWx0ZXIoKHNwZWNpZmllcikgPT5cbiAgICAgICAgc3BlY2lmaWVyLnN0YXJ0c1dpdGgoJy4nKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGV4dHJhY3RJbXBvcnRTcGVjaWZpZXJzKHNvdXJjZTogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgICAgY29uc3QgcmVsYXRpdmVTcGVjaWZpZXJzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBjb25zdCBpbXBvcnRQYXR0ZXJucyA9IFtcbiAgICAgICAgL2Zyb21cXHMrWydcIl0oW14nXCJdKylbJ1wiXS9nLFxuICAgICAgICAvaW1wb3J0XFxzK1snXCJdKFteJ1wiXSspWydcIl0vZyxcbiAgICAgICAgL2ltcG9ydFxcKFxccypbJ1wiXShbXidcIl0rKVsnXCJdXFxzKlxcKS9nLFxuICAgICAgICAvcmVxdWlyZVxcKFxccypbJ1wiXShbXidcIl0rKVsnXCJdXFxzKlxcKS9nLFxuICAgICAgXTtcblxuICAgICAgZm9yIChjb25zdCBpbXBvcnRQYXR0ZXJuIG9mIGltcG9ydFBhdHRlcm5zKSB7XG4gICAgICAgIGZvciAoY29uc3QgbWF0Y2ggb2Ygc291cmNlLm1hdGNoQWxsKGltcG9ydFBhdHRlcm4pKSB7XG4gICAgICAgICAgY29uc3Qgc3BlY2lmaWVyID0gbWF0Y2hbMV07XG4gICAgICAgICAgaWYgKHNwZWNpZmllcikge1xuICAgICAgICAgICAgcmVsYXRpdmVTcGVjaWZpZXJzLmFkZChzcGVjaWZpZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gQXJyYXkuZnJvbShyZWxhdGl2ZVNwZWNpZmllcnMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZ2V0UmVsYXRpdmVGaWxlbmFtZUZvclN3YyhmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgIGNvbnN0IHdvcmtpbmdEaXIgPSB0aGlzLmNvbmZpZy53b3JraW5nRGlyO1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFdvcmtpbmdEaXIgPSB3b3JraW5nRGlyXG4gICAgICAgIC5yZXBsYWNlKC9cXFxcL2csICcvJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLyQvLCAnJyk7XG4gICAgICBjb25zdCBub3JtYWxpemVkRmlsZXBhdGggPSBmaWxlUGF0aC5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG5cbiAgICAgIC8vIFdpbmRvd3MgZml4OiBVc2UgY2FzZS1pbnNlbnNpdGl2ZSBjb21wYXJpc29uIHRvIHdvcmsgYXJvdW5kIGRyaXZlIGxldHRlciBjYXNpbmcgaXNzdWVzLlxuICAgICAgY29uc3QgbG93ZXJXZCA9IG5vcm1hbGl6ZWRXb3JraW5nRGlyLnRvTG93ZXJDYXNlKCk7XG4gICAgICBjb25zdCBsb3dlclBhdGggPSBub3JtYWxpemVkRmlsZXBhdGgudG9Mb3dlckNhc2UoKTtcblxuICAgICAgbGV0IHJlbGF0aXZlRmlsZW5hbWU6IHN0cmluZztcbiAgICAgIGlmIChsb3dlclBhdGguc3RhcnRzV2l0aChgJHtsb3dlcldkfS9gKSkge1xuICAgICAgICByZWxhdGl2ZUZpbGVuYW1lID0gbm9ybWFsaXplZEZpbGVwYXRoLnN1YnN0cmluZyhcbiAgICAgICAgICBub3JtYWxpemVkV29ya2luZ0Rpci5sZW5ndGggKyAxXG4gICAgICAgICk7XG4gICAgICB9IGVsc2UgaWYgKGxvd2VyUGF0aCA9PT0gbG93ZXJXZCkge1xuICAgICAgICByZWxhdGl2ZUZpbGVuYW1lID0gJy4nO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVsYXRpdmVGaWxlbmFtZSA9IHJlbGF0aXZlKHdvcmtpbmdEaXIsIGZpbGVQYXRoKS5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gICAgICAgIGlmIChyZWxhdGl2ZUZpbGVuYW1lLnN0YXJ0c1dpdGgoJy4uLycpKSB7XG4gICAgICAgICAgY29uc3QgYWxpYXNlZFJlbGF0aXZlUGF0aCA9IGF3YWl0IHJlc29sdmVXb3JrZmxvd0FsaWFzUmVsYXRpdmVQYXRoKFxuICAgICAgICAgICAgZmlsZVBhdGgsXG4gICAgICAgICAgICB3b3JraW5nRGlyXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoYWxpYXNlZFJlbGF0aXZlUGF0aCkge1xuICAgICAgICAgICAgcmVsYXRpdmVGaWxlbmFtZSA9IGFsaWFzZWRSZWxhdGl2ZVBhdGg7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlbGF0aXZlRmlsZW5hbWUgPSByZWxhdGl2ZUZpbGVuYW1lXG4gICAgICAgICAgICAgIC5zcGxpdCgnLycpXG4gICAgICAgICAgICAgIC5maWx0ZXIoKHBhcnQpID0+IHBhcnQgIT09ICcuLicpXG4gICAgICAgICAgICAgIC5qb2luKCcvJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChyZWxhdGl2ZUZpbGVuYW1lLmluY2x1ZGVzKCc6JykgfHwgcmVsYXRpdmVGaWxlbmFtZS5zdGFydHNXaXRoKCcvJykpIHtcbiAgICAgICAgcmVsYXRpdmVGaWxlbmFtZSA9IGJhc2VuYW1lKG5vcm1hbGl6ZWRGaWxlcGF0aCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZWxhdGl2ZUZpbGVuYW1lO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVzb2x2ZUltcG9ydFRhcmdldFdpdGhFeHRlbnNpb25GYWxsYmFja3MoXG4gICAgICB0YXJnZXRQYXRoOiBzdHJpbmdcbiAgICApOiBzdHJpbmcge1xuICAgICAgaWYgKGV4aXN0c1N5bmModGFyZ2V0UGF0aCkpIHtcbiAgICAgICAgcmV0dXJuIHRhcmdldFBhdGg7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGV4dGVuc2lvbk1hdGNoID0gdGFyZ2V0UGF0aC5tYXRjaCgvKFxcLlteLi9cXFxcXSspJC8pO1xuICAgICAgY29uc3QgZXh0ZW5zaW9uID0gZXh0ZW5zaW9uTWF0Y2g/LlsxXT8udG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmICghZXh0ZW5zaW9uKSB7XG4gICAgICAgIHJldHVybiB0YXJnZXRQYXRoO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBleHRlbnNpb25GYWxsYmFja3MgPVxuICAgICAgICBleHRlbnNpb24gPT09ICcuanMnXG4gICAgICAgICAgPyBbJy50cycsICcudHN4JywgJy5tdHMnLCAnLmN0cyddXG4gICAgICAgICAgOiBleHRlbnNpb24gPT09ICcubWpzJ1xuICAgICAgICAgICAgPyBbJy5tdHMnXVxuICAgICAgICAgICAgOiBleHRlbnNpb24gPT09ICcuY2pzJ1xuICAgICAgICAgICAgICA/IFsnLmN0cyddXG4gICAgICAgICAgICAgIDogZXh0ZW5zaW9uID09PSAnLmpzeCdcbiAgICAgICAgICAgICAgICA/IFsnLnRzeCddXG4gICAgICAgICAgICAgICAgOiBbXTtcblxuICAgICAgaWYgKGV4dGVuc2lvbkZhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRhcmdldFBhdGg7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRhcmdldFdpdGhvdXRFeHRlbnNpb24gPSB0YXJnZXRQYXRoLnNsaWNlKDAsIC1leHRlbnNpb24ubGVuZ3RoKTtcbiAgICAgIGZvciAoY29uc3QgZmFsbGJhY2tFeHRlbnNpb24gb2YgZXh0ZW5zaW9uRmFsbGJhY2tzKSB7XG4gICAgICAgIGNvbnN0IGZhbGxiYWNrUGF0aCA9IGAke3RhcmdldFdpdGhvdXRFeHRlbnNpb259JHtmYWxsYmFja0V4dGVuc2lvbn1gO1xuICAgICAgICBpZiAoZXhpc3RzU3luYyhmYWxsYmFja1BhdGgpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbGxiYWNrUGF0aDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGFyZ2V0UGF0aDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNob3VsZFNraXBUcmFuc2l0aXZlU3RlcEZpbGUoZmlsZVBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFBhdGggPSBmaWxlUGF0aC5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gICAgICBjb25zdCBpc1NvdXJjZUJhY2tlZFBhY2thZ2VQYXRoID1cbiAgICAgICAgdGhpcy5zaG91bGRQcmVmZXJTb3VyY2VCYWNrZWRQYWNrYWdlUGF0aChmaWxlUGF0aCk7XG4gICAgICByZXR1cm4gKFxuICAgICAgICBub3JtYWxpemVkUGF0aC5pbmNsdWRlcygnLy53ZWxsLWtub3duL3dvcmtmbG93LycpIHx8XG4gICAgICAgIG5vcm1hbGl6ZWRQYXRoLmluY2x1ZGVzKCcvLm5leHQvJykgfHxcbiAgICAgICAgKCFpc1NvdXJjZUJhY2tlZFBhY2thZ2VQYXRoICYmXG4gICAgICAgICAgKG5vcm1hbGl6ZWRQYXRoLmluY2x1ZGVzKCcvbm9kZV9tb2R1bGVzLycpIHx8XG4gICAgICAgICAgICBub3JtYWxpemVkUGF0aC5pbmNsdWRlcygnLy5wbnBtLycpKSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZXNvbHZlVHJhbnNpdGl2ZVN0ZXBJbXBvcnRUYXJnZXRQYXRoKFxuICAgICAgc291cmNlRmlsZVBhdGg6IHN0cmluZyxcbiAgICAgIHNwZWNpZmllcjogc3RyaW5nXG4gICAgKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgICBjb25zdCBzcGVjaWZpZXJNYXRjaCA9IHNwZWNpZmllci5tYXRjaCgvXihbXj8jXSspKC4qKSQvKTtcbiAgICAgIGNvbnN0IGltcG9ydFBhdGggPSBzcGVjaWZpZXJNYXRjaD8uWzFdID8/IHNwZWNpZmllcjtcblxuICAgICAgaWYgKCFpbXBvcnRQYXRoLnN0YXJ0c1dpdGgoJy4nKSkge1xuICAgICAgICBpZiAoaW1wb3J0UGF0aCAhPT0gJ3dvcmtmbG93JyAmJiAhaW1wb3J0UGF0aC5zdGFydHNXaXRoKCdAd29ya2Zsb3cvJykpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID1cbiAgICAgICAgICAgIGNyZWF0ZVJlcXVpcmUoc291cmNlRmlsZVBhdGgpLnJlc29sdmUoaW1wb3J0UGF0aCk7XG4gICAgICAgICAgY29uc3Qgbm9ybWFsaXplZFJlc29sdmVkUGF0aCA9XG4gICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgIGlmICh0aGlzLnNob3VsZFNraXBUcmFuc2l0aXZlU3RlcEZpbGUobm9ybWFsaXplZFJlc29sdmVkUGF0aCkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGZpbGVTdGF0cyA9IGF3YWl0IHN0YXQobm9ybWFsaXplZFJlc29sdmVkUGF0aCk7XG4gICAgICAgICAgcmV0dXJuIGZpbGVTdGF0cy5pc0ZpbGUoKSA/IG5vcm1hbGl6ZWRSZXNvbHZlZFBhdGggOiBudWxsO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBhYnNvbHV0ZVRhcmdldFBhdGggPSByZXNvbHZlKGRpcm5hbWUoc291cmNlRmlsZVBhdGgpLCBpbXBvcnRQYXRoKTtcblxuICAgICAgY29uc3QgY2FuZGlkYXRlUGF0aHMgPSBuZXcgU2V0PHN0cmluZz4oW1xuICAgICAgICB0aGlzLnJlc29sdmVJbXBvcnRUYXJnZXRXaXRoRXh0ZW5zaW9uRmFsbGJhY2tzKGFic29sdXRlVGFyZ2V0UGF0aCksXG4gICAgICBdKTtcblxuICAgICAgaWYgKCFleHRuYW1lKGFic29sdXRlVGFyZ2V0UGF0aCkpIHtcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9uQ2FuZGlkYXRlcyA9IFtcbiAgICAgICAgICAnLnRzJyxcbiAgICAgICAgICAnLnRzeCcsXG4gICAgICAgICAgJy5tdHMnLFxuICAgICAgICAgICcuY3RzJyxcbiAgICAgICAgICAnLmpzJyxcbiAgICAgICAgICAnLmpzeCcsXG4gICAgICAgICAgJy5tanMnLFxuICAgICAgICAgICcuY2pzJyxcbiAgICAgICAgXTtcbiAgICAgICAgZm9yIChjb25zdCBleHRlbnNpb25DYW5kaWRhdGUgb2YgZXh0ZW5zaW9uQ2FuZGlkYXRlcykge1xuICAgICAgICAgIGNhbmRpZGF0ZVBhdGhzLmFkZChgJHthYnNvbHV0ZVRhcmdldFBhdGh9JHtleHRlbnNpb25DYW5kaWRhdGV9YCk7XG4gICAgICAgICAgY2FuZGlkYXRlUGF0aHMuYWRkKFxuICAgICAgICAgICAgam9pbihhYnNvbHV0ZVRhcmdldFBhdGgsIGBpbmRleCR7ZXh0ZW5zaW9uQ2FuZGlkYXRlfWApXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGNhbmRpZGF0ZVBhdGggb2YgY2FuZGlkYXRlUGF0aHMpIHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID1cbiAgICAgICAgICB0aGlzLnJlc29sdmVJbXBvcnRUYXJnZXRXaXRoRXh0ZW5zaW9uRmFsbGJhY2tzKGNhbmRpZGF0ZVBhdGgpO1xuICAgICAgICBjb25zdCBub3JtYWxpemVkUmVzb2x2ZWRQYXRoID1cbiAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChyZXNvbHZlZFBhdGgpO1xuXG4gICAgICAgIGlmICh0aGlzLnNob3VsZFNraXBUcmFuc2l0aXZlU3RlcEZpbGUobm9ybWFsaXplZFJlc29sdmVkUGF0aCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZmlsZVN0YXRzID0gYXdhaXQgc3RhdChub3JtYWxpemVkUmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgICBpZiAoZmlsZVN0YXRzLmlzRmlsZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaXplZFJlc29sdmVkUGF0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8vIFRyeSB0aGUgbmV4dCBjYW5kaWRhdGUgcGF0aC5cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGNvbGxlY3RUcmFuc2l0aXZlU3RlcEZpbGVzKHtcbiAgICAgIGVudHJ5RmlsZXMsXG4gICAgICBzdGVwRmlsZXMsXG4gICAgfToge1xuICAgICAgZW50cnlGaWxlczogc3RyaW5nW107XG4gICAgICBzdGVwRmlsZXM6IHN0cmluZ1tdO1xuICAgIH0pOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICBjb25zdCBub3JtYWxpemVkRW50cnlGaWxlcyA9IEFycmF5LmZyb20oXG4gICAgICAgIG5ldyBTZXQoXG4gICAgICAgICAgZW50cnlGaWxlcy5tYXAoKGVudHJ5RmlsZSkgPT5cbiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplRGlzY292ZXJlZEZpbGVQYXRoKGVudHJ5RmlsZSlcbiAgICAgICAgICApXG4gICAgICAgIClcbiAgICAgICkuc29ydCgpO1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFN0ZXBTZWVkRmlsZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFxuICAgICAgICAgIHN0ZXBGaWxlcy5tYXAoKHN0ZXBGaWxlKSA9PlxuICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoc3RlcEZpbGUpXG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgICApLnNvcnQoKTtcbiAgICAgIGNvbnN0IGRpc2NvdmVyZWRTdGVwRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4obm9ybWFsaXplZFN0ZXBTZWVkRmlsZXMpO1xuICAgICAgY29uc3QgcXVldWVkRmlsZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFsuLi5ub3JtYWxpemVkRW50cnlGaWxlcywgLi4ubm9ybWFsaXplZFN0ZXBTZWVkRmlsZXNdKVxuICAgICAgKTtcbiAgICAgIGNvbnN0IHZpc2l0ZWRGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgY29uc3Qgc291cmNlQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nIHwgbnVsbD4oKTtcbiAgICAgIGNvbnN0IHBhdHRlcm5DYWNoZSA9IG5ldyBNYXA8XG4gICAgICAgIHN0cmluZyxcbiAgICAgICAgUmV0dXJuVHlwZTx0eXBlb2YgZGV0ZWN0V29ya2Zsb3dQYXR0ZXJucz4gfCBudWxsXG4gICAgICA+KCk7XG5cbiAgICAgIGNvbnN0IGdldFNvdXJjZSA9IGFzeW5jIChmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiA9PiB7XG4gICAgICAgIGlmIChzb3VyY2VDYWNoZS5oYXMoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgcmV0dXJuIHNvdXJjZUNhY2hlLmdldChmaWxlUGF0aCkgPz8gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IGF3YWl0IHJlYWRGaWxlKGZpbGVQYXRoLCAndXRmLTgnKTtcbiAgICAgICAgICBzb3VyY2VDYWNoZS5zZXQoZmlsZVBhdGgsIHNvdXJjZSk7XG4gICAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgc291cmNlQ2FjaGUuc2V0KGZpbGVQYXRoLCBudWxsKTtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgY29uc3QgZ2V0UGF0dGVybnMgPSBhc3luYyAoXG4gICAgICAgIGZpbGVQYXRoOiBzdHJpbmdcbiAgICAgICk6IFByb21pc2U8UmV0dXJuVHlwZTx0eXBlb2YgZGV0ZWN0V29ya2Zsb3dQYXR0ZXJucz4gfCBudWxsPiA9PiB7XG4gICAgICAgIGlmIChwYXR0ZXJuQ2FjaGUuaGFzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHJldHVybiBwYXR0ZXJuQ2FjaGUuZ2V0KGZpbGVQYXRoKSA/PyBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNvdXJjZSA9IGF3YWl0IGdldFNvdXJjZShmaWxlUGF0aCk7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IG51bGwpIHtcbiAgICAgICAgICBwYXR0ZXJuQ2FjaGUuc2V0KGZpbGVQYXRoLCBudWxsKTtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwYXR0ZXJucyA9IGRldGVjdFdvcmtmbG93UGF0dGVybnMoc291cmNlKTtcbiAgICAgICAgcGF0dGVybkNhY2hlLnNldChmaWxlUGF0aCwgcGF0dGVybnMpO1xuICAgICAgICByZXR1cm4gcGF0dGVybnM7XG4gICAgICB9O1xuXG4gICAgICB3aGlsZSAocXVldWVkRmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zdCBjdXJyZW50RmlsZSA9IHF1ZXVlZEZpbGVzLnBvcCgpO1xuICAgICAgICBpZiAoIWN1cnJlbnRGaWxlIHx8IHZpc2l0ZWRGaWxlcy5oYXMoY3VycmVudEZpbGUpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdmlzaXRlZEZpbGVzLmFkZChjdXJyZW50RmlsZSk7XG5cbiAgICAgICAgY29uc3QgY3VycmVudFNvdXJjZSA9IGF3YWl0IGdldFNvdXJjZShjdXJyZW50RmlsZSk7XG4gICAgICAgIGlmIChjdXJyZW50U291cmNlID09PSBudWxsKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpbXBvcnRTcGVjaWZpZXJzID0gdGhpcy5leHRyYWN0SW1wb3J0U3BlY2lmaWVycyhjdXJyZW50U291cmNlKTtcbiAgICAgICAgZm9yIChjb25zdCBzcGVjaWZpZXIgb2YgaW1wb3J0U3BlY2lmaWVycykge1xuICAgICAgICAgIGNvbnN0IHJlc29sdmVkSW1wb3J0UGF0aCA9XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlc29sdmVUcmFuc2l0aXZlU3RlcEltcG9ydFRhcmdldFBhdGgoXG4gICAgICAgICAgICAgIGN1cnJlbnRGaWxlLFxuICAgICAgICAgICAgICBzcGVjaWZpZXJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKCFyZXNvbHZlZEltcG9ydFBhdGgpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghdmlzaXRlZEZpbGVzLmhhcyhyZXNvbHZlZEltcG9ydFBhdGgpKSB7XG4gICAgICAgICAgICBxdWV1ZWRGaWxlcy5wdXNoKHJlc29sdmVkSW1wb3J0UGF0aCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgaW1wb3J0UGF0dGVybnMgPSBhd2FpdCBnZXRQYXR0ZXJucyhyZXNvbHZlZEltcG9ydFBhdGgpO1xuICAgICAgICAgIGlmIChpbXBvcnRQYXR0ZXJucz8uaGFzVXNlU3RlcCkge1xuICAgICAgICAgICAgZGlzY292ZXJlZFN0ZXBGaWxlcy5hZGQocmVzb2x2ZWRJbXBvcnRQYXRoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIEFycmF5LmZyb20oZGlzY292ZXJlZFN0ZXBGaWxlcykuc29ydCgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29sbGVjdFRyYW5zaXRpdmVTZXJkZUZpbGVzKHtcbiAgICAgIGVudHJ5RmlsZXMsXG4gICAgICBzZXJkZUZpbGVzLFxuICAgIH06IHtcbiAgICAgIGVudHJ5RmlsZXM6IHN0cmluZ1tdO1xuICAgICAgc2VyZGVGaWxlczogc3RyaW5nW107XG4gICAgfSk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRFbnRyeUZpbGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChcbiAgICAgICAgICBlbnRyeUZpbGVzLm1hcCgoZW50cnlGaWxlKSA9PlxuICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoZW50cnlGaWxlKVxuICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICAgKS5zb3J0KCk7XG4gICAgICBjb25zdCBub3JtYWxpemVkU2VyZGVTZWVkRmlsZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFxuICAgICAgICAgIHNlcmRlRmlsZXMubWFwKChzZXJkZUZpbGUpID0+XG4gICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChzZXJkZUZpbGUpXG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgICApLnNvcnQoKTtcbiAgICAgIC8vIEludGVudGlvbmFsbHkgcmUtdmFsaWRhdGUgc2VyZGUgc2VlZHMgYWdhaW5zdCBzb3VyY2UgcGF0dGVybnMuXG4gICAgICAvLyBUaGlzIGtlZXBzIHByZXZpb3VzbHkgZGlzY292ZXJlZC9tYW51YWwgc2VlZCBlbnRyaWVzIGZyb20gc3RpY2tpbmcgd2hlblxuICAgICAgLy8gZmlsZXMgbm8gbG9uZ2VyIG1hdGNoIHNlcmRlIHBhdHRlcm5zLlxuICAgICAgY29uc3QgZGlzY292ZXJlZFNlcmRlRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgIGNvbnN0IHF1ZXVlZEZpbGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbLi4ubm9ybWFsaXplZEVudHJ5RmlsZXMsIC4uLm5vcm1hbGl6ZWRTZXJkZVNlZWRGaWxlc10pXG4gICAgICApO1xuICAgICAgY29uc3QgdmlzaXRlZEZpbGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBjb25zdCBzb3VyY2VDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmcgfCBudWxsPigpO1xuICAgICAgY29uc3QgcGF0dGVybkNhY2hlID0gbmV3IE1hcDxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICBSZXR1cm5UeXBlPHR5cGVvZiBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zPiB8IG51bGxcbiAgICAgID4oKTtcblxuICAgICAgY29uc3QgZ2V0U291cmNlID0gYXN5bmMgKGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+ID0+IHtcbiAgICAgICAgaWYgKHNvdXJjZUNhY2hlLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICByZXR1cm4gc291cmNlQ2FjaGUuZ2V0KGZpbGVQYXRoKSA/PyBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgICAgIHNvdXJjZUNhY2hlLnNldChmaWxlUGF0aCwgc291cmNlKTtcbiAgICAgICAgICByZXR1cm4gc291cmNlO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICBzb3VyY2VDYWNoZS5zZXQoZmlsZVBhdGgsIG51bGwpO1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBnZXRQYXR0ZXJucyA9IGFzeW5jIChcbiAgICAgICAgZmlsZVBhdGg6IHN0cmluZ1xuICAgICAgKTogUHJvbWlzZTxSZXR1cm5UeXBlPHR5cGVvZiBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zPiB8IG51bGw+ID0+IHtcbiAgICAgICAgaWYgKHBhdHRlcm5DYWNoZS5oYXMoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgcmV0dXJuIHBhdHRlcm5DYWNoZS5nZXQoZmlsZVBhdGgpID8/IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgZ2V0U291cmNlKGZpbGVQYXRoKTtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHBhdHRlcm5DYWNoZS5zZXQoZmlsZVBhdGgsIG51bGwpO1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhdHRlcm5zID0gZGV0ZWN0V29ya2Zsb3dQYXR0ZXJucyhzb3VyY2UpO1xuICAgICAgICBwYXR0ZXJuQ2FjaGUuc2V0KGZpbGVQYXRoLCBwYXR0ZXJucyk7XG4gICAgICAgIHJldHVybiBwYXR0ZXJucztcbiAgICAgIH07XG5cbiAgICAgIGZvciAoY29uc3Qgc2VyZGVTZWVkRmlsZSBvZiBub3JtYWxpemVkU2VyZGVTZWVkRmlsZXMpIHtcbiAgICAgICAgY29uc3Qgc2VlZFBhdHRlcm5zID0gYXdhaXQgZ2V0UGF0dGVybnMoc2VyZGVTZWVkRmlsZSk7XG4gICAgICAgIGlmIChzZWVkUGF0dGVybnM/Lmhhc1NlcmRlKSB7XG4gICAgICAgICAgZGlzY292ZXJlZFNlcmRlRmlsZXMuYWRkKHNlcmRlU2VlZEZpbGUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHdoaWxlIChxdWV1ZWRGaWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRGaWxlID0gcXVldWVkRmlsZXMucG9wKCk7XG4gICAgICAgIGlmICghY3VycmVudEZpbGUgfHwgdmlzaXRlZEZpbGVzLmhhcyhjdXJyZW50RmlsZSkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB2aXNpdGVkRmlsZXMuYWRkKGN1cnJlbnRGaWxlKTtcblxuICAgICAgICBjb25zdCBjdXJyZW50U291cmNlID0gYXdhaXQgZ2V0U291cmNlKGN1cnJlbnRGaWxlKTtcbiAgICAgICAgaWYgKGN1cnJlbnRTb3VyY2UgPT09IG51bGwpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlbGF0aXZlSW1wb3J0U3BlY2lmaWVycyA9XG4gICAgICAgICAgdGhpcy5leHRyYWN0UmVsYXRpdmVJbXBvcnRTcGVjaWZpZXJzKGN1cnJlbnRTb3VyY2UpO1xuICAgICAgICBmb3IgKGNvbnN0IHNwZWNpZmllciBvZiByZWxhdGl2ZUltcG9ydFNwZWNpZmllcnMpIHtcbiAgICAgICAgICBjb25zdCByZXNvbHZlZEltcG9ydFBhdGggPVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5yZXNvbHZlVHJhbnNpdGl2ZVN0ZXBJbXBvcnRUYXJnZXRQYXRoKFxuICAgICAgICAgICAgICBjdXJyZW50RmlsZSxcbiAgICAgICAgICAgICAgc3BlY2lmaWVyXG4gICAgICAgICAgICApO1xuICAgICAgICAgIGlmICghcmVzb2x2ZWRJbXBvcnRQYXRoKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIXZpc2l0ZWRGaWxlcy5oYXMocmVzb2x2ZWRJbXBvcnRQYXRoKSkge1xuICAgICAgICAgICAgcXVldWVkRmlsZXMucHVzaChyZXNvbHZlZEltcG9ydFBhdGgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGltcG9ydFBhdHRlcm5zID0gYXdhaXQgZ2V0UGF0dGVybnMocmVzb2x2ZWRJbXBvcnRQYXRoKTtcbiAgICAgICAgICBpZiAoaW1wb3J0UGF0dGVybnM/Lmhhc1NlcmRlKSB7XG4gICAgICAgICAgICBkaXNjb3ZlcmVkU2VyZGVGaWxlcy5hZGQocmVzb2x2ZWRJbXBvcnRQYXRoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQVNULWxldmVsIHZlcmlmaWNhdGlvbjogcnVuIFNXQyBkZXRlY3QgbW9kZSBvbiByZWdleC1tYXRjaGVkIGNhbmRpZGF0ZXNcbiAgICAgIC8vIHRvIGNvbmZpcm0gdGhleSBhY3R1YWxseSBkZWZpbmUgc2VyZGUgY2xhc3Nlcy4gVGhpcyBwcmV2ZW50cyBTREsgaW50ZXJuYWxcbiAgICAgIC8vIGZpbGVzICh3aGljaCBtYXRjaCBzZXJkZSByZWdleCBwYXR0ZXJucyBidXQgZGVmaW5lIG5vIGNsYXNzZXMpIGZyb20gYmVpbmdcbiAgICAgIC8vIGJ1bmRsZWQgaW50byB0aGUgd29ya2Zsb3cgc2FuZGJveC5cbiAgICAgIGNvbnN0IHByb2plY3RSb290ID0gdGhpcy5jb25maWcucHJvamVjdFJvb3QgfHwgdGhpcy5jb25maWcud29ya2luZ0RpcjtcbiAgICAgIGNvbnN0IHZlcmlmaWVkU2VyZGVGaWxlczogc3RyaW5nW10gPSBbXTtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBBcnJheS5mcm9tKGRpc2NvdmVyZWRTZXJkZUZpbGVzKS5tYXAoYXN5bmMgKGZpbGVQYXRoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgZ2V0U291cmNlKGZpbGVQYXRoKTtcbiAgICAgICAgICBpZiAoIXNvdXJjZSkgcmV0dXJuO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZWxhdGl2ZUZpbGVuYW1lID1cbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy5nZXRSZWxhdGl2ZUZpbGVuYW1lRm9yU3djKGZpbGVQYXRoKTtcbiAgICAgICAgICAgIGNvbnN0IHsgd29ya2Zsb3dNYW5pZmVzdCB9ID0gYXdhaXQgYXBwbHlTd2NUcmFuc2Zvcm0oXG4gICAgICAgICAgICAgIHJlbGF0aXZlRmlsZW5hbWUsXG4gICAgICAgICAgICAgIHNvdXJjZSxcbiAgICAgICAgICAgICAgJ2RldGVjdCcsXG4gICAgICAgICAgICAgIGZpbGVQYXRoLFxuICAgICAgICAgICAgICBwcm9qZWN0Um9vdFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIC8vIE9ubHkgaW5jbHVkZSBmaWxlcyB0aGF0IGFjdHVhbGx5IGRlZmluZSBzZXJkZSBjbGFzc2VzXG4gICAgICAgICAgICBjb25zdCBoYXNDbGFzc2VzID1cbiAgICAgICAgICAgICAgd29ya2Zsb3dNYW5pZmVzdC5jbGFzc2VzICYmXG4gICAgICAgICAgICAgIE9iamVjdC52YWx1ZXMod29ya2Zsb3dNYW5pZmVzdC5jbGFzc2VzKS5zb21lKFxuICAgICAgICAgICAgICAgIChlbnRyaWVzKSA9PiBPYmplY3Qua2V5cyhlbnRyaWVzKS5sZW5ndGggPiAwXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoaGFzQ2xhc3Nlcykge1xuICAgICAgICAgICAgICB2ZXJpZmllZFNlcmRlRmlsZXMucHVzaChmaWxlUGF0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAvLyBJZiBkZXRlY3QgZmFpbHMsIGluY2x1ZGUgdGhlIGZpbGUgdG8gYmUgc2FmZVxuICAgICAgICAgICAgdmVyaWZpZWRTZXJkZUZpbGVzLnB1c2goZmlsZVBhdGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiB2ZXJpZmllZFNlcmRlRmlsZXMuc29ydCgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgYnVpbGRXZWJob29rUm91dGUoe1xuICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXIsXG4gICAgICByb3V0ZUZpbGVOYW1lID0gJ3JvdXRlLmpzJyxcbiAgICB9OiB7XG4gICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcjogc3RyaW5nO1xuICAgICAgcm91dGVGaWxlTmFtZT86IHN0cmluZztcbiAgICB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBjb25zdCB3ZWJob29rUm91dGVGaWxlID0gam9pbihcbiAgICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXIsXG4gICAgICAgIGB3ZWJob29rL1t0b2tlbl0vJHtyb3V0ZUZpbGVOYW1lfWBcbiAgICAgICk7XG4gICAgICBhd2FpdCB0aGlzLmNyZWF0ZVdlYmhvb2tCdW5kbGUoe1xuICAgICAgICBvdXRmaWxlOiB3ZWJob29rUm91dGVGaWxlLFxuICAgICAgICBidW5kbGU6IGZhbHNlLCAvLyBOZXh0LmpzIGRvZXNuJ3QgbmVlZCBidW5kbGluZ1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBmaW5kQXBwRGlyZWN0b3J5KCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICBjb25zdCBhcHBEaXIgPSByZXNvbHZlKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsICdhcHAnKTtcbiAgICAgIGNvbnN0IHNyY0FwcERpciA9IHJlc29sdmUodGhpcy5jb25maWcud29ya2luZ0RpciwgJ3NyYy9hcHAnKTtcbiAgICAgIGNvbnN0IHBhZ2VzRGlyID0gcmVzb2x2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCAncGFnZXMnKTtcbiAgICAgIGNvbnN0IHNyY1BhZ2VzRGlyID0gcmVzb2x2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCAnc3JjL3BhZ2VzJyk7XG5cbiAgICAgIC8vIEhlbHBlciB0byBjaGVjayBpZiBhIHBhdGggZXhpc3RzIGFuZCBpcyBhIGRpcmVjdG9yeVxuICAgICAgY29uc3QgaXNEaXJlY3RvcnkgPSBhc3luYyAocGF0aDogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgYWNjZXNzKHBhdGgsIGNvbnN0YW50cy5GX09LKTtcbiAgICAgICAgICBjb25zdCBzdGF0cyA9IGF3YWl0IHN0YXQocGF0aCk7XG4gICAgICAgICAgaWYgKCFzdGF0cy5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFBhdGggZXhpc3RzIGJ1dCBpcyBub3QgYSBkaXJlY3Rvcnk6ICR7cGF0aH1gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIEVycm9yICYmIGUubWVzc2FnZS5pbmNsdWRlcygnbm90IGEgZGlyZWN0b3J5JykpIHtcbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgLy8gQ2hlY2sgaWYgYXBwIGRpcmVjdG9yeSBleGlzdHNcbiAgICAgIGlmIChhd2FpdCBpc0RpcmVjdG9yeShhcHBEaXIpKSB7XG4gICAgICAgIHJldHVybiBhcHBEaXI7XG4gICAgICB9XG5cbiAgICAgIC8vIENoZWNrIGlmIHNyYy9hcHAgZGlyZWN0b3J5IGV4aXN0c1xuICAgICAgaWYgKGF3YWl0IGlzRGlyZWN0b3J5KHNyY0FwcERpcikpIHtcbiAgICAgICAgcmV0dXJuIHNyY0FwcERpcjtcbiAgICAgIH1cblxuICAgICAgLy8gSWYgbm8gYXBwIGRpcmVjdG9yeSBleGlzdHMsIGNoZWNrIGZvciBwYWdlcyBkaXJlY3RvcnkgYW5kIGNyZWF0ZSBhcHAgbmV4dCB0byBpdFxuICAgICAgaWYgKGF3YWl0IGlzRGlyZWN0b3J5KHBhZ2VzRGlyKSkge1xuICAgICAgICAvLyBDcmVhdGUgYXBwIGRpcmVjdG9yeSBuZXh0IHRvIHBhZ2VzIGRpcmVjdG9yeVxuICAgICAgICBhd2FpdCBta2RpcihhcHBEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgICByZXR1cm4gYXBwRGlyO1xuICAgICAgfVxuXG4gICAgICBpZiAoYXdhaXQgaXNEaXJlY3Rvcnkoc3JjUGFnZXNEaXIpKSB7XG4gICAgICAgIC8vIENyZWF0ZSBzcmMvYXBwIGRpcmVjdG9yeSBuZXh0IHRvIHNyYy9wYWdlcyBkaXJlY3RvcnlcbiAgICAgICAgYXdhaXQgbWtkaXIoc3JjQXBwRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgcmV0dXJuIHNyY0FwcERpcjtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnQ291bGQgbm90IGZpbmQgTmV4dC5qcyBhcHAgb3IgcGFnZXMgZGlyZWN0b3J5LiBFeHBlY3RlZCBvbmUgb2Y6IFwiYXBwXCIsIFwic3JjL2FwcFwiLCBcInBhZ2VzXCIsIG9yIFwic3JjL3BhZ2VzXCIgdG8gZXhpc3QuJ1xuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBDYWNoZWROZXh0QnVpbGRlckRlZmVycmVkID0gTmV4dERlZmVycmVkQnVpbGRlcjtcbiAgcmV0dXJuIE5leHREZWZlcnJlZEJ1aWxkZXI7XG59XG4iXX0=