@workflow/next 5.0.0-beta.2 → 5.0.0-beta.20

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,13 +7,13 @@ 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
- const enhanced_resolve_1 = __importDefault(require("enhanced-resolve"));
13
13
  const socket_server_js_1 = require("./socket-server.js");
14
- const step_copy_utils_js_1 = require("./step-copy-utils.js");
15
14
  const ROUTE_STUB_FILE_MARKER = 'WORKFLOW_ROUTE_STUB_FILE';
16
15
  const ROUTE_STUB_MARKER_SCAN_BYTES = 4 * 1024;
16
+ const DEV_WORKFLOW_CODE_FILENAME = '__workflow_code.txt';
17
17
  let CachedNextBuilderDeferred;
18
18
  // Create the deferred Next builder dynamically by extending the ESM BaseBuilder.
19
19
  // Exported as getNextBuilderDeferred() to allow CommonJS modules to import from
@@ -22,46 +22,15 @@ async function getNextBuilderDeferred() {
22
22
  if (CachedNextBuilderDeferred) {
23
23
  return CachedNextBuilderDeferred;
24
24
  }
25
- const { BaseBuilder: BaseBuilderClass, STEP_QUEUE_TRIGGER, WORKFLOW_QUEUE_TRIGGER, applySwcTransform, detectWorkflowPatterns, getImportPath, resolveWorkflowAliasRelativePath,
25
+ // V2: STEP_QUEUE_TRIGGER and enhanced-resolve infrastructure
26
+ // were removed because the V2 combined handler eliminates the separate step
27
+ // route/topic. The step copy import rewriting (getRelativeImportSpecifier,
28
+ // getStepCopyFileName, rewriteRelativeImportsForCopiedStep) from main was also
29
+ // removed — V2 doesn't use step copies. If step copy support is needed, it
30
+ // should land as a complete feature set.
31
+ const { BaseBuilder: BaseBuilderClass, WORKFLOW_QUEUE_TRIGGER, createWorkflowEntrypointOptionsCode, detectWorkflowPatterns, applySwcTransform, getImportPath, resolveWorkflowAliasRelativePath,
26
32
  // biome-ignore lint/security/noGlobalEval: Need to use eval here to avoid TypeScript from transpiling the import statement into `require()`
27
33
  } = (await eval('import("@workflow/builders")'));
28
- // Shared resolve options matching the configuration used by the SWC
29
- // esbuild plugin (swc-esbuild-plugin.ts) for consistent resolution
30
- // semantics across the toolchain.
31
- const NODE_RESOLVE_OPTIONS = {
32
- dependencyType: 'commonjs',
33
- modules: ['node_modules'],
34
- exportsFields: ['exports'],
35
- importsFields: ['imports'],
36
- conditionNames: ['node', 'require'],
37
- descriptionFiles: ['package.json'],
38
- extensions: [
39
- '.ts',
40
- '.tsx',
41
- '.mts',
42
- '.cts',
43
- '.cjs',
44
- '.mjs',
45
- '.js',
46
- '.jsx',
47
- '.json',
48
- '.node',
49
- ],
50
- enforceExtensions: false,
51
- symlinks: true,
52
- mainFields: ['main'],
53
- mainFiles: ['index'],
54
- roots: [],
55
- fullySpecified: false,
56
- preferRelative: false,
57
- preferAbsolute: false,
58
- restrictions: [],
59
- };
60
- const NODE_ESM_RESOLVE_OPTIONS = {
61
- ...NODE_RESOLVE_OPTIONS,
62
- dependencyType: 'esm',
63
- conditionNames: ['node', 'import'],
64
- };
65
34
  class NextDeferredBuilder extends BaseBuilderClass {
66
35
  socketIO;
67
36
  discoveredWorkflowFiles = new Set();
@@ -73,11 +42,6 @@ async function getNextBuilderDeferred() {
73
42
  cacheWriteTimer = null;
74
43
  deferredRebuildTimer = null;
75
44
  lastDeferredBuildSignature = null;
76
- // Lazily initialized resolvers for bare specifier rewriting.
77
- // Cached to avoid re-creating on every import rewrite.
78
- esmSyncResolver;
79
- cjsSyncResolver;
80
- manifestStepResolveBaseDirs = null;
81
45
  async build() {
82
46
  const outputDir = await this.findAppDirectory();
83
47
  await this.initializeDiscoveryState();
@@ -141,6 +105,14 @@ async function getNextBuilderDeferred() {
141
105
  }
142
106
  }
143
107
  this.lastDeferredBuildSignature = buildSignature;
108
+ if (!this.config.watch) {
109
+ // Production builds can persist newly discovered deferred-entry files to
110
+ // the cache after the first pass completes. Reload that cache before we
111
+ // decide whether the input signature stabilized so staged tarball builds
112
+ // can immediately replay with the expanded step set.
113
+ await new Promise((resolve) => setTimeout(resolve, 250));
114
+ await this.loadWorkflowsCache();
115
+ }
144
116
  const postBuildInputFiles = this.getCurrentInputFiles(implicitStepFiles);
145
117
  const postBuildSignature = await this.createDeferredBuildSignature(postBuildInputFiles);
146
118
  if (postBuildSignature === buildSignature) {
@@ -157,15 +129,11 @@ async function getNextBuilderDeferred() {
157
129
  const outputDir = await this.findAppDirectory();
158
130
  const generatedRouteFiles = [
159
131
  (0, node_path_1.join)(outputDir, '.well-known/workflow/v1/flow/route.js'),
160
- (0, node_path_1.join)(outputDir, '.well-known/workflow/v1/step/route.js'),
161
132
  (0, node_path_1.join)(outputDir, '.well-known/workflow/v1/webhook/[token]/route.js'),
162
133
  ];
163
134
  for (const routeFilePath of generatedRouteFiles) {
164
135
  const routeState = await this.getGeneratedRouteState(routeFilePath);
165
- if (routeState === 'missing') {
166
- return true;
167
- }
168
- if (routeState === 'stub') {
136
+ if (routeState === 'missing' || routeState === 'stub') {
169
137
  return true;
170
138
  }
171
139
  }
@@ -383,18 +351,17 @@ async function getNextBuilderDeferred() {
383
351
  ...this.discoveredSerdeFiles,
384
352
  ...trackedDiscoveredEntries.discoveredSerdeFiles,
385
353
  ])).sort();
386
- const discoveredStepFiles = await this.filterExistingFiles(discoveredStepFileCandidates);
387
354
  const discoveredWorkflowFiles = await this.filterExistingFiles(discoveredWorkflowFileCandidates);
355
+ const existingStepFileCandidates = await this.filterExistingFiles(discoveredStepFileCandidates);
356
+ const discoveredStepFiles = await this.collectTransitiveStepFiles({
357
+ entryFiles: [...existingStepFileCandidates, ...discoveredWorkflowFiles],
358
+ stepFiles: existingStepFileCandidates,
359
+ });
388
360
  const existingSerdeFileCandidates = await this.filterExistingFiles(discoveredSerdeFileCandidates);
389
361
  const discoveredSerdeFiles = await this.collectTransitiveSerdeFiles({
390
362
  entryFiles: [...discoveredStepFiles, ...discoveredWorkflowFiles],
391
363
  serdeFiles: existingSerdeFileCandidates,
392
364
  });
393
- const discoveredEntries = {
394
- discoveredSteps: new Set(discoveredStepFiles),
395
- discoveredWorkflows: new Set(discoveredWorkflowFiles),
396
- discoveredSerdeFiles: new Set(discoveredSerdeFiles),
397
- };
398
365
  const existingInputFiles = await this.filterExistingFiles(inputFiles);
399
366
  const buildInputFiles = Array.from(new Set([
400
367
  ...existingInputFiles,
@@ -402,38 +369,32 @@ async function getNextBuilderDeferred() {
402
369
  ...discoveredWorkflowFiles,
403
370
  ...discoveredSerdeFiles,
404
371
  ])).sort();
372
+ const discoveredEntries = {
373
+ discoveredSteps: new Set(discoveredStepFiles),
374
+ discoveredWorkflows: new Set(discoveredWorkflowFiles),
375
+ discoveredSerdeFiles: new Set(discoveredSerdeFiles),
376
+ };
405
377
  // Ensure output directories exist
406
378
  await (0, promises_1.mkdir)(workflowGeneratedDir, { recursive: true });
407
379
  await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, '.gitignore'), '*');
408
380
  const tsconfigPath = await this.findTsConfigPath();
409
- const options = {
381
+ const flowRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'flow');
382
+ await (0, promises_1.mkdir)(flowRouteDir, { recursive: true });
383
+ const combinedResult = await this.createDeferredFlowRoute({
410
384
  inputFiles: buildInputFiles,
411
- workflowGeneratedDir,
385
+ flowOutfile: (0, node_path_1.join)(flowRouteDir, tempRouteFileName),
412
386
  tsconfigPath,
413
- routeFileName: tempRouteFileName,
414
387
  discoveredEntries,
415
- };
416
- const workflowsBundle = await this.buildWorkflowsFunction(options);
417
- const { manifest: stepsManifest } = await this.buildStepsFunction({
418
- ...options,
419
- additionalStepSourceManifest: workflowsBundle?.manifest,
420
388
  });
421
389
  await this.buildWebhookRoute({
422
390
  workflowGeneratedDir,
423
391
  routeFileName: tempRouteFileName,
424
392
  });
425
393
  await this.refreshTrackedDependencyFiles(workflowGeneratedDir, tempRouteFileName);
426
- // Merge manifests from both bundles
427
394
  const manifest = {
428
- steps: { ...stepsManifest.steps, ...workflowsBundle?.manifest?.steps },
429
- workflows: {
430
- ...stepsManifest.workflows,
431
- ...workflowsBundle?.manifest?.workflows,
432
- },
433
- classes: {
434
- ...stepsManifest.classes,
435
- ...workflowsBundle?.manifest?.classes,
436
- },
395
+ steps: { ...combinedResult?.manifest?.steps },
396
+ workflows: { ...combinedResult?.manifest?.workflows },
397
+ classes: { ...combinedResult?.manifest?.classes },
437
398
  };
438
399
  const manifestFilePath = (0, node_path_1.join)(workflowGeneratedDir, 'manifest.json');
439
400
  const manifestBuildPath = (0, node_path_1.join)(manifestBuildDir, 'manifest.json');
@@ -452,19 +413,197 @@ async function getNextBuilderDeferred() {
452
413
  await (0, promises_1.rm)(manifestFilePath, { force: true });
453
414
  }
454
415
  await this.writeFunctionsConfig(outputDir);
416
+ // V2: Combined route (flow) — step registrations already at final path
455
417
  await this.copyFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, `flow/${tempRouteFileName}`), (0, node_path_1.join)(workflowGeneratedDir, 'flow/route.js'));
456
- await this.copyFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, `step/${tempRouteFileName}`), (0, node_path_1.join)(workflowGeneratedDir, 'step/route.js'));
457
418
  await this.copyFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, `webhook/[token]/${tempRouteFileName}`), (0, node_path_1.join)(workflowGeneratedDir, 'webhook/[token]/route.js'));
458
419
  // Expose manifest as a static file when WORKFLOW_PUBLIC_MANIFEST=1.
459
420
  // Next.js serves files from public/ at the root URL.
460
421
  if (this.shouldExposePublicManifest && manifestJson) {
461
422
  const publicManifestDir = (0, node_path_1.join)(this.config.workingDir, 'public/.well-known/workflow/v1');
462
423
  await (0, promises_1.mkdir)(publicManifestDir, { recursive: true });
424
+ if (process.env.VERCEL_DEPLOYMENT_ID === undefined) {
425
+ await this.writeFileIfChanged((0, node_path_1.join)(publicManifestDir, '.gitignore'), '*');
426
+ }
463
427
  await this.copyFileIfChanged(manifestFilePath, (0, node_path_1.join)(publicManifestDir, 'manifest.json'));
464
428
  }
465
429
  // Notify deferred entry loaders waiting on route.js stubs.
466
430
  this.socketIO?.emit('build-complete');
467
431
  }
432
+ async createDeferredFlowRoute({ inputFiles, flowOutfile, tsconfigPath, discoveredEntries, }) {
433
+ const workflowResult = await this.createWorkflowsBundle({
434
+ inputFiles,
435
+ outfile: `${flowOutfile}.__wf_tmp.js`,
436
+ format: 'esm',
437
+ bundleFinalOutput: false,
438
+ tsconfigPath,
439
+ discoveredEntries,
440
+ });
441
+ const workflowVMCode = workflowResult.interimBundleText;
442
+ if (!workflowVMCode) {
443
+ throw new Error('createWorkflowsBundle did not return interimBundleText');
444
+ }
445
+ try {
446
+ await (0, promises_1.rm)(`${flowOutfile}.__wf_tmp.js`, { force: true });
447
+ }
448
+ catch {
449
+ // Ignore cleanup errors.
450
+ }
451
+ const stepAndSerdeFiles = Array.from(new Set([
452
+ ...discoveredEntries.discoveredSteps,
453
+ ...discoveredEntries.discoveredSerdeFiles,
454
+ ])).sort();
455
+ const stepImports = await this.createDeferredStepSideEffectImports(stepAndSerdeFiles, (0, node_path_1.dirname)(flowOutfile));
456
+ const stepManifest = await this.createDeferredStepManifest(stepAndSerdeFiles);
457
+ const escapedVMCode = workflowVMCode.replace(/[\\`$]/g, '\\$&');
458
+ const workflowEntrypointOptionsCode = createWorkflowEntrypointOptionsCode();
459
+ let routeCode;
460
+ if (this.config.watch) {
461
+ const workflowCodePath = (0, node_path_1.join)((0, node_path_1.dirname)(flowOutfile), DEV_WORKFLOW_CODE_FILENAME);
462
+ await this.writeFileIfChanged(workflowCodePath, workflowVMCode);
463
+ routeCode = `// biome-ignore-all lint: generated file
464
+ /* eslint-disable */
465
+ import 'workflow/internal/builtins';
466
+ ${stepImports}
467
+ import { readFile, stat } from 'node:fs/promises';
468
+ import { workflowEntrypoint } from 'workflow/runtime';
469
+
470
+ const workflowCodePath = ${JSON.stringify(workflowCodePath)};
471
+ let cachedWorkflowHandler;
472
+ let cachedWorkflowCodeSignature;
473
+
474
+ async function getWorkflowHandler() {
475
+ const workflowCodeStats = await stat(workflowCodePath);
476
+ const workflowCodeSignature = \`\${workflowCodeStats.size}:\${workflowCodeStats.mtimeMs}\`;
477
+ if (!cachedWorkflowHandler || cachedWorkflowCodeSignature !== workflowCodeSignature) {
478
+ const workflowCode = await readFile(workflowCodePath, 'utf8');
479
+ cachedWorkflowHandler = workflowEntrypoint(workflowCode${workflowEntrypointOptionsCode});
480
+ cachedWorkflowCodeSignature = workflowCodeSignature;
481
+ }
482
+ return cachedWorkflowHandler;
483
+ }
484
+
485
+ export async function POST(req) {
486
+ return (await getWorkflowHandler())(req);
487
+ }`;
488
+ }
489
+ else {
490
+ routeCode = `// biome-ignore-all lint: generated file
491
+ /* eslint-disable */
492
+ import 'workflow/internal/builtins';
493
+ ${stepImports}
494
+ import { workflowEntrypoint } from 'workflow/runtime';
495
+
496
+ const workflowCode = \`${escapedVMCode}\`;
497
+
498
+ export const POST = workflowEntrypoint(workflowCode${workflowEntrypointOptionsCode});`;
499
+ }
500
+ await this.writeFileIfChanged(flowOutfile, routeCode);
501
+ return {
502
+ manifest: {
503
+ ...stepManifest,
504
+ workflows: {
505
+ ...stepManifest.workflows,
506
+ ...workflowResult.manifest.workflows,
507
+ },
508
+ classes: {
509
+ ...stepManifest.classes,
510
+ ...workflowResult.manifest.classes,
511
+ },
512
+ },
513
+ };
514
+ }
515
+ async createDeferredStepSideEffectImports(files, routeDir) {
516
+ const importSpecifiers = await Promise.all(files.map((file) => this.getDeferredRouteImportSpecifier(file, routeDir)));
517
+ return importSpecifiers
518
+ .map((specifier) => `import ${JSON.stringify(specifier)};`)
519
+ .join('\n');
520
+ }
521
+ async getDeferredRouteImportSpecifier(file, routeDir) {
522
+ const { importPath, isPackage } = getImportPath(file, this.config.workingDir);
523
+ if (isPackage) {
524
+ return importPath;
525
+ }
526
+ const absolutePath = await this.resolveDeferredRouteImportFilePath((0, node_path_1.resolve)(this.config.workingDir, importPath));
527
+ let relativePath = (0, node_path_1.relative)(routeDir, absolutePath).replace(/\\/g, '/');
528
+ if (!relativePath.startsWith('./') && !relativePath.startsWith('../')) {
529
+ relativePath = `./${relativePath}`;
530
+ }
531
+ return relativePath;
532
+ }
533
+ async resolveDeferredRouteImportFilePath(filePath) {
534
+ const packageDistPath = this.resolvePackageSourceDistFilePathForRouteImport(filePath);
535
+ if (packageDistPath) {
536
+ return packageDistPath;
537
+ }
538
+ return filePath;
539
+ }
540
+ resolvePackageSourceDistFilePathForRouteImport(filePath) {
541
+ const relativeToWorkingDir = (0, node_path_1.relative)(this.config.workingDir, filePath);
542
+ if (!relativeToWorkingDir.startsWith('..') &&
543
+ !(0, node_path_1.isAbsolute)(relativeToWorkingDir)) {
544
+ return null;
545
+ }
546
+ const packageRoot = this.findPackageRootForRouteImportSource(filePath);
547
+ if (!packageRoot) {
548
+ return null;
549
+ }
550
+ const relativeToPackageRoot = (0, node_path_1.relative)(packageRoot, filePath).replace(/\\/g, '/');
551
+ const srcPrefix = 'src/';
552
+ if (!relativeToPackageRoot.startsWith(srcPrefix)) {
553
+ return null;
554
+ }
555
+ const extension = (0, node_path_1.extname)(relativeToPackageRoot);
556
+ const outputExtension = extension === '.mts' ? '.mjs' : extension === '.cts' ? '.cjs' : '.js';
557
+ const withoutExtension = relativeToPackageRoot.slice(srcPrefix.length, relativeToPackageRoot.length - extension.length);
558
+ const distPath = (0, node_path_1.join)(packageRoot, 'dist', `${withoutExtension}${outputExtension}`);
559
+ return (0, node_fs_1.existsSync)(distPath) ? distPath : null;
560
+ }
561
+ findPackageRootForRouteImportSource(filePath) {
562
+ let currentDir = (0, node_path_1.dirname)(filePath);
563
+ while (true) {
564
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(currentDir, 'package.json'))) {
565
+ return currentDir;
566
+ }
567
+ const parentDir = (0, node_path_1.dirname)(currentDir);
568
+ if (parentDir === currentDir) {
569
+ return null;
570
+ }
571
+ currentDir = parentDir;
572
+ }
573
+ }
574
+ async createDeferredStepManifest(files) {
575
+ const manifest = {};
576
+ const manifestFiles = Array.from(new Set([
577
+ ...files,
578
+ ...(await this.resolveBuiltInStepFilesForManifest()),
579
+ ])).sort();
580
+ for (const file of manifestFiles) {
581
+ const source = await (0, promises_1.readFile)(file, 'utf8').catch(() => undefined);
582
+ if (!source) {
583
+ continue;
584
+ }
585
+ const relativeFilepath = await this.getRelativeFilenameForSwc(file);
586
+ const { workflowManifest } = await applySwcTransform(relativeFilepath, source, 'step', file, this.transformProjectRoot, this.moduleSpecifierRoot);
587
+ this.mergeWorkflowManifest(manifest, workflowManifest);
588
+ }
589
+ return manifest;
590
+ }
591
+ async resolveBuiltInStepFilesForManifest() {
592
+ try {
593
+ const workflowRequire = (0, node_module_1.createRequire)((0, node_path_1.join)(this.config.workingDir, 'package.json'));
594
+ return [
595
+ this.normalizeDiscoveredFilePath(workflowRequire.resolve('workflow/internal/builtins')),
596
+ ];
597
+ }
598
+ catch {
599
+ return [];
600
+ }
601
+ }
602
+ mergeWorkflowManifest(target, source) {
603
+ target.workflows = Object.assign(target.workflows || {}, source.workflows);
604
+ target.steps = Object.assign(target.steps || {}, source.steps);
605
+ target.classes = Object.assign(target.classes || {}, source.classes);
606
+ }
468
607
  async cleanupGeneratedArtifactsOnBoot(outputDir) {
469
608
  const workflowGeneratedDir = (0, node_path_1.join)(outputDir, '.well-known/workflow/v1');
470
609
  const flowRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'flow');
@@ -474,17 +613,18 @@ async function getNextBuilderDeferred() {
474
613
  (0, node_path_1.join)(flowRouteDir, 'route.js.temp'),
475
614
  (0, node_path_1.join)(flowRouteDir, 'route.js.temp.debug.json'),
476
615
  (0, node_path_1.join)(flowRouteDir, 'route.js.debug.json'),
477
- (0, node_path_1.join)(stepRouteDir, 'route.js.temp'),
478
- (0, node_path_1.join)(stepRouteDir, 'route.js.temp.debug.json'),
479
- (0, node_path_1.join)(stepRouteDir, 'route.js.debug.json'),
480
- (0, node_path_1.join)(stepRouteDir, step_copy_utils_js_1.DEFERRED_STEP_COPY_DIR_NAME),
616
+ (0, node_path_1.join)(flowRouteDir, DEV_WORKFLOW_CODE_FILENAME),
617
+ (0, node_path_1.join)(flowRouteDir, '__step_registrations.route.js.temp'),
618
+ (0, node_path_1.join)(flowRouteDir, '__step_registrations.route.js.temp.debug.json'),
619
+ // V2: clean up stale V1 step route directory
620
+ stepRouteDir,
481
621
  (0, node_path_1.join)(webhookRouteDir, 'route.js.temp'),
482
622
  (0, node_path_1.join)(workflowGeneratedDir, 'manifest.json'),
483
623
  ];
484
- await Promise.all(staleArtifactPaths.map((stalePath) => (0, promises_1.rm)(stalePath, { recursive: true, force: true })));
485
624
  await Promise.all([
625
+ ...staleArtifactPaths.map((stalePath) => (0, promises_1.rm)(stalePath, { recursive: true, force: true })),
626
+ (0, socket_server_js_1.cleanupStaleSocketInfoFiles)((0, node_path_1.join)(this.config.workingDir, this.getDistDir())),
486
627
  this.removeStaleDeferredTempFiles(flowRouteDir),
487
- this.removeStaleDeferredTempFiles(stepRouteDir),
488
628
  this.removeStaleDeferredTempFiles(webhookRouteDir),
489
629
  ]);
490
630
  }
@@ -545,7 +685,11 @@ async function getNextBuilderDeferred() {
545
685
  if (hasCacheTrackingChange) {
546
686
  this.scheduleWorkflowsCacheWrite();
547
687
  }
548
- if (hasCacheTrackingChange || wasTrackedDependency) {
688
+ if (hasWorkflow ||
689
+ hasStep ||
690
+ hasSerde ||
691
+ hasCacheTrackingChange ||
692
+ wasTrackedDependency) {
549
693
  this.scheduleDeferredRebuild();
550
694
  }
551
695
  },
@@ -571,41 +715,52 @@ async function getNextBuilderDeferred() {
571
715
  return (0, node_path_1.join)(this.config.workingDir, this.getDistDir(), 'cache', 'workflows.json');
572
716
  }
573
717
  getSocketInfoFilePath() {
574
- return (0, node_path_1.join)(this.config.workingDir, this.getDistDir(), 'cache', 'workflow-socket.json');
718
+ return (0, node_path_1.join)(this.config.workingDir, this.getDistDir(), socket_server_js_1.SOCKET_INFO_FILENAME);
575
719
  }
576
- normalizeDiscoveredFilePath(filePath) {
577
- const resolvedPath = (0, node_path_1.isAbsolute)(filePath)
578
- ? filePath
579
- : (0, node_path_1.resolve)(this.config.workingDir, filePath);
720
+ findPackageJsonPath(filePath) {
721
+ let currentDir = (0, node_path_1.dirname)(filePath);
722
+ let previousDir = '';
723
+ while (currentDir !== previousDir) {
724
+ const packageJsonPath = (0, node_path_1.join)(currentDir, 'package.json');
725
+ if ((0, node_fs_1.existsSync)(packageJsonPath)) {
726
+ return packageJsonPath;
727
+ }
728
+ previousDir = currentDir;
729
+ currentDir = (0, node_path_1.dirname)(currentDir);
730
+ }
731
+ return null;
732
+ }
733
+ shouldPreferSourceBackedPackagePath(filePath) {
734
+ const normalizedPath = filePath.replace(/\\/g, '/');
735
+ // Only prefer source for workspace packages (not in node_modules).
736
+ // For tarball-installed packages, using source-backed paths causes
737
+ // esbuild to bundle the full source tree (including world.ts with
738
+ // process.cwd()) instead of externalizing properly.
739
+ if (normalizedPath.includes('/packages/') &&
740
+ !normalizedPath.includes('/node_modules/')) {
741
+ return true;
742
+ }
743
+ if (!normalizedPath.includes('/node_modules/')) {
744
+ return false;
745
+ }
746
+ const packageJsonPath = this.findPackageJsonPath(filePath);
747
+ if (!packageJsonPath) {
748
+ return false;
749
+ }
580
750
  try {
581
- return (0, node_fs_1.realpathSync)(resolvedPath);
751
+ const packageJson = JSON.parse((0, node_fs_1.readFileSync)(packageJsonPath, 'utf-8'));
752
+ return (packageJson.name === 'workflow' ||
753
+ (typeof packageJson.name === 'string' &&
754
+ packageJson.name.startsWith('@workflow/')));
582
755
  }
583
756
  catch {
584
- return resolvedPath;
757
+ return false;
585
758
  }
586
759
  }
587
- getManifestStepResolveBaseDirs() {
588
- if (this.manifestStepResolveBaseDirs) {
589
- return this.manifestStepResolveBaseDirs;
590
- }
591
- const resolveBaseDirs = new Set();
592
- const addResolveBaseDir = (baseDir) => {
593
- resolveBaseDirs.add(this.normalizeDiscoveredFilePath(baseDir));
594
- };
595
- if (this.config.projectRoot) {
596
- addResolveBaseDir(this.config.projectRoot);
597
- }
598
- let currentResolveDir = this.config.workingDir;
599
- while (currentResolveDir) {
600
- addResolveBaseDir(currentResolveDir);
601
- const parentResolveDir = (0, node_path_1.dirname)(currentResolveDir);
602
- if (parentResolveDir === currentResolveDir) {
603
- break;
604
- }
605
- currentResolveDir = parentResolveDir;
606
- }
607
- this.manifestStepResolveBaseDirs = Array.from(resolveBaseDirs);
608
- return this.manifestStepResolveBaseDirs;
760
+ normalizeDiscoveredFilePath(filePath) {
761
+ return (0, node_path_1.isAbsolute)(filePath)
762
+ ? filePath
763
+ : (0, node_path_1.resolve)(this.config.workingDir, filePath);
609
764
  }
610
765
  async filterExistingFiles(filePaths) {
611
766
  const normalizedFilePaths = Array.from(new Set(filePaths.map((filePath) => this.normalizeDiscoveredFilePath(filePath)))).sort();
@@ -687,9 +842,62 @@ async function getNextBuilderDeferred() {
687
842
  }
688
843
  const baseDirectory = (0, node_path_1.dirname)(bundleFilePath);
689
844
  const localSourceFiles = new Set();
690
- const sourceMapMatches = bundleContents.matchAll(/\/\/# sourceMappingURL=data:application\/json[^,]*;base64,([A-Za-z0-9+/=]+)/g);
845
+ // Extract inline base64 sourcemaps via string scanning. A previous
846
+ // implementation used `bundleContents.matchAll(/...[A-Za-z0-9+/=]+.../g)`
847
+ // which overflows V8's regex stack
848
+ // (`RangeError: Maximum call stack size exceeded at RegExpStringIterator.next`)
849
+ // on bundles with large inline sourcemaps — V8's irregexp uses
850
+ // recursion for greedy character-class quantifiers and certain long
851
+ // base64 inputs exhaust the call stack.
852
+ const sourceMapPrefix = '//# sourceMappingURL=data:application/json';
853
+ const base64Marker = ';base64,';
854
+ const sourceMapMatches = [];
855
+ let scanFrom = 0;
856
+ while (scanFrom < bundleContents.length) {
857
+ const prefixIdx = bundleContents.indexOf(sourceMapPrefix, scanFrom);
858
+ if (prefixIdx === -1)
859
+ break;
860
+ const base64Start = bundleContents.indexOf(base64Marker, prefixIdx + sourceMapPrefix.length);
861
+ if (base64Start === -1) {
862
+ scanFrom = prefixIdx + sourceMapPrefix.length;
863
+ continue;
864
+ }
865
+ // Bail if a comma appears before `;base64,` — that means this
866
+ // wasn't a `data:application/json[;params];base64,...` URL after
867
+ // all (the comma would terminate the data URL parameters).
868
+ const commaBefore = bundleContents.indexOf(',', prefixIdx);
869
+ if (commaBefore !== -1 && commaBefore < base64Start) {
870
+ scanFrom = base64Start;
871
+ continue;
872
+ }
873
+ const valueStart = base64Start + base64Marker.length;
874
+ // Base64 payload terminates at first non-base64 char (newline,
875
+ // closing `*/`, etc.). Scanning a small alphabet by char is far
876
+ // cheaper than backtracking a regex over a multi-MB capture.
877
+ let valueEnd = valueStart;
878
+ while (valueEnd < bundleContents.length) {
879
+ const code = bundleContents.charCodeAt(valueEnd);
880
+ // A-Z 0x41-0x5A, a-z 0x61-0x7A, 0-9 0x30-0x39, '+' 0x2B,
881
+ // '/' 0x2F, '=' 0x3D
882
+ if (!((code >= 0x41 && code <= 0x5a) ||
883
+ (code >= 0x61 && code <= 0x7a) ||
884
+ (code >= 0x30 && code <= 0x39) ||
885
+ code === 0x2b ||
886
+ code === 0x2f ||
887
+ code === 0x3d)) {
888
+ break;
889
+ }
890
+ valueEnd++;
891
+ }
892
+ if (valueEnd > valueStart) {
893
+ sourceMapMatches.push({
894
+ base64Value: bundleContents.slice(valueStart, valueEnd),
895
+ });
896
+ }
897
+ scanFrom = valueEnd;
898
+ }
691
899
  for (const match of sourceMapMatches) {
692
- const base64Value = match[1];
900
+ const base64Value = match.base64Value;
693
901
  if (!base64Value) {
694
902
  continue;
695
903
  }
@@ -725,9 +933,12 @@ async function getNextBuilderDeferred() {
725
933
  }
726
934
  const normalizedSourcePath = this.normalizeDiscoveredFilePath(resolvedSourcePath);
727
935
  const normalizedSourcePathForCheck = normalizedSourcePath.replace(/\\/g, '/');
936
+ const isSourceBackedPackagePath = this.shouldPreferSourceBackedPackagePath(normalizedSourcePath);
728
937
  if (normalizedSourcePathForCheck.includes('/.well-known/workflow/') ||
729
- normalizedSourcePathForCheck.includes('/node_modules/') ||
730
- normalizedSourcePathForCheck.includes('/.pnpm/') ||
938
+ (!isSourceBackedPackagePath &&
939
+ normalizedSourcePathForCheck.includes('/node_modules/')) ||
940
+ (!isSourceBackedPackagePath &&
941
+ normalizedSourcePathForCheck.includes('/.pnpm/')) ||
731
942
  normalizedSourcePathForCheck.includes('/.next/') ||
732
943
  normalizedSourcePathForCheck.endsWith('/virtual-entry.js')) {
733
944
  continue;
@@ -749,9 +960,6 @@ async function getNextBuilderDeferred() {
749
960
  }, 50);
750
961
  }
751
962
  scheduleDeferredRebuild() {
752
- if (!this.config.watch) {
753
- return;
754
- }
755
963
  if (this.deferredRebuildTimer) {
756
964
  clearTimeout(this.deferredRebuildTimer);
757
965
  }
@@ -826,35 +1034,61 @@ async function getNextBuilderDeferred() {
826
1034
  ].join('\n');
827
1035
  const workflowGeneratedDir = (0, node_path_1.join)(outputDir, '.well-known/workflow/v1');
828
1036
  await (0, promises_1.mkdir)((0, node_path_1.join)(workflowGeneratedDir, 'flow'), { recursive: true });
829
- await (0, promises_1.mkdir)((0, node_path_1.join)(workflowGeneratedDir, 'step'), { recursive: true });
830
1037
  await (0, promises_1.mkdir)((0, node_path_1.join)(workflowGeneratedDir, 'webhook/[token]'), {
831
1038
  recursive: true,
832
1039
  });
833
1040
  await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, '.gitignore'), '*');
834
- // route.js stubs are replaced by generated route.js output once discovery
835
- // finishes and a deferred build completes.
1041
+ // V2: Only flow + webhook stubs needed (no separate step route).
1042
+ // Stubs are replaced by generated output once discovery finishes.
836
1043
  await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, 'flow/route.js'), routeStubContent);
837
- await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, 'step/route.js'), routeStubContent);
838
1044
  await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, 'webhook/[token]/route.js'), routeStubContent);
839
1045
  }
1046
+ async getInputFiles() {
1047
+ // Read Next.js's app-paths-manifest.json from a previous build to
1048
+ // determine which files are actual route entrypoints. This avoids
1049
+ // predicting Next.js conventions with regexes and instead reads
1050
+ // from Next.js's own output.
1051
+ const nextDir = (0, node_path_1.join)(this.config.workingDir, '.next');
1052
+ const manifestPath = (0, node_path_1.join)(nextDir, 'app-paths-manifest.json');
1053
+ try {
1054
+ const manifestContent = (0, node_fs_1.readFileSync)(manifestPath, 'utf-8');
1055
+ const manifest = JSON.parse(manifestContent);
1056
+ // The manifest maps route paths to their source files.
1057
+ // Extract the source file paths and resolve them.
1058
+ const manifestFiles = new Set();
1059
+ for (const sourcePath of Object.values(manifest)) {
1060
+ const resolved = (0, node_path_1.resolve)(nextDir, 'server', sourcePath);
1061
+ // The manifest points to built output; find the source file
1062
+ // by matching against the base builder's full file list.
1063
+ manifestFiles.add(resolved);
1064
+ }
1065
+ // Use the manifest route paths to filter the input files.
1066
+ // A file is included if it matches a known route segment from
1067
+ // the manifest (e.g., app/api/route contains 'app/api/route').
1068
+ const inputFiles = await super.getInputFiles();
1069
+ const routeSegments = Object.keys(manifest).map((route) => route.replace(/^\//, '').replace(/\/route$/, ''));
1070
+ return inputFiles.filter((item) => routeSegments.some((segment) => item.includes(segment)));
1071
+ }
1072
+ catch {
1073
+ // No manifest from a previous build — fall back to the base
1074
+ // builder's full file scan. This is safe but slower; subsequent
1075
+ // builds will use the manifest.
1076
+ return super.getInputFiles();
1077
+ }
1078
+ }
840
1079
  async writeFunctionsConfig(outputDir) {
841
1080
  // we don't run this in development mode as it's not needed
842
1081
  if (process.env.NODE_ENV === 'development') {
843
1082
  return;
844
1083
  }
1084
+ // V2: Single combined trigger handles both workflow and step execution
845
1085
  const generatedConfig = {
846
1086
  version: '0',
847
- steps: {
848
- maxDuration: 'max',
849
- experimentalTriggers: [STEP_QUEUE_TRIGGER],
850
- },
851
1087
  workflows: {
852
1088
  maxDuration: 'max',
853
1089
  experimentalTriggers: [WORKFLOW_QUEUE_TRIGGER],
854
1090
  },
855
1091
  };
856
- // We write this file to the generated directory for
857
- // the Next.js builder to consume
858
1092
  await this.writeFileIfChanged((0, node_path_1.join)(outputDir, '.well-known/workflow/v1/config.json'), JSON.stringify(generatedConfig, null, 2));
859
1093
  }
860
1094
  async writeFileIfChanged(filePath, contents) {
@@ -901,16 +1135,26 @@ async function getNextBuilderDeferred() {
901
1135
  // Manifest may not exist (e.g. manifest generation failed); ignore.
902
1136
  }
903
1137
  }
904
- mergeWorkflowManifest(target, source) {
905
- if (source.steps) {
906
- target.steps = Object.assign(target.steps || {}, source.steps);
907
- }
908
- if (source.workflows) {
909
- target.workflows = Object.assign(target.workflows || {}, source.workflows);
910
- }
911
- if (source.classes) {
912
- target.classes = Object.assign(target.classes || {}, source.classes);
1138
+ extractRelativeImportSpecifiers(source) {
1139
+ return this.extractImportSpecifiers(source).filter((specifier) => specifier.startsWith('.'));
1140
+ }
1141
+ extractImportSpecifiers(source) {
1142
+ const relativeSpecifiers = new Set();
1143
+ const importPatterns = [
1144
+ /from\s+['"]([^'"]+)['"]/g,
1145
+ /import\s+['"]([^'"]+)['"]/g,
1146
+ /import\(\s*['"]([^'"]+)['"]\s*\)/g,
1147
+ /require\(\s*['"]([^'"]+)['"]\s*\)/g,
1148
+ ];
1149
+ for (const importPattern of importPatterns) {
1150
+ for (const match of source.matchAll(importPattern)) {
1151
+ const specifier = match[1];
1152
+ if (specifier) {
1153
+ relativeSpecifiers.add(specifier);
1154
+ }
1155
+ }
913
1156
  }
1157
+ return Array.from(relativeSpecifiers);
914
1158
  }
915
1159
  async getRelativeFilenameForSwc(filePath) {
916
1160
  const workingDir = this.config.workingDir;
@@ -948,98 +1192,7 @@ async function getNextBuilderDeferred() {
948
1192
  }
949
1193
  return relativeFilename;
950
1194
  }
951
- getRelativeImportSpecifier(fromFilePath, toFilePath) {
952
- let relativePath = (0, node_path_1.relative)((0, node_path_1.dirname)(fromFilePath), toFilePath).replace(/\\/g, '/');
953
- if (!relativePath.startsWith('.')) {
954
- relativePath = `./${relativePath}`;
955
- }
956
- return relativePath;
957
- }
958
- getStepCopyFileName(filePath) {
959
- const normalizedPath = filePath.replace(/\\/g, '/');
960
- const hash = (0, node_crypto_1.createHash)('sha256').update(normalizedPath).digest('hex');
961
- const extension = (0, node_path_1.extname)(normalizedPath);
962
- return `${hash.slice(0, 16)}${extension || '.js'}`;
963
- }
964
- rewriteCopiedStepImportSpecifier(specifier, sourceFilePath, copiedFilePath, copiedStepFileBySourcePath) {
965
- if (!specifier.startsWith('.')) {
966
- // Bare specifiers (e.g. '@workflow/serde') that are transitive
967
- // dependencies of SDK packages can't be resolved by the bundler
968
- // from the copied file's location (__workflow_step_files__/ inside
969
- // the app dir) because the app doesn't directly depend on them.
970
- //
971
- // Only rewrite when the specifier can't be resolved from the app
972
- // directory. If the package is a direct dependency of the app,
973
- // the bare specifier will resolve normally and should be left as-is.
974
- const appResolvable = this.resolveBareCopiedStepSpecifier(specifier, copiedFilePath);
975
- if (!appResolvable) {
976
- const resolved = this.resolveBareCopiedStepSpecifier(specifier, sourceFilePath);
977
- if (!resolved)
978
- return specifier;
979
- let rewrittenPath = (0, node_path_1.relative)((0, node_path_1.dirname)(copiedFilePath), resolved).replace(/\\/g, '/');
980
- if (!rewrittenPath.startsWith('.')) {
981
- rewrittenPath = `./${rewrittenPath}`;
982
- }
983
- return rewrittenPath;
984
- }
985
- return specifier;
986
- }
987
- const specifierMatch = specifier.match(/^([^?#]+)(.*)$/);
988
- const importPath = specifierMatch?.[1] ?? specifier;
989
- const suffix = specifierMatch?.[2] ?? '';
990
- const absoluteTargetPath = (0, node_path_1.resolve)((0, node_path_1.dirname)(sourceFilePath), importPath);
991
- const resolvedTargetPath = this.resolveCopiedStepImportTargetPath(absoluteTargetPath);
992
- const normalizedTargetPath = resolvedTargetPath.replace(/\\/g, '/');
993
- const copiedTargetPath = copiedStepFileBySourcePath.get(normalizedTargetPath) ||
994
- (() => {
995
- try {
996
- const realTargetPath = (0, node_fs_1.realpathSync)(resolvedTargetPath).replace(/\\/g, '/');
997
- return copiedStepFileBySourcePath.get(realTargetPath);
998
- }
999
- catch {
1000
- return undefined;
1001
- }
1002
- })();
1003
- let rewrittenPath = (0, node_path_1.relative)((0, node_path_1.dirname)(copiedFilePath), copiedTargetPath || resolvedTargetPath).replace(/\\/g, '/');
1004
- if (!rewrittenPath.startsWith('.')) {
1005
- rewrittenPath = `./${rewrittenPath}`;
1006
- }
1007
- return `${rewrittenPath}${suffix}`;
1008
- }
1009
- /**
1010
- * Resolves a bare specifier (e.g. '@workflow/serde', 'workflow') to an
1011
- * absolute file path using ESM-compatible resolution semantics via
1012
- * `enhanced-resolve`. Tries ESM conditions first (`node`, `import`),
1013
- * falling back to CJS resolution if ESM fails.
1014
- */
1015
- resolveBareCopiedStepSpecifier(specifier, sourceFilePath) {
1016
- if (!this.esmSyncResolver) {
1017
- this.esmSyncResolver = enhanced_resolve_1.default.create.sync(NODE_ESM_RESOLVE_OPTIONS);
1018
- }
1019
- if (!this.cjsSyncResolver) {
1020
- this.cjsSyncResolver =
1021
- enhanced_resolve_1.default.create.sync(NODE_RESOLVE_OPTIONS);
1022
- }
1023
- const context = (0, node_path_1.dirname)(sourceFilePath);
1024
- try {
1025
- const resolved = this.esmSyncResolver(context, specifier);
1026
- if (resolved)
1027
- return resolved;
1028
- }
1029
- catch {
1030
- // ESM resolution failed, try CJS
1031
- }
1032
- try {
1033
- const resolved = this.cjsSyncResolver(context, specifier);
1034
- if (resolved)
1035
- return resolved;
1036
- }
1037
- catch {
1038
- // CJS resolution also failed
1039
- }
1040
- return undefined;
1041
- }
1042
- resolveCopiedStepImportTargetPath(targetPath) {
1195
+ resolveImportTargetWithExtensionFallbacks(targetPath) {
1043
1196
  if ((0, node_fs_1.existsSync)(targetPath)) {
1044
1197
  return targetPath;
1045
1198
  }
@@ -1069,51 +1222,38 @@ async function getNextBuilderDeferred() {
1069
1222
  }
1070
1223
  return targetPath;
1071
1224
  }
1072
- rewriteRelativeImportsForCopiedStep(source, sourceFilePath, copiedFilePath, copiedStepFileBySourcePath) {
1073
- const rewriteSpecifier = (specifier) => this.rewriteCopiedStepImportSpecifier(specifier, sourceFilePath, copiedFilePath, copiedStepFileBySourcePath);
1074
- const rewritePattern = (currentSource, pattern) => currentSource.replace(pattern, (_match, prefix, specifier, suffix) => `${prefix}${rewriteSpecifier(specifier)}${suffix}`);
1075
- let rewrittenSource = source;
1076
- rewrittenSource = rewritePattern(rewrittenSource, /(from\s+['"])([^'"]+)(['"])/g);
1077
- rewrittenSource = rewritePattern(rewrittenSource, /(import\s+['"])([^'"]+)(['"])/g);
1078
- rewrittenSource = rewritePattern(rewrittenSource, /(import\(\s*['"])([^'"]+)(['"]\s*\))/g);
1079
- rewrittenSource = rewritePattern(rewrittenSource, /(require\(\s*['"])([^'"]+)(['"]\s*\))/g);
1080
- return rewrittenSource;
1081
- }
1082
- extractRelativeImportSpecifiers(source) {
1083
- const relativeSpecifiers = new Set();
1084
- const importPatterns = [
1085
- /from\s+['"]([^'"]+)['"]/g,
1086
- /import\s+['"]([^'"]+)['"]/g,
1087
- /import\(\s*['"]([^'"]+)['"]\s*\)/g,
1088
- /require\(\s*['"]([^'"]+)['"]\s*\)/g,
1089
- ];
1090
- for (const importPattern of importPatterns) {
1091
- for (const match of source.matchAll(importPattern)) {
1092
- const specifier = match[1];
1093
- if (specifier?.startsWith('.')) {
1094
- relativeSpecifiers.add(specifier);
1095
- }
1096
- }
1097
- }
1098
- return Array.from(relativeSpecifiers);
1099
- }
1100
- isGeneratedWorkflowArtifact(filePath) {
1101
- const normalizedPath = filePath.replace(/\\/g, '/');
1102
- return (normalizedPath.includes('/.well-known/workflow/') ||
1103
- normalizedPath.includes('/.next/'));
1104
- }
1105
1225
  shouldSkipTransitiveStepFile(filePath) {
1106
1226
  const normalizedPath = filePath.replace(/\\/g, '/');
1107
- return (this.isGeneratedWorkflowArtifact(normalizedPath) ||
1108
- normalizedPath.includes('/node_modules/') ||
1109
- normalizedPath.includes('/.pnpm/'));
1227
+ const isSourceBackedPackagePath = this.shouldPreferSourceBackedPackagePath(filePath);
1228
+ return (normalizedPath.includes('/.well-known/workflow/') ||
1229
+ normalizedPath.includes('/.next/') ||
1230
+ (!isSourceBackedPackagePath &&
1231
+ (normalizedPath.includes('/node_modules/') ||
1232
+ normalizedPath.includes('/.pnpm/'))));
1110
1233
  }
1111
1234
  async resolveTransitiveStepImportTargetPath(sourceFilePath, specifier) {
1112
1235
  const specifierMatch = specifier.match(/^([^?#]+)(.*)$/);
1113
1236
  const importPath = specifierMatch?.[1] ?? specifier;
1237
+ if (!importPath.startsWith('.')) {
1238
+ if (importPath !== 'workflow' && !importPath.startsWith('@workflow/')) {
1239
+ return null;
1240
+ }
1241
+ try {
1242
+ const resolvedPath = (0, node_module_1.createRequire)(sourceFilePath).resolve(importPath);
1243
+ const normalizedResolvedPath = this.normalizeDiscoveredFilePath(resolvedPath);
1244
+ if (this.shouldSkipTransitiveStepFile(normalizedResolvedPath)) {
1245
+ return null;
1246
+ }
1247
+ const fileStats = await (0, promises_1.stat)(normalizedResolvedPath);
1248
+ return fileStats.isFile() ? normalizedResolvedPath : null;
1249
+ }
1250
+ catch {
1251
+ return null;
1252
+ }
1253
+ }
1114
1254
  const absoluteTargetPath = (0, node_path_1.resolve)((0, node_path_1.dirname)(sourceFilePath), importPath);
1115
1255
  const candidatePaths = new Set([
1116
- this.resolveCopiedStepImportTargetPath(absoluteTargetPath),
1256
+ this.resolveImportTargetWithExtensionFallbacks(absoluteTargetPath),
1117
1257
  ]);
1118
1258
  if (!(0, node_path_1.extname)(absoluteTargetPath)) {
1119
1259
  const extensionCandidates = [
@@ -1132,7 +1272,7 @@ async function getNextBuilderDeferred() {
1132
1272
  }
1133
1273
  }
1134
1274
  for (const candidatePath of candidatePaths) {
1135
- const resolvedPath = this.resolveCopiedStepImportTargetPath(candidatePath);
1275
+ const resolvedPath = this.resolveImportTargetWithExtensionFallbacks(candidatePath);
1136
1276
  const normalizedResolvedPath = this.normalizeDiscoveredFilePath(resolvedPath);
1137
1277
  if (this.shouldSkipTransitiveStepFile(normalizedResolvedPath)) {
1138
1278
  continue;
@@ -1149,13 +1289,11 @@ async function getNextBuilderDeferred() {
1149
1289
  }
1150
1290
  return null;
1151
1291
  }
1152
- async collectTransitiveStepFiles({ stepFiles, seedFiles = [], }) {
1153
- const normalizedSeedFiles = Array.from(new Set([...stepFiles, ...seedFiles].map((stepFile) => this.normalizeDiscoveredFilePath(stepFile)))).sort();
1154
- // Intentionally re-validate step seeds against current file contents
1155
- // instead of blindly trusting callers. This prevents stale/manual seed
1156
- // paths from persisting when files no longer contain "use step".
1157
- const discoveredStepFiles = new Set();
1158
- const queuedFiles = [...normalizedSeedFiles];
1292
+ async collectTransitiveStepFiles({ entryFiles, stepFiles, }) {
1293
+ const normalizedEntryFiles = Array.from(new Set(entryFiles.map((entryFile) => this.normalizeDiscoveredFilePath(entryFile)))).sort();
1294
+ const normalizedStepSeedFiles = Array.from(new Set(stepFiles.map((stepFile) => this.normalizeDiscoveredFilePath(stepFile)))).sort();
1295
+ const discoveredStepFiles = new Set(normalizedStepSeedFiles);
1296
+ const queuedFiles = Array.from(new Set([...normalizedEntryFiles, ...normalizedStepSeedFiles]));
1159
1297
  const visitedFiles = new Set();
1160
1298
  const sourceCache = new Map();
1161
1299
  const patternCache = new Map();
@@ -1196,12 +1334,8 @@ async function getNextBuilderDeferred() {
1196
1334
  if (currentSource === null) {
1197
1335
  continue;
1198
1336
  }
1199
- const currentPatterns = await getPatterns(currentFile);
1200
- if (currentPatterns?.hasUseStep) {
1201
- discoveredStepFiles.add(currentFile);
1202
- }
1203
- const relativeImportSpecifiers = this.extractRelativeImportSpecifiers(currentSource);
1204
- for (const specifier of relativeImportSpecifiers) {
1337
+ const importSpecifiers = this.extractImportSpecifiers(currentSource);
1338
+ for (const specifier of importSpecifiers) {
1205
1339
  const resolvedImportPath = await this.resolveTransitiveStepImportTargetPath(currentFile, specifier);
1206
1340
  if (!resolvedImportPath) {
1207
1341
  continue;
@@ -1298,7 +1432,7 @@ async function getNextBuilderDeferred() {
1298
1432
  return;
1299
1433
  try {
1300
1434
  const relativeFilename = await this.getRelativeFilenameForSwc(filePath);
1301
- const { workflowManifest } = await applySwcTransform(relativeFilename, source, 'detect', filePath, projectRoot);
1435
+ const { workflowManifest } = await applySwcTransform(relativeFilename, source, 'detect', filePath, projectRoot, this.moduleSpecifierRoot);
1302
1436
  // Only include files that actually define serde classes
1303
1437
  const hasClasses = workflowManifest.classes &&
1304
1438
  Object.values(workflowManifest.classes).some((entries) => Object.keys(entries).length > 0);
@@ -1313,225 +1447,6 @@ async function getNextBuilderDeferred() {
1313
1447
  }));
1314
1448
  return verifiedSerdeFiles.sort();
1315
1449
  }
1316
- async createResponseBuiltinsStepFile({ stepsRouteDir, }) {
1317
- const copiedStepsDir = (0, node_path_1.join)(stepsRouteDir, step_copy_utils_js_1.DEFERRED_STEP_COPY_DIR_NAME);
1318
- await (0, promises_1.mkdir)(copiedStepsDir, { recursive: true });
1319
- const responseBuiltinsFilePath = (0, node_path_1.join)(copiedStepsDir, 'workflow-response-builtins.ts');
1320
- const source = [
1321
- 'export async function __builtin_response_array_buffer(this: Request | Response) {',
1322
- " 'use step';",
1323
- ' return this.arrayBuffer();',
1324
- '}',
1325
- '',
1326
- 'export async function __builtin_response_json(this: Request | Response) {',
1327
- " 'use step';",
1328
- ' return this.json();',
1329
- '}',
1330
- '',
1331
- 'export async function __builtin_response_text(this: Request | Response) {',
1332
- " 'use step';",
1333
- ' return this.text();',
1334
- '}',
1335
- ].join('\n');
1336
- const sourceMapComment = (0, step_copy_utils_js_1.createDeferredStepCopyInlineSourceMapComment)({
1337
- sourcePath: responseBuiltinsFilePath,
1338
- sourceContent: source,
1339
- });
1340
- await this.writeFileIfChanged(responseBuiltinsFilePath, `${source}\n${sourceMapComment}\n`);
1341
- return responseBuiltinsFilePath;
1342
- }
1343
- async copyDiscoveredStepFiles({ stepFiles, stepsRouteDir, preserveFileNames = [], }) {
1344
- const copiedStepsDir = (0, node_path_1.join)(stepsRouteDir, step_copy_utils_js_1.DEFERRED_STEP_COPY_DIR_NAME);
1345
- await (0, promises_1.mkdir)(copiedStepsDir, { recursive: true });
1346
- const normalizedStepFiles = Array.from(new Set(stepFiles.map((stepFile) => this.normalizeDiscoveredFilePath(stepFile)))).sort();
1347
- const copiedStepFileBySourcePath = new Map();
1348
- const expectedFileNames = new Set(preserveFileNames);
1349
- const copiedStepFiles = [];
1350
- for (const normalizedStepFile of normalizedStepFiles) {
1351
- const copiedFileName = this.getStepCopyFileName(normalizedStepFile);
1352
- const copiedFilePath = (0, node_path_1.join)(copiedStepsDir, copiedFileName);
1353
- const normalizedPathKey = normalizedStepFile.replace(/\\/g, '/');
1354
- copiedStepFileBySourcePath.set(normalizedPathKey, copiedFilePath);
1355
- try {
1356
- const realPathKey = (0, node_fs_1.realpathSync)(normalizedStepFile).replace(/\\/g, '/');
1357
- copiedStepFileBySourcePath.set(realPathKey, copiedFilePath);
1358
- }
1359
- catch {
1360
- // Keep best-effort mapping when source cannot be realpath-resolved.
1361
- }
1362
- expectedFileNames.add(copiedFileName);
1363
- copiedStepFiles.push(copiedFilePath);
1364
- }
1365
- for (const normalizedStepFile of normalizedStepFiles) {
1366
- const source = await (0, promises_1.readFile)(normalizedStepFile, 'utf-8');
1367
- const copiedFilePath = copiedStepFileBySourcePath.get(normalizedStepFile.replace(/\\/g, '/'));
1368
- if (!copiedFilePath) {
1369
- continue;
1370
- }
1371
- const rewrittenSource = this.rewriteRelativeImportsForCopiedStep(source, normalizedStepFile, copiedFilePath, copiedStepFileBySourcePath);
1372
- const metadataComment = (0, step_copy_utils_js_1.createDeferredStepSourceMetadataComment)({
1373
- relativeFilename: await this.getRelativeFilenameForSwc(normalizedStepFile),
1374
- absolutePath: normalizedStepFile.replace(/\\/g, '/'),
1375
- });
1376
- const sourceMapComment = (0, step_copy_utils_js_1.createDeferredStepCopyInlineSourceMapComment)({
1377
- sourcePath: normalizedStepFile,
1378
- sourceContent: source,
1379
- generatedContent: rewrittenSource,
1380
- });
1381
- const copiedSource = `${metadataComment}\n${rewrittenSource}\n${sourceMapComment}`;
1382
- await this.writeFileIfChanged(copiedFilePath, copiedSource);
1383
- }
1384
- const existingEntries = await (0, promises_1.readdir)(copiedStepsDir, {
1385
- withFileTypes: true,
1386
- }).catch(() => []);
1387
- await Promise.all(existingEntries
1388
- .filter((entry) => !expectedFileNames.has(entry.name))
1389
- .map((entry) => (0, promises_1.rm)((0, node_path_1.join)(copiedStepsDir, entry.name), {
1390
- recursive: true,
1391
- force: true,
1392
- })));
1393
- return copiedStepFiles;
1394
- }
1395
- async createDeferredStepsManifest({ stepFiles, workflowFiles, serdeOnlyFiles, }) {
1396
- const workflowManifest = {};
1397
- const filesForStepTransform = Array.from(new Set([...stepFiles, ...serdeOnlyFiles])).sort();
1398
- await Promise.all(filesForStepTransform.map(async (stepFile) => {
1399
- const source = await (0, promises_1.readFile)(stepFile, 'utf-8');
1400
- const relativeFilename = await this.getRelativeFilenameForSwc(stepFile);
1401
- const { workflowManifest: fileManifest } = await applySwcTransform(relativeFilename, source, 'step', stepFile, this.config.projectRoot || this.config.workingDir);
1402
- this.mergeWorkflowManifest(workflowManifest, fileManifest);
1403
- }));
1404
- const stepFileSet = new Set(stepFiles);
1405
- const workflowOnlyFiles = workflowFiles
1406
- .filter((workflowFile) => !stepFileSet.has(workflowFile))
1407
- .sort();
1408
- await Promise.all(workflowOnlyFiles.map(async (workflowFile) => {
1409
- try {
1410
- const source = await (0, promises_1.readFile)(workflowFile, 'utf-8');
1411
- const relativeFilename = await this.getRelativeFilenameForSwc(workflowFile);
1412
- const { workflowManifest: fileManifest } = await applySwcTransform(relativeFilename, source, 'workflow', workflowFile, this.config.projectRoot || this.config.workingDir);
1413
- this.mergeWorkflowManifest(workflowManifest, {
1414
- workflows: fileManifest.workflows,
1415
- classes: fileManifest.classes,
1416
- });
1417
- }
1418
- catch (error) {
1419
- console.log(`Warning: Failed to extract workflow metadata from ${workflowFile}:`, error instanceof Error ? error.message : String(error));
1420
- }
1421
- }));
1422
- return workflowManifest;
1423
- }
1424
- async collectManifestStepSourceFiles(manifest) {
1425
- const manifestStepEntries = Object.keys(manifest.steps || {});
1426
- if (manifestStepEntries.length === 0) {
1427
- return [];
1428
- }
1429
- const resolveBaseDirs = this.getManifestStepResolveBaseDirs();
1430
- const candidateFiles = manifestStepEntries
1431
- .flatMap((stepEntry) => {
1432
- if ((0, node_path_1.isAbsolute)(stepEntry)) {
1433
- return [this.normalizeDiscoveredFilePath(stepEntry)];
1434
- }
1435
- return resolveBaseDirs.map((baseDir) => this.normalizeDiscoveredFilePath((0, node_path_1.resolve)(baseDir, stepEntry)));
1436
- })
1437
- .filter((candidateFile) => !this.isGeneratedWorkflowArtifact(candidateFile));
1438
- const existingCandidates = await this.filterExistingFiles(candidateFiles);
1439
- return Array.from(new Set(existingCandidates)).sort();
1440
- }
1441
- async buildStepsFunction({ workflowGeneratedDir, routeFileName = 'route.js', discoveredEntries, additionalStepSourceManifest, }) {
1442
- const stepsRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'step');
1443
- await (0, promises_1.mkdir)(stepsRouteDir, { recursive: true });
1444
- const discovered = discoveredEntries;
1445
- const workflowFiles = [...discovered.discoveredWorkflows].sort();
1446
- const stepFiles = await this.collectTransitiveStepFiles({
1447
- stepFiles: [...discovered.discoveredSteps].sort(),
1448
- // Workflow transforms can inline step IDs and remove runtime imports,
1449
- // so seed transitive traversal with workflow files too.
1450
- seedFiles: workflowFiles,
1451
- });
1452
- const serdeFiles = [...discovered.discoveredSerdeFiles].sort();
1453
- const stepFileSet = new Set(stepFiles);
1454
- const serdeOnlyFiles = serdeFiles.filter((file) => !stepFileSet.has(file));
1455
- const additionalManifestStepFiles = additionalStepSourceManifest
1456
- ? await this.collectManifestStepSourceFiles(additionalStepSourceManifest)
1457
- : [];
1458
- const stepFilesWithManifestSources = Array.from(new Set([...stepFiles, ...additionalManifestStepFiles])).sort();
1459
- const responseBuiltinsStepFilePath = await this.createResponseBuiltinsStepFile({
1460
- stepsRouteDir,
1461
- });
1462
- const manifestStepFiles = Array.from(new Set([...stepFilesWithManifestSources, responseBuiltinsStepFilePath])).sort();
1463
- const manifest = await this.createDeferredStepsManifest({
1464
- stepFiles: manifestStepFiles,
1465
- workflowFiles,
1466
- serdeOnlyFiles,
1467
- });
1468
- const manifestDiscoveredStepFiles = await this.collectManifestStepSourceFiles(manifest);
1469
- // Copy all discovered step sources so they are transformed in step mode.
1470
- // Importing raw node_modules files directly can bypass loader transforms,
1471
- // which prevents step registrars from being emitted.
1472
- const copiedStepSourceFiles = Array.from(new Set([
1473
- ...stepFilesWithManifestSources,
1474
- ...manifestDiscoveredStepFiles,
1475
- ])).sort();
1476
- const copiedDiscoveredStepFiles = await this.copyDiscoveredStepFiles({
1477
- stepFiles: copiedStepSourceFiles,
1478
- stepsRouteDir,
1479
- preserveFileNames: [(0, node_path_1.basename)(responseBuiltinsStepFilePath)],
1480
- });
1481
- const copiedStepFiles = [
1482
- responseBuiltinsStepFilePath,
1483
- ...copiedDiscoveredStepFiles,
1484
- ];
1485
- const stepRouteFile = (0, node_path_1.join)(stepsRouteDir, routeFileName);
1486
- const copiedStepImports = copiedStepFiles
1487
- .map((copiedStepFile) => {
1488
- const importSpecifier = this.getRelativeImportSpecifier(stepRouteFile, copiedStepFile);
1489
- return `import '${importSpecifier}';`;
1490
- })
1491
- .join('\n');
1492
- const serdeImports = serdeOnlyFiles
1493
- .map((serdeFile) => {
1494
- const normalizedSerdeFile = this.normalizeDiscoveredFilePath(serdeFile);
1495
- const { importPath, isPackage } = getImportPath(normalizedSerdeFile, this.config.workingDir);
1496
- if (isPackage) {
1497
- return `import '${importPath}';`;
1498
- }
1499
- const importSpecifier = this.getRelativeImportSpecifier(stepRouteFile, normalizedSerdeFile);
1500
- return `import '${importSpecifier}';`;
1501
- })
1502
- .join('\n');
1503
- const routeContents = [
1504
- '// biome-ignore-all lint: generated file',
1505
- '/* eslint-disable */',
1506
- copiedStepImports,
1507
- serdeImports
1508
- ? `// Serde files for cross-context class registration\n${serdeImports}`
1509
- : '',
1510
- "export { stepEntrypoint as POST } from 'workflow/runtime';",
1511
- ]
1512
- .filter(Boolean)
1513
- .join('\n');
1514
- await this.writeFileIfChanged(stepRouteFile, routeContents);
1515
- return {
1516
- context: undefined,
1517
- manifest,
1518
- };
1519
- }
1520
- async buildWorkflowsFunction({ inputFiles, workflowGeneratedDir, tsconfigPath, routeFileName = 'route.js', discoveredEntries, }) {
1521
- const workflowsRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'flow');
1522
- await (0, promises_1.mkdir)(workflowsRouteDir, { recursive: true });
1523
- return await this.createWorkflowsBundle({
1524
- format: 'esm',
1525
- outfile: (0, node_path_1.join)(workflowsRouteDir, routeFileName),
1526
- bundleFinalOutput: false,
1527
- // Deferred builds do not reuse the interim esbuild context. Dispose it
1528
- // after each pass to avoid leaking contexts during watch-mode rebuilds.
1529
- keepInterimBundleContext: false,
1530
- inputFiles,
1531
- tsconfigPath,
1532
- discoveredEntries,
1533
- });
1534
- }
1535
1450
  async buildWebhookRoute({ workflowGeneratedDir, routeFileName = 'route.js', }) {
1536
1451
  const webhookRouteFile = (0, node_path_1.join)(workflowGeneratedDir, `webhook/[token]/${routeFileName}`);
1537
1452
  await this.createWebhookBundle({
@@ -1586,4 +1501,4 @@ async function getNextBuilderDeferred() {
1586
1501
  CachedNextBuilderDeferred = NextDeferredBuilder;
1587
1502
  return NextDeferredBuilder;
1588
1503
  }
1589
- //# sourceMappingURL=builder-deferred.js.map
1504
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGRlci1kZWZlcnJlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9idWlsZGVyLWRlZmVycmVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBeUNBLHdEQWlpRUM7QUExa0VELDZDQUF5QztBQUN6QyxxQ0FBOEQ7QUFDOUQsK0NBUzBCO0FBQzFCLDZDQUE0QztBQUM1QyxzREFBeUI7QUFDekIseUNBUW1CO0FBRW5CLHlEQU00QjtBQUU1QixNQUFNLHNCQUFzQixHQUFHLDBCQUEwQixDQUFDO0FBQzFELE1BQU0sNEJBQTRCLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztBQUM5QyxNQUFNLDBCQUEwQixHQUFHLHFCQUFxQixDQUFDO0FBRXpELElBQUkseUJBQThCLENBQUM7QUFFbkMsaUZBQWlGO0FBQ2pGLGdGQUFnRjtBQUNoRixvRUFBb0U7QUFDN0QsS0FBSyxVQUFVLHNCQUFzQjtJQUMxQyxJQUFJLHlCQUF5QixFQUFFLENBQUM7UUFDOUIsT0FBTyx5QkFBeUIsQ0FBQztJQUNuQyxDQUFDO0lBRUQsNkRBQTZEO0lBQzdELDRFQUE0RTtJQUM1RSwyRUFBMkU7SUFDM0UsK0VBQStFO0lBQy9FLDJFQUEyRTtJQUMzRSx5Q0FBeUM7SUFDekMsTUFBTSxFQUNKLFdBQVcsRUFBRSxnQkFBZ0IsRUFDN0Isc0JBQXNCLEVBQ3RCLG1DQUFtQyxFQUNuQyxzQkFBc0IsRUFDdEIsaUJBQWlCLEVBQ2pCLGFBQWEsRUFDYixnQ0FBZ0M7SUFDaEMsNElBQTRJO01BQzdJLEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FDYiw4QkFBOEIsQ0FDL0IsQ0FBd0MsQ0FBQztJQUUxQyxNQUFNLG1CQUFvQixTQUFRLGdCQUFnQjtRQUN4QyxRQUFRLENBQVk7UUFDWCx1QkFBdUIsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQzVDLG1CQUFtQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDeEMsb0JBQW9CLEdBQUcsSUFBSSxHQUFHLEVBQVUs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QUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUM7d0JBQ2hFLE1BQU0sQ0FBQyxDQUFDO29CQUNWLENBQUM7b0JBQ0QsT0FBTyxLQUFLLENBQUM7Z0JBQ2YsQ0FBQztZQUNILENBQUMsQ0FBQztZQUVGLGdDQUFnQztZQUNoQyxJQUFJLE1BQU0sV0FBVyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQzlCLE9BQU8sTUFBTSxDQUFDO1lBQ2hCLENBQUM7WUFFRCxvQ0FBb0M7WUFDcEMsSUFBSSxNQUFNLFdBQVcsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUNqQyxPQUFPLFNBQVMsQ0FBQztZQUNuQixDQUFDO1lBRUQsa0ZBQWtGO1lBQ2xGLElBQUksTUFBTSxXQUFXLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztnQkFDaEMsK0NBQStDO2dCQUMvQyxNQUFNLElBQUEsZ0JBQUssRUFBQyxNQUFNLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztnQkFDekMsT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQztZQUVELElBQUksTUFBTSxXQUFXLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztnQkFDbkMsdURBQXVEO2dCQUN2RCxNQUFNLElBQUEsZ0JBQUssRUFBQyxTQUFTLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztnQkFDNUMsT0FBTyxTQUFTLENBQUM7WUFDbkIsQ0FBQztZQUVELE1BQU0sSUFBSSxLQUFLLENBQ2IscUhBQXFILENBQ3RILENBQUM7UUFDSixDQUFDO0tBQ0Y7SUFFRCx5QkFBeUIsR0FBRyxtQkFBbUIsQ0FBQztJQUNoRCxPQUFPLG1CQUFtQixDQUFDO0FBQzdCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0IHsgY29uc3RhbnRzLCBleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMgfSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7XG4gIGFjY2VzcyxcbiAgbWtkaXIsXG4gIG9wZW4sXG4gIHJlYWRkaXIsXG4gIHJlYWRGaWxlLFxuICBybSxcbiAgc3RhdCxcbiAgd3JpdGVGaWxlLFxufSBmcm9tICdub2RlOmZzL3Byb21pc2VzJztcbmltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tICdub2RlOm1vZHVsZSc7XG5pbXBvcnQgb3MgZnJvbSAnbm9kZTpvcyc7XG5pbXBvcnQge1xuICBiYXNlbmFtZSxcbiAgZGlybmFtZSxcbiAgZXh0bmFtZSxcbiAgaXNBYnNvbHV0ZSxcbiAgam9pbixcbiAgcmVsYXRpdmUsXG4gIHJlc29sdmUsXG59IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgdHlwZSB7IFdvcmtmbG93TWFuaWZlc3QgfSBmcm9tICdAd29ya2Zsb3cvYnVpbGRlcnMnO1xuaW1wb3J0IHtcbiAgY2xlYW51cFN0YWxlU29ja2V0SW5mb0ZpbGVzLFxuICBjcmVhdGVTb2NrZXRTZXJ2ZXIsXG4gIFNPQ0tFVF9JTkZPX0ZJTEVOQU1FLFxuICB0eXBlIFNvY2tldElPLFxuICB0eXBlIFNvY2tldFNlcnZlckNvbmZpZyxcbn0gZnJvbSAnLi9zb2NrZXQtc2VydmVyLmpzJztcblxuY29uc3QgUk9VVEVfU1RVQl9GSUxFX01BUktFUiA9ICdXT1JLRkxPV19ST1VURV9TVFVCX0ZJTEUnO1xuY29uc3QgUk9VVEVfU1RVQl9NQVJLRVJfU0NBTl9CWVRFUyA9IDQgKiAxMDI0O1xuY29uc3QgREVWX1dPUktGTE9XX0NPREVfRklMRU5BTUUgPSAnX193b3JrZmxvd19jb2RlLnR4dCc7XG5cbmxldCBDYWNoZWROZXh0QnVpbGRlckRlZmVycmVkOiBhbnk7XG5cbi8vIENyZWF0ZSB0aGUgZGVmZXJyZWQgTmV4dCBidWlsZGVyIGR5bmFtaWNhbGx5IGJ5IGV4dGVuZGluZyB0aGUgRVNNIEJhc2VCdWlsZGVyLlxuLy8gRXhwb3J0ZWQgYXMgZ2V0TmV4dEJ1aWxkZXJEZWZlcnJlZCgpIHRvIGFsbG93IENvbW1vbkpTIG1vZHVsZXMgdG8gaW1wb3J0IGZyb21cbi8vIHRoZSBFU00gQHdvcmtmbG93L2J1aWxkZXJzIHBhY2thZ2UgdmlhIGR5bmFtaWMgaW1wb3J0IGF0IHJ1bnRpbWUuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0TmV4dEJ1aWxkZXJEZWZlcnJlZCgpIHtcbiAgaWYgKENhY2hlZE5leHRCdWlsZGVyRGVmZXJyZWQpIHtcbiAgICByZXR1cm4gQ2FjaGVkTmV4dEJ1aWxkZXJEZWZlcnJlZDtcbiAgfVxuXG4gIC8vIFYyOiBTVEVQX1FVRVVFX1RSSUdHRVIgYW5kIGVuaGFuY2VkLXJlc29sdmUgaW5mcmFzdHJ1Y3R1cmVcbiAgLy8gd2VyZSByZW1vdmVkIGJlY2F1c2UgdGhlIFYyIGNvbWJpbmVkIGhhbmRsZXIgZWxpbWluYXRlcyB0aGUgc2VwYXJhdGUgc3RlcFxuICAvLyByb3V0ZS90b3BpYy4gVGhlIHN0ZXAgY29weSBpbXBvcnQgcmV3cml0aW5nIChnZXRSZWxhdGl2ZUltcG9ydFNwZWNpZmllcixcbiAgLy8gZ2V0U3RlcENvcHlGaWxlTmFtZSwgcmV3cml0ZVJlbGF0aXZlSW1wb3J0c0ZvckNvcGllZFN0ZXApIGZyb20gbWFpbiB3YXMgYWxzb1xuICAvLyByZW1vdmVkIOKAlCBWMiBkb2Vzbid0IHVzZSBzdGVwIGNvcGllcy4gSWYgc3RlcCBjb3B5IHN1cHBvcnQgaXMgbmVlZGVkLCBpdFxuICAvLyBzaG91bGQgbGFuZCBhcyBhIGNvbXBsZXRlIGZlYXR1cmUgc2V0LlxuICBjb25zdCB7XG4gICAgQmFzZUJ1aWxkZXI6IEJhc2VCdWlsZGVyQ2xhc3MsXG4gICAgV09SS0ZMT1dfUVVFVUVfVFJJR0dFUixcbiAgICBjcmVhdGVXb3JrZmxvd0VudHJ5cG9pbnRPcHRpb25zQ29kZSxcbiAgICBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zLFxuICAgIGFwcGx5U3djVHJhbnNmb3JtLFxuICAgIGdldEltcG9ydFBhdGgsXG4gICAgcmVzb2x2ZVdvcmtmbG93QWxpYXNSZWxhdGl2ZVBhdGgsXG4gICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc2VjdXJpdHkvbm9HbG9iYWxFdmFsOiBOZWVkIHRvIHVzZSBldmFsIGhlcmUgdG8gYXZvaWQgVHlwZVNjcmlwdCBmcm9tIHRyYW5zcGlsaW5nIHRoZSBpbXBvcnQgc3RhdGVtZW50IGludG8gYHJlcXVpcmUoKWBcbiAgfSA9IChhd2FpdCBldmFsKFxuICAgICdpbXBvcnQoXCJAd29ya2Zsb3cvYnVpbGRlcnNcIiknXG4gICkpIGFzIHR5cGVvZiBpbXBvcnQoJ0B3b3JrZmxvdy9idWlsZGVycycpO1xuXG4gIGNsYXNzIE5leHREZWZlcnJlZEJ1aWxkZXIgZXh0ZW5kcyBCYXNlQnVpbGRlckNsYXNzIHtcbiAgICBwcml2YXRlIHNvY2tldElPPzogU29ja2V0SU87XG4gICAgcHJpdmF0ZSByZWFkb25seSBkaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZGlzY292ZXJlZFN0ZXBGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZGlzY292ZXJlZFNlcmRlRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBwcml2YXRlIHRyYWNrZWREZXBlbmRlbmN5RmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBwcml2YXRlIGRlZmVycmVkQnVpbGRRdWV1ZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIHByaXZhdGUgY2FjaGVJbml0aWFsaXplZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgY2FjaGVXcml0ZVRpbWVyOiBOb2RlSlMuVGltZW91dCB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgZGVmZXJyZWRSZWJ1aWxkVGltZXI6IE5vZGVKUy5UaW1lb3V0IHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBsYXN0RGVmZXJyZWRCdWlsZFNpZ25hdHVyZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICBhc3luYyBidWlsZCgpIHtcbiAgICAgIGNvbnN0IG91dHB1dERpciA9IGF3YWl0IHRoaXMuZmluZEFwcERpcmVjdG9yeSgpO1xuXG4gICAgICBhd2FpdCB0aGlzLmluaXRpYWxpemVEaXNjb3ZlcnlTdGF0ZSgpO1xuICAgICAgYXdhaXQgdGhpcy5jbGVhbnVwR2VuZXJhdGVkQXJ0aWZhY3RzT25Cb290KG91dHB1dERpcik7XG5cbiAgICAgIGF3YWl0IHRoaXMud3JpdGVTdHViRmlsZXMob3V0cHV0RGlyKTtcbiAgICAgIGF3YWl0IHRoaXMuY3JlYXRlRGlzY292ZXJ5U29ja2V0U2VydmVyKCk7XG4gICAgfVxuXG4gICAgYXN5bmMgb25CZWZvcmVEZWZlcnJlZEVudHJpZXMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBhd2FpdCB0aGlzLmluaXRpYWxpemVEaXNjb3ZlcnlTdGF0ZSgpO1xuICAgICAgYXdhaXQgdGhpcy52YWxpZGF0ZURpc2NvdmVyZWRFbnRyeUZpbGVzKCk7XG4gICAgICBjb25zdCBpbXBsaWNpdFN0ZXBGaWxlcyA9IGF3YWl0IHRoaXMucmVzb2x2ZUltcGxpY2l0U3RlcEZpbGVzKCk7XG5cbiAgICAgIGNvbnN0IHBlbmRpbmdCdWlsZCA9IHRoaXMuZGVmZXJyZWRCdWlsZFF1ZXVlLnRoZW4oKCkgPT5cbiAgICAgICAgdGhpcy5idWlsZERlZmVycmVkRW50cmllc1VudGlsU3RhYmxlKGltcGxpY2l0U3RlcEZpbGVzKVxuICAgICAgKTtcblxuICAgICAgLy8gS2VlcCB0aGUgcXVldWUgY2hhaW4gYWxpdmUgZXZlbiB3aGVuIHRoZSBjdXJyZW50IGJ1aWxkIGZhaWxzIHNvIGZ1dHVyZVxuICAgICAgLy8gY2FsbGJhY2tzIGNhbiBlbnF1ZXVlIGFub3RoZXIgYXR0ZW1wdCB3aXRob3V0IHRyaWdnZXJpbmcgdW5oYW5kbGVkXG4gICAgICAvLyByZWplY3Rpb24gd2FybmluZ3MuXG4gICAgICB0aGlzLmRlZmVycmVkQnVpbGRRdWV1ZSA9IHBlbmRpbmdCdWlsZC5jYXRjaCgoKSA9PiB7XG4gICAgICAgIC8vIEVycm9yIGlzIHN1cmZhY2VkIHRocm91Z2ggYHBlbmRpbmdCdWlsZGAgYmVsb3cuXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgcGVuZGluZ0J1aWxkO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Q3VycmVudElucHV0RmlsZXMoaW1wbGljaXRTdGVwRmlsZXM6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuICAgICAgcmV0dXJuIEFycmF5LmZyb20oXG4gICAgICAgIG5ldyBTZXQoW1xuICAgICAgICAgIC4uLnRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMsXG4gICAgICAgICAgLi4udGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLFxuICAgICAgICAgIC4uLnRoaXMuZGlzY292ZXJlZFNlcmRlRmlsZXMsXG4gICAgICAgICAgLi4uaW1wbGljaXRTdGVwRmlsZXMsXG4gICAgICAgIF0pXG4gICAgICApLnNvcnQoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGJ1aWxkRGVmZXJyZWRFbnRyaWVzVW50aWxTdGFibGUoXG4gICAgICBpbXBsaWNpdFN0ZXBGaWxlczogc3RyaW5nW11cbiAgICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIC8vIEEgc3VjY2Vzc2Z1bCBidWlsZCBjYW4gZGlzY292ZXIgYWRkaXRpb25hbCB0cmFuc2l0aXZlIGRlcGVuZGVuY3kgZmlsZXNcbiAgICAgIC8vICh2aWEgc291cmNlIG1hcHMpLCB3aGljaCBjaGFuZ2VzIHRoZSBzaWduYXR1cmUgYW5kIG1heSByZXF1aXJlIG9uZSBtb3JlXG4gICAgICAvLyBidWlsZCBwYXNzIHRvIGluY2x1ZGUgbmV3bHkgZGlzY292ZXJlZCBzZXJkZSBmaWxlcy5cbiAgICAgIGNvbnN0IG1heEJ1aWxkUGFzc2VzID0gMztcblxuICAgICAgZm9yIChsZXQgYnVpbGRQYXNzID0gMDsgYnVpbGRQYXNzIDwgbWF4QnVpbGRQYXNzZXM7IGJ1aWxkUGFzcysrKSB7XG4gICAgICAgIGNvbnN0IGlucHV0RmlsZXMgPSB0aGlzLmdldEN1cnJlbnRJbnB1dEZpbGVzKGltcGxpY2l0U3RlcEZpbGVzKTtcbiAgICAgICAgY29uc3QgYnVpbGRTaWduYXR1cmUgPVxuICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlRGVmZXJyZWRCdWlsZFNpZ25hdHVyZShpbnB1dEZpbGVzKTtcbiAgICAgICAgY29uc3Qgc2hvdWxkRm9yY2VCdWlsZEZvckdlbmVyYXRlZFJvdXRlcyA9XG4gICAgICAgICAgYXdhaXQgdGhpcy5zaG91bGRGb3JjZUJ1aWxkRm9yR2VuZXJhdGVkUm91dGVzKCk7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBidWlsZFNpZ25hdHVyZSA9PT0gdGhpcy5sYXN0RGVmZXJyZWRCdWlsZFNpZ25hdHVyZSAmJlxuICAgICAgICAgICFzaG91bGRGb3JjZUJ1aWxkRm9yR2VuZXJhdGVkUm91dGVzXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5idWlsZERpc2NvdmVyZWRGaWxlcyhpbnB1dEZpbGVzLCBpbXBsaWNpdFN0ZXBGaWxlcyk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgaWYgKHRoaXMuY29uZmlnLndhdGNoKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnZhbGlkYXRlRGlzY292ZXJlZEVudHJ5RmlsZXMoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlY292ZXJlZElucHV0RmlsZXMgPVxuICAgICAgICAgICAgICB0aGlzLmdldEN1cnJlbnRJbnB1dEZpbGVzKGltcGxpY2l0U3RlcEZpbGVzKTtcbiAgICAgICAgICAgIGNvbnN0IHJlY292ZXJlZFNpZ25hdHVyZSA9XG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlRGVmZXJyZWRCdWlsZFNpZ25hdHVyZShyZWNvdmVyZWRJbnB1dEZpbGVzKTtcbiAgICAgICAgICAgIGlmIChyZWNvdmVyZWRTaWduYXR1cmUgIT09IGJ1aWxkU2lnbmF0dXJlKSB7XG4gICAgICAgICAgICAgIC8vIEEgZmlsZSB3YXMgYWRkZWQvcmVtb3ZlZCB3aGlsZSB0aGlzIGJ1aWxkIHdhcyBydW5uaW5nOyByZXRyeVxuICAgICAgICAgICAgICAvLyBpbW1lZGlhdGVseSB3aXRoIHRoZSByZWZyZXNoZWQgZGlzY292ZXJlZC1lbnRyeSBzdGF0ZS5cbiAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICdbd29ya2Zsb3ddIERlZmVycmVkIGVudHJpZXMgYnVpbGQgZmFpbGVkLiBXaWxsIHJldHJ5IG9ubHkgYWZ0ZXIgaW5wdXRzIGNoYW5nZS4nLFxuICAgICAgICAgICAgICBlcnJvclxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMubGFzdERlZmVycmVkQnVpbGRTaWduYXR1cmUgPSBidWlsZFNpZ25hdHVyZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMubGFzdERlZmVycmVkQnVpbGRTaWduYXR1cmUgPSBidWlsZFNpZ25hdHVyZTtcblxuICAgICAgICBpZiAoIXRoaXMuY29uZmlnLndhdGNoKSB7XG4gICAgICAgICAgLy8gUHJvZHVjdGlvbiBidWlsZHMgY2FuIHBlcnNpc3QgbmV3bHkgZGlzY292ZXJlZCBkZWZlcnJlZC1lbnRyeSBmaWxlcyB0b1xuICAgICAgICAgIC8vIHRoZSBjYWNoZSBhZnRlciB0aGUgZmlyc3QgcGFzcyBjb21wbGV0ZXMuIFJlbG9hZCB0aGF0IGNhY2hlIGJlZm9yZSB3ZVxuICAgICAgICAgIC8vIGRlY2lkZSB3aGV0aGVyIHRoZSBpbnB1dCBzaWduYXR1cmUgc3RhYmlsaXplZCBzbyBzdGFnZWQgdGFyYmFsbCBidWlsZHNcbiAgICAgICAgICAvLyBjYW4gaW1tZWRpYXRlbHkgcmVwbGF5IHdpdGggdGhlIGV4cGFuZGVkIHN0ZXAgc2V0LlxuICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDI1MCkpO1xuICAgICAgICAgIGF3YWl0IHRoaXMubG9hZFdvcmtmbG93c0NhY2hlKCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwb3N0QnVpbGRJbnB1dEZpbGVzID1cbiAgICAgICAgICB0aGlzLmdldEN1cnJlbnRJbnB1dEZpbGVzKGltcGxpY2l0U3RlcEZpbGVzKTtcbiAgICAgICAgY29uc3QgcG9zdEJ1aWxkU2lnbmF0dXJlID1cbiAgICAgICAgICBhd2FpdCB0aGlzLmNyZWF0ZURlZmVycmVkQnVpbGRTaWduYXR1cmUocG9zdEJ1aWxkSW5wdXRGaWxlcyk7XG4gICAgICAgIGlmIChwb3N0QnVpbGRTaWduYXR1cmUgPT09IGJ1aWxkU2lnbmF0dXJlKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgJ1t3b3JrZmxvd10gRGVmZXJyZWQgZW50cmllcyBidWlsZCBzaWduYXR1cmUgZGlkIG5vdCBzdGFiaWxpemUgYWZ0ZXIgMyBwYXNzZXMuJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJlc29sdmVJbXBsaWNpdFN0ZXBGaWxlcygpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICBjb25zdCB3b3JrZmxvd1N0ZGxpYlBhdGggPSB0aGlzLnJlc29sdmVXb3JrZmxvd1N0ZGxpYlN0ZXBGaWxlUGF0aCgpO1xuICAgICAgcmV0dXJuIHdvcmtmbG93U3RkbGliUGF0aCA/IFt3b3JrZmxvd1N0ZGxpYlBhdGhdIDogW107XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBzaG91bGRGb3JjZUJ1aWxkRm9yR2VuZXJhdGVkUm91dGVzKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgY29uc3Qgb3V0cHV0RGlyID0gYXdhaXQgdGhpcy5maW5kQXBwRGlyZWN0b3J5KCk7XG4gICAgICBjb25zdCBnZW5lcmF0ZWRSb3V0ZUZpbGVzID0gW1xuICAgICAgICBqb2luKG91dHB1dERpciwgJy53ZWxsLWtub3duL3dvcmtmbG93L3YxL2Zsb3cvcm91dGUuanMnKSxcbiAgICAgICAgam9pbihvdXRwdXREaXIsICcud2VsbC1rbm93bi93b3JrZmxvdy92MS93ZWJob29rL1t0b2tlbl0vcm91dGUuanMnKSxcbiAgICAgIF07XG5cbiAgICAgIGZvciAoY29uc3Qgcm91dGVGaWxlUGF0aCBvZiBnZW5lcmF0ZWRSb3V0ZUZpbGVzKSB7XG4gICAgICAgIGNvbnN0IHJvdXRlU3RhdGUgPSBhd2FpdCB0aGlzLmdldEdlbmVyYXRlZFJvdXRlU3RhdGUocm91dGVGaWxlUGF0aCk7XG4gICAgICAgIGlmIChyb3V0ZVN0YXRlID09PSAnbWlzc2luZycgfHwgcm91dGVTdGF0ZSA9PT0gJ3N0dWInKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZ2V0R2VuZXJhdGVkUm91dGVTdGF0ZShcbiAgICAgIHJvdXRlRmlsZVBhdGg6IHN0cmluZ1xuICAgICk6IFByb21pc2U8J21pc3NpbmcnIHwgJ3N0dWInIHwgJ2dlbmVyYXRlZCc+IHtcbiAgICAgIGxldCByb3V0ZVN0YXRzOiBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIHN0YXQ+PjtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJvdXRlU3RhdHMgPSBhd2FpdCBzdGF0KHJvdXRlRmlsZVBhdGgpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiAnbWlzc2luZyc7XG4gICAgICB9XG4gICAgICBpZiAoIXJvdXRlU3RhdHMuaXNGaWxlKCkpIHtcbiAgICAgICAgcmV0dXJuICdtaXNzaW5nJztcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3Qgcm91dGVGaWxlSGFuZGxlID0gYXdhaXQgb3Blbihyb3V0ZUZpbGVQYXRoLCAncicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IG1hcmtlclNjYW5CdWZmZXIgPSBCdWZmZXIuYWxsb2MoUk9VVEVfU1RVQl9NQVJLRVJfU0NBTl9CWVRFUyk7XG4gICAgICAgICAgY29uc3QgeyBieXRlc1JlYWQgfSA9IGF3YWl0IHJvdXRlRmlsZUhhbmRsZS5yZWFkKFxuICAgICAgICAgICAgbWFya2VyU2NhbkJ1ZmZlcixcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICBST1VURV9TVFVCX01BUktFUl9TQ0FOX0JZVEVTLFxuICAgICAgICAgICAgMFxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgbWFya2VyU2NhblNvdXJjZSA9IG1hcmtlclNjYW5CdWZmZXIudG9TdHJpbmcoXG4gICAgICAgICAgICAndXRmOCcsXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgYnl0ZXNSZWFkXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4gbWFya2VyU2NhblNvdXJjZS5pbmNsdWRlcyhST1VURV9TVFVCX0ZJTEVfTUFSS0VSKVxuICAgICAgICAgICAgPyAnc3R1YidcbiAgICAgICAgICAgIDogJ2dlbmVyYXRlZCc7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgYXdhaXQgcm91dGVGaWxlSGFuZGxlLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gJ21pc3NpbmcnO1xuICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcmVzb2x2ZVdvcmtmbG93U3RkbGliU3RlcEZpbGVQYXRoKCk6IHN0cmluZyB8IG51bGwge1xuICAgICAgbGV0IHdvcmtmbG93Q2pzRW50cnk6IHN0cmluZztcbiAgICAgIHRyeSB7XG4gICAgICAgIHdvcmtmbG93Q2pzRW50cnkgPSByZXF1aXJlLnJlc29sdmUoJ3dvcmtmbG93Jywge1xuICAgICAgICAgIHBhdGhzOiBbdGhpcy5jb25maWcud29ya2luZ0Rpcl0sXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB3b3JrZmxvd0Rpc3REaXIgPSBkaXJuYW1lKHdvcmtmbG93Q2pzRW50cnkpO1xuICAgICAgY29uc3Qgd29ya2Zsb3dTdGRsaWJQYXRoID0gdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoXG4gICAgICAgIGpvaW4od29ya2Zsb3dEaXN0RGlyLCAnc3RkbGliLmpzJylcbiAgICAgICk7XG4gICAgICByZXR1cm4gZXhpc3RzU3luYyh3b3JrZmxvd1N0ZGxpYlBhdGgpID8gd29ya2Zsb3dTdGRsaWJQYXRoIDogbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJlY29uY2lsZURpc2NvdmVyZWRFbnRyaWVzKHtcbiAgICAgIHdvcmtmbG93Q2FuZGlkYXRlcyxcbiAgICAgIHN0ZXBDYW5kaWRhdGVzLFxuICAgICAgc2VyZGVDYW5kaWRhdGVzLFxuICAgICAgdmFsaWRhdGVQYXR0ZXJucyxcbiAgICB9OiB7XG4gICAgICB3b3JrZmxvd0NhbmRpZGF0ZXM6IEl0ZXJhYmxlPHN0cmluZz47XG4gICAgICBzdGVwQ2FuZGlkYXRlczogSXRlcmFibGU8c3RyaW5nPjtcbiAgICAgIHNlcmRlQ2FuZGlkYXRlcz86IEl0ZXJhYmxlPHN0cmluZz47XG4gICAgICB2YWxpZGF0ZVBhdHRlcm5zOiBib29sZWFuO1xuICAgIH0pOiBQcm9taXNlPHtcbiAgICAgIHdvcmtmbG93RmlsZXM6IFNldDxzdHJpbmc+O1xuICAgICAgc3RlcEZpbGVzOiBTZXQ8c3RyaW5nPjtcbiAgICAgIHNlcmRlRmlsZXM6IFNldDxzdHJpbmc+O1xuICAgIH0+IHtcbiAgICAgIGNvbnN0IGNhbmRpZGF0ZXNCeUZpbGUgPSBuZXcgTWFwPFxuICAgICAgICBzdHJpbmcsXG4gICAgICAgIHtcbiAgICAgICAgICBoYXNXb3JrZmxvd0NhbmRpZGF0ZTogYm9vbGVhbjtcbiAgICAgICAgICBoYXNTdGVwQ2FuZGlkYXRlOiBib29sZWFuO1xuICAgICAgICAgIGhhc1NlcmRlQ2FuZGlkYXRlOiBib29sZWFuO1xuICAgICAgICB9XG4gICAgICA+KCk7XG5cbiAgICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2Ygd29ya2Zsb3dDYW5kaWRhdGVzKSB7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoZmlsZVBhdGgpO1xuICAgICAgICBjb25zdCBleGlzdGluZyA9IGNhbmRpZGF0ZXNCeUZpbGUuZ2V0KG5vcm1hbGl6ZWRQYXRoKTtcbiAgICAgICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICAgICAgZXhpc3RpbmcuaGFzV29ya2Zsb3dDYW5kaWRhdGUgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbmRpZGF0ZXNCeUZpbGUuc2V0KG5vcm1hbGl6ZWRQYXRoLCB7XG4gICAgICAgICAgICBoYXNXb3JrZmxvd0NhbmRpZGF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIGhhc1N0ZXBDYW5kaWRhdGU6IGZhbHNlLFxuICAgICAgICAgICAgaGFzU2VyZGVDYW5kaWRhdGU6IGZhbHNlLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2Ygc3RlcENhbmRpZGF0ZXMpIHtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFBhdGggPSB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChmaWxlUGF0aCk7XG4gICAgICAgIGNvbnN0IGV4aXN0aW5nID0gY2FuZGlkYXRlc0J5RmlsZS5nZXQobm9ybWFsaXplZFBhdGgpO1xuICAgICAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgICAgICBleGlzdGluZy5oYXNTdGVwQ2FuZGlkYXRlID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjYW5kaWRhdGVzQnlGaWxlLnNldChub3JtYWxpemVkUGF0aCwge1xuICAgICAgICAgICAgaGFzV29ya2Zsb3dDYW5kaWRhdGU6IGZhbHNlLFxuICAgICAgICAgICAgaGFzU3RlcENhbmRpZGF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIGhhc1NlcmRlQ2FuZGlkYXRlOiBmYWxzZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoc2VyZGVDYW5kaWRhdGVzKSB7XG4gICAgICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2Ygc2VyZGVDYW5kaWRhdGVzKSB7XG4gICAgICAgICAgY29uc3Qgbm9ybWFsaXplZFBhdGggPSB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChmaWxlUGF0aCk7XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBjYW5kaWRhdGVzQnlGaWxlLmdldChub3JtYWxpemVkUGF0aCk7XG4gICAgICAgICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICAgICAgICBleGlzdGluZy5oYXNTZXJkZUNhbmRpZGF0ZSA9IHRydWU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbmRpZGF0ZXNCeUZpbGUuc2V0KG5vcm1hbGl6ZWRQYXRoLCB7XG4gICAgICAgICAgICAgIGhhc1dvcmtmbG93Q2FuZGlkYXRlOiBmYWxzZSxcbiAgICAgICAgICAgICAgaGFzU3RlcENhbmRpZGF0ZTogZmFsc2UsXG4gICAgICAgICAgICAgIGhhc1NlcmRlQ2FuZGlkYXRlOiB0cnVlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGZpbGVFbnRyaWVzID0gQXJyYXkuZnJvbShjYW5kaWRhdGVzQnlGaWxlLmVudHJpZXMoKSkuc29ydChcbiAgICAgICAgKFthXSwgW2JdKSA9PiBhLmxvY2FsZUNvbXBhcmUoYilcbiAgICAgICk7XG4gICAgICBjb25zdCB2YWxpZGF0ZWRFbnRyaWVzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGZpbGVFbnRyaWVzLm1hcChhc3luYyAoW2ZpbGVQYXRoLCBjYW5kaWRhdGVzXSkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBmaWxlU3RhdHMgPSBhd2FpdCBzdGF0KGZpbGVQYXRoKTtcbiAgICAgICAgICAgIGlmICghZmlsZVN0YXRzLmlzRmlsZSgpKSB7XG4gICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIXZhbGlkYXRlUGF0dGVybnMpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBmaWxlUGF0aCxcbiAgICAgICAgICAgICAgICBoYXNVc2VXb3JrZmxvdzogY2FuZGlkYXRlcy5oYXNXb3JrZmxvd0NhbmRpZGF0ZSxcbiAgICAgICAgICAgICAgICBoYXNVc2VTdGVwOiBjYW5kaWRhdGVzLmhhc1N0ZXBDYW5kaWRhdGUsXG4gICAgICAgICAgICAgICAgaGFzU2VyZGU6IGNhbmRpZGF0ZXMuaGFzU2VyZGVDYW5kaWRhdGUsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IGF3YWl0IHJlYWRGaWxlKGZpbGVQYXRoLCAndXRmLTgnKTtcbiAgICAgICAgICAgIGNvbnN0IHBhdHRlcm5zID0gZGV0ZWN0V29ya2Zsb3dQYXR0ZXJucyhzb3VyY2UpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZmlsZVBhdGgsXG4gICAgICAgICAgICAgIGhhc1VzZVdvcmtmbG93OiBwYXR0ZXJucy5oYXNVc2VXb3JrZmxvdyxcbiAgICAgICAgICAgICAgaGFzVXNlU3RlcDogcGF0dGVybnMuaGFzVXNlU3RlcCxcbiAgICAgICAgICAgICAgaGFzU2VyZGU6IHBhdHRlcm5zLmhhc1NlcmRlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHdvcmtmbG93RmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgIGNvbnN0IHN0ZXBGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgY29uc3Qgc2VyZGVGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiB2YWxpZGF0ZWRFbnRyaWVzKSB7XG4gICAgICAgIGlmICghZW50cnkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW50cnkuaGFzVXNlV29ya2Zsb3cpIHtcbiAgICAgICAgICB3b3JrZmxvd0ZpbGVzLmFkZChlbnRyeS5maWxlUGF0aCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVudHJ5Lmhhc1VzZVN0ZXApIHtcbiAgICAgICAgICBzdGVwRmlsZXMuYWRkKGVudHJ5LmZpbGVQYXRoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW50cnkuaGFzU2VyZGUpIHtcbiAgICAgICAgICBzZXJkZUZpbGVzLmFkZChlbnRyeS5maWxlUGF0aCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHsgd29ya2Zsb3dGaWxlcywgc3RlcEZpbGVzLCBzZXJkZUZpbGVzIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyB2YWxpZGF0ZURpc2NvdmVyZWRFbnRyeUZpbGVzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgY29uc3Qgd29ya2Zsb3dDYW5kaWRhdGVzID0gbmV3IFNldCh0aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzKTtcbiAgICAgIGNvbnN0IHN0ZXBDYW5kaWRhdGVzID0gbmV3IFNldCh0aGlzLmRpc2NvdmVyZWRTdGVwRmlsZXMpO1xuICAgICAgY29uc3Qgc2VyZGVDYW5kaWRhdGVzID0gbmV3IFNldCh0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzKTtcbiAgICAgIGNvbnN0IHsgd29ya2Zsb3dGaWxlcywgc3RlcEZpbGVzLCBzZXJkZUZpbGVzIH0gPVxuICAgICAgICBhd2FpdCB0aGlzLnJlY29uY2lsZURpc2NvdmVyZWRFbnRyaWVzKHtcbiAgICAgICAgICB3b3JrZmxvd0NhbmRpZGF0ZXMsXG4gICAgICAgICAgc3RlcENhbmRpZGF0ZXMsXG4gICAgICAgICAgc2VyZGVDYW5kaWRhdGVzLFxuICAgICAgICAgIHZhbGlkYXRlUGF0dGVybnM6IHRydWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAvLyBSZWNvbmNpbGUgdmFsaWRhdGVkIGVudHJpZXMgYWdhaW5zdCB0aGUgc25hcHNob3Qgd2Ugc3RhcnRlZCB3aXRoIHNvXG4gICAgICAvLyBmaWxlIGRpc2NvdmVyaWVzIHRoYXQgYXJyaXZlIGR1cmluZyB2YWxpZGF0aW9uIGFyZSBwcmVzZXJ2ZWQuXG4gICAgICBsZXQgd29ya2Zsb3dzQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgbGV0IHN0ZXBzQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgbGV0IHNlcmRlQ2hhbmdlZCA9IGZhbHNlO1xuXG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHdvcmtmbG93Q2FuZGlkYXRlcykge1xuICAgICAgICBpZiAoIXdvcmtmbG93RmlsZXMuaGFzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHdvcmtmbG93c0NoYW5nZWQgPVxuICAgICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcy5kZWxldGUoZmlsZVBhdGgpIHx8IHdvcmtmbG93c0NoYW5nZWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2Ygd29ya2Zsb3dGaWxlcykge1xuICAgICAgICBpZiAoIXRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMuaGFzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMuYWRkKGZpbGVQYXRoKTtcbiAgICAgICAgICB3b3JrZmxvd3NDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHN0ZXBDYW5kaWRhdGVzKSB7XG4gICAgICAgIGlmICghc3RlcEZpbGVzLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICBzdGVwc0NoYW5nZWQgPVxuICAgICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLmRlbGV0ZShmaWxlUGF0aCkgfHwgc3RlcHNDaGFuZ2VkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHN0ZXBGaWxlcykge1xuICAgICAgICBpZiAoIXRoaXMuZGlzY292ZXJlZFN0ZXBGaWxlcy5oYXMoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLmFkZChmaWxlUGF0aCk7XG4gICAgICAgICAgc3RlcHNDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHNlcmRlQ2FuZGlkYXRlcykge1xuICAgICAgICBpZiAoIXNlcmRlRmlsZXMuaGFzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHNlcmRlQ2hhbmdlZCA9XG4gICAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmRlbGV0ZShmaWxlUGF0aCkgfHwgc2VyZGVDaGFuZ2VkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHNlcmRlRmlsZXMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmFkZChmaWxlUGF0aCk7XG4gICAgICAgICAgc2VyZGVDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAod29ya2Zsb3dzQ2hhbmdlZCB8fCBzdGVwc0NoYW5nZWQpIHtcbiAgICAgICAgdGhpcy5zY2hlZHVsZVdvcmtmbG93c0NhY2hlV3JpdGUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGJ1aWxkRGlzY292ZXJlZEZpbGVzKFxuICAgICAgaW5wdXRGaWxlczogc3RyaW5nW10sXG4gICAgICBpbXBsaWNpdFN0ZXBGaWxlczogc3RyaW5nW11cbiAgICApIHtcbiAgICAgIGNvbnN0IG91dHB1dERpciA9IGF3YWl0IHRoaXMuZmluZEFwcERpcmVjdG9yeSgpO1xuICAgICAgY29uc3Qgd29ya2Zsb3dHZW5lcmF0ZWREaXIgPSBqb2luKG91dHB1dERpciwgJy53ZWxsLWtub3duL3dvcmtmbG93L3YxJyk7XG4gICAgICBjb25zdCBjYWNoZURpciA9IGpvaW4odGhpcy5jb25maWcud29ya2luZ0RpciwgdGhpcy5nZXREaXN0RGlyKCksICdjYWNoZScpO1xuICAgICAgYXdhaXQgbWtkaXIoY2FjaGVEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgY29uc3QgbWFuaWZlc3RCdWlsZERpciA9IGpvaW4oY2FjaGVEaXIsICd3b3JrZmxvdy1nZW5lcmF0ZWQtbWFuaWZlc3QnKTtcbiAgICAgIGNvbnN0IHRlbXBSb3V0ZUZpbGVOYW1lID0gJ3JvdXRlLmpzLnRlbXAnO1xuICAgICAgY29uc3QgdHJhY2tlZERpc2NvdmVyZWRFbnRyaWVzID1cbiAgICAgICAgYXdhaXQgdGhpcy5jb2xsZWN0VHJhY2tlZERpc2NvdmVyZWRFbnRyaWVzKCk7XG4gICAgICBjb25zdCBkaXNjb3ZlcmVkU3RlcEZpbGVDYW5kaWRhdGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbXG4gICAgICAgICAgLi4udGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLFxuICAgICAgICAgIC4uLnRyYWNrZWREaXNjb3ZlcmVkRW50cmllcy5kaXNjb3ZlcmVkU3RlcHMsXG4gICAgICAgICAgLi4uaW1wbGljaXRTdGVwRmlsZXMsXG4gICAgICAgIF0pXG4gICAgICApLnNvcnQoKTtcbiAgICAgIGNvbnN0IGRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVDYW5kaWRhdGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbXG4gICAgICAgICAgLi4udGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcyxcbiAgICAgICAgICAuLi50cmFja2VkRGlzY292ZXJlZEVudHJpZXMuZGlzY292ZXJlZFdvcmtmbG93cyxcbiAgICAgICAgXSlcbiAgICAgICkuc29ydCgpO1xuICAgICAgY29uc3QgZGlzY292ZXJlZFNlcmRlRmlsZUNhbmRpZGF0ZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFtcbiAgICAgICAgICAuLi50aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLFxuICAgICAgICAgIC4uLnRyYWNrZWREaXNjb3ZlcmVkRW50cmllcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcyxcbiAgICAgICAgXSlcbiAgICAgICkuc29ydCgpO1xuICAgICAgY29uc3QgZGlzY292ZXJlZFdvcmtmbG93RmlsZXMgPSBhd2FpdCB0aGlzLmZpbHRlckV4aXN0aW5nRmlsZXMoXG4gICAgICAgIGRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVDYW5kaWRhdGVzXG4gICAgICApO1xuICAgICAgY29uc3QgZXhpc3RpbmdTdGVwRmlsZUNhbmRpZGF0ZXMgPSBhd2FpdCB0aGlzLmZpbHRlckV4aXN0aW5nRmlsZXMoXG4gICAgICAgIGRpc2NvdmVyZWRTdGVwRmlsZUNhbmRpZGF0ZXNcbiAgICAgICk7XG4gICAgICBjb25zdCBkaXNjb3ZlcmVkU3RlcEZpbGVzID0gYXdhaXQgdGhpcy5jb2xsZWN0VHJhbnNpdGl2ZVN0ZXBGaWxlcyh7XG4gICAgICAgIGVudHJ5RmlsZXM6IFsuLi5leGlzdGluZ1N0ZXBGaWxlQ2FuZGlkYXRlcywgLi4uZGlzY292ZXJlZFdvcmtmbG93RmlsZXNdLFxuICAgICAgICBzdGVwRmlsZXM6IGV4aXN0aW5nU3RlcEZpbGVDYW5kaWRhdGVzLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBleGlzdGluZ1NlcmRlRmlsZUNhbmRpZGF0ZXMgPSBhd2FpdCB0aGlzLmZpbHRlckV4aXN0aW5nRmlsZXMoXG4gICAgICAgIGRpc2NvdmVyZWRTZXJkZUZpbGVDYW5kaWRhdGVzXG4gICAgICApO1xuICAgICAgY29uc3QgZGlzY292ZXJlZFNlcmRlRmlsZXMgPSBhd2FpdCB0aGlzLmNvbGxlY3RUcmFuc2l0aXZlU2VyZGVGaWxlcyh7XG4gICAgICAgIGVudHJ5RmlsZXM6IFsuLi5kaXNjb3ZlcmVkU3RlcEZpbGVzLCAuLi5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlc10sXG4gICAgICAgIHNlcmRlRmlsZXM6IGV4aXN0aW5nU2VyZGVGaWxlQ2FuZGlkYXRlcyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgZXhpc3RpbmdJbnB1dEZpbGVzID0gYXdhaXQgdGhpcy5maWx0ZXJFeGlzdGluZ0ZpbGVzKGlucHV0RmlsZXMpO1xuICAgICAgY29uc3QgYnVpbGRJbnB1dEZpbGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbXG4gICAgICAgICAgLi4uZXhpc3RpbmdJbnB1dEZpbGVzLFxuICAgICAgICAgIC4uLmRpc2NvdmVyZWRTdGVwRmlsZXMsXG4gICAgICAgICAgLi4uZGlzY292ZXJlZFdvcmtmbG93RmlsZXMsXG4gICAgICAgICAgLi4uZGlzY292ZXJlZFNlcmRlRmlsZXMsXG4gICAgICAgIF0pXG4gICAgICApLnNvcnQoKTtcbiAgICAgIGNvbnN0IGRpc2NvdmVyZWRFbnRyaWVzID0ge1xuICAgICAgICBkaXNjb3ZlcmVkU3RlcHM6IG5ldyBTZXQoZGlzY292ZXJlZFN0ZXBGaWxlcyksXG4gICAgICAgIGRpc2NvdmVyZWRXb3JrZmxvd3M6IG5ldyBTZXQoZGlzY292ZXJlZFdvcmtmbG93RmlsZXMpLFxuICAgICAgICBkaXNjb3ZlcmVkU2VyZGVGaWxlczogbmV3IFNldChkaXNjb3ZlcmVkU2VyZGVGaWxlcyksXG4gICAgICB9O1xuXG4gICAgICAvLyBFbnN1cmUgb3V0cHV0IGRpcmVjdG9yaWVzIGV4aXN0XG4gICAgICBhd2FpdCBta2Rpcih3b3JrZmxvd0dlbmVyYXRlZERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgICAgIGF3YWl0IHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnLmdpdGlnbm9yZScpLFxuICAgICAgICAnKidcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHRzY29uZmlnUGF0aCA9IGF3YWl0IHRoaXMuZmluZFRzQ29uZmlnUGF0aCgpO1xuXG4gICAgICBjb25zdCBmbG93Um91dGVEaXIgPSBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnZmxvdycpO1xuICAgICAgYXdhaXQgbWtkaXIoZmxvd1JvdXRlRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICAgICAgY29uc3QgY29tYmluZWRSZXN1bHQgPSBhd2FpdCB0aGlzLmNyZWF0ZURlZmVycmVkRmxvd1JvdXRlKHtcbiAgICAgICAgaW5wdXRGaWxlczogYnVpbGRJbnB1dEZpbGVzLFxuICAgICAgICBmbG93T3V0ZmlsZTogam9pbihmbG93Um91dGVEaXIsIHRlbXBSb3V0ZUZpbGVOYW1lKSxcbiAgICAgICAgdHNjb25maWdQYXRoLFxuICAgICAgICBkaXNjb3ZlcmVkRW50cmllcyxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhpcy5idWlsZFdlYmhvb2tSb3V0ZSh7XG4gICAgICAgIHdvcmtmbG93R2VuZXJhdGVkRGlyLFxuICAgICAgICByb3V0ZUZpbGVOYW1lOiB0ZW1wUm91dGVGaWxlTmFtZSxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhpcy5yZWZyZXNoVHJhY2tlZERlcGVuZGVuY3lGaWxlcyhcbiAgICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXIsXG4gICAgICAgIHRlbXBSb3V0ZUZpbGVOYW1lXG4gICAgICApO1xuXG4gICAgICBjb25zdCBtYW5pZmVzdCA9IHtcbiAgICAgICAgc3RlcHM6IHsgLi4uY29tYmluZWRSZXN1bHQ/Lm1hbmlmZXN0Py5zdGVwcyB9LFxuICAgICAgICB3b3JrZmxvd3M6IHsgLi4uY29tYmluZWRSZXN1bHQ/Lm1hbmlmZXN0Py53b3JrZmxvd3MgfSxcbiAgICAgICAgY2xhc3NlczogeyAuLi5jb21iaW5lZFJlc3VsdD8ubWFuaWZlc3Q/LmNsYXNzZXMgfSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IG1hbmlmZXN0RmlsZVBhdGggPSBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnbWFuaWZlc3QuanNvbicpO1xuICAgICAgY29uc3QgbWFuaWZlc3RCdWlsZFBhdGggPSBqb2luKG1hbmlmZXN0QnVpbGREaXIsICdtYW5pZmVzdC5qc29uJyk7XG4gICAgICBjb25zdCB3b3JrZmxvd0J1bmRsZVBhdGggPSBqb2luKFxuICAgICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcixcbiAgICAgICAgYGZsb3cvJHt0ZW1wUm91dGVGaWxlTmFtZX1gXG4gICAgICApO1xuICAgICAgY29uc3QgbWFuaWZlc3RKc29uID0gYXdhaXQgdGhpcy5jcmVhdGVNYW5pZmVzdCh7XG4gICAgICAgIHdvcmtmbG93QnVuZGxlUGF0aCxcbiAgICAgICAgbWFuaWZlc3REaXI6IG1hbmlmZXN0QnVpbGREaXIsXG4gICAgICAgIG1hbmlmZXN0LFxuICAgICAgfSk7XG4gICAgICBpZiAobWFuaWZlc3RKc29uKSB7XG4gICAgICAgIGF3YWl0IHRoaXMucmV3cml0ZUpzb25GaWxlV2l0aFN0YWJsZUtleU9yZGVyKG1hbmlmZXN0QnVpbGRQYXRoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5jb3B5RmlsZUlmQ2hhbmdlZChtYW5pZmVzdEJ1aWxkUGF0aCwgbWFuaWZlc3RGaWxlUGF0aCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCBybShtYW5pZmVzdEJ1aWxkUGF0aCwgeyBmb3JjZTogdHJ1ZSB9KTtcbiAgICAgICAgYXdhaXQgcm0obWFuaWZlc3RGaWxlUGF0aCwgeyBmb3JjZTogdHJ1ZSB9KTtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgdGhpcy53cml0ZUZ1bmN0aW9uc0NvbmZpZyhvdXRwdXREaXIpO1xuXG4gICAgICAvLyBWMjogQ29tYmluZWQgcm91dGUgKGZsb3cpIOKAlCBzdGVwIHJlZ2lzdHJhdGlvbnMgYWxyZWFkeSBhdCBmaW5hbCBwYXRoXG4gICAgICBhd2FpdCB0aGlzLmNvcHlGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCBgZmxvdy8ke3RlbXBSb3V0ZUZpbGVOYW1lfWApLFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnZmxvdy9yb3V0ZS5qcycpXG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy5jb3B5RmlsZUlmQ2hhbmdlZChcbiAgICAgICAgam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgYHdlYmhvb2svW3Rva2VuXS8ke3RlbXBSb3V0ZUZpbGVOYW1lfWApLFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnd2ViaG9vay9bdG9rZW5dL3JvdXRlLmpzJylcbiAgICAgICk7XG5cbiAgICAgIC8vIEV4cG9zZSBtYW5pZmVzdCBhcyBhIHN0YXRpYyBmaWxlIHdoZW4gV09SS0ZMT1dfUFVCTElDX01BTklGRVNUPTEuXG4gICAgICAvLyBOZXh0LmpzIHNlcnZlcyBmaWxlcyBmcm9tIHB1YmxpYy8gYXQgdGhlIHJvb3QgVVJMLlxuICAgICAgaWYgKHRoaXMuc2hvdWxkRXhwb3NlUHVibGljTWFuaWZlc3QgJiYgbWFuaWZlc3RKc29uKSB7XG4gICAgICAgIGNvbnN0IHB1YmxpY01hbmlmZXN0RGlyID0gam9pbihcbiAgICAgICAgICB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgICAgICdwdWJsaWMvLndlbGwta25vd24vd29ya2Zsb3cvdjEnXG4gICAgICAgICk7XG4gICAgICAgIGF3YWl0IG1rZGlyKHB1YmxpY01hbmlmZXN0RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgaWYgKHByb2Nlc3MuZW52LlZFUkNFTF9ERVBMT1lNRU5UX0lEID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLndyaXRlRmlsZUlmQ2hhbmdlZChcbiAgICAgICAgICAgIGpvaW4ocHVibGljTWFuaWZlc3REaXIsICcuZ2l0aWdub3JlJyksXG4gICAgICAgICAgICAnKidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMuY29weUZpbGVJZkNoYW5nZWQoXG4gICAgICAgICAgbWFuaWZlc3RGaWxlUGF0aCxcbiAgICAgICAgICBqb2luKHB1YmxpY01hbmlmZXN0RGlyLCAnbWFuaWZlc3QuanNvbicpXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vIE5vdGlmeSBkZWZlcnJlZCBlbnRyeSBsb2FkZXJzIHdhaXRpbmcgb24gcm91dGUuanMgc3R1YnMuXG4gICAgICB0aGlzLnNvY2tldElPPy5lbWl0KCdidWlsZC1jb21wbGV0ZScpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY3JlYXRlRGVmZXJyZWRGbG93Um91dGUoe1xuICAgICAgaW5wdXRGaWxlcyxcbiAgICAgIGZsb3dPdXRmaWxlLFxuICAgICAgdHNjb25maWdQYXRoLFxuICAgICAgZGlzY292ZXJlZEVudHJpZXMsXG4gICAgfToge1xuICAgICAgaW5wdXRGaWxlczogc3RyaW5nW107XG4gICAgICBmbG93T3V0ZmlsZTogc3RyaW5nO1xuICAgICAgdHNjb25maWdQYXRoPzogc3RyaW5nO1xuICAgICAgZGlzY292ZXJlZEVudHJpZXM6IHtcbiAgICAgICAgZGlzY292ZXJlZFN0ZXBzOiBTZXQ8c3RyaW5nPjtcbiAgICAgICAgZGlzY292ZXJlZFdvcmtmbG93czogU2V0PHN0cmluZz47XG4gICAgICAgIGRpc2NvdmVyZWRTZXJkZUZpbGVzOiBTZXQ8c3RyaW5nPjtcbiAgICAgIH07XG4gICAgfSk6IFByb21pc2U8eyBtYW5pZmVzdDogV29ya2Zsb3dNYW5pZmVzdCB9PiB7XG4gICAgICBjb25zdCB3b3JrZmxvd1Jlc3VsdCA9IGF3YWl0IHRoaXMuY3JlYXRlV29ya2Zsb3dzQnVuZGxlKHtcbiAgICAgICAgaW5wdXRGaWxlcyxcbiAgICAgICAgb3V0ZmlsZTogYCR7Zmxvd091dGZpbGV9Ll9fd2ZfdG1wLmpzYCxcbiAgICAgICAgZm9ybWF0OiAnZXNtJyxcbiAgICAgICAgYnVuZGxlRmluYWxPdXRwdXQ6IGZhbHNlLFxuICAgICAgICB0c2NvbmZpZ1BhdGgsXG4gICAgICAgIGRpc2NvdmVyZWRFbnRyaWVzLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHdvcmtmbG93Vk1Db2RlID0gd29ya2Zsb3dSZXN1bHQuaW50ZXJpbUJ1bmRsZVRleHQ7XG4gICAgICBpZiAoIXdvcmtmbG93Vk1Db2RlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnY3JlYXRlV29ya2Zsb3dzQnVuZGxlIGRpZCBub3QgcmV0dXJuIGludGVyaW1CdW5kbGVUZXh0J1xuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBybShgJHtmbG93T3V0ZmlsZX0uX193Zl90bXAuanNgLCB7IGZvcmNlOiB0cnVlIH0pO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIElnbm9yZSBjbGVhbnVwIGVycm9ycy5cbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RlcEFuZFNlcmRlRmlsZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFtcbiAgICAgICAgICAuLi5kaXNjb3ZlcmVkRW50cmllcy5kaXNjb3ZlcmVkU3RlcHMsXG4gICAgICAgICAgLi4uZGlzY292ZXJlZEVudHJpZXMuZGlzY292ZXJlZFNlcmRlRmlsZXMsXG4gICAgICAgIF0pXG4gICAgICApLnNvcnQoKTtcbiAgICAgIGNvbnN0IHN0ZXBJbXBvcnRzID0gYXdhaXQgdGhpcy5jcmVhdGVEZWZlcnJlZFN0ZXBTaWRlRWZmZWN0SW1wb3J0cyhcbiAgICAgICAgc3RlcEFuZFNlcmRlRmlsZXMsXG4gICAgICAgIGRpcm5hbWUoZmxvd091dGZpbGUpXG4gICAgICApO1xuICAgICAgY29uc3Qgc3RlcE1hbmlmZXN0ID1cbiAgICAgICAgYXdhaXQgdGhpcy5jcmVhdGVEZWZlcnJlZFN0ZXBNYW5pZmVzdChzdGVwQW5kU2VyZGVGaWxlcyk7XG4gICAgICBjb25zdCBlc2NhcGVkVk1Db2RlID0gd29ya2Zsb3dWTUNvZGUucmVwbGFjZSgvW1xcXFxgJF0vZywgJ1xcXFwkJicpO1xuICAgICAgY29uc3Qgd29ya2Zsb3dFbnRyeXBvaW50T3B0aW9uc0NvZGUgPVxuICAgICAgICBjcmVhdGVXb3JrZmxvd0VudHJ5cG9pbnRPcHRpb25zQ29kZSgpO1xuICAgICAgbGV0IHJvdXRlQ29kZTogc3RyaW5nO1xuXG4gICAgICBpZiAodGhpcy5jb25maWcud2F0Y2gpIHtcbiAgICAgICAgY29uc3Qgd29ya2Zsb3dDb2RlUGF0aCA9IGpvaW4oXG4gICAgICAgICAgZGlybmFtZShmbG93T3V0ZmlsZSksXG4gICAgICAgICAgREVWX1dPUktGTE9XX0NPREVfRklMRU5BTUVcbiAgICAgICAgKTtcbiAgICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQod29ya2Zsb3dDb2RlUGF0aCwgd29ya2Zsb3dWTUNvZGUpO1xuICAgICAgICByb3V0ZUNvZGUgPSBgLy8gYmlvbWUtaWdub3JlLWFsbCBsaW50OiBnZW5lcmF0ZWQgZmlsZVxuLyogZXNsaW50LWRpc2FibGUgKi9cbmltcG9ydCAnd29ya2Zsb3cvaW50ZXJuYWwvYnVpbHRpbnMnO1xuJHtzdGVwSW1wb3J0c31cbmltcG9ydCB7IHJlYWRGaWxlLCBzdGF0IH0gZnJvbSAnbm9kZTpmcy9wcm9taXNlcyc7XG5pbXBvcnQgeyB3b3JrZmxvd0VudHJ5cG9pbnQgfSBmcm9tICd3b3JrZmxvdy9ydW50aW1lJztcblxuY29uc3Qgd29ya2Zsb3dDb2RlUGF0aCA9ICR7SlNPTi5zdHJpbmdpZnkod29ya2Zsb3dDb2RlUGF0aCl9O1xubGV0IGNhY2hlZFdvcmtmbG93SGFuZGxlcjtcbmxldCBjYWNoZWRXb3JrZmxvd0NvZGVTaWduYXR1cmU7XG5cbmFzeW5jIGZ1bmN0aW9uIGdldFdvcmtmbG93SGFuZGxlcigpIHtcbiAgY29uc3Qgd29ya2Zsb3dDb2RlU3RhdHMgPSBhd2FpdCBzdGF0KHdvcmtmbG93Q29kZVBhdGgpO1xuICBjb25zdCB3b3JrZmxvd0NvZGVTaWduYXR1cmUgPSBcXGBcXCR7d29ya2Zsb3dDb2RlU3RhdHMuc2l6ZX06XFwke3dvcmtmbG93Q29kZVN0YXRzLm10aW1lTXN9XFxgO1xuICBpZiAoIWNhY2hlZFdvcmtmbG93SGFuZGxlciB8fCBjYWNoZWRXb3JrZmxvd0NvZGVTaWduYXR1cmUgIT09IHdvcmtmbG93Q29kZVNpZ25hdHVyZSkge1xuICAgIGNvbnN0IHdvcmtmbG93Q29kZSA9IGF3YWl0IHJlYWRGaWxlKHdvcmtmbG93Q29kZVBhdGgsICd1dGY4Jyk7XG4gICAgY2FjaGVkV29ya2Zsb3dIYW5kbGVyID0gd29ya2Zsb3dFbnRyeXBvaW50KHdvcmtmbG93Q29kZSR7d29ya2Zsb3dFbnRyeXBvaW50T3B0aW9uc0NvZGV9KTtcbiAgICBjYWNoZWRXb3JrZmxvd0NvZGVTaWduYXR1cmUgPSB3b3JrZmxvd0NvZGVTaWduYXR1cmU7XG4gIH1cbiAgcmV0dXJuIGNhY2hlZFdvcmtmbG93SGFuZGxlcjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIFBPU1QocmVxKSB7XG4gIHJldHVybiAoYXdhaXQgZ2V0V29ya2Zsb3dIYW5kbGVyKCkpKHJlcSk7XG59YDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJvdXRlQ29kZSA9IGAvLyBiaW9tZS1pZ25vcmUtYWxsIGxpbnQ6IGdlbmVyYXRlZCBmaWxlXG4vKiBlc2xpbnQtZGlzYWJsZSAqL1xuaW1wb3J0ICd3b3JrZmxvdy9pbnRlcm5hbC9idWlsdGlucyc7XG4ke3N0ZXBJbXBvcnRzfVxuaW1wb3J0IHsgd29ya2Zsb3dFbnRyeXBvaW50IH0gZnJvbSAnd29ya2Zsb3cvcnVudGltZSc7XG5cbmNvbnN0IHdvcmtmbG93Q29kZSA9IFxcYCR7ZXNjYXBlZFZNQ29kZX1cXGA7XG5cbmV4cG9ydCBjb25zdCBQT1NUID0gd29ya2Zsb3dFbnRyeXBvaW50KHdvcmtmbG93Q29kZSR7d29ya2Zsb3dFbnRyeXBvaW50T3B0aW9uc0NvZGV9KTtgO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCB0aGlzLndyaXRlRmlsZUlmQ2hhbmdlZChmbG93T3V0ZmlsZSwgcm91dGVDb2RlKTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbWFuaWZlc3Q6IHtcbiAgICAgICAgICAuLi5zdGVwTWFuaWZlc3QsXG4gICAgICAgICAgd29ya2Zsb3dzOiB7XG4gICAgICAgICAgICAuLi5zdGVwTWFuaWZlc3Qud29ya2Zsb3dzLFxuICAgICAgICAgICAgLi4ud29ya2Zsb3dSZXN1bHQubWFuaWZlc3Qud29ya2Zsb3dzLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgY2xhc3Nlczoge1xuICAgICAgICAgICAgLi4uc3RlcE1hbmlmZXN0LmNsYXNzZXMsXG4gICAgICAgICAgICAuLi53b3JrZmxvd1Jlc3VsdC5tYW5pZmVzdC5jbGFzc2VzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY3JlYXRlRGVmZXJyZWRTdGVwU2lkZUVmZmVjdEltcG9ydHMoXG4gICAgICBmaWxlczogc3RyaW5nW10sXG4gICAgICByb3V0ZURpcjogc3RyaW5nXG4gICAgKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgIGNvbnN0IGltcG9ydFNwZWNpZmllcnMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgZmlsZXMubWFwKChmaWxlKSA9PlxuICAgICAgICAgIHRoaXMuZ2V0RGVmZXJyZWRSb3V0ZUltcG9ydFNwZWNpZmllcihmaWxlLCByb3V0ZURpcilcbiAgICAgICAgKVxuICAgICAgKTtcblxuICAgICAgcmV0dXJuIGltcG9ydFNwZWNpZmllcnNcbiAgICAgICAgLm1hcCgoc3BlY2lmaWVyKSA9PiBgaW1wb3J0ICR7SlNPTi5zdHJpbmdpZnkoc3BlY2lmaWVyKX07YClcbiAgICAgICAgLmpvaW4oJ1xcbicpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZ2V0RGVmZXJyZWRSb3V0ZUltcG9ydFNwZWNpZmllcihcbiAgICAgIGZpbGU6IHN0cmluZyxcbiAgICAgIHJvdXRlRGlyOiBzdHJpbmdcbiAgICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgY29uc3QgeyBpbXBvcnRQYXRoLCBpc1BhY2thZ2UgfSA9IGdldEltcG9ydFBhdGgoXG4gICAgICAgIGZpbGUsXG4gICAgICAgIHRoaXMuY29uZmlnLndvcmtpbmdEaXJcbiAgICAgICk7XG5cbiAgICAgIGlmIChpc1BhY2thZ2UpIHtcbiAgICAgICAgcmV0dXJuIGltcG9ydFBhdGg7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IGF3YWl0IHRoaXMucmVzb2x2ZURlZmVycmVkUm91dGVJbXBvcnRGaWxlUGF0aChcbiAgICAgICAgcmVzb2x2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCBpbXBvcnRQYXRoKVxuICAgICAgKTtcbiAgICAgIGxldCByZWxhdGl2ZVBhdGggPSByZWxhdGl2ZShyb3V0ZURpciwgYWJzb2x1dGVQYXRoKS5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gICAgICBpZiAoIXJlbGF0aXZlUGF0aC5zdGFydHNXaXRoKCcuLycpICYmICFyZWxhdGl2ZVBhdGguc3RhcnRzV2l0aCgnLi4vJykpIHtcbiAgICAgICAgcmVsYXRpdmVQYXRoID0gYC4vJHtyZWxhdGl2ZVBhdGh9YDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZWxhdGl2ZVBhdGg7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZXNvbHZlRGVmZXJyZWRSb3V0ZUltcG9ydEZpbGVQYXRoKFxuICAgICAgZmlsZVBhdGg6IHN0cmluZ1xuICAgICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICBjb25zdCBwYWNrYWdlRGlzdFBhdGggPVxuICAgICAgICB0aGlzLnJlc29sdmVQYWNrYWdlU291cmNlRGlzdEZpbGVQYXRoRm9yUm91dGVJbXBvcnQoZmlsZVBhdGgpO1xuICAgICAgaWYgKHBhY2thZ2VEaXN0UGF0aCkge1xuICAgICAgICByZXR1cm4gcGFja2FnZURpc3RQYXRoO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmlsZVBhdGg7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZXNvbHZlUGFja2FnZVNvdXJjZURpc3RGaWxlUGF0aEZvclJvdXRlSW1wb3J0KFxuICAgICAgZmlsZVBhdGg6IHN0cmluZ1xuICAgICk6IHN0cmluZyB8IG51bGwge1xuICAgICAgY29uc3QgcmVsYXRpdmVUb1dvcmtpbmdEaXIgPSByZWxhdGl2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCBmaWxlUGF0aCk7XG4gICAgICBpZiAoXG4gICAgICAgICFyZWxhdGl2ZVRvV29ya2luZ0Rpci5zdGFydHNXaXRoKCcuLicpICYmXG4gICAgICAgICFpc0Fic29sdXRlKHJlbGF0aXZlVG9Xb3JraW5nRGlyKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYWNrYWdlUm9vdCA9IHRoaXMuZmluZFBhY2thZ2VSb290Rm9yUm91dGVJbXBvcnRTb3VyY2UoZmlsZVBhdGgpO1xuICAgICAgaWYgKCFwYWNrYWdlUm9vdCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVsYXRpdmVUb1BhY2thZ2VSb290ID0gcmVsYXRpdmUocGFja2FnZVJvb3QsIGZpbGVQYXRoKS5yZXBsYWNlKFxuICAgICAgICAvXFxcXC9nLFxuICAgICAgICAnLydcbiAgICAgICk7XG4gICAgICBjb25zdCBzcmNQcmVmaXggPSAnc3JjLyc7XG4gICAgICBpZiAoIXJlbGF0aXZlVG9QYWNrYWdlUm9vdC5zdGFydHNXaXRoKHNyY1ByZWZpeCkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGV4dGVuc2lvbiA9IGV4dG5hbWUocmVsYXRpdmVUb1BhY2thZ2VSb290KTtcbiAgICAgIGNvbnN0IG91dHB1dEV4dGVuc2lvbiA9XG4gICAgICAgIGV4dGVuc2lvbiA9PT0gJy5tdHMnID8gJy5tanMnIDogZXh0ZW5zaW9uID09PSAnLmN0cycgPyAnLmNqcycgOiAnLmpzJztcbiAgICAgIGNvbnN0IHdpdGhvdXRFeHRlbnNpb24gPSByZWxhdGl2ZVRvUGFja2FnZVJvb3Quc2xpY2UoXG4gICAgICAgIHNyY1ByZWZpeC5sZW5ndGgsXG4gICAgICAgIHJlbGF0aXZlVG9QYWNrYWdlUm9vdC5sZW5ndGggLSBleHRlbnNpb24ubGVuZ3RoXG4gICAgICApO1xuICAgICAgY29uc3QgZGlzdFBhdGggPSBqb2luKFxuICAgICAgICBwYWNrYWdlUm9vdCxcbiAgICAgICAgJ2Rpc3QnLFxuICAgICAgICBgJHt3aXRob3V0RXh0ZW5zaW9ufSR7b3V0cHV0RXh0ZW5zaW9ufWBcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiBleGlzdHNTeW5jKGRpc3RQYXRoKSA/IGRpc3RQYXRoIDogbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGZpbmRQYWNrYWdlUm9vdEZvclJvdXRlSW1wb3J0U291cmNlKFxuICAgICAgZmlsZVBhdGg6IHN0cmluZ1xuICAgICk6IHN0cmluZyB8IG51bGwge1xuICAgICAgbGV0IGN1cnJlbnREaXIgPSBkaXJuYW1lKGZpbGVQYXRoKTtcblxuICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgaWYgKGV4aXN0c1N5bmMoam9pbihjdXJyZW50RGlyLCAncGFja2FnZS5qc29uJykpKSB7XG4gICAgICAgICAgcmV0dXJuIGN1cnJlbnREaXI7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwYXJlbnREaXIgPSBkaXJuYW1lKGN1cnJlbnREaXIpO1xuICAgICAgICBpZiAocGFyZW50RGlyID09PSBjdXJyZW50RGlyKSB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudERpciA9IHBhcmVudERpcjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGNyZWF0ZURlZmVycmVkU3RlcE1hbmlmZXN0KFxuICAgICAgZmlsZXM6IHN0cmluZ1tdXG4gICAgKTogUHJvbWlzZTxXb3JrZmxvd01hbmlmZXN0PiB7XG4gICAgICBjb25zdCBtYW5pZmVzdDogV29ya2Zsb3dNYW5pZmVzdCA9IHt9O1xuICAgICAgY29uc3QgbWFuaWZlc3RGaWxlcyA9IEFycmF5LmZyb20oXG4gICAgICAgIG5ldyBTZXQoW1xuICAgICAgICAgIC4uLmZpbGVzLFxuICAgICAgICAgIC4uLihhd2FpdCB0aGlzLnJlc29sdmVCdWlsdEluU3RlcEZpbGVzRm9yTWFuaWZlc3QoKSksXG4gICAgICAgIF0pXG4gICAgICApLnNvcnQoKTtcblxuICAgICAgZm9yIChjb25zdCBmaWxlIG9mIG1hbmlmZXN0RmlsZXMpIHtcbiAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgcmVhZEZpbGUoZmlsZSwgJ3V0ZjgnKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgICBpZiAoIXNvdXJjZSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVsYXRpdmVGaWxlcGF0aCA9IGF3YWl0IHRoaXMuZ2V0UmVsYXRpdmVGaWxlbmFtZUZvclN3YyhmaWxlKTtcbiAgICAgICAgY29uc3QgeyB3b3JrZmxvd01hbmlmZXN0IH0gPSBhd2FpdCBhcHBseVN3Y1RyYW5zZm9ybShcbiAgICAgICAgICByZWxhdGl2ZUZpbGVwYXRoLFxuICAgICAgICAgIHNvdXJjZSxcbiAgICAgICAgICAnc3RlcCcsXG4gICAgICAgICAgZmlsZSxcbiAgICAgICAgICB0aGlzLnRyYW5zZm9ybVByb2plY3RSb290LFxuICAgICAgICAgIHRoaXMubW9kdWxlU3BlY2lmaWVyUm9vdFxuICAgICAgICApO1xuICAgICAgICB0aGlzLm1lcmdlV29ya2Zsb3dNYW5pZmVzdChtYW5pZmVzdCwgd29ya2Zsb3dNYW5pZmVzdCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBtYW5pZmVzdDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJlc29sdmVCdWlsdEluU3RlcEZpbGVzRm9yTWFuaWZlc3QoKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3Qgd29ya2Zsb3dSZXF1aXJlID0gY3JlYXRlUmVxdWlyZShcbiAgICAgICAgICBqb2luKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsICdwYWNrYWdlLmpzb24nKVxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgIHRoaXMubm9ybWFsaXplRGlzY292ZXJlZEZpbGVQYXRoKFxuICAgICAgICAgICAgd29ya2Zsb3dSZXF1aXJlLnJlc29sdmUoJ3dvcmtmbG93L2ludGVybmFsL2J1aWx0aW5zJylcbiAgICAgICAgICApLFxuICAgICAgICBdO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG1lcmdlV29ya2Zsb3dNYW5pZmVzdChcbiAgICAgIHRhcmdldDogV29ya2Zsb3dNYW5pZmVzdCxcbiAgICAgIHNvdXJjZTogV29ya2Zsb3dNYW5pZmVzdFxuICAgICk6IHZvaWQge1xuICAgICAgdGFyZ2V0LndvcmtmbG93cyA9IE9iamVjdC5hc3NpZ24oXG4gICAgICAgIHRhcmdldC53b3JrZmxvd3MgfHwge30sXG4gICAgICAgIHNvdXJjZS53b3JrZmxvd3NcbiAgICAgICk7XG4gICAgICB0YXJnZXQuc3RlcHMgPSBPYmplY3QuYXNzaWduKHRhcmdldC5zdGVwcyB8fCB7fSwgc291cmNlLnN0ZXBzKTtcbiAgICAgIHRhcmdldC5jbGFzc2VzID0gT2JqZWN0LmFzc2lnbih0YXJnZXQuY2xhc3NlcyB8fCB7fSwgc291cmNlLmNsYXNzZXMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY2xlYW51cEdlbmVyYXRlZEFydGlmYWN0c09uQm9vdChcbiAgICAgIG91dHB1dERpcjogc3RyaW5nXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBjb25zdCB3b3JrZmxvd0dlbmVyYXRlZERpciA9IGpvaW4ob3V0cHV0RGlyLCAnLndlbGwta25vd24vd29ya2Zsb3cvdjEnKTtcbiAgICAgIGNvbnN0IGZsb3dSb3V0ZURpciA9IGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdmbG93Jyk7XG4gICAgICBjb25zdCBzdGVwUm91dGVEaXIgPSBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnc3RlcCcpO1xuICAgICAgY29uc3Qgd2ViaG9va1JvdXRlRGlyID0gam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgJ3dlYmhvb2svW3Rva2VuXScpO1xuXG4gICAgICBjb25zdCBzdGFsZUFydGlmYWN0UGF0aHMgPSBbXG4gICAgICAgIGpvaW4oZmxvd1JvdXRlRGlyLCAncm91dGUuanMudGVtcCcpLFxuICAgICAgICBqb2luKGZsb3dSb3V0ZURpciwgJ3JvdXRlLmpzLnRlbXAuZGVidWcuanNvbicpLFxuICAgICAgICBqb2luKGZsb3dSb3V0ZURpciwgJ3JvdXRlLmpzLmRlYnVnLmpzb24nKSxcbiAgICAgICAgam9pbihmbG93Um91dGVEaXIsIERFVl9XT1JLRkxPV19DT0RFX0ZJTEVOQU1FKSxcbiAgICAgICAgam9pbihmbG93Um91dGVEaXIsICdfX3N0ZXBfcmVnaXN0cmF0aW9ucy5yb3V0ZS5qcy50ZW1wJyksXG4gICAgICAgIGpvaW4oZmxvd1JvdXRlRGlyLCAnX19zdGVwX3JlZ2lzdHJhdGlvbnMucm91dGUuanMudGVtcC5kZWJ1Zy5qc29uJyksXG4gICAgICAgIC8vIFYyOiBjbGVhbiB1cCBzdGFsZSBWMSBzdGVwIHJvdXRlIGRpcmVjdG9yeVxuICAgICAgICBzdGVwUm91dGVEaXIsXG4gICAgICAgIGpvaW4od2ViaG9va1JvdXRlRGlyLCAncm91dGUuanMudGVtcCcpLFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnbWFuaWZlc3QuanNvbicpLFxuICAgICAgXTtcblxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAuLi5zdGFsZUFydGlmYWN0UGF0aHMubWFwKChzdGFsZVBhdGgpID0+XG4gICAgICAgICAgcm0oc3RhbGVQYXRoLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSlcbiAgICAgICAgKSxcbiAgICAgICAgY2xlYW51cFN0YWxlU29ja2V0SW5mb0ZpbGVzKFxuICAgICAgICAgIGpvaW4odGhpcy5jb25maWcud29ya2luZ0RpciwgdGhpcy5nZXREaXN0RGlyKCkpXG4gICAgICAgICksXG4gICAgICAgIHRoaXMucmVtb3ZlU3RhbGVEZWZlcnJlZFRlbXBGaWxlcyhmbG93Um91dGVEaXIpLFxuICAgICAgICB0aGlzLnJlbW92ZVN0YWxlRGVmZXJyZWRUZW1wRmlsZXMod2ViaG9va1JvdXRlRGlyKSxcbiAgICAgIF0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcmVtb3ZlU3RhbGVEZWZlcnJlZFRlbXBGaWxlcyhcbiAgICAgIHJvdXRlRGlyOiBzdHJpbmdcbiAgICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IHJvdXRlRW50cmllcyA9IGF3YWl0IHJlYWRkaXIocm91dGVEaXIsIHtcbiAgICAgICAgd2l0aEZpbGVUeXBlczogdHJ1ZSxcbiAgICAgIH0pLmNhdGNoKCgpID0+IFtdKTtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICByb3V0ZUVudHJpZXNcbiAgICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgKGVudHJ5KSA9PlxuICAgICAgICAgICAgICBlbnRyeS5pc0ZpbGUoKSAmJlxuICAgICAgICAgICAgICBlbnRyeS5uYW1lLnN0YXJ0c1dpdGgoJ3JvdXRlLmpzLicpICYmXG4gICAgICAgICAgICAgIGVudHJ5Lm5hbWUuZW5kc1dpdGgoJy50bXAnKVxuICAgICAgICAgIClcbiAgICAgICAgICAubWFwKChlbnRyeSkgPT5cbiAgICAgICAgICAgIHJtKGpvaW4ocm91dGVEaXIsIGVudHJ5Lm5hbWUpLCB7XG4gICAgICAgICAgICAgIGZvcmNlOiB0cnVlLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICApXG4gICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY3JlYXRlRGlzY292ZXJ5U29ja2V0U2VydmVyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgaWYgKHRoaXMuc29ja2V0SU8gfHwgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfU09DS0VUX1BPUlQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzLmVudi5XT1JLRkxPV19TT0NLRVRfSU5GT19QQVRIID0gdGhpcy5nZXRTb2NrZXRJbmZvRmlsZVBhdGgoKTtcbiAgICAgIGNvbnN0IGNvbmZpZzogU29ja2V0U2VydmVyQ29uZmlnID0ge1xuICAgICAgICBpc0RldlNlcnZlcjogQm9vbGVhbih0aGlzLmNvbmZpZy53YXRjaCksXG4gICAgICAgIHNvY2tldEluZm9GaWxlUGF0aDogdGhpcy5nZXRTb2NrZXRJbmZvRmlsZVBhdGgoKSxcbiAgICAgICAgb25GaWxlRGlzY292ZXJlZDogKFxuICAgICAgICAgIGZpbGVQYXRoOiBzdHJpbmcsXG4gICAgICAgICAgaGFzV29ya2Zsb3c6IGJvb2xlYW4sXG4gICAgICAgICAgaGFzU3RlcDogYm9vbGVhbixcbiAgICAgICAgICBoYXNTZXJkZTogYm9vbGVhblxuICAgICAgICApID0+IHtcbiAgICAgICAgICBjb25zdCBub3JtYWxpemVkRmlsZVBhdGggPSB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChmaWxlUGF0aCk7XG4gICAgICAgICAgbGV0IGhhc0NhY2hlVHJhY2tpbmdDaGFuZ2UgPSBmYWxzZTtcbiAgICAgICAgICBjb25zdCB3YXNUcmFja2VkRGVwZW5kZW5jeSA9XG4gICAgICAgICAgICB0aGlzLnRyYWNrZWREZXBlbmRlbmN5RmlsZXMuaGFzKG5vcm1hbGl6ZWRGaWxlUGF0aCk7XG5cbiAgICAgICAgICBpZiAoaGFzV29ya2Zsb3cpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcy5oYXMobm9ybWFsaXplZEZpbGVQYXRoKSkge1xuICAgICAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzLmFkZChub3JtYWxpemVkRmlsZVBhdGgpO1xuICAgICAgICAgICAgICBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3Qgd2FzRGVsZXRlZCA9XG4gICAgICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMuZGVsZXRlKG5vcm1hbGl6ZWRGaWxlUGF0aCk7XG4gICAgICAgICAgICBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlID0gd2FzRGVsZXRlZCB8fCBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChoYXNTdGVwKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZGlzY292ZXJlZFN0ZXBGaWxlcy5oYXMobm9ybWFsaXplZEZpbGVQYXRoKSkge1xuICAgICAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRTdGVwRmlsZXMuYWRkKG5vcm1hbGl6ZWRGaWxlUGF0aCk7XG4gICAgICAgICAgICAgIGhhc0NhY2hlVHJhY2tpbmdDaGFuZ2UgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCB3YXNEZWxldGVkID1cbiAgICAgICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLmRlbGV0ZShub3JtYWxpemVkRmlsZVBhdGgpO1xuICAgICAgICAgICAgaGFzQ2FjaGVUcmFja2luZ0NoYW5nZSA9IHdhc0RlbGV0ZWQgfHwgaGFzQ2FjaGVUcmFja2luZ0NoYW5nZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaGFzU2VyZGUpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcy5oYXMobm9ybWFsaXplZEZpbGVQYXRoKSkge1xuICAgICAgICAgICAgICBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFNlcmRlRmlsZXMuYWRkKG5vcm1hbGl6ZWRGaWxlUGF0aCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHdhc0RlbGV0ZWQgPVxuICAgICAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmRlbGV0ZShub3JtYWxpemVkRmlsZVBhdGgpO1xuICAgICAgICAgICAgaGFzQ2FjaGVUcmFja2luZ0NoYW5nZSA9IHdhc0RlbGV0ZWQgfHwgaGFzQ2FjaGVUcmFja2luZ0NoYW5nZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaGFzQ2FjaGVUcmFja2luZ0NoYW5nZSkge1xuICAgICAgICAgICAgdGhpcy5zY2hlZHVsZVdvcmtmbG93c0NhY2hlV3JpdGUoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBoYXNXb3JrZmxvdyB8fFxuICAgICAgICAgICAgaGFzU3RlcCB8fFxuICAgICAgICAgICAgaGFzU2VyZGUgfHxcbiAgICAgICAgICAgIGhhc0NhY2hlVHJhY2tpbmdDaGFuZ2UgfHxcbiAgICAgICAgICAgIHdhc1RyYWNrZWREZXBlbmRlbmN5XG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLnNjaGVkdWxlRGVmZXJyZWRSZWJ1aWxkKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvblRyaWdnZXJCdWlsZDogKCkgPT4ge1xuICAgICAgICAgIHRoaXMuc2NoZWR1bGVEZWZlcnJlZFJlYnVpbGQoKTtcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuc29ja2V0SU8gPSBhd2FpdCBjcmVhdGVTb2NrZXRTZXJ2ZXIoY29uZmlnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemVEaXNjb3ZlcnlTdGF0ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGlmICh0aGlzLmNhY2hlSW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCB0aGlzLmxvYWRXb3JrZmxvd3NDYWNoZSgpO1xuICAgICAgLy8gRGVmZXJyZWQgbW9kZSBtdXN0IG5vdCBydW4gZWFnZXIgaW5wdXQtZ3JhcGggZGlzY292ZXJ5OyBlbnRyaWVzIGFyZVxuICAgICAgLy8gZGlzY292ZXJlZCB2aWEgbG9hZGVyLT5zb2NrZXQgbm90aWZpY2F0aW9ucyBkdXJpbmcgTmV4dCdzIGJ1aWxkLlxuICAgICAgdGhpcy5jYWNoZUluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldERpc3REaXIoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiAodGhpcy5jb25maWcgYXMgeyBkaXN0RGlyPzogc3RyaW5nIH0pLmRpc3REaXIgfHwgJy5uZXh0JztcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFdvcmtmbG93c0NhY2hlRmlsZVBhdGgoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiBqb2luKFxuICAgICAgICB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgICB0aGlzLmdldERpc3REaXIoKSxcbiAgICAgICAgJ2NhY2hlJyxcbiAgICAgICAgJ3dvcmtmbG93cy5qc29uJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFNvY2tldEluZm9GaWxlUGF0aCgpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIGpvaW4oXG4gICAgICAgIHRoaXMuY29uZmlnLndvcmtpbmdEaXIsXG4gICAgICAgIHRoaXMuZ2V0RGlzdERpcigpLFxuICAgICAgICBTT0NLRVRfSU5GT19GSUxFTkFNRVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGZpbmRQYWNrYWdlSnNvblBhdGgoZmlsZVBhdGg6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICAgICAgbGV0IGN1cnJlbnREaXIgPSBkaXJuYW1lKGZpbGVQYXRoKTtcbiAgICAgIGxldCBwcmV2aW91c0RpciA9ICcnO1xuXG4gICAgICB3aGlsZSAoY3VycmVudERpciAhPT0gcHJldmlvdXNEaXIpIHtcbiAgICAgICAgY29uc3QgcGFja2FnZUpzb25QYXRoID0gam9pbihjdXJyZW50RGlyLCAncGFja2FnZS5qc29uJyk7XG4gICAgICAgIGlmIChleGlzdHNTeW5jKHBhY2thZ2VKc29uUGF0aCkpIHtcbiAgICAgICAgICByZXR1cm4gcGFja2FnZUpzb25QYXRoO1xuICAgICAgICB9XG4gICAgICAgIHByZXZpb3VzRGlyID0gY3VycmVudERpcjtcbiAgICAgICAgY3VycmVudERpciA9IGRpcm5hbWUoY3VycmVudERpcik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2hvdWxkUHJlZmVyU291cmNlQmFja2VkUGFja2FnZVBhdGgoZmlsZVBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFBhdGggPSBmaWxlUGF0aC5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gICAgICAvLyBPbmx5IHByZWZlciBzb3VyY2UgZm9yIHdvcmtzcGFjZSBwYWNrYWdlcyAobm90IGluIG5vZGVfbW9kdWxlcykuXG4gICAgICAvLyBGb3IgdGFyYmFsbC1pbnN0YWxsZWQgcGFja2FnZXMsIHVzaW5nIHNvdXJjZS1iYWNrZWQgcGF0aHMgY2F1c2VzXG4gICAgICAvLyBlc2J1aWxkIHRvIGJ1bmRsZSB0aGUgZnVsbCBzb3VyY2UgdHJlZSAoaW5jbHVkaW5nIHdvcmxkLnRzIHdpdGhcbiAgICAgIC8vIHByb2Nlc3MuY3dkKCkpIGluc3RlYWQgb2YgZXh0ZXJuYWxpemluZyBwcm9wZXJseS5cbiAgICAgIGlmIChcbiAgICAgICAgbm9ybWFsaXplZFBhdGguaW5jbHVkZXMoJy9wYWNrYWdlcy8nKSAmJlxuICAgICAgICAhbm9ybWFsaXplZFBhdGguaW5jbHVkZXMoJy9ub2RlX21vZHVsZXMvJylcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFub3JtYWxpemVkUGF0aC5pbmNsdWRlcygnL25vZGVfbW9kdWxlcy8nKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBhY2thZ2VKc29uUGF0aCA9IHRoaXMuZmluZFBhY2thZ2VKc29uUGF0aChmaWxlUGF0aCk7XG4gICAgICBpZiAoIXBhY2thZ2VKc29uUGF0aCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHBhY2thZ2VKc29uID0gSlNPTi5wYXJzZShcbiAgICAgICAgICByZWFkRmlsZVN5bmMocGFja2FnZUpzb25QYXRoLCAndXRmLTgnKVxuICAgICAgICApIGFzIHsgbmFtZT86IHVua25vd24gfTtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICBwYWNrYWdlSnNvbi5uYW1lID09PSAnd29ya2Zsb3cnIHx8XG4gICAgICAgICAgKHR5cGVvZiBwYWNrYWdlSnNvbi5uYW1lID09PSAnc3RyaW5nJyAmJlxuICAgICAgICAgICAgcGFja2FnZUpzb24ubmFtZS5zdGFydHNXaXRoKCdAd29ya2Zsb3cvJykpXG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgbm9ybWFsaXplRGlzY292ZXJlZEZpbGVQYXRoKGZpbGVQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIGlzQWJzb2x1dGUoZmlsZVBhdGgpXG4gICAgICAgID8gZmlsZVBhdGhcbiAgICAgICAgOiByZXNvbHZlKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsIGZpbGVQYXRoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGZpbHRlckV4aXN0aW5nRmlsZXMoZmlsZVBhdGhzOiBzdHJpbmdbXSk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRGaWxlUGF0aHMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFxuICAgICAgICAgIGZpbGVQYXRocy5tYXAoKGZpbGVQYXRoKSA9PlxuICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoZmlsZVBhdGgpXG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgICApLnNvcnQoKTtcblxuICAgICAgY29uc3QgZXhpc3RpbmdGaWxlcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBub3JtYWxpemVkRmlsZVBhdGhzLm1hcChhc3luYyAoZmlsZVBhdGgpID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgZmlsZVN0YXRzID0gYXdhaXQgc3RhdChmaWxlUGF0aCk7XG4gICAgICAgICAgICByZXR1cm4gZmlsZVN0YXRzLmlzRmlsZSgpID8gZmlsZVBhdGggOiBudWxsO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgKTtcblxuICAgICAgcmV0dXJuIGV4aXN0aW5nRmlsZXMuZmlsdGVyKChmaWxlUGF0aCk6IGZpbGVQYXRoIGlzIHN0cmluZyA9PlxuICAgICAgICBCb29sZWFuKGZpbGVQYXRoKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGNyZWF0ZURlZmVycmVkQnVpbGRTaWduYXR1cmUoXG4gICAgICBpbnB1dEZpbGVzOiBzdHJpbmdbXVxuICAgICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICBjb25zdCBub3JtYWxpemVkRmlsZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFtcbiAgICAgICAgICAuLi5pbnB1dEZpbGVzLm1hcCgoZmlsZVBhdGgpID0+XG4gICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChmaWxlUGF0aClcbiAgICAgICAgICApLFxuICAgICAgICAgIC4uLnRoaXMudHJhY2tlZERlcGVuZGVuY3lGaWxlcyxcbiAgICAgICAgXSlcbiAgICAgICkuc29ydCgpO1xuXG4gICAgICBjb25zdCBzaWduYXR1cmVQYXJ0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBub3JtYWxpemVkRmlsZXMubWFwKGFzeW5jIChmaWxlUGF0aCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBmaWxlU3RhdHMgPSBhd2FpdCBzdGF0KGZpbGVQYXRoKTtcbiAgICAgICAgICAgIHJldHVybiBgJHtmaWxlUGF0aH06JHtmaWxlU3RhdHMuc2l6ZX06JHtNYXRoLnRydW5jKGZpbGVTdGF0cy5tdGltZU1zKX1gO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcmV0dXJuIGAke2ZpbGVQYXRofTptaXNzaW5nYDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgICBjb25zdCBzaWduYXR1cmVIYXNoID0gY3JlYXRlSGFzaCgnc2hhMjU2Jyk7XG4gICAgICBmb3IgKGNvbnN0IHNpZ25hdHVyZVBhcnQgb2Ygc2lnbmF0dXJlUGFydHMpIHtcbiAgICAgICAgc2lnbmF0dXJlSGFzaC51cGRhdGUoc2lnbmF0dXJlUGFydCk7XG4gICAgICAgIHNpZ25hdHVyZUhhc2gudXBkYXRlKCdcXG4nKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHNpZ25hdHVyZUhhc2guZGlnZXN0KCdoZXgnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGNvbGxlY3RUcmFja2VkRGlzY292ZXJlZEVudHJpZXMoKTogUHJvbWlzZTx7XG4gICAgICBkaXNjb3ZlcmVkU3RlcHM6IHN0cmluZ1tdO1xuICAgICAgZGlzY292ZXJlZFdvcmtmbG93czogc3RyaW5nW107XG4gICAgICBkaXNjb3ZlcmVkU2VyZGVGaWxlczogc3RyaW5nW107XG4gICAgfT4ge1xuICAgICAgaWYgKHRoaXMudHJhY2tlZERlcGVuZGVuY3lGaWxlcy5zaXplID09PSAwKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZGlzY292ZXJlZFN0ZXBzOiBbXSxcbiAgICAgICAgICBkaXNjb3ZlcmVkV29ya2Zsb3dzOiBbXSxcbiAgICAgICAgICBkaXNjb3ZlcmVkU2VyZGVGaWxlczogW10sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgd29ya2Zsb3dGaWxlcywgc3RlcEZpbGVzLCBzZXJkZUZpbGVzIH0gPVxuICAgICAgICBhd2FpdCB0aGlzLnJlY29uY2lsZURpc2NvdmVyZWRFbnRyaWVzKHtcbiAgICAgICAgICB3b3JrZmxvd0NhbmRpZGF0ZXM6IHRoaXMudHJhY2tlZERlcGVuZGVuY3lGaWxlcyxcbiAgICAgICAgICBzdGVwQ2FuZGlkYXRlczogdGhpcy50cmFja2VkRGVwZW5kZW5jeUZpbGVzLFxuICAgICAgICAgIHNlcmRlQ2FuZGlkYXRlczogdGhpcy50cmFja2VkRGVwZW5kZW5jeUZpbGVzLFxuICAgICAgICAgIHZhbGlkYXRlUGF0dGVybnM6IHRydWUsXG4gICAgICAgIH0pO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBkaXNjb3ZlcmVkU3RlcHM6IEFycmF5LmZyb20oc3RlcEZpbGVzKS5zb3J0KCksXG4gICAgICAgIGRpc2NvdmVyZWRXb3JrZmxvd3M6IEFycmF5LmZyb20od29ya2Zsb3dGaWxlcykuc29ydCgpLFxuICAgICAgICBkaXNjb3ZlcmVkU2VyZGVGaWxlczogQXJyYXkuZnJvbShzZXJkZUZpbGVzKS5zb3J0KCksXG4gICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcmVmcmVzaFRyYWNrZWREZXBlbmRlbmN5RmlsZXMoXG4gICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcjogc3RyaW5nLFxuICAgICAgcm91dGVGaWxlTmFtZTogc3RyaW5nXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBjb25zdCBidW5kbGVGaWxlcyA9IFtcbiAgICAgICAgam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgYHN0ZXAvJHtyb3V0ZUZpbGVOYW1lfWApLFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCBgZmxvdy8ke3JvdXRlRmlsZU5hbWV9YCksXG4gICAgICBdO1xuICAgICAgY29uc3QgdHJhY2tlZEZpbGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICAgIGZvciAoY29uc3QgYnVuZGxlRmlsZSBvZiBidW5kbGVGaWxlcykge1xuICAgICAgICBjb25zdCBidW5kbGVTb3VyY2VzID0gYXdhaXQgdGhpcy5leHRyYWN0QnVuZGxlU291cmNlRmlsZXMoYnVuZGxlRmlsZSk7XG4gICAgICAgIGZvciAoY29uc3Qgc291cmNlRmlsZSBvZiBidW5kbGVTb3VyY2VzKSB7XG4gICAgICAgICAgdHJhY2tlZEZpbGVzLmFkZChzb3VyY2VGaWxlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodHJhY2tlZEZpbGVzLnNpemUgPiAwKSB7XG4gICAgICAgIHRoaXMudHJhY2tlZERlcGVuZGVuY3lGaWxlcyA9IHRyYWNrZWRGaWxlcztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGV4dHJhY3RCdW5kbGVTb3VyY2VGaWxlcyhcbiAgICAgIGJ1bmRsZUZpbGVQYXRoOiBzdHJpbmdcbiAgICApOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICBsZXQgYnVuZGxlQ29udGVudHM6IHN0cmluZztcbiAgICAgIHRyeSB7XG4gICAgICAgIGJ1bmRsZUNvbnRlbnRzID0gYXdhaXQgcmVhZEZpbGUoYnVuZGxlRmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYmFzZURpcmVjdG9yeSA9IGRpcm5hbWUoYnVuZGxlRmlsZVBhdGgpO1xuICAgICAgY29uc3QgbG9jYWxTb3VyY2VGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgICAvLyBFeHRyYWN0IGlubGluZSBiYXNlNjQgc291cmNlbWFwcyB2aWEgc3RyaW5nIHNjYW5uaW5nLiBBIHByZXZpb3VzXG4gICAgICAvLyBpbXBsZW1lbnRhdGlvbiB1c2VkIGBidW5kbGVDb250ZW50cy5tYXRjaEFsbCgvLi4uW0EtWmEtejAtOSsvPV0rLi4uL2cpYFxuICAgICAgLy8gd2hpY2ggb3ZlcmZsb3dzIFY4J3MgcmVnZXggc3RhY2tcbiAgICAgIC8vIChgUmFuZ2VFcnJvcjogTWF4aW11bSBjYWxsIHN0YWNrIHNpemUgZXhjZWVkZWQgYXQgUmVnRXhwU3RyaW5nSXRlcmF0b3IubmV4dGApXG4gICAgICAvLyBvbiBidW5kbGVzIHdpdGggbGFyZ2UgaW5saW5lIHNvdXJjZW1hcHMg4oCUIFY4J3MgaXJyZWdleHAgdXNlc1xuICAgICAgLy8gcmVjdXJzaW9uIGZvciBncmVlZHkgY2hhcmFjdGVyLWNsYXNzIHF1YW50aWZpZXJzIGFuZCBjZXJ0YWluIGxvbmdcbiAgICAgIC8vIGJhc2U2NCBpbnB1dHMgZXhoYXVzdCB0aGUgY2FsbCBzdGFjay5cbiAgICAgIGNvbnN0IHNvdXJjZU1hcFByZWZpeCA9ICcvLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb24nO1xuICAgICAgY29uc3QgYmFzZTY0TWFya2VyID0gJztiYXNlNjQsJztcbiAgICAgIGNvbnN0IHNvdXJjZU1hcE1hdGNoZXM6IEFycmF5PHsgYmFzZTY0VmFsdWU6IHN0cmluZyB9PiA9IFtdO1xuICAgICAgbGV0IHNjYW5Gcm9tID0gMDtcbiAgICAgIHdoaWxlIChzY2FuRnJvbSA8IGJ1bmRsZUNvbnRlbnRzLmxlbmd0aCkge1xuICAgICAgICBjb25zdCBwcmVmaXhJZHggPSBidW5kbGVDb250ZW50cy5pbmRleE9mKHNvdXJjZU1hcFByZWZpeCwgc2NhbkZyb20pO1xuICAgICAgICBpZiAocHJlZml4SWR4ID09PSAtMSkgYnJlYWs7XG4gICAgICAgIGNvbnN0IGJhc2U2NFN0YXJ0ID0gYnVuZGxlQ29udGVudHMuaW5kZXhPZihcbiAgICAgICAgICBiYXNlNjRNYXJrZXIsXG4gICAgICAgICAgcHJlZml4SWR4ICsgc291cmNlTWFwUHJlZml4Lmxlbmd0aFxuICAgICAgICApO1xuICAgICAgICBpZiAoYmFzZTY0U3RhcnQgPT09IC0xKSB7XG4gICAgICAgICAgc2NhbkZyb20gPSBwcmVmaXhJZHggKyBzb3VyY2VNYXBQcmVmaXgubGVuZ3RoO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIEJhaWwgaWYgYSBjb21tYSBhcHBlYXJzIGJlZm9yZSBgO2Jhc2U2NCxgIOKAlCB0aGF0IG1lYW5zIHRoaXNcbiAgICAgICAgLy8gd2Fzbid0IGEgYGRhdGE6YXBwbGljYXRpb24vanNvbls7cGFyYW1zXTtiYXNlNjQsLi4uYCBVUkwgYWZ0ZXJcbiAgICAgICAgLy8gYWxsICh0aGUgY29tbWEgd291bGQgdGVybWluYXRlIHRoZSBkYXRhIFVSTCBwYXJhbWV0ZXJzKS5cbiAgICAgICAgY29uc3QgY29tbWFCZWZvcmUgPSBidW5kbGVDb250ZW50cy5pbmRleE9mKCcsJywgcHJlZml4SWR4KTtcbiAgICAgICAgaWYgKGNvbW1hQmVmb3JlICE9PSAtMSAmJiBjb21tYUJlZm9yZSA8IGJhc2U2NFN0YXJ0KSB7XG4gICAgICAgICAgc2NhbkZyb20gPSBiYXNlNjRTdGFydDtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2YWx1ZVN0YXJ0ID0gYmFzZTY0U3RhcnQgKyBiYXNlNjRNYXJrZXIubGVuZ3RoO1xuICAgICAgICAvLyBCYXNlNjQgcGF5bG9hZCB0ZXJtaW5hdGVzIGF0IGZpcnN0IG5vbi1iYXNlNjQgY2hhciAobmV3bGluZSxcbiAgICAgICAgLy8gY2xvc2luZyBgKi9gLCBldGMuKS4gU2Nhbm5pbmcgYSBzbWFsbCBhbHBoYWJldCBieSBjaGFyIGlzIGZhclxuICAgICAgICAvLyBjaGVhcGVyIHRoYW4gYmFja3RyYWNraW5nIGEgcmVnZXggb3ZlciBhIG11bHRpLU1CIGNhcHR1cmUuXG4gICAgICAgIGxldCB2YWx1ZUVuZCA9IHZhbHVlU3RhcnQ7XG4gICAgICAgIHdoaWxlICh2YWx1ZUVuZCA8IGJ1bmRsZUNvbnRlbnRzLmxlbmd0aCkge1xuICAgICAgICAgIGNvbnN0IGNvZGUgPSBidW5kbGVDb250ZW50cy5jaGFyQ29kZUF0KHZhbHVlRW5kKTtcbiAgICAgICAgICAvLyBBLVogMHg0MS0weDVBLCBhLXogMHg2MS0weDdBLCAwLTkgMHgzMC0weDM5LCAnKycgMHgyQixcbiAgICAgICAgICAvLyAnLycgMHgyRiwgJz0nIDB4M0RcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhKFxuICAgICAgICAgICAgICAoY29kZSA+PSAweDQxICYmIGNvZGUgPD0gMHg1YSkgfHxcbiAgICAgICAgICAgICAgKGNvZGUgPj0gMHg2MSAmJiBjb2RlIDw9IDB4N2EpIHx8XG4gICAgICAgICAgICAgIChjb2RlID49IDB4MzAgJiYgY29kZSA8PSAweDM5KSB8fFxuICAgICAgICAgICAgICBjb2RlID09PSAweDJiIHx8XG4gICAgICAgICAgICAgIGNvZGUgPT09IDB4MmYgfHxcbiAgICAgICAgICAgICAgY29kZSA9PT0gMHgzZFxuICAgICAgICAgICAgKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhbHVlRW5kKys7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlRW5kID4gdmFsdWVTdGFydCkge1xuICAgICAgICAgIHNvdXJjZU1hcE1hdGNoZXMucHVzaCh7XG4gICAgICAgICAgICBiYXNlNjRWYWx1ZTogYnVuZGxlQ29udGVudHMuc2xpY2UodmFsdWVTdGFydCwgdmFsdWVFbmQpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHNjYW5Gcm9tID0gdmFsdWVFbmQ7XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgbWF0Y2ggb2Ygc291cmNlTWFwTWF0Y2hlcykge1xuICAgICAgICBjb25zdCBiYXNlNjRWYWx1ZSA9IG1hdGNoLmJhc2U2NFZhbHVlO1xuICAgICAgICBpZiAoIWJhc2U2NFZhbHVlKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgc291cmNlTWFwOiB7IHNvdXJjZVJvb3Q/OiB1bmtub3duOyBzb3VyY2VzPzogdW5rbm93biB9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHNvdXJjZU1hcCA9IEpTT04ucGFyc2UoXG4gICAgICAgICAgICBCdWZmZXIuZnJvbShiYXNlNjRWYWx1ZSwgJ2Jhc2U2NCcpLnRvU3RyaW5nKCd1dGYtOCcpXG4gICAgICAgICAgKSBhcyB7IHNvdXJjZVJvb3Q/OiB1bmtub3duOyBzb3VyY2VzPzogdW5rbm93biB9O1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNvdXJjZVJvb3QgPVxuICAgICAgICAgIHR5cGVvZiBzb3VyY2VNYXAuc291cmNlUm9vdCA9PT0gJ3N0cmluZycgPyBzb3VyY2VNYXAuc291cmNlUm9vdCA6ICcnO1xuICAgICAgICBjb25zdCBzb3VyY2VzID0gQXJyYXkuaXNBcnJheShzb3VyY2VNYXAuc291cmNlcylcbiAgICAgICAgICA/IHNvdXJjZU1hcC5zb3VyY2VzLmZpbHRlcihcbiAgICAgICAgICAgICAgKHNvdXJjZSk6IHNvdXJjZSBpcyBzdHJpbmcgPT4gdHlwZW9mIHNvdXJjZSA9PT0gJ3N0cmluZydcbiAgICAgICAgICAgIClcbiAgICAgICAgICA6IFtdO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc291cmNlIG9mIHNvdXJjZXMpIHtcbiAgICAgICAgICBpZiAoc291cmNlLnN0YXJ0c1dpdGgoJ3dlYnBhY2s6Ly8nKSB8fCBzb3VyY2Uuc3RhcnRzV2l0aCgnPCcpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsZXQgcmVzb2x2ZWRTb3VyY2VQYXRoOiBzdHJpbmc7XG4gICAgICAgICAgaWYgKHNvdXJjZS5zdGFydHNXaXRoKCdmaWxlOi8vJykpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIHJlc29sdmVkU291cmNlUGF0aCA9IGRlY29kZVVSSUNvbXBvbmVudChuZXcgVVJMKHNvdXJjZSkucGF0aG5hbWUpO1xuICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAoaXNBYnNvbHV0ZShzb3VyY2UpKSB7XG4gICAgICAgICAgICByZXNvbHZlZFNvdXJjZVBhdGggPSBzb3VyY2U7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc29sdmVkU291cmNlUGF0aCA9IHJlc29sdmUoYmFzZURpcmVjdG9yeSwgc291cmNlUm9vdCwgc291cmNlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBub3JtYWxpemVkU291cmNlUGF0aCA9XG4gICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChyZXNvbHZlZFNvdXJjZVBhdGgpO1xuICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRTb3VyY2VQYXRoRm9yQ2hlY2sgPSBub3JtYWxpemVkU291cmNlUGF0aC5yZXBsYWNlKFxuICAgICAgICAgICAgL1xcXFwvZyxcbiAgICAgICAgICAgICcvJ1xuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgaXNTb3VyY2VCYWNrZWRQYWNrYWdlUGF0aCA9XG4gICAgICAgICAgICB0aGlzLnNob3VsZFByZWZlclNvdXJjZUJhY2tlZFBhY2thZ2VQYXRoKG5vcm1hbGl6ZWRTb3VyY2VQYXRoKTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBub3JtYWxpemVkU291cmNlUGF0aEZvckNoZWNrLmluY2x1ZGVzKCcvLndlbGwta25vd24vd29ya2Zsb3cvJykgfHxcbiAgICAgICAgICAgICghaXNTb3VyY2VCYWNrZWRQYWNrYWdlUGF0aCAmJlxuICAgICAgICAgICAgICBub3JtYWxpemVkU291cmNlUGF0aEZvckNoZWNrLmluY2x1ZGVzKCcvbm9kZV9tb2R1bGVzLycpKSB8fFxuICAgICAgICAgICAgKCFpc1NvdXJjZUJhY2tlZFBhY2thZ2VQYXRoICYmXG4gICAgICAgICAgICAgIG5vcm1hbGl6ZWRTb3VyY2VQYXRoRm9yQ2hlY2suaW5jbHVkZXMoJy8ucG5wbS8nKSkgfHxcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRTb3VyY2VQYXRoRm9yQ2hlY2suaW5jbHVkZXMoJy8ubmV4dC8nKSB8fFxuICAgICAgICAgICAgbm9ybWFsaXplZFNvdXJjZVBhdGhGb3JDaGVjay5lbmRzV2l0aCgnL3ZpcnR1YWwtZW50cnkuanMnKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbG9jYWxTb3VyY2VGaWxlcy5hZGQobm9ybWFsaXplZFNvdXJjZVBhdGgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBBcnJheS5mcm9tKGxvY2FsU291cmNlRmlsZXMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2NoZWR1bGVXb3JrZmxvd3NDYWNoZVdyaXRlKCk6IHZvaWQge1xuICAgICAgaWYgKHRoaXMuY2FjaGVXcml0ZVRpbWVyKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmNhY2hlV3JpdGVUaW1lcik7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY2FjaGVXcml0ZVRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMuY2FjaGVXcml0ZVRpbWVyID0gbnVsbDtcbiAgICAgICAgdm9pZCB0aGlzLndyaXRlV29ya2Zsb3dzQ2FjaGUoKS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ0ZhaWxlZCB0byB3cml0ZSB3b3JrZmxvdyBkaXNjb3ZlcnkgY2FjaGUnLCBlcnJvcik7XG4gICAgICAgIH0pO1xuICAgICAgfSwgNTApO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2NoZWR1bGVEZWZlcnJlZFJlYnVpbGQoKTogdm9pZCB7XG4gICAgICBpZiAodGhpcy5kZWZlcnJlZFJlYnVpbGRUaW1lcikge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5kZWZlcnJlZFJlYnVpbGRUaW1lcik7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZGVmZXJyZWRSZWJ1aWxkVGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdGhpcy5kZWZlcnJlZFJlYnVpbGRUaW1lciA9IG51bGw7XG4gICAgICAgIHZvaWQgdGhpcy5vbkJlZm9yZURlZmVycmVkRW50cmllcygpLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICdbd29ya2Zsb3ddIERlZmVycmVkIHJlYnVpbGQgYWZ0ZXIgc291cmNlIHVwZGF0ZSBmYWlsZWQuJyxcbiAgICAgICAgICAgIGVycm9yXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9LCA3NSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZWFkV29ya2Zsb3dzQ2FjaGUoKTogUHJvbWlzZTx7XG4gICAgICB3b3JrZmxvd0ZpbGVzOiBzdHJpbmdbXTtcbiAgICAgIHN0ZXBGaWxlczogc3RyaW5nW107XG4gICAgfSB8IG51bGw+IHtcbiAgICAgIGNvbnN0IGNhY2hlRmlsZVBhdGggPSB0aGlzLmdldFdvcmtmbG93c0NhY2hlRmlsZVBhdGgoKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY2FjaGVDb250ZW50cyA9IGF3YWl0IHJlYWRGaWxlKGNhY2hlRmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGNhY2hlQ29udGVudHMpIGFzIHtcbiAgICAgICAgICB3b3JrZmxvd0ZpbGVzPzogdW5rbm93bjtcbiAgICAgICAgICBzdGVwRmlsZXM/OiB1bmtub3duO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHdvcmtmbG93RmlsZXMgPSBBcnJheS5pc0FycmF5KHBhcnNlZC53b3JrZmxvd0ZpbGVzKVxuICAgICAgICAgID8gcGFyc2VkLndvcmtmbG93RmlsZXMuZmlsdGVyKFxuICAgICAgICAgICAgICAoaXRlbSk6IGl0ZW0gaXMgc3RyaW5nID0+IHR5cGVvZiBpdGVtID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgKVxuICAgICAgICAgIDogW107XG4gICAgICAgIGNvbnN0IHN0ZXBGaWxlcyA9IEFycmF5LmlzQXJyYXkocGFyc2VkLnN0ZXBGaWxlcylcbiAgICAgICAgICA/IHBhcnNlZC5zdGVwRmlsZXMuZmlsdGVyKFxuICAgICAgICAgICAgICAoaXRlbSk6IGl0ZW0gaXMgc3RyaW5nID0+IHR5cGVvZiBpdGVtID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgKVxuICAgICAgICAgIDogW107XG5cbiAgICAgICAgcmV0dXJuIHsgd29ya2Zsb3dGaWxlcywgc3RlcEZpbGVzIH07XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBsb2FkV29ya2Zsb3dzQ2FjaGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBjb25zdCBjYWNoZWREYXRhID0gYXdhaXQgdGhpcy5yZWFkV29ya2Zsb3dzQ2FjaGUoKTtcbiAgICAgIGlmICghY2FjaGVkRGF0YSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCB7IHdvcmtmbG93RmlsZXMsIHN0ZXBGaWxlcywgc2VyZGVGaWxlcyB9ID1cbiAgICAgICAgYXdhaXQgdGhpcy5yZWNvbmNpbGVEaXNjb3ZlcmVkRW50cmllcyh7XG4gICAgICAgICAgd29ya2Zsb3dDYW5kaWRhdGVzOiBjYWNoZWREYXRhLndvcmtmbG93RmlsZXMsXG4gICAgICAgICAgc3RlcENhbmRpZGF0ZXM6IGNhY2hlZERhdGEuc3RlcEZpbGVzLFxuICAgICAgICAgIHNlcmRlQ2FuZGlkYXRlczogdGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcyxcbiAgICAgICAgICB2YWxpZGF0ZVBhdHRlcm5zOiB0cnVlLFxuICAgICAgICB9KTtcblxuICAgICAgdGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcy5jbGVhcigpO1xuICAgICAgdGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLmNsZWFyKCk7XG4gICAgICB0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmNsZWFyKCk7XG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHdvcmtmbG93RmlsZXMpIHtcbiAgICAgICAgdGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcy5hZGQoZmlsZVBhdGgpO1xuICAgICAgfVxuICAgICAgZm9yIChjb25zdCBmaWxlUGF0aCBvZiBzdGVwRmlsZXMpIHtcbiAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLmFkZChmaWxlUGF0aCk7XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHNlcmRlRmlsZXMpIHtcbiAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcy5hZGQoZmlsZVBhdGgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgd3JpdGVXb3JrZmxvd3NDYWNoZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IGNhY2hlRmlsZVBhdGggPSB0aGlzLmdldFdvcmtmbG93c0NhY2hlRmlsZVBhdGgoKTtcbiAgICAgIGNvbnN0IGNhY2hlRGlyID0gam9pbih0aGlzLmNvbmZpZy53b3JraW5nRGlyLCB0aGlzLmdldERpc3REaXIoKSwgJ2NhY2hlJyk7XG4gICAgICBhd2FpdCBta2RpcihjYWNoZURpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgICAgIGNvbnN0IGNhY2hlRGF0YSA9IHtcbiAgICAgICAgd29ya2Zsb3dGaWxlczogQXJyYXkuZnJvbSh0aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzKS5zb3J0KCksXG4gICAgICAgIHN0ZXBGaWxlczogQXJyYXkuZnJvbSh0aGlzLmRpc2NvdmVyZWRTdGVwRmlsZXMpLnNvcnQoKSxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IHdyaXRlRmlsZShjYWNoZUZpbGVQYXRoLCBKU09OLnN0cmluZ2lmeShjYWNoZURhdGEsIG51bGwsIDIpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHdyaXRlU3R1YkZpbGVzKG91dHB1dERpcjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAvLyBUdXJib3BhY2sgY3VycmVudGx5IGhhcyBhIHdvcmtlci1jb25jdXJyZW5jeSBsaW1pdGF0aW9uIGZvciBwZW5kaW5nXG4gICAgICAvLyB2aXJ0dWFsIGVudHJpZXMuIFdhcm4gaWYgcGFyYWxsZWxpc20gaXMgdG9vIGxvdyB0byByZWxpYWJseSBkaXNjb3Zlci5cbiAgICAgIGNvbnN0IHBhcmFsbGVsaXNtQ291bnQgPSBvcy5hdmFpbGFibGVQYXJhbGxlbGlzbSgpO1xuICAgICAgaWYgKHByb2Nlc3MuZW52LlRVUkJPUEFDSyAmJiBwYXJhbGxlbGlzbUNvdW50IDwgNCkge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgYEF2YWlsYWJsZSBwYXJhbGxlbGlzbSBvZiAke3BhcmFsbGVsaXNtQ291bnR9IGlzIGxlc3MgdGhhbiBuZWVkZWQgNC4gVGhpcyBjYW4gY2F1c2Ugd29ya2Zsb3dzL3N0ZXBzIHRvIGZhaWwgdG8gZGlzY292ZXIgcHJvcGVybHkgaW4gdHVyYm9wYWNrYFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByb3V0ZVN0dWJDb250ZW50ID0gW1xuICAgICAgICBgLy8gJHtST1VURV9TVFVCX0ZJTEVfTUFSS0VSfWAsXG4gICAgICAgICdleHBvcnQgY29uc3QgX193b3JrZmxvd1JvdXRlU3R1YiA9IHRydWU7JyxcbiAgICAgIF0uam9pbignXFxuJyk7XG4gICAgICBjb25zdCB3b3JrZmxvd0dlbmVyYXRlZERpciA9IGpvaW4ob3V0cHV0RGlyLCAnLndlbGwta25vd24vd29ya2Zsb3cvdjEnKTtcblxuICAgICAgYXdhaXQgbWtkaXIoam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgJ2Zsb3cnKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBhd2FpdCBta2Rpcihqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnd2ViaG9vay9bdG9rZW5dJyksIHtcbiAgICAgICAgcmVjdXJzaXZlOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnLmdpdGlnbm9yZScpLFxuICAgICAgICAnKidcbiAgICAgICk7XG5cbiAgICAgIC8vIFYyOiBPbmx5IGZsb3cgKyB3ZWJob29rIHN0dWJzIG5lZWRlZCAobm8gc2VwYXJhdGUgc3RlcCByb3V0ZSkuXG4gICAgICAvLyBTdHVicyBhcmUgcmVwbGFjZWQgYnkgZ2VuZXJhdGVkIG91dHB1dCBvbmNlIGRpc2NvdmVyeSBmaW5pc2hlcy5cbiAgICAgIGF3YWl0IHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnZmxvdy9yb3V0ZS5qcycpLFxuICAgICAgICByb3V0ZVN0dWJDb250ZW50XG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQoXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICd3ZWJob29rL1t0b2tlbl0vcm91dGUuanMnKSxcbiAgICAgICAgcm91dGVTdHViQ29udGVudFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYXN5bmMgZ2V0SW5wdXRGaWxlcygpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICAvLyBSZWFkIE5leHQuanMncyBhcHAtcGF0aHMtbWFuaWZlc3QuanNvbiBmcm9tIGEgcHJldmlvdXMgYnVpbGQgdG9cbiAgICAgIC8vIGRldGVybWluZSB3aGljaCBmaWxlcyBhcmUgYWN0dWFsIHJvdXRlIGVudHJ5cG9pbnRzLiBUaGlzIGF2b2lkc1xuICAgICAgLy8gcHJlZGljdGluZyBOZXh0LmpzIGNvbnZlbnRpb25zIHdpdGggcmVnZXhlcyBhbmQgaW5zdGVhZCByZWFkc1xuICAgICAgLy8gZnJvbSBOZXh0LmpzJ3Mgb3duIG91dHB1dC5cbiAgICAgIGNvbnN0IG5leHREaXIgPSBqb2luKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsICcubmV4dCcpO1xuICAgICAgY29uc3QgbWFuaWZlc3RQYXRoID0gam9pbihuZXh0RGlyLCAnYXBwLXBhdGhzLW1hbmlmZXN0Lmpzb24nKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IG1hbmlmZXN0Q29udGVudCA9IHJlYWRGaWxlU3luYyhtYW5pZmVzdFBhdGgsICd1dGYtOCcpO1xuICAgICAgICBjb25zdCBtYW5pZmVzdCA9IEpTT04ucGFyc2UobWFuaWZlc3RDb250ZW50KSBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAgICAgICAvLyBUaGUgbWFuaWZlc3QgbWFwcyByb3V0ZSBwYXRocyB0byB0aGVpciBzb3VyY2UgZmlsZXMuXG4gICAgICAgIC8vIEV4dHJhY3QgdGhlIHNvdXJjZSBmaWxlIHBhdGhzIGFuZCByZXNvbHZlIHRoZW0uXG4gICAgICAgIGNvbnN0IG1hbmlmZXN0RmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgICAgZm9yIChjb25zdCBzb3VyY2VQYXRoIG9mIE9iamVjdC52YWx1ZXMobWFuaWZlc3QpKSB7XG4gICAgICAgICAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlKG5leHREaXIsICdzZXJ2ZXInLCBzb3VyY2VQYXRoKTtcbiAgICAgICAgICAvLyBUaGUgbWFuaWZlc3QgcG9pbnRzIHRvIGJ1aWx0IG91dHB1dDsgZmluZCB0aGUgc291cmNlIGZpbGVcbiAgICAgICAgICAvLyBieSBtYXRjaGluZyBhZ2FpbnN0IHRoZSBiYXNlIGJ1aWxkZXIncyBmdWxsIGZpbGUgbGlzdC5cbiAgICAgICAgICBtYW5pZmVzdEZpbGVzLmFkZChyZXNvbHZlZCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVc2UgdGhlIG1hbmlmZXN0IHJvdXRlIHBhdGhzIHRvIGZpbHRlciB0aGUgaW5wdXQgZmlsZXMuXG4gICAgICAgIC8vIEEgZmlsZSBpcyBpbmNsdWRlZCBpZiBpdCBtYXRjaGVzIGEga25vd24gcm91dGUgc2VnbWVudCBmcm9tXG4gICAgICAgIC8vIHRoZSBtYW5pZmVzdCAoZS5nLiwgYXBwL2FwaS9yb3V0ZSBjb250YWlucyAnYXBwL2FwaS9yb3V0ZScpLlxuICAgICAgICBjb25zdCBpbnB1dEZpbGVzID0gYXdhaXQgc3VwZXIuZ2V0SW5wdXRGaWxlcygpO1xuICAgICAgICBjb25zdCByb3V0ZVNlZ21lbnRzID0gT2JqZWN0LmtleXMobWFuaWZlc3QpLm1hcCgocm91dGUpID0+XG4gICAgICAgICAgcm91dGUucmVwbGFjZSgvXlxcLy8sICcnKS5yZXBsYWNlKC9cXC9yb3V0ZSQvLCAnJylcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIGlucHV0RmlsZXMuZmlsdGVyKChpdGVtKSA9PlxuICAgICAgICAgIHJvdXRlU2VnbWVudHMuc29tZSgoc2VnbWVudCkgPT4gaXRlbS5pbmNsdWRlcyhzZWdtZW50KSlcbiAgICAgICAgKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBObyBtYW5pZmVzdCBmcm9tIGEgcHJldmlvdXMgYnVpbGQg4oCUIGZhbGwgYmFjayB0byB0aGUgYmFzZVxuICAgICAgICAvLyBidWlsZGVyJ3MgZnVsbCBmaWxlIHNjYW4uIFRoaXMgaXMgc2FmZSBidXQgc2xvd2VyOyBzdWJzZXF1ZW50XG4gICAgICAgIC8vIGJ1aWxkcyB3aWxsIHVzZSB0aGUgbWFuaWZlc3QuXG4gICAgICAgIHJldHVybiBzdXBlci5nZXRJbnB1dEZpbGVzKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyB3cml0ZUZ1bmN0aW9uc0NvbmZpZyhvdXRwdXREaXI6IHN0cmluZykge1xuICAgICAgLy8gd2UgZG9uJ3QgcnVuIHRoaXMgaW4gZGV2ZWxvcG1lbnQgbW9kZSBhcyBpdCdzIG5vdCBuZWVkZWRcbiAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50Jykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICAvLyBWMjogU2luZ2xlIGNvbWJpbmVkIHRyaWdnZXIgaGFuZGxlcyBib3RoIHdvcmtmbG93IGFuZCBzdGVwIGV4ZWN1dGlvblxuICAgICAgY29uc3QgZ2VuZXJhdGVkQ29uZmlnID0ge1xuICAgICAgICB2ZXJzaW9uOiAnMCcsXG4gICAgICAgIHdvcmtmbG93czoge1xuICAgICAgICAgIG1heER1cmF0aW9uOiAnbWF4JyxcbiAgICAgICAgICBleHBlcmltZW50YWxUcmlnZ2VyczogW1dPUktGTE9XX1FVRVVFX1RSSUdHRVJdLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQoXG4gICAgICAgIGpvaW4ob3V0cHV0RGlyLCAnLndlbGwta25vd24vd29ya2Zsb3cvdjEvY29uZmlnLmpzb24nKSxcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoZ2VuZXJhdGVkQ29uZmlnLCBudWxsLCAyKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHdyaXRlRmlsZUlmQ2hhbmdlZChcbiAgICAgIGZpbGVQYXRoOiBzdHJpbmcsXG4gICAgICBjb250ZW50czogc3RyaW5nIHwgQnVmZmVyXG4gICAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICBjb25zdCBuZXh0QnVmZmVyID0gQnVmZmVyLmlzQnVmZmVyKGNvbnRlbnRzKVxuICAgICAgICA/IGNvbnRlbnRzXG4gICAgICAgIDogQnVmZmVyLmZyb20oY29udGVudHMpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjdXJyZW50QnVmZmVyID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgpO1xuICAgICAgICBpZiAoY3VycmVudEJ1ZmZlci5lcXVhbHMobmV4dEJ1ZmZlcikpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBGaWxlIGRvZXMgbm90IGV4aXN0IHlldCBvciBjYW5ub3QgYmUgcmVhZDsgd3JpdGUgYSBmcmVzaCBjb3B5LlxuICAgICAgfVxuXG4gICAgICBhd2FpdCBta2RpcihkaXJuYW1lKGZpbGVQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBhd2FpdCB3cml0ZUZpbGUoZmlsZVBhdGgsIG5leHRCdWZmZXIpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjb3B5RmlsZUlmQ2hhbmdlZChcbiAgICAgIHNvdXJjZVBhdGg6IHN0cmluZyxcbiAgICAgIGRlc3RpbmF0aW9uUGF0aDogc3RyaW5nXG4gICAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICBjb25zdCBzb3VyY2VDb250ZW50cyA9IGF3YWl0IHJlYWRGaWxlKHNvdXJjZVBhdGgpO1xuICAgICAgcmV0dXJuIHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKGRlc3RpbmF0aW9uUGF0aCwgc291cmNlQ29udGVudHMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc29ydEpzb25WYWx1ZSh2YWx1ZTogdW5rbm93bik6IHVua25vd24ge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZS5tYXAoKGl0ZW0pID0+IHRoaXMuc29ydEpzb25WYWx1ZShpdGVtKSk7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgICBjb25zdCBzb3J0ZWRFbnRyaWVzID0gT2JqZWN0LmVudHJpZXModmFsdWUgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pXG4gICAgICAgICAgLnNvcnQoKFthXSwgW2JdKSA9PiBhLmxvY2FsZUNvbXBhcmUoYikpXG4gICAgICAgICAgLm1hcCgoW2tleSwgZW50cnlWYWx1ZV0pID0+IFtrZXksIHRoaXMuc29ydEpzb25WYWx1ZShlbnRyeVZhbHVlKV0pO1xuICAgICAgICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKHNvcnRlZEVudHJpZXMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcmV3cml0ZUpzb25GaWxlV2l0aFN0YWJsZUtleU9yZGVyKFxuICAgICAgZmlsZVBhdGg6IHN0cmluZ1xuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY29udGVudHMgPSBhd2FpdCByZWFkRmlsZShmaWxlUGF0aCwgJ3V0Zi04Jyk7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UoY29udGVudHMpIGFzIHVua25vd247XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSB0aGlzLnNvcnRKc29uVmFsdWUocGFyc2VkKTtcbiAgICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQoXG4gICAgICAgICAgZmlsZVBhdGgsXG4gICAgICAgICAgYCR7SlNPTi5zdHJpbmdpZnkobm9ybWFsaXplZCwgbnVsbCwgMil9XFxuYFxuICAgICAgICApO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIE1hbmlmZXN0IG1heSBub3QgZXhpc3QgKGUuZy4gbWFuaWZlc3QgZ2VuZXJhdGlvbiBmYWlsZWQpOyBpZ25vcmUuXG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBleHRyYWN0UmVsYXRpdmVJbXBvcnRTcGVjaWZpZXJzKHNvdXJjZTogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgICAgcmV0dXJuIHRoaXMuZXh0cmFjdEltcG9ydFNwZWNpZmllcnMoc291cmNlKS5maWx0ZXIoKHNwZWNpZmllcikgPT5cbiAgICAgICAgc3BlY2lmaWVyLnN0YXJ0c1dpdGgoJy4nKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGV4dHJhY3RJbXBvcnRTcGVjaWZpZXJzKHNvdXJjZTogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgICAgY29uc3QgcmVsYXRpdmVTcGVjaWZpZXJzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBjb25zdCBpbXBvcnRQYXR0ZXJucyA9IFtcbiAgICAgICAgL2Zyb21cXHMrWydcIl0oW14nXCJdKylbJ1wiXS9nLFxuICAgICAgICAvaW1wb3J0XFxzK1snXCJdKFteJ1wiXSspWydcIl0vZyxcbiAgICAgICAgL2ltcG9ydFxcKFxccypbJ1wiXShbXidcIl0rKVsnXCJdXFxzKlxcKS9nLFxuICAgICAgICAvcmVxdWlyZVxcKFxccypbJ1wiXShbXidcIl0rKVsnXCJdXFxzKlxcKS9nLFxuICAgICAgXTtcblxuICAgICAgZm9yIChjb25zdCBpbXBvcnRQYXR0ZXJuIG9mIGltcG9ydFBhdHRlcm5zKSB7XG4gICAgICAgIGZvciAoY29uc3QgbWF0Y2ggb2Ygc291cmNlLm1hdGNoQWxsKGltcG9ydFBhdHRlcm4pKSB7XG4gICAgICAgICAgY29uc3Qgc3BlY2lmaWVyID0gbWF0Y2hbMV07XG4gICAgICAgICAgaWYgKHNwZWNpZmllcikge1xuICAgICAgICAgICAgcmVsYXRpdmVTcGVjaWZpZXJzLmFkZChzcGVjaWZpZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gQXJyYXkuZnJvbShyZWxhdGl2ZVNwZWNpZmllcnMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZ2V0UmVsYXRpdmVGaWxlbmFtZUZvclN3YyhmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgIGNvbnN0IHdvcmtpbmdEaXIgPSB0aGlzLmNvbmZpZy53b3JraW5nRGlyO1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFdvcmtpbmdEaXIgPSB3b3JraW5nRGlyXG4gICAgICAgIC5yZXBsYWNlKC9cXFxcL2csICcvJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLyQvLCAnJyk7XG4gICAgICBjb25zdCBub3JtYWxpemVkRmlsZXBhdGggPSBmaWxlUGF0aC5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG5cbiAgICAgIC8vIFdpbmRvd3MgZml4OiBVc2UgY2FzZS1pbnNlbnNpdGl2ZSBjb21wYXJpc29uIHRvIHdvcmsgYXJvdW5kIGRyaXZlIGxldHRlciBjYXNpbmcgaXNzdWVzLlxuICAgICAgY29uc3QgbG93ZXJXZCA9IG5vcm1hbGl6ZWRXb3JraW5nRGlyLnRvTG93ZXJDYXNlKCk7XG4gICAgICBjb25zdCBsb3dlclBhdGggPSBub3JtYWxpemVkRmlsZXBhdGgudG9Mb3dlckNhc2UoKTtcblxuICAgICAgbGV0IHJlbGF0aXZlRmlsZW5hbWU6IHN0cmluZztcbiAgICAgIGlmIChsb3dlclBhdGguc3RhcnRzV2l0aChgJHtsb3dlcldkfS9gKSkge1xuICAgICAgICByZWxhdGl2ZUZpbGVuYW1lID0gbm9ybWFsaXplZEZpbGVwYXRoLnN1YnN0cmluZyhcbiAgICAgICAgICBub3JtYWxpemVkV29ya2luZ0Rpci5sZW5ndGggKyAxXG4gICAgICAgICk7XG4gICAgICB9IGVsc2UgaWYgKGxvd2VyUGF0aCA9PT0gbG93ZXJXZCkge1xuICAgICAgICByZWxhdGl2ZUZpbGVuYW1lID0gJy4nO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVsYXRpdmVGaWxlbmFtZSA9IHJlbGF0aXZlKHdvcmtpbmdEaXIsIGZpbGVQYXRoKS5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gICAgICAgIGlmIChyZWxhdGl2ZUZpbGVuYW1lLnN0YXJ0c1dpdGgoJy4uLycpKSB7XG4gICAgICAgICAgY29uc3QgYWxpYXNlZFJlbGF0aXZlUGF0aCA9IGF3YWl0IHJlc29sdmVXb3JrZmxvd0FsaWFzUmVsYXRpdmVQYXRoKFxuICAgICAgICAgICAgZmlsZVBhdGgsXG4gICAgICAgICAgICB3b3JraW5nRGlyXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoYWxpYXNlZFJlbGF0aXZlUGF0aCkge1xuICAgICAgICAgICAgcmVsYXRpdmVGaWxlbmFtZSA9IGFsaWFzZWRSZWxhdGl2ZVBhdGg7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlbGF0aXZlRmlsZW5hbWUgPSByZWxhdGl2ZUZpbGVuYW1lXG4gICAgICAgICAgICAgIC5zcGxpdCgnLycpXG4gICAgICAgICAgICAgIC5maWx0ZXIoKHBhcnQpID0+IHBhcnQgIT09ICcuLicpXG4gICAgICAgICAgICAgIC5qb2luKCcvJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChyZWxhdGl2ZUZpbGVuYW1lLmluY2x1ZGVzKCc6JykgfHwgcmVsYXRpdmVGaWxlbmFtZS5zdGFydHNXaXRoKCcvJykpIHtcbiAgICAgICAgcmVsYXRpdmVGaWxlbmFtZSA9IGJhc2VuYW1lKG5vcm1hbGl6ZWRGaWxlcGF0aCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZWxhdGl2ZUZpbGVuYW1lO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVzb2x2ZUltcG9ydFRhcmdldFdpdGhFeHRlbnNpb25GYWxsYmFja3MoXG4gICAgICB0YXJnZXRQYXRoOiBzdHJpbmdcbiAgICApOiBzdHJpbmcge1xuICAgICAgaWYgKGV4aXN0c1N5bmModGFyZ2V0UGF0aCkpIHtcbiAgICAgICAgcmV0dXJuIHRhcmdldFBhdGg7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGV4dGVuc2lvbk1hdGNoID0gdGFyZ2V0UGF0aC5tYXRjaCgvKFxcLlteLi9cXFxcXSspJC8pO1xuICAgICAgY29uc3QgZXh0ZW5zaW9uID0gZXh0ZW5zaW9uTWF0Y2g/LlsxXT8udG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmICghZXh0ZW5zaW9uKSB7XG4gICAgICAgIHJldHVybiB0YXJnZXRQYXRoO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBleHRlbnNpb25GYWxsYmFja3MgPVxuICAgICAgICBleHRlbnNpb24gPT09ICcuanMnXG4gICAgICAgICAgPyBbJy50cycsICcudHN4JywgJy5tdHMnLCAnLmN0cyddXG4gICAgICAgICAgOiBleHRlbnNpb24gPT09ICcubWpzJ1xuICAgICAgICAgICAgPyBbJy5tdHMnXVxuICAgICAgICAgICAgOiBleHRlbnNpb24gPT09ICcuY2pzJ1xuICAgICAgICAgICAgICA/IFsnLmN0cyddXG4gICAgICAgICAgICAgIDogZXh0ZW5zaW9uID09PSAnLmpzeCdcbiAgICAgICAgICAgICAgICA/IFsnLnRzeCddXG4gICAgICAgICAgICAgICAgOiBbXTtcblxuICAgICAgaWYgKGV4dGVuc2lvbkZhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRhcmdldFBhdGg7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRhcmdldFdpdGhvdXRFeHRlbnNpb24gPSB0YXJnZXRQYXRoLnNsaWNlKDAsIC1leHRlbnNpb24ubGVuZ3RoKTtcbiAgICAgIGZvciAoY29uc3QgZmFsbGJhY2tFeHRlbnNpb24gb2YgZXh0ZW5zaW9uRmFsbGJhY2tzKSB7XG4gICAgICAgIGNvbnN0IGZhbGxiYWNrUGF0aCA9IGAke3RhcmdldFdpdGhvdXRFeHRlbnNpb259JHtmYWxsYmFja0V4dGVuc2lvbn1gO1xuICAgICAgICBpZiAoZXhpc3RzU3luYyhmYWxsYmFja1BhdGgpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbGxiYWNrUGF0aDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGFyZ2V0UGF0aDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNob3VsZFNraXBUcmFuc2l0aXZlU3RlcEZpbGUoZmlsZVBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFBhdGggPSBmaWxlUGF0aC5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gICAgICBjb25zdCBpc1NvdXJjZUJhY2tlZFBhY2thZ2VQYXRoID1cbiAgICAgICAgdGhpcy5zaG91bGRQcmVmZXJTb3VyY2VCYWNrZWRQYWNrYWdlUGF0aChmaWxlUGF0aCk7XG4gICAgICByZXR1cm4gKFxuICAgICAgICBub3JtYWxpemVkUGF0aC5pbmNsdWRlcygnLy53ZWxsLWtub3duL3dvcmtmbG93LycpIHx8XG4gICAgICAgIG5vcm1hbGl6ZWRQYXRoLmluY2x1ZGVzKCcvLm5leHQvJykgfHxcbiAgICAgICAgKCFpc1NvdXJjZUJhY2tlZFBhY2thZ2VQYXRoICYmXG4gICAgICAgICAgKG5vcm1hbGl6ZWRQYXRoLmluY2x1ZGVzKCcvbm9kZV9tb2R1bGVzLycpIHx8XG4gICAgICAgICAgICBub3JtYWxpemVkUGF0aC5pbmNsdWRlcygnLy5wbnBtLycpKSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZXNvbHZlVHJhbnNpdGl2ZVN0ZXBJbXBvcnRUYXJnZXRQYXRoKFxuICAgICAgc291cmNlRmlsZVBhdGg6IHN0cmluZyxcbiAgICAgIHNwZWNpZmllcjogc3RyaW5nXG4gICAgKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgICBjb25zdCBzcGVjaWZpZXJNYXRjaCA9IHNwZWNpZmllci5tYXRjaCgvXihbXj8jXSspKC4qKSQvKTtcbiAgICAgIGNvbnN0IGltcG9ydFBhdGggPSBzcGVjaWZpZXJNYXRjaD8uWzFdID8/IHNwZWNpZmllcjtcblxuICAgICAgaWYgKCFpbXBvcnRQYXRoLnN0YXJ0c1dpdGgoJy4nKSkge1xuICAgICAgICBpZiAoaW1wb3J0UGF0aCAhPT0gJ3dvcmtmbG93JyAmJiAhaW1wb3J0UGF0aC5zdGFydHNXaXRoKCdAd29ya2Zsb3cvJykpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID1cbiAgICAgICAgICAgIGNyZWF0ZVJlcXVpcmUoc291cmNlRmlsZVBhdGgpLnJlc29sdmUoaW1wb3J0UGF0aCk7XG4gICAgICAgICAgY29uc3Qgbm9ybWFsaXplZFJlc29sdmVkUGF0aCA9XG4gICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgIGlmICh0aGlzLnNob3VsZFNraXBUcmFuc2l0aXZlU3RlcEZpbGUobm9ybWFsaXplZFJlc29sdmVkUGF0aCkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGZpbGVTdGF0cyA9IGF3YWl0IHN0YXQobm9ybWFsaXplZFJlc29sdmVkUGF0aCk7XG4gICAgICAgICAgcmV0dXJuIGZpbGVTdGF0cy5pc0ZpbGUoKSA/IG5vcm1hbGl6ZWRSZXNvbHZlZFBhdGggOiBudWxsO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBhYnNvbHV0ZVRhcmdldFBhdGggPSByZXNvbHZlKGRpcm5hbWUoc291cmNlRmlsZVBhdGgpLCBpbXBvcnRQYXRoKTtcblxuICAgICAgY29uc3QgY2FuZGlkYXRlUGF0aHMgPSBuZXcgU2V0PHN0cmluZz4oW1xuICAgICAgICB0aGlzLnJlc29sdmVJbXBvcnRUYXJnZXRXaXRoRXh0ZW5zaW9uRmFsbGJhY2tzKGFic29sdXRlVGFyZ2V0UGF0aCksXG4gICAgICBdKTtcblxuICAgICAgaWYgKCFleHRuYW1lKGFic29sdXRlVGFyZ2V0UGF0aCkpIHtcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9uQ2FuZGlkYXRlcyA9IFtcbiAgICAgICAgICAnLnRzJyxcbiAgICAgICAgICAnLnRzeCcsXG4gICAgICAgICAgJy5tdHMnLFxuICAgICAgICAgICcuY3RzJyxcbiAgICAgICAgICAnLmpzJyxcbiAgICAgICAgICAnLmpzeCcsXG4gICAgICAgICAgJy5tanMnLFxuICAgICAgICAgICcuY2pzJyxcbiAgICAgICAgXTtcbiAgICAgICAgZm9yIChjb25zdCBleHRlbnNpb25DYW5kaWRhdGUgb2YgZXh0ZW5zaW9uQ2FuZGlkYXRlcykge1xuICAgICAgICAgIGNhbmRpZGF0ZVBhdGhzLmFkZChgJHthYnNvbHV0ZVRhcmdldFBhdGh9JHtleHRlbnNpb25DYW5kaWRhdGV9YCk7XG4gICAgICAgICAgY2FuZGlkYXRlUGF0aHMuYWRkKFxuICAgICAgICAgICAgam9pbihhYnNvbHV0ZVRhcmdldFBhdGgsIGBpbmRleCR7ZXh0ZW5zaW9uQ2FuZGlkYXRlfWApXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGNhbmRpZGF0ZVBhdGggb2YgY2FuZGlkYXRlUGF0aHMpIHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID1cbiAgICAgICAgICB0aGlzLnJlc29sdmVJbXBvcnRUYXJnZXRXaXRoRXh0ZW5zaW9uRmFsbGJhY2tzKGNhbmRpZGF0ZVBhdGgpO1xuICAgICAgICBjb25zdCBub3JtYWxpemVkUmVzb2x2ZWRQYXRoID1cbiAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChyZXNvbHZlZFBhdGgpO1xuXG4gICAgICAgIGlmICh0aGlzLnNob3VsZFNraXBUcmFuc2l0aXZlU3RlcEZpbGUobm9ybWFsaXplZFJlc29sdmVkUGF0aCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZmlsZVN0YXRzID0gYXdhaXQgc3RhdChub3JtYWxpemVkUmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgICBpZiAoZmlsZVN0YXRzLmlzRmlsZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaXplZFJlc29sdmVkUGF0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8vIFRyeSB0aGUgbmV4dCBjYW5kaWRhdGUgcGF0aC5cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGNvbGxlY3RUcmFuc2l0aXZlU3RlcEZpbGVzKHtcbiAgICAgIGVudHJ5RmlsZXMsXG4gICAgICBzdGVwRmlsZXMsXG4gICAgfToge1xuICAgICAgZW50cnlGaWxlczogc3RyaW5nW107XG4gICAgICBzdGVwRmlsZXM6IHN0cmluZ1tdO1xuICAgIH0pOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICBjb25zdCBub3JtYWxpemVkRW50cnlGaWxlcyA9IEFycmF5LmZyb20oXG4gICAgICAgIG5ldyBTZXQoXG4gICAgICAgICAgZW50cnlGaWxlcy5tYXAoKGVudHJ5RmlsZSkgPT5cbiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplRGlzY292ZXJlZEZpbGVQYXRoKGVudHJ5RmlsZSlcbiAgICAgICAgICApXG4gICAgICAgIClcbiAgICAgICkuc29ydCgpO1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFN0ZXBTZWVkRmlsZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFxuICAgICAgICAgIHN0ZXBGaWxlcy5tYXAoKHN0ZXBGaWxlKSA9PlxuICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoc3RlcEZpbGUpXG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgICApLnNvcnQoKTtcbiAgICAgIGNvbnN0IGRpc2NvdmVyZWRTdGVwRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4obm9ybWFsaXplZFN0ZXBTZWVkRmlsZXMpO1xuICAgICAgY29uc3QgcXVldWVkRmlsZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFsuLi5ub3JtYWxpemVkRW50cnlGaWxlcywgLi4ubm9ybWFsaXplZFN0ZXBTZWVkRmlsZXNdKVxuICAgICAgKTtcbiAgICAgIGNvbnN0IHZpc2l0ZWRGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgY29uc3Qgc291cmNlQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nIHwgbnVsbD4oKTtcbiAgICAgIGNvbnN0IHBhdHRlcm5DYWNoZSA9IG5ldyBNYXA8XG4gICAgICAgIHN0cmluZyxcbiAgICAgICAgUmV0dXJuVHlwZTx0eXBlb2YgZGV0ZWN0V29ya2Zsb3dQYXR0ZXJucz4gfCBudWxsXG4gICAgICA+KCk7XG5cbiAgICAgIGNvbnN0IGdldFNvdXJjZSA9IGFzeW5jIChmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiA9PiB7XG4gICAgICAgIGlmIChzb3VyY2VDYWNoZS5oYXMoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgcmV0dXJuIHNvdXJjZUNhY2hlLmdldChmaWxlUGF0aCkgPz8gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IGF3YWl0IHJlYWRGaWxlKGZpbGVQYXRoLCAndXRmLTgnKTtcbiAgICAgICAgICBzb3VyY2VDYWNoZS5zZXQoZmlsZVBhdGgsIHNvdXJjZSk7XG4gICAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgc291cmNlQ2FjaGUuc2V0KGZpbGVQYXRoLCBudWxsKTtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgY29uc3QgZ2V0UGF0dGVybnMgPSBhc3luYyAoXG4gICAgICAgIGZpbGVQYXRoOiBzdHJpbmdcbiAgICAgICk6IFByb21pc2U8UmV0dXJuVHlwZTx0eXBlb2YgZGV0ZWN0V29ya2Zsb3dQYXR0ZXJucz4gfCBudWxsPiA9PiB7XG4gICAgICAgIGlmIChwYXR0ZXJuQ2FjaGUuaGFzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHJldHVybiBwYXR0ZXJuQ2FjaGUuZ2V0KGZpbGVQYXRoKSA/PyBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNvdXJjZSA9IGF3YWl0IGdldFNvdXJjZShmaWxlUGF0aCk7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IG51bGwpIHtcbiAgICAgICAgICBwYXR0ZXJuQ2FjaGUuc2V0KGZpbGVQYXRoLCBudWxsKTtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwYXR0ZXJucyA9IGRldGVjdFdvcmtmbG93UGF0dGVybnMoc291cmNlKTtcbiAgICAgICAgcGF0dGVybkNhY2hlLnNldChmaWxlUGF0aCwgcGF0dGVybnMpO1xuICAgICAgICByZXR1cm4gcGF0dGVybnM7XG4gICAgICB9O1xuXG4gICAgICB3aGlsZSAocXVldWVkRmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zdCBjdXJyZW50RmlsZSA9IHF1ZXVlZEZpbGVzLnBvcCgpO1xuICAgICAgICBpZiAoIWN1cnJlbnRGaWxlIHx8IHZpc2l0ZWRGaWxlcy5oYXMoY3VycmVudEZpbGUpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdmlzaXRlZEZpbGVzLmFkZChjdXJyZW50RmlsZSk7XG5cbiAgICAgICAgY29uc3QgY3VycmVudFNvdXJjZSA9IGF3YWl0IGdldFNvdXJjZShjdXJyZW50RmlsZSk7XG4gICAgICAgIGlmIChjdXJyZW50U291cmNlID09PSBudWxsKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpbXBvcnRTcGVjaWZpZXJzID0gdGhpcy5leHRyYWN0SW1wb3J0U3BlY2lmaWVycyhjdXJyZW50U291cmNlKTtcbiAgICAgICAgZm9yIChjb25zdCBzcGVjaWZpZXIgb2YgaW1wb3J0U3BlY2lmaWVycykge1xuICAgICAgICAgIGNvbnN0IHJlc29sdmVkSW1wb3J0UGF0aCA9XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlc29sdmVUcmFuc2l0aXZlU3RlcEltcG9ydFRhcmdldFBhdGgoXG4gICAgICAgICAgICAgIGN1cnJlbnRGaWxlLFxuICAgICAgICAgICAgICBzcGVjaWZpZXJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKCFyZXNvbHZlZEltcG9ydFBhdGgpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghdmlzaXRlZEZpbGVzLmhhcyhyZXNvbHZlZEltcG9ydFBhdGgpKSB7XG4gICAgICAgICAgICBxdWV1ZWRGaWxlcy5wdXNoKHJlc29sdmVkSW1wb3J0UGF0aCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgaW1wb3J0UGF0dGVybnMgPSBhd2FpdCBnZXRQYXR0ZXJucyhyZXNvbHZlZEltcG9ydFBhdGgpO1xuICAgICAgICAgIGlmIChpbXBvcnRQYXR0ZXJucz8uaGFzVXNlU3RlcCkge1xuICAgICAgICAgICAgZGlzY292ZXJlZFN0ZXBGaWxlcy5hZGQocmVzb2x2ZWRJbXBvcnRQYXRoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIEFycmF5LmZyb20oZGlzY292ZXJlZFN0ZXBGaWxlcykuc29ydCgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29sbGVjdFRyYW5zaXRpdmVTZXJkZUZpbGVzKHtcbiAgICAgIGVudHJ5RmlsZXMsXG4gICAgICBzZXJkZUZpbGVzLFxuICAgIH06IHtcbiAgICAgIGVudHJ5RmlsZXM6IHN0cmluZ1tdO1xuICAgICAgc2VyZGVGaWxlczogc3RyaW5nW107XG4gICAgfSk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRFbnRyeUZpbGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChcbiAgICAgICAgICBlbnRyeUZpbGVzLm1hcCgoZW50cnlGaWxlKSA9PlxuICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoZW50cnlGaWxlKVxuICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICAgKS5zb3J0KCk7XG4gICAgICBjb25zdCBub3JtYWxpemVkU2VyZGVTZWVkRmlsZXMgPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFxuICAgICAgICAgIHNlcmRlRmlsZXMubWFwKChzZXJkZUZpbGUpID0+XG4gICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChzZXJkZUZpbGUpXG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgICApLnNvcnQoKTtcbiAgICAgIC8vIEludGVudGlvbmFsbHkgcmUtdmFsaWRhdGUgc2VyZGUgc2VlZHMgYWdhaW5zdCBzb3VyY2UgcGF0dGVybnMuXG4gICAgICAvLyBUaGlzIGtlZXBzIHByZXZpb3VzbHkgZGlzY292ZXJlZC9tYW51YWwgc2VlZCBlbnRyaWVzIGZyb20gc3RpY2tpbmcgd2hlblxuICAgICAgLy8gZmlsZXMgbm8gbG9uZ2VyIG1hdGNoIHNlcmRlIHBhdHRlcm5zLlxuICAgICAgY29uc3QgZGlzY292ZXJlZFNlcmRlRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgIGNvbnN0IHF1ZXVlZEZpbGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbLi4ubm9ybWFsaXplZEVudHJ5RmlsZXMsIC4uLm5vcm1hbGl6ZWRTZXJkZVNlZWRGaWxlc10pXG4gICAgICApO1xuICAgICAgY29uc3QgdmlzaXRlZEZpbGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBjb25zdCBzb3VyY2VDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmcgfCBudWxsPigpO1xuICAgICAgY29uc3QgcGF0dGVybkNhY2hlID0gbmV3IE1hcDxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICBSZXR1cm5UeXBlPHR5cGVvZiBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zPiB8IG51bGxcbiAgICAgID4oKTtcblxuICAgICAgY29uc3QgZ2V0U291cmNlID0gYXN5bmMgKGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+ID0+IHtcbiAgICAgICAgaWYgKHNvdXJjZUNhY2hlLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICByZXR1cm4gc291cmNlQ2FjaGUuZ2V0KGZpbGVQYXRoKSA/PyBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgICAgIHNvdXJjZUNhY2hlLnNldChmaWxlUGF0aCwgc291cmNlKTtcbiAgICAgICAgICByZXR1cm4gc291cmNlO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICBzb3VyY2VDYWNoZS5zZXQoZmlsZVBhdGgsIG51bGwpO1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBnZXRQYXR0ZXJucyA9IGFzeW5jIChcbiAgICAgICAgZmlsZVBhdGg6IHN0cmluZ1xuICAgICAgKTogUHJvbWlzZTxSZXR1cm5UeXBlPHR5cGVvZiBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zPiB8IG51bGw+ID0+IHtcbiAgICAgICAgaWYgKHBhdHRlcm5DYWNoZS5oYXMoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgcmV0dXJuIHBhdHRlcm5DYWNoZS5nZXQoZmlsZVBhdGgpID8/IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgZ2V0U291cmNlKGZpbGVQYXRoKTtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHBhdHRlcm5DYWNoZS5zZXQoZmlsZVBhdGgsIG51bGwpO1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhdHRlcm5zID0gZGV0ZWN0V29ya2Zsb3dQYXR0ZXJucyhzb3VyY2UpO1xuICAgICAgICBwYXR0ZXJuQ2FjaGUuc2V0KGZpbGVQYXRoLCBwYXR0ZXJucyk7XG4gICAgICAgIHJldHVybiBwYXR0ZXJucztcbiAgICAgIH07XG5cbiAgICAgIGZvciAoY29uc3Qgc2VyZGVTZWVkRmlsZSBvZiBub3JtYWxpemVkU2VyZGVTZWVkRmlsZXMpIHtcbiAgICAgICAgY29uc3Qgc2VlZFBhdHRlcm5zID0gYXdhaXQgZ2V0UGF0dGVybnMoc2VyZGVTZWVkRmlsZSk7XG4gICAgICAgIGlmIChzZWVkUGF0dGVybnM/Lmhhc1NlcmRlKSB7XG4gICAgICAgICAgZGlzY292ZXJlZFNlcmRlRmlsZXMuYWRkKHNlcmRlU2VlZEZpbGUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHdoaWxlIChxdWV1ZWRGaWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRGaWxlID0gcXVldWVkRmlsZXMucG9wKCk7XG4gICAgICAgIGlmICghY3VycmVudEZpbGUgfHwgdmlzaXRlZEZpbGVzLmhhcyhjdXJyZW50RmlsZSkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB2aXNpdGVkRmlsZXMuYWRkKGN1cnJlbnRGaWxlKTtcblxuICAgICAgICBjb25zdCBjdXJyZW50U291cmNlID0gYXdhaXQgZ2V0U291cmNlKGN1cnJlbnRGaWxlKTtcbiAgICAgICAgaWYgKGN1cnJlbnRTb3VyY2UgPT09IG51bGwpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlbGF0aXZlSW1wb3J0U3BlY2lmaWVycyA9XG4gICAgICAgICAgdGhpcy5leHRyYWN0UmVsYXRpdmVJbXBvcnRTcGVjaWZpZXJzKGN1cnJlbnRTb3VyY2UpO1xuICAgICAgICBmb3IgKGNvbnN0IHNwZWNpZmllciBvZiByZWxhdGl2ZUltcG9ydFNwZWNpZmllcnMpIHtcbiAgICAgICAgICBjb25zdCByZXNvbHZlZEltcG9ydFBhdGggPVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5yZXNvbHZlVHJhbnNpdGl2ZVN0ZXBJbXBvcnRUYXJnZXRQYXRoKFxuICAgICAgICAgICAgICBjdXJyZW50RmlsZSxcbiAgICAgICAgICAgICAgc3BlY2lmaWVyXG4gICAgICAgICAgICApO1xuICAgICAgICAgIGlmICghcmVzb2x2ZWRJbXBvcnRQYXRoKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIXZpc2l0ZWRGaWxlcy5oYXMocmVzb2x2ZWRJbXBvcnRQYXRoKSkge1xuICAgICAgICAgICAgcXVldWVkRmlsZXMucHVzaChyZXNvbHZlZEltcG9ydFBhdGgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGltcG9ydFBhdHRlcm5zID0gYXdhaXQgZ2V0UGF0dGVybnMocmVzb2x2ZWRJbXBvcnRQYXRoKTtcbiAgICAgICAgICBpZiAoaW1wb3J0UGF0dGVybnM/Lmhhc1NlcmRlKSB7XG4gICAgICAgICAgICBkaXNjb3ZlcmVkU2VyZGVGaWxlcy5hZGQocmVzb2x2ZWRJbXBvcnRQYXRoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQVNULWxldmVsIHZlcmlmaWNhdGlvbjogcnVuIFNXQyBkZXRlY3QgbW9kZSBvbiByZWdleC1tYXRjaGVkIGNhbmRpZGF0ZXNcbiAgICAgIC8vIHRvIGNvbmZpcm0gdGhleSBhY3R1YWxseSBkZWZpbmUgc2VyZGUgY2xhc3Nlcy4gVGhpcyBwcmV2ZW50cyBTREsgaW50ZXJuYWxcbiAgICAgIC8vIGZpbGVzICh3aGljaCBtYXRjaCBzZXJkZSByZWdleCBwYXR0ZXJucyBidXQgZGVmaW5lIG5vIGNsYXNzZXMpIGZyb20gYmVpbmdcbiAgICAgIC8vIGJ1bmRsZWQgaW50byB0aGUgd29ya2Zsb3cgc2FuZGJveC5cbiAgICAgIGNvbnN0IHByb2plY3RSb290ID0gdGhpcy5jb25maWcucHJvamVjdFJvb3QgfHwgdGhpcy5jb25maWcud29ya2luZ0RpcjtcbiAgICAgIGNvbnN0IHZlcmlmaWVkU2VyZGVGaWxlczogc3RyaW5nW10gPSBbXTtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBBcnJheS5mcm9tKGRpc2NvdmVyZWRTZXJkZUZpbGVzKS5tYXAoYXN5bmMgKGZpbGVQYXRoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgZ2V0U291cmNlKGZpbGVQYXRoKTtcbiAgICAgICAgICBpZiAoIXNvdXJjZSkgcmV0dXJuO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZWxhdGl2ZUZpbGVuYW1lID1cbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy5nZXRSZWxhdGl2ZUZpbGVuYW1lRm9yU3djKGZpbGVQYXRoKTtcbiAgICAgICAgICAgIGNvbnN0IHsgd29ya2Zsb3dNYW5pZmVzdCB9ID0gYXdhaXQgYXBwbHlTd2NUcmFuc2Zvcm0oXG4gICAgICAgICAgICAgIHJlbGF0aXZlRmlsZW5hbWUsXG4gICAgICAgICAgICAgIHNvdXJjZSxcbiAgICAgICAgICAgICAgJ2RldGVjdCcsXG4gICAgICAgICAgICAgIGZpbGVQYXRoLFxuICAgICAgICAgICAgICBwcm9qZWN0Um9vdCxcbiAgICAgICAgICAgICAgdGhpcy5tb2R1bGVTcGVjaWZpZXJSb290XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgLy8gT25seSBpbmNsdWRlIGZpbGVzIHRoYXQgYWN0dWFsbHkgZGVmaW5lIHNlcmRlIGNsYXNzZXNcbiAgICAgICAgICAgIGNvbnN0IGhhc0NsYXNzZXMgPVxuICAgICAgICAgICAgICB3b3JrZmxvd01hbmlmZXN0LmNsYXNzZXMgJiZcbiAgICAgICAgICAgICAgT2JqZWN0LnZhbHVlcyh3b3JrZmxvd01hbmlmZXN0LmNsYXNzZXMpLnNvbWUoXG4gICAgICAgICAgICAgICAgKGVudHJpZXMpID0+IE9iamVjdC5rZXlzKGVudHJpZXMpLmxlbmd0aCA+IDBcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChoYXNDbGFzc2VzKSB7XG4gICAgICAgICAgICAgIHZlcmlmaWVkU2VyZGVGaWxlcy5wdXNoKGZpbGVQYXRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIElmIGRldGVjdCBmYWlscywgaW5jbHVkZSB0aGUgZmlsZSB0byBiZSBzYWZlXG4gICAgICAgICAgICB2ZXJpZmllZFNlcmRlRmlsZXMucHVzaChmaWxlUGF0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgKTtcblxuICAgICAgcmV0dXJuIHZlcmlmaWVkU2VyZGVGaWxlcy5zb3J0KCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBidWlsZFdlYmhvb2tSb3V0ZSh7XG4gICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcixcbiAgICAgIHJvdXRlRmlsZU5hbWUgPSAncm91dGUuanMnLFxuICAgIH06IHtcbiAgICAgIHdvcmtmbG93R2VuZXJhdGVkRGlyOiBzdHJpbmc7XG4gICAgICByb3V0ZUZpbGVOYW1lPzogc3RyaW5nO1xuICAgIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IHdlYmhvb2tSb3V0ZUZpbGUgPSBqb2luKFxuICAgICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcixcbiAgICAgICAgYHdlYmhvb2svW3Rva2VuXS8ke3JvdXRlRmlsZU5hbWV9YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMuY3JlYXRlV2ViaG9va0J1bmRsZSh7XG4gICAgICAgIG91dGZpbGU6IHdlYmhvb2tSb3V0ZUZpbGUsXG4gICAgICAgIGJ1bmRsZTogZmFsc2UsIC8vIE5leHQuanMgZG9lc24ndCBuZWVkIGJ1bmRsaW5nXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGZpbmRBcHBEaXJlY3RvcnkoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgIGNvbnN0IGFwcERpciA9IHJlc29sdmUodGhpcy5jb25maWcud29ya2luZ0RpciwgJ2FwcCcpO1xuICAgICAgY29uc3Qgc3JjQXBwRGlyID0gcmVzb2x2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCAnc3JjL2FwcCcpO1xuICAgICAgY29uc3QgcGFnZXNEaXIgPSByZXNvbHZlKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsICdwYWdlcycpO1xuICAgICAgY29uc3Qgc3JjUGFnZXNEaXIgPSByZXNvbHZlKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsICdzcmMvcGFnZXMnKTtcblxuICAgICAgLy8gSGVscGVyIHRvIGNoZWNrIGlmIGEgcGF0aCBleGlzdHMgYW5kIGlzIGEgZGlyZWN0b3J5XG4gICAgICBjb25zdCBpc0RpcmVjdG9yeSA9IGFzeW5jIChwYXRoOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBhY2Nlc3MocGF0aCwgY29uc3RhbnRzLkZfT0spO1xuICAgICAgICAgIGNvbnN0IHN0YXRzID0gYXdhaXQgc3RhdChwYXRoKTtcbiAgICAgICAgICBpZiAoIXN0YXRzLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUGF0aCBleGlzdHMgYnV0IGlzIG5vdCBhIGRpcmVjdG9yeTogJHtwYXRofWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgRXJyb3IgJiYgZS5tZXNzYWdlLmluY2x1ZGVzKCdub3QgYSBkaXJlY3RvcnknKSkge1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICAvLyBDaGVjayBpZiBhcHAgZGlyZWN0b3J5IGV4aXN0c1xuICAgICAgaWYgKGF3YWl0IGlzRGlyZWN0b3J5KGFwcERpcikpIHtcbiAgICAgICAgcmV0dXJuIGFwcERpcjtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgc3JjL2FwcCBkaXJlY3RvcnkgZXhpc3RzXG4gICAgICBpZiAoYXdhaXQgaXNEaXJlY3Rvcnkoc3JjQXBwRGlyKSkge1xuICAgICAgICByZXR1cm4gc3JjQXBwRGlyO1xuICAgICAgfVxuXG4gICAgICAvLyBJZiBubyBhcHAgZGlyZWN0b3J5IGV4aXN0cywgY2hlY2sgZm9yIHBhZ2VzIGRpcmVjdG9yeSBhbmQgY3JlYXRlIGFwcCBuZXh0IHRvIGl0XG4gICAgICBpZiAoYXdhaXQgaXNEaXJlY3RvcnkocGFnZXNEaXIpKSB7XG4gICAgICAgIC8vIENyZWF0ZSBhcHAgZGlyZWN0b3J5IG5leHQgdG8gcGFnZXMgZGlyZWN0b3J5XG4gICAgICAgIGF3YWl0IG1rZGlyKGFwcERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICAgIHJldHVybiBhcHBEaXI7XG4gICAgICB9XG5cbiAgICAgIGlmIChhd2FpdCBpc0RpcmVjdG9yeShzcmNQYWdlc0RpcikpIHtcbiAgICAgICAgLy8gQ3JlYXRlIHNyYy9hcHAgZGlyZWN0b3J5IG5leHQgdG8gc3JjL3BhZ2VzIGRpcmVjdG9yeVxuICAgICAgICBhd2FpdCBta2RpcihzcmNBcHBEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgICByZXR1cm4gc3JjQXBwRGlyO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdDb3VsZCBub3QgZmluZCBOZXh0LmpzIGFwcCBvciBwYWdlcyBkaXJlY3RvcnkuIEV4cGVjdGVkIG9uZSBvZjogXCJhcHBcIiwgXCJzcmMvYXBwXCIsIFwicGFnZXNcIiwgb3IgXCJzcmMvcGFnZXNcIiB0byBleGlzdC4nXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIENhY2hlZE5leHRCdWlsZGVyRGVmZXJyZWQgPSBOZXh0RGVmZXJyZWRCdWlsZGVyO1xuICByZXR1cm4gTmV4dERlZmVycmVkQnVpbGRlcjtcbn1cbiJdfQ==