@workflow/builders 5.0.0-beta.4 → 5.0.0-beta.40

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.
Files changed (119) hide show
  1. package/dist/apply-swc-transform.d.ts +7 -2
  2. package/dist/apply-swc-transform.d.ts.map +1 -1
  3. package/dist/apply-swc-transform.js +10 -4
  4. package/dist/base-builder-logging.test.d.ts +2 -0
  5. package/dist/base-builder-logging.test.d.ts.map +1 -0
  6. package/dist/base-builder-logging.test.js +99 -0
  7. package/dist/base-builder.d.ts +132 -13
  8. package/dist/base-builder.d.ts.map +1 -1
  9. package/dist/base-builder.js +785 -92
  10. package/dist/build-queue.js +1 -1
  11. package/dist/config-helpers.d.ts +4 -1
  12. package/dist/config-helpers.d.ts.map +1 -1
  13. package/dist/config-helpers.js +63 -1
  14. package/dist/config-helpers.test.d.ts +2 -0
  15. package/dist/config-helpers.test.d.ts.map +1 -0
  16. package/dist/config-helpers.test.js +17 -0
  17. package/dist/constants.d.ts +66 -5
  18. package/dist/constants.d.ts.map +1 -1
  19. package/dist/constants.js +106 -19
  20. package/dist/constants.test.d.ts +2 -0
  21. package/dist/constants.test.d.ts.map +1 -0
  22. package/dist/constants.test.js +90 -0
  23. package/dist/discover-entries-esbuild-plugin.d.ts +3 -1
  24. package/dist/discover-entries-esbuild-plugin.d.ts.map +1 -1
  25. package/dist/discover-entries-esbuild-plugin.js +24 -4
  26. package/dist/discover-entries-esbuild-plugin.test.js +1 -1
  27. package/dist/esbuild-tsconfig.js +1 -1
  28. package/dist/esbuild-tsconfig.test.js +1 -1
  29. package/dist/external-package-warning.test.d.ts +2 -0
  30. package/dist/external-package-warning.test.d.ts.map +1 -0
  31. package/dist/external-package-warning.test.js +219 -0
  32. package/dist/fast-discovery.d.ts +29 -0
  33. package/dist/fast-discovery.d.ts.map +1 -0
  34. package/dist/fast-discovery.js +771 -0
  35. package/dist/fast-discovery.test.d.ts +2 -0
  36. package/dist/fast-discovery.test.d.ts.map +1 -0
  37. package/dist/fast-discovery.test.js +453 -0
  38. package/dist/get-input-files.test.js +34 -2
  39. package/dist/index.d.ts +5 -3
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +6 -4
  42. package/dist/module-specifier.d.ts +20 -2
  43. package/dist/module-specifier.d.ts.map +1 -1
  44. package/dist/module-specifier.js +92 -17
  45. package/dist/module-specifier.test.js +45 -3
  46. package/dist/node-module-esbuild-plugin.d.ts.map +1 -1
  47. package/dist/node-module-esbuild-plugin.js +73 -23
  48. package/dist/node-module-esbuild-plugin.test.js +97 -1
  49. package/dist/optional-otel-api.d.ts +14 -0
  50. package/dist/optional-otel-api.d.ts.map +1 -0
  51. package/dist/optional-otel-api.js +14 -0
  52. package/dist/optional-typescript-alias.d.ts +2 -0
  53. package/dist/optional-typescript-alias.d.ts.map +1 -0
  54. package/dist/optional-typescript-alias.js +3 -0
  55. package/dist/optional-typescript.d.ts +3 -0
  56. package/dist/optional-typescript.d.ts.map +1 -0
  57. package/dist/optional-typescript.js +9 -0
  58. package/dist/pseudo-package-esbuild-plugin.js +1 -1
  59. package/dist/pseudo-package-esbuild-plugin.test.js +1 -1
  60. package/dist/request-converter.js +1 -1
  61. package/dist/resolve-sourcemap.test.d.ts +2 -0
  62. package/dist/resolve-sourcemap.test.d.ts.map +1 -0
  63. package/dist/resolve-sourcemap.test.js +194 -0
  64. package/dist/serde-checker.js +1 -1
  65. package/dist/standalone.d.ts +0 -3
  66. package/dist/standalone.d.ts.map +1 -1
  67. package/dist/standalone.js +17 -41
  68. package/dist/step-source-registration.test.d.ts +2 -0
  69. package/dist/step-source-registration.test.d.ts.map +1 -0
  70. package/dist/step-source-registration.test.js +82 -0
  71. package/dist/swc-esbuild-plugin.d.ts +10 -0
  72. package/dist/swc-esbuild-plugin.d.ts.map +1 -1
  73. package/dist/swc-esbuild-plugin.js +116 -14
  74. package/dist/swc-esbuild-plugin.test.js +370 -6
  75. package/dist/transform-utils.d.ts.map +1 -1
  76. package/dist/transform-utils.js +45 -6
  77. package/dist/transform-utils.test.js +78 -6
  78. package/dist/types.d.ts +61 -2
  79. package/dist/types.d.ts.map +1 -1
  80. package/dist/types.js +1 -1
  81. package/dist/vercel-build-output-api.d.ts +0 -2
  82. package/dist/vercel-build-output-api.d.ts.map +1 -1
  83. package/dist/vercel-build-output-api.js +37 -60
  84. package/dist/workflow-alias.js +1 -1
  85. package/dist/workflow-alias.test.js +2 -2
  86. package/dist/workflows-extractor.js +8 -3
  87. package/dist/workflows-extractor.test.d.ts +2 -0
  88. package/dist/workflows-extractor.test.d.ts.map +1 -0
  89. package/dist/workflows-extractor.test.js +70 -0
  90. package/package.json +8 -7
  91. package/dist/apply-swc-transform.js.map +0 -1
  92. package/dist/base-builder.js.map +0 -1
  93. package/dist/build-queue.js.map +0 -1
  94. package/dist/config-helpers.js.map +0 -1
  95. package/dist/constants.js.map +0 -1
  96. package/dist/discover-entries-esbuild-plugin.js.map +0 -1
  97. package/dist/discover-entries-esbuild-plugin.test.js.map +0 -1
  98. package/dist/esbuild-tsconfig.js.map +0 -1
  99. package/dist/esbuild-tsconfig.test.js.map +0 -1
  100. package/dist/get-input-files.test.js.map +0 -1
  101. package/dist/index.js.map +0 -1
  102. package/dist/module-specifier.js.map +0 -1
  103. package/dist/module-specifier.test.js.map +0 -1
  104. package/dist/node-module-esbuild-plugin.js.map +0 -1
  105. package/dist/node-module-esbuild-plugin.test.js.map +0 -1
  106. package/dist/pseudo-package-esbuild-plugin.js.map +0 -1
  107. package/dist/pseudo-package-esbuild-plugin.test.js.map +0 -1
  108. package/dist/request-converter.js.map +0 -1
  109. package/dist/serde-checker.js.map +0 -1
  110. package/dist/standalone.js.map +0 -1
  111. package/dist/swc-esbuild-plugin.js.map +0 -1
  112. package/dist/swc-esbuild-plugin.test.js.map +0 -1
  113. package/dist/transform-utils.js.map +0 -1
  114. package/dist/transform-utils.test.js.map +0 -1
  115. package/dist/types.js.map +0 -1
  116. package/dist/vercel-build-output-api.js.map +0 -1
  117. package/dist/workflow-alias.js.map +0 -1
  118. package/dist/workflow-alias.test.js.map +0 -1
  119. package/dist/workflows-extractor.js.map +0 -1
@@ -1,7 +1,10 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { mkdir, readFile, realpath, rename, writeFile } from 'node:fs/promises';
2
+ import { mkdir, readFile, realpath, rename, rm, stat, writeFile, } from 'node:fs/promises';
3
+ import { createRequire } from 'node:module';
3
4
  import { basename, dirname, join, relative, resolve } from 'node:path';
4
5
  import { promisify } from 'node:util';
6
+ import { buildLogger } from '@workflow/core/logger';
7
+ import { WorkflowBuildError } from '@workflow/errors';
5
8
  import { pluralize } from '@workflow/utils';
6
9
  import chalk from 'chalk';
7
10
  import enhancedResolveOriginal from 'enhanced-resolve';
@@ -9,15 +12,70 @@ import * as esbuild from 'esbuild';
9
12
  import { findUp } from 'find-up';
10
13
  import { glob } from 'tinyglobby';
11
14
  import { applySwcTransform, } from './apply-swc-transform.js';
12
- import { createDiscoverEntriesPlugin } from './discover-entries-esbuild-plugin.js';
15
+ import { createWorkflowEntrypointOptionsCode, createWorkflowRouteHandlersCode, } from './constants.js';
13
16
  import { getEsbuildTsconfigOptions } from './esbuild-tsconfig.js';
14
- import { getImportPath } from './module-specifier.js';
17
+ import { fastDiscoverEntries, } from './fast-discovery.js';
18
+ import { getImportPath, resolveModuleSpecifier, stripPackageVersion, } from './module-specifier.js';
15
19
  import { createNodeModuleErrorPlugin } from './node-module-esbuild-plugin.js';
16
20
  import { createPseudoPackagePlugin } from './pseudo-package-esbuild-plugin.js';
17
21
  import { createSwcPlugin } from './swc-esbuild-plugin.js';
22
+ import { detectWorkflowPatterns } from './transform-utils.js';
18
23
  import { extractWorkflowGraphs } from './workflows-extractor.js';
19
24
  const enhancedResolve = promisify(enhancedResolveOriginal);
25
+ const require = createRequire(import.meta.url);
26
+ /**
27
+ * Legacy opt-in for source maps on the final workflow wrapper + webhook
28
+ * bundles (which default to off, unlike the step/interim workflow bundles
29
+ * that default to inline). Superseded by the `sourcemap` config option and
30
+ * the `WORKFLOW_SOURCEMAP` environment variable; kept for back-compat.
31
+ */
20
32
  const EMIT_SOURCEMAPS_FOR_DEBUGGING = process.env.WORKFLOW_EMIT_SOURCEMAPS_FOR_DEBUGGING === '1';
33
+ const VALID_SOURCEMAP_STRINGS = new Set([
34
+ 'inline',
35
+ 'linked',
36
+ 'external',
37
+ 'both',
38
+ ]);
39
+ /**
40
+ * Parse the value of the `WORKFLOW_SOURCEMAP` environment variable into a
41
+ * `SourcemapMode`. Returns `undefined` if the env var is unset, empty, or
42
+ * unrecognized (a warning is emitted for unrecognized values).
43
+ */
44
+ function parseSourcemapEnv(value) {
45
+ if (value === undefined || value === '')
46
+ return undefined;
47
+ switch (value) {
48
+ case '0':
49
+ case 'false':
50
+ return false;
51
+ case '1':
52
+ case 'true':
53
+ return true;
54
+ default:
55
+ if (VALID_SOURCEMAP_STRINGS.has(value)) {
56
+ return value;
57
+ }
58
+ console.warn(`Ignoring unrecognized WORKFLOW_SOURCEMAP=${value}. ` +
59
+ `Expected one of: true, false, 0, 1, inline, linked, external, both.`);
60
+ return undefined;
61
+ }
62
+ }
63
+ /**
64
+ * Parse the value of the `WORKFLOW_DISCOVER_NODE_MODULES` environment variable
65
+ * into a boolean. Returns `undefined` if the env var is unset or empty so
66
+ * callers can fall back to config/default.
67
+ */
68
+ function parseDiscoverNodeModulesEnv(value) {
69
+ if (value === undefined || value === '')
70
+ return undefined;
71
+ return value !== '0' && value !== 'false';
72
+ }
73
+ function formatBuildDuration(durationMs) {
74
+ if (durationMs < 1000) {
75
+ return `${durationMs}ms`;
76
+ }
77
+ return `${(durationMs / 1000).toFixed(1)}s`;
78
+ }
21
79
  /**
22
80
  * Normalize an array of file paths by appending the `realpath()` of each entry
23
81
  * (to handle symlinks, e.g. pnpm/workspace layouts) and deduplicating.
@@ -28,6 +86,64 @@ async function withRealpaths(entries) {
28
86
  return resolved ? [entry, resolved] : [entry];
29
87
  }))).flat()));
30
88
  }
89
+ /**
90
+ * Canonical "what module does this file represent?" key used to dedupe
91
+ * virtual-entry imports.
92
+ *
93
+ * If the file resolves to a real package specifier (`workflow/internal/builtins`,
94
+ * `@internal/agent/server`, etc.), we return the bare specifier — version
95
+ * stripped — because esbuild's package resolution will collapse all
96
+ * importers of that specifier to the same physical module regardless of
97
+ * which on-disk copy (src vs dist) any one importer wrote.
98
+ *
99
+ * Otherwise we fall back to the absolute file path. Distinct local-app
100
+ * files have distinct paths, so this still dedupes a file against itself
101
+ * (e.g. if it shows up in both `stepFiles` and `serdeOnlyFiles`) without
102
+ * conflating unrelated files.
103
+ */
104
+ function moduleIdentityKey(file, moduleSpecifierRoot) {
105
+ const { moduleSpecifier } = resolveModuleSpecifier(file, moduleSpecifierRoot);
106
+ if (moduleSpecifier) {
107
+ // Strip the "@<version>" suffix so source and dist copies of the same
108
+ // export collapse to the same key.
109
+ return stripPackageVersion(moduleSpecifier);
110
+ }
111
+ return file.replace(/\\/g, '/');
112
+ }
113
+ function formatIdLocation(location) {
114
+ return `${location.filePath}#${location.name}`;
115
+ }
116
+ function assertUniqueManifestIds(entriesByFile, ids, getId, label) {
117
+ for (const [filePath, entries] of Object.entries(entriesByFile || {})) {
118
+ for (const [name, data] of Object.entries(entries)) {
119
+ const id = getId(data);
120
+ const existing = ids.get(id);
121
+ const current = { filePath, name };
122
+ if (existing &&
123
+ (existing.filePath !== current.filePath ||
124
+ existing.name !== current.name)) {
125
+ const idName = label === 'step' ? 'workflow step ID' : 'workflow ID';
126
+ const functionName = `${label} function`;
127
+ const capitalizedLabel = label === 'step' ? 'Step' : 'Workflow';
128
+ throw new WorkflowBuildError(`Duplicate ${idName} "${id}" generated for ${formatIdLocation(existing)} and ${formatIdLocation(current)}.`, {
129
+ hint: `${capitalizedLabel} IDs must be unique across a build. ` +
130
+ `If you own one of the colliding files, rename the ${functionName} or export ` +
131
+ `the package file through a unique package subpath. If the collision is in a ` +
132
+ `transitive dependency you don't control, file an issue with the upstream ` +
133
+ `package or pin to a non-colliding version.`,
134
+ });
135
+ }
136
+ ids.set(id, current);
137
+ }
138
+ }
139
+ }
140
+ function mergeWorkflowManifest(target, incoming, stepIds, workflowIds) {
141
+ assertUniqueManifestIds(incoming.steps, stepIds, (data) => data.stepId, 'step');
142
+ assertUniqueManifestIds(incoming.workflows, workflowIds, (data) => data.workflowId, 'workflow');
143
+ target.workflows = Object.assign(target.workflows || {}, incoming.workflows);
144
+ target.steps = Object.assign(target.steps || {}, incoming.steps);
145
+ target.classes = Object.assign(target.classes || {}, incoming.classes);
146
+ }
31
147
  /**
32
148
  * Base class for workflow builders. Provides common build logic for transforming
33
149
  * workflow source files into deployable bundles using esbuild and SWC.
@@ -36,23 +152,37 @@ async function withRealpaths(entries) {
36
152
  */
37
153
  export class BaseBuilder {
38
154
  config;
155
+ /**
156
+ * Tracks which external packages have already been warned about
157
+ * to avoid duplicate warnings across multiple discoverEntries() calls.
158
+ */
159
+ warnedExternalPackages = new Set();
160
+ workflowBuildStartTime;
161
+ manifestTransformCache = new Map();
39
162
  constructor(config) {
40
163
  this.config = config;
41
164
  }
42
165
  get transformProjectRoot() {
43
166
  return this.config.projectRoot || this.config.workingDir;
44
167
  }
45
- /**
46
- * Whether informational BaseBuilder logs should be printed.
47
- * Subclasses can override this to silence progress logs while keeping warnings/errors.
48
- */
49
- get shouldLogBaseBuilderInfo() {
50
- return true;
168
+ get moduleSpecifierRoot() {
169
+ return this.config.moduleSpecifierRoot || this.transformProjectRoot;
51
170
  }
52
171
  logBaseBuilderInfo(...args) {
53
- if (this.shouldLogBaseBuilderInfo) {
54
- console.log(...args);
55
- }
172
+ buildLogger.debug(args.map(String).join(' '));
173
+ }
174
+ startWorkflowBuildTimer() {
175
+ this.workflowBuildStartTime = Date.now();
176
+ }
177
+ getWorkflowBuildDuration() {
178
+ return Date.now() - (this.workflowBuildStartTime ?? Date.now());
179
+ }
180
+ resetWorkflowBuildTimer() {
181
+ this.workflowBuildStartTime = undefined;
182
+ }
183
+ getWorkflowBuildSummary({ stepCount, workflowCount, }) {
184
+ const counts = `${stepCount} ${pluralize('step', 'steps', stepCount)}, ${workflowCount} ${pluralize('workflow', 'workflows', workflowCount)}`;
185
+ return `✓ Compiled workflows in ${formatBuildDuration(this.getWorkflowBuildDuration())} (${counts})`;
56
186
  }
57
187
  logCreateWorkflowsBundleInfo(...args) {
58
188
  if (!this.config.suppressCreateWorkflowsBundleLogs) {
@@ -118,12 +248,14 @@ export class BaseBuilder {
118
248
  '**/node_modules/**',
119
249
  '**/.git/**',
120
250
  '**/.next/**',
251
+ '**/.nitro/**',
121
252
  '**/.nuxt/**',
122
253
  '**/.output/**',
123
254
  '**/.vercel/**',
124
255
  '**/.workflow-data/**',
125
256
  '**/.workflow-vitest/**',
126
257
  '**/.well-known/workflow/**',
258
+ '**/.swc/**',
127
259
  '**/.svelte-kit/**',
128
260
  '**/.turbo/**',
129
261
  '**/.cache/**',
@@ -152,6 +284,111 @@ export class BaseBuilder {
152
284
  * (e.g., when files are added/removed during watch mode).
153
285
  */
154
286
  discoveredEntries = new WeakMap();
287
+ clearDiscoveredEntriesCache() {
288
+ this.discoveredEntries = new WeakMap();
289
+ }
290
+ clearManifestTransformCache() {
291
+ this.manifestTransformCache.clear();
292
+ }
293
+ /**
294
+ * Pseudo-packages that should not be checked for workflow patterns.
295
+ */
296
+ static PSEUDO_PACKAGES = new Set([
297
+ 'server-only',
298
+ 'client-only',
299
+ ]);
300
+ /**
301
+ * Checks each package in externalPackages for workflow patterns and emits
302
+ * warnings if any contain "use step", "use workflow" directives, or
303
+ * serialization classes. These patterns will not be transformed by the
304
+ * workflow compiler when the package is externalized.
305
+ */
306
+ async warnAboutExternalWorkflowPackages() {
307
+ const externalPackages = this.config.externalPackages;
308
+ if (!externalPackages?.length)
309
+ return;
310
+ for (const pkg of externalPackages) {
311
+ if (BaseBuilder.PSEUDO_PACKAGES.has(pkg))
312
+ continue;
313
+ if (this.warnedExternalPackages.has(pkg))
314
+ continue;
315
+ if (pkg.startsWith('.') ||
316
+ pkg.startsWith('/') ||
317
+ pkg.startsWith('$') ||
318
+ pkg.includes('*') ||
319
+ pkg.includes(':')) {
320
+ continue;
321
+ }
322
+ try {
323
+ // Check package.json dependencies for @workflow/serde (fast path)
324
+ let hasWorkflowSerdeDep = false;
325
+ try {
326
+ const pkgJsonPath = require.resolve(`${pkg}/package.json`, {
327
+ paths: [this.config.workingDir],
328
+ });
329
+ const pkgJsonSource = await readFile(pkgJsonPath, 'utf-8');
330
+ const pkgJson = JSON.parse(pkgJsonSource);
331
+ const dependencies = typeof pkgJson.dependencies === 'object' &&
332
+ pkgJson.dependencies !== null &&
333
+ !Array.isArray(pkgJson.dependencies)
334
+ ? pkgJson.dependencies
335
+ : {};
336
+ const peerDependencies = typeof pkgJson.peerDependencies === 'object' &&
337
+ pkgJson.peerDependencies !== null &&
338
+ !Array.isArray(pkgJson.peerDependencies)
339
+ ? pkgJson.peerDependencies
340
+ : {};
341
+ hasWorkflowSerdeDep =
342
+ Object.hasOwn(dependencies, '@workflow/serde') ||
343
+ Object.hasOwn(peerDependencies, '@workflow/serde');
344
+ }
345
+ catch {
346
+ // package.json not resolvable - continue to source check
347
+ }
348
+ // Check source patterns (thorough path).
349
+ // Note: require.resolve only inspects the package's main entry point.
350
+ // If workflow constructs live in sub-paths (e.g. `my-pkg/workflows`),
351
+ // they won't be detected here. The @workflow/serde dep check above
352
+ // partially covers serde cases. This is acceptable as a best-effort
353
+ // heuristic — the primary fix is auto-removal in withWorkflow().
354
+ let hasUseStep = false;
355
+ let hasUseWorkflow = false;
356
+ let hasSerde = hasWorkflowSerdeDep;
357
+ try {
358
+ const entryPath = require.resolve(pkg, {
359
+ paths: [this.config.workingDir],
360
+ });
361
+ const source = await readFile(entryPath, 'utf-8');
362
+ const patterns = detectWorkflowPatterns(source);
363
+ hasUseStep = patterns.hasUseStep;
364
+ hasUseWorkflow = patterns.hasUseWorkflow;
365
+ if (!hasSerde) {
366
+ hasSerde = patterns.hasSerde;
367
+ }
368
+ }
369
+ catch {
370
+ // Entry file not resolvable or not readable - use what we have
371
+ }
372
+ if (!hasUseStep && !hasUseWorkflow && !hasSerde)
373
+ continue;
374
+ // Build a specific description of what was found
375
+ const issues = [];
376
+ if (hasUseWorkflow)
377
+ issues.push('"use workflow" functions');
378
+ if (hasUseStep)
379
+ issues.push('"use step" functions');
380
+ if (hasSerde)
381
+ issues.push('serialization classes');
382
+ this.warnedExternalPackages.add(pkg);
383
+ console.warn(`\n${chalk.yellow('⚠')} Warning: ${chalk.bold(`"${pkg}"`)} is listed in ${chalk.bold('externalPackages')} (${chalk.bold('serverExternalPackages')} in Next.js) but contains workflow code (${issues.join(', ')}).` +
384
+ `\n This code will ${chalk.bold('not')} be transformed by the workflow compiler, which can cause runtime failures.` +
385
+ `\n Remove ${chalk.bold(`"${pkg}"`)} from ${chalk.bold('externalPackages')} (${chalk.bold('serverExternalPackages')} in Next.js) to fix this.\n`);
386
+ }
387
+ catch {
388
+ // Best-effort: if anything goes wrong, skip this package silently
389
+ }
390
+ }
391
+ }
155
392
  async discoverEntries(inputs, outdir, tsconfigPath) {
156
393
  const previousResult = this.discoveredEntries.get(inputs);
157
394
  if (previousResult) {
@@ -161,46 +398,59 @@ export class BaseBuilder {
161
398
  discoveredSteps: new Set(),
162
399
  discoveredWorkflows: new Set(),
163
400
  discoveredSerdeFiles: new Set(),
401
+ discoveredFiles: new Set(),
164
402
  };
165
403
  const discoverStart = Date.now();
166
- // Resolve the SDK runtime entry point so that the discovery pass
167
- // traces through it and discovers serde classes (like `Run`) that
168
- // live inside SDK packages. Without this, files like `run.js` are
169
- // only discovered when user code happens to import them.
404
+ // Resolve the SDK runtime serde entry point so that the discovery pass
405
+ // discovers classes like `Run` that live inside SDK packages. Without this,
406
+ // files like `run.js` are only discovered when user code imports them.
170
407
  // This is resolved here (rather than in callers) so that the original
171
408
  // `inputs` array reference is preserved for WeakMap caching — callers
172
409
  // like createWorkflowsBundle and createStepsBundle can share the same
173
410
  // cache entry when they pass the same inputFiles array.
174
- const resolvedWorkflowRuntime = await enhancedResolve(outdir, 'workflow/runtime').catch(() => undefined);
411
+ const resolvedWorkflowRuntime = await enhancedResolve(outdir, '@workflow/core/runtime/run').catch(() => undefined);
175
412
  const entryPoints = resolvedWorkflowRuntime
176
413
  ? [...inputs, resolvedWorkflowRuntime]
177
414
  : inputs;
178
415
  const effectiveTsconfigPath = tsconfigPath ?? (await this.findTsConfigPath());
179
- const esbuildTsconfigOptions = await getEsbuildTsconfigOptions(effectiveTsconfigPath);
180
- try {
181
- await esbuild.build({
182
- treeShaking: true,
183
- entryPoints,
184
- plugins: [
185
- createDiscoverEntriesPlugin(state, this.transformProjectRoot),
186
- ],
187
- platform: 'node',
188
- write: false,
189
- outdir,
190
- bundle: true,
191
- sourcemap: false,
192
- absWorkingDir: this.config.workingDir,
193
- logLevel: 'silent',
194
- ...esbuildTsconfigOptions,
195
- // External packages that should not be bundled during discovery
196
- external: this.config.externalPackages || [],
197
- });
198
- }
199
- catch (_) { }
416
+ await fastDiscoverEntries({
417
+ entryPoints,
418
+ state,
419
+ defaultTsconfigPath: effectiveTsconfigPath,
420
+ workingDir: this.config.workingDir,
421
+ discoverWorkflowsInNodeModules: this.resolveDiscoverWorkflowsInNodeModules(),
422
+ });
200
423
  this.logBaseBuilderInfo(`Discovering workflow directives`, `${Date.now() - discoverStart}ms`);
424
+ // Warn about external packages that contain workflow code
425
+ await this.warnAboutExternalWorkflowPackages();
201
426
  this.discoveredEntries.set(inputs, state);
202
427
  return state;
203
428
  }
429
+ /**
430
+ * Writes generated files atomically where possible. On Windows, Next.js can
431
+ * briefly hold generated route files open while compiling them, which makes
432
+ * rename-over-existing fail with EPERM/EACCES. In that case, fall back to a
433
+ * direct overwrite so watch rebuilds can still make progress.
434
+ */
435
+ async writeGeneratedFile(targetPath, content) {
436
+ const tempPath = `${targetPath}.${randomUUID()}.tmp`;
437
+ await writeFile(tempPath, content);
438
+ try {
439
+ await rename(tempPath, targetPath);
440
+ }
441
+ catch (error) {
442
+ const errorCode = error && typeof error === 'object' && 'code' in error
443
+ ? error.code
444
+ : undefined;
445
+ if (process.platform === 'win32' &&
446
+ (errorCode === 'EPERM' || errorCode === 'EACCES')) {
447
+ await writeFile(targetPath, content);
448
+ await rm(tempPath, { force: true });
449
+ return;
450
+ }
451
+ throw error;
452
+ }
453
+ }
204
454
  /**
205
455
  * Writes debug information to a JSON file for troubleshooting build issues.
206
456
  * Uses atomic write (temp file + rename) to prevent race conditions when
@@ -228,12 +478,7 @@ export class BaseBuilder {
228
478
  ...existing,
229
479
  ...debugData,
230
480
  }, null, 2);
231
- // Write atomically: write to temp file, then rename.
232
- // rename() is atomic on POSIX systems and provides best-effort atomicity on Windows.
233
- // Prevents race conditions where concurrent builds read partially-written files.
234
- const tempPath = `${targetPath}.${randomUUID()}.tmp`;
235
- await writeFile(tempPath, mergedData);
236
- await rename(tempPath, targetPath);
481
+ await this.writeGeneratedFile(targetPath, mergedData);
237
482
  }
238
483
  catch (error) {
239
484
  console.warn('Failed to write debug file:', error);
@@ -257,7 +502,9 @@ export class BaseBuilder {
257
502
  }
258
503
  }
259
504
  if (throwOnError) {
260
- throw new Error(`Build failed during ${phase}:\n${errorMessages.join('\n')}`);
505
+ throw new WorkflowBuildError(`Build failed during ${phase}:\n${errorMessages.join('\n')}`, {
506
+ hint: `Review the esbuild errors above — they come from the ${phase} bundle. Fix the offending source files and re-run the build.`,
507
+ });
261
508
  }
262
509
  }
263
510
  if (!options?.suppressWarnings &&
@@ -288,24 +535,117 @@ export class BaseBuilder {
288
535
  }
289
536
  return relativePath;
290
537
  }
538
+ async getCachedManifestTransform(file, mode) {
539
+ const stats = await stat(file);
540
+ const cacheKey = `${mode}:${file}`;
541
+ const cached = this.manifestTransformCache.get(cacheKey);
542
+ if (cached &&
543
+ cached.size === stats.size &&
544
+ cached.mtimeMs === stats.mtimeMs) {
545
+ return cached.manifest;
546
+ }
547
+ const source = await readFile(file, 'utf8');
548
+ const relativeFilepath = this.getRelativeFilepath(file);
549
+ const { workflowManifest } = await applySwcTransform(relativeFilepath, source, mode, file, this.transformProjectRoot, this.moduleSpecifierRoot);
550
+ this.manifestTransformCache.set(cacheKey, {
551
+ size: stats.size,
552
+ mtimeMs: stats.mtimeMs,
553
+ manifest: workflowManifest,
554
+ });
555
+ return workflowManifest;
556
+ }
557
+ createRouteImportSpecifier(file, routeDir) {
558
+ const { importPath, isPackage } = getImportPath(file, this.config.workingDir);
559
+ if (isPackage) {
560
+ return importPath;
561
+ }
562
+ let relativePath = relative(routeDir, file).replace(/\\/g, '/');
563
+ if (!relativePath.startsWith('./') && !relativePath.startsWith('../')) {
564
+ relativePath = `./${relativePath}`;
565
+ }
566
+ return relativePath;
567
+ }
568
+ async createStepSourceRegistrationFile({ inputFiles, outfile, tsconfigPath, discoveredEntries, }) {
569
+ const stepsBundleStart = Date.now();
570
+ const workflowManifest = {};
571
+ const builtInSteps = 'workflow/internal/builtins';
572
+ const resolvedBuiltInSteps = (await enhancedResolve(dirname(outfile), builtInSteps).catch((err) => {
573
+ throw new WorkflowBuildError(`Failed to resolve built-in steps sources.\n\nCaused by: ${String(err)}`, {
574
+ hint: 'run `pnpm install workflow` to resolve this issue.',
575
+ cause: err,
576
+ });
577
+ }));
578
+ const discovered = discoveredEntries ??
579
+ (await this.discoverEntries(inputFiles, dirname(outfile), tsconfigPath));
580
+ const stepFiles = [...discovered.discoveredSteps].sort();
581
+ const workflowFiles = [...discovered.discoveredWorkflows].sort();
582
+ const serdeFiles = [...discovered.discoveredSerdeFiles].sort();
583
+ const stepFilesSet = new Set(stepFiles);
584
+ const serdeOnlyFiles = serdeFiles.filter((f) => !stepFilesSet.has(f));
585
+ await this.writeDebugFile(outfile, {
586
+ stepFiles,
587
+ workflowFiles,
588
+ serdeOnlyFiles,
589
+ sourceImports: true,
590
+ });
591
+ const emittedImportIdentities = new Set([builtInSteps]);
592
+ const importStatements = [];
593
+ const routeDir = dirname(outfile);
594
+ const addRegistrationImport = (specifier) => {
595
+ importStatements.push(`import ${JSON.stringify(specifier)};`);
596
+ };
597
+ const addRegistrationFileImport = (file) => {
598
+ const identity = moduleIdentityKey(file, this.moduleSpecifierRoot);
599
+ if (emittedImportIdentities.has(identity)) {
600
+ return;
601
+ }
602
+ emittedImportIdentities.add(identity);
603
+ addRegistrationImport(this.createRouteImportSpecifier(file, routeDir));
604
+ };
605
+ addRegistrationImport(builtInSteps);
606
+ for (const file of stepFiles) {
607
+ addRegistrationFileImport(file);
608
+ }
609
+ for (const file of serdeOnlyFiles) {
610
+ addRegistrationFileImport(file);
611
+ }
612
+ const output = `// biome-ignore-all lint: generated file
613
+ /* eslint-disable */
614
+ ${importStatements.join('\n')}
615
+
616
+ export const __steps_registered = true;
617
+ `;
618
+ await mkdir(dirname(outfile), { recursive: true });
619
+ await this.writeGeneratedFile(outfile, output);
620
+ const manifestFiles = Array.from(new Set([...stepFiles, ...serdeOnlyFiles, resolvedBuiltInSteps])).sort();
621
+ const stepIds = new Map();
622
+ const workflowIds = new Map();
623
+ await Promise.all(manifestFiles.map(async (file) => {
624
+ const fileManifest = await this.getCachedManifestTransform(file, 'step');
625
+ mergeWorkflowManifest(workflowManifest, fileManifest, stepIds, workflowIds);
626
+ }));
627
+ await this.ensureSwcIgnored();
628
+ this.logBaseBuilderInfo('Created step registrations', `${Date.now() - stepsBundleStart}ms`);
629
+ return workflowManifest;
630
+ }
291
631
  /**
292
632
  * Creates a bundle for workflow step functions.
293
633
  * Steps have full Node.js runtime access and handle side effects, API calls, etc.
294
634
  *
295
635
  * @param externalizeNonSteps - If true, only bundles step entry points and externalizes other code
636
+ * @param sourceStepRegistrationImports - If true, emits a source import registration file instead of bundling step registrations
637
+ * @param bundleTransitiveLocalStepDependencies - If true, also bundles project-local files imported by step entries for direct runtime loading
296
638
  * @returns Build context (for watch mode) and the collected workflow manifest
297
639
  */
298
- async createStepsBundle({ inputFiles, format = 'esm', outfile, externalizeNonSteps, rewriteTsExtensions, tsconfigPath, discoveredEntries, }) {
640
+ async createStepsBundle({ inputFiles, format = 'esm', outfile, externalizeNonSteps, bundleTransitiveLocalStepDependencies, sourceStepRegistrationImports, rewriteTsExtensions, tsconfigPath, discoveredEntries, skipEsmRequireBanner = false, }) {
299
641
  const stepsBundleStart = Date.now();
300
642
  const workflowManifest = {};
301
643
  const builtInSteps = 'workflow/internal/builtins';
302
644
  const resolvedBuiltInSteps = await enhancedResolve(dirname(outfile), 'workflow/internal/builtins').catch((err) => {
303
- throw new Error([
304
- chalk.red('Failed to resolve built-in steps sources.'),
305
- `${chalk.yellow.bold('hint:')} run \`${chalk.cyan.italic('npm install workflow')}\` to resolve this issue.`,
306
- '',
307
- `Caused by: ${chalk.red(String(err))}`,
308
- ].join('\n'));
645
+ throw new WorkflowBuildError(`Failed to resolve built-in steps sources.\n\nCaused by: ${String(err)}`, {
646
+ hint: 'run `pnpm install workflow` to resolve this issue.',
647
+ cause: err,
648
+ });
309
649
  });
310
650
  // Discovery of workflow/step/serde entries. The SDK runtime entry point
311
651
  // (workflow/runtime) is resolved inside discoverEntries() itself so that
@@ -321,6 +661,19 @@ export class BaseBuilder {
321
661
  // when receiving data from workflows and serialized when returning data to workflows.
322
662
  const stepFilesSet = new Set(stepFiles);
323
663
  const serdeOnlyFiles = serdeFiles.filter((f) => !stepFilesSet.has(f));
664
+ if (sourceStepRegistrationImports &&
665
+ externalizeNonSteps &&
666
+ !bundleTransitiveLocalStepDependencies) {
667
+ return {
668
+ context: undefined,
669
+ manifest: await this.createStepSourceRegistrationFile({
670
+ inputFiles,
671
+ outfile,
672
+ tsconfigPath,
673
+ discoveredEntries: discovered,
674
+ }),
675
+ };
676
+ }
324
677
  // log the step files for debugging
325
678
  await this.writeDebugFile(outfile, {
326
679
  stepFiles,
@@ -331,6 +684,28 @@ export class BaseBuilder {
331
684
  // For workspace/node_modules packages, uses the package name so esbuild
332
685
  // will resolve through package.json exports with the appropriate conditions
333
686
  const createImport = (file) => {
687
+ const normalizedWorkspaceRoot = this.config.workingDir
688
+ .replace(/\\/g, '/')
689
+ .replace(/\/$/, '');
690
+ const normalizedWorkspaceFile = file.replace(/\\/g, '/');
691
+ // Only use relative source paths for workspace symlinks (files
692
+ // outside node_modules in a packages/*/src/ directory). For tarball-
693
+ // installed packages (files inside node_modules/), fall through to
694
+ // getImportPath which returns package specifiers — this allows the
695
+ // SWC plugin's externalizeNonSteps to work correctly.
696
+ const isWorkspaceSourceBackedPackageFile = normalizedWorkspaceFile.includes('/packages/') &&
697
+ normalizedWorkspaceFile.includes('/src/') &&
698
+ !normalizedWorkspaceFile.includes('/node_modules/') &&
699
+ !(normalizedWorkspaceFile === normalizedWorkspaceRoot ||
700
+ normalizedWorkspaceFile.startsWith(`${normalizedWorkspaceRoot}/`));
701
+ const isSourceBackedPackageFile = isWorkspaceSourceBackedPackageFile;
702
+ if (isSourceBackedPackageFile) {
703
+ let relativePath = relative(normalizedWorkspaceRoot, normalizedWorkspaceFile).replace(/\\/g, '/');
704
+ if (!relativePath.startsWith('./') && !relativePath.startsWith('../')) {
705
+ relativePath = `./${relativePath}`;
706
+ }
707
+ return `import '${relativePath}';`;
708
+ }
334
709
  const { importPath, isPackage } = getImportPath(file, this.config.workingDir);
335
710
  if (isPackage) {
336
711
  // Use package name - esbuild will resolve via package.json exports
@@ -353,9 +728,27 @@ export class BaseBuilder {
353
728
  };
354
729
  // Create a virtual entry that imports all files. All step definitions
355
730
  // will get registered thanks to the swc transform.
356
- const stepImports = stepFiles.map(createImport).join('\n');
731
+ //
732
+ // Dedupe imports by canonical module identity so we never emit two
733
+ // import lines that resolve to the same physical module. Pre-seed the
734
+ // set with the built-in steps import so a workspace step file at
735
+ // `packages/workflow/src/internal/builtins.ts` doesn't emit a second,
736
+ // relative-path competing import — esbuild would otherwise transform
737
+ // both copies and the swc plugin would generate duplicate step IDs.
738
+ const emittedImportIdentities = new Set([builtInSteps]);
739
+ const buildImports = (files) => files
740
+ .filter((file) => {
741
+ const identity = moduleIdentityKey(file, this.moduleSpecifierRoot);
742
+ if (emittedImportIdentities.has(identity))
743
+ return false;
744
+ emittedImportIdentities.add(identity);
745
+ return true;
746
+ })
747
+ .map(createImport)
748
+ .join('\n');
749
+ const stepImports = buildImports(stepFiles);
357
750
  // Include serde-only files for class registration side effects
358
- const serdeImports = serdeOnlyFiles.map(createImport).join('\n');
751
+ const serdeImports = buildImports(serdeOnlyFiles);
359
752
  const entryContent = `
360
753
  // Built in steps
361
754
  import '${builtInSteps}';
@@ -363,8 +756,9 @@ export class BaseBuilder {
363
756
  ${stepImports}
364
757
  // Serde files for cross-context class registration
365
758
  ${serdeImports}
366
- // API entrypoint
367
- export { stepEntrypoint as POST } from 'workflow/runtime';`;
759
+ // Sentinel export so bundlers (rollup) don't tree-shake this module
760
+ // when it's imported as a side-effect-only dependency.
761
+ export const __steps_registered = true;`;
368
762
  // Bundle with esbuild and our custom SWC plugin
369
763
  const entriesToBundle = externalizeNonSteps
370
764
  ? [
@@ -383,7 +777,9 @@ export class BaseBuilder {
383
777
  ]);
384
778
  const esbuildTsconfigOptions = await getEsbuildTsconfigOptions(tsconfigPath);
385
779
  const { banner: importMetaBanner, define: importMetaDefine } = this.getCjsImportMetaPolyfill(format);
386
- const esmRequireBanner = this.getEsmRequireBanner(format);
780
+ const esmRequireBanner = skipEsmRequireBanner
781
+ ? ''
782
+ : this.getEsmRequireBanner(format);
387
783
  const esbuildCtx = await esbuild.context({
388
784
  banner: {
389
785
  js: `// biome-ignore-all lint: generated file\n/* eslint-disable */\n${importMetaBanner}${esmRequireBanner}`,
@@ -421,11 +817,14 @@ export class BaseBuilder {
421
817
  '.mjs',
422
818
  '.cjs',
423
819
  ],
424
- // Inline source maps for better stack traces in step execution.
425
- // Steps execute in Node.js context and inline sourcemaps ensure we get
426
- // meaningful stack traces with proper file names and line numbers when errors
427
- // occur in deeply nested function calls across multiple files.
428
- sourcemap: 'inline',
820
+ // Source maps for better stack traces in step execution. Steps execute
821
+ // in Node.js context and inline sourcemaps give meaningful stack traces
822
+ // with proper file names and line numbers when errors occur in deeply
823
+ // nested function calls across multiple files. Defaults to inline in
824
+ // development and off in production (see `defaultSourcemapMode`) to keep
825
+ // production function bundles small; override with the `sourcemap`
826
+ // config option or the `WORKFLOW_SOURCEMAP` env var.
827
+ sourcemap: this.resolveSourcemap(this.defaultSourcemapMode),
429
828
  plugins: [
430
829
  // Handle pseudo-packages like 'server-only' and 'client-only' by providing
431
830
  // empty modules. Must run first to intercept these before other resolution.
@@ -435,7 +834,9 @@ export class BaseBuilder {
435
834
  entriesToBundle: normalizedEntriesToBundle,
436
835
  outdir: outfile ? dirname(outfile) : undefined,
437
836
  projectRoot: this.transformProjectRoot,
837
+ moduleSpecifierRoot: this.moduleSpecifierRoot,
438
838
  workflowManifest,
839
+ bundleTransitiveLocalStepDependencies,
439
840
  rewriteTsExtensions,
440
841
  sideEffectEntries: normalizedSideEffectEntries,
441
842
  }),
@@ -453,9 +854,7 @@ export class BaseBuilder {
453
854
  const workflowOnlyFiles = workflowFiles.filter((f) => !stepFiles.includes(f));
454
855
  await Promise.all(workflowOnlyFiles.map(async (workflowFile) => {
455
856
  try {
456
- const source = await readFile(workflowFile, 'utf8');
457
- const relativeFilepath = this.getRelativeFilepath(workflowFile);
458
- const { workflowManifest: fileManifest } = await applySwcTransform(relativeFilepath, source, 'workflow', workflowFile, this.transformProjectRoot);
857
+ const fileManifest = await this.getCachedManifestTransform(workflowFile, 'workflow');
459
858
  if (fileManifest.workflows) {
460
859
  workflowManifest.workflows = Object.assign(workflowManifest.workflows || {}, fileManifest.workflows);
461
860
  }
@@ -468,8 +867,7 @@ export class BaseBuilder {
468
867
  console.warn(`Warning: Failed to extract workflow metadata from ${workflowFile}:`, error instanceof Error ? error.message : String(error));
469
868
  }
470
869
  }));
471
- // Create .gitignore in .swc directory
472
- await this.createSwcGitignore();
870
+ await this.ensureSwcIgnored();
473
871
  if (this.config.watch) {
474
872
  return { context: esbuildCtx, manifest: workflowManifest };
475
873
  }
@@ -519,12 +917,26 @@ export class BaseBuilder {
519
917
  }
520
918
  return `import '${relativePath}';`;
521
919
  };
522
- // Create a virtual entry that imports all workflow files
920
+ // Create a virtual entry that imports all workflow files. Dedupe by
921
+ // canonical module identity so source/dist copies of the same workspace
922
+ // package export don't both get imported (which would make the swc
923
+ // plugin generate duplicate workflow IDs).
924
+ const emittedImportIdentities = new Set();
925
+ const buildImports = (files) => files
926
+ .filter((file) => {
927
+ const identity = moduleIdentityKey(file, this.moduleSpecifierRoot);
928
+ if (emittedImportIdentities.has(identity))
929
+ return false;
930
+ emittedImportIdentities.add(identity);
931
+ return true;
932
+ })
933
+ .map(createImport)
934
+ .join('\n');
523
935
  // The SWC plugin in workflow mode emits `globalThis.__private_workflows.set(workflowId, fn)`
524
936
  // calls directly, so we just need to import the files (Map is initialized via banner)
525
- const workflowImports = workflowFiles.map(createImport).join('\n');
937
+ const workflowImports = buildImports(workflowFiles);
526
938
  // Include serde-only files for class registration side effects
527
- const serdeImports = serdeOnlyFiles.map(createImport).join('\n');
939
+ const serdeImports = buildImports(serdeOnlyFiles);
528
940
  const imports = serdeImports
529
941
  ? `${workflowImports}\n// Serde files for cross-context class registration\n${serdeImports}`
530
942
  : workflowImports;
@@ -561,10 +973,15 @@ export class BaseBuilder {
561
973
  banner: {
562
974
  js: 'globalThis.__private_workflows = new Map();',
563
975
  },
564
- // Inline source maps for better stack traces in workflow VM execution.
565
- // This intermediate bundle is executed via runInContext() in a VM, so we need
566
- // inline source maps to get meaningful stack traces instead of "evalmachine.<anonymous>".
567
- sourcemap: 'inline',
976
+ // Source maps for better stack traces in workflow VM execution. This
977
+ // intermediate bundle is executed via runInContext() in a VM, so inline
978
+ // source maps give meaningful stack traces instead of
979
+ // "evalmachine.<anonymous>". Defaults to inline in development and off in
980
+ // production (see `defaultSourcemapMode`) to keep production function
981
+ // bundles small; override with the `sourcemap` config option or the
982
+ // `WORKFLOW_SOURCEMAP` env var. The runtime remaps stacks only when a
983
+ // map is present, so disabling maps degrades gracefully.
984
+ sourcemap: this.resolveSourcemap(this.defaultSourcemapMode),
568
985
  // Use tsconfig for path alias resolution.
569
986
  // For symlinked configs this uses tsconfigRaw to preserve cwd-relative aliases.
570
987
  ...esbuildTsconfigOptions,
@@ -585,6 +1002,7 @@ export class BaseBuilder {
585
1002
  createSwcPlugin({
586
1003
  mode: 'workflow',
587
1004
  projectRoot: this.transformProjectRoot,
1005
+ moduleSpecifierRoot: this.moduleSpecifierRoot,
588
1006
  workflowManifest,
589
1007
  sideEffectEntries: normalizedWorkflowSideEffectEntries,
590
1008
  }),
@@ -621,11 +1039,12 @@ export class BaseBuilder {
621
1039
  await mkdir(dirname(resolvedPath), { recursive: true });
622
1040
  await writeFile(resolvedPath, prefix + JSON.stringify(workflowManifest, null, 2));
623
1041
  }
624
- // Create .gitignore in .swc directory
625
- await this.createSwcGitignore();
1042
+ await this.ensureSwcIgnored();
626
1043
  if (!interimBundle.outputFiles ||
627
1044
  interimBundle.outputFiles.length === 0) {
628
- throw new Error('No output files generated from esbuild');
1045
+ throw new WorkflowBuildError('No output files generated from esbuild', {
1046
+ hint: 'This usually indicates a misconfigured entry point or an empty workflow directory. Check that your workflow files contain a `"use workflow"` or `"use step"` directive.',
1047
+ });
629
1048
  }
630
1049
  // Serde compliance warnings: check if workflow bundle has Node.js imports
631
1050
  // alongside serde-registered classes (these will fail at runtime in the sandbox)
@@ -660,15 +1079,20 @@ export class BaseBuilder {
660
1079
  console.warn(chalk.yellow(`⚠ Serde warning for ${classLabel}: `) + issue);
661
1080
  }
662
1081
  }
1082
+ const workflowEntrypointOptionsCode = createWorkflowEntrypointOptionsCode({
1083
+ basePath: this.config.basePath,
1084
+ routeModuleBodyStartedAt: 'workflowRouteModuleBodyStartedAt',
1085
+ });
663
1086
  const bundleFinal = async (interimBundle) => {
664
1087
  const workflowBundleCode = interimBundle;
665
1088
  const workflowFunctionCode = `// biome-ignore-all lint: generated file
666
1089
  /* eslint-disable */
667
1090
  import { workflowEntrypoint } from 'workflow/runtime';
668
1091
 
1092
+ const workflowRouteModuleBodyStartedAt = Date.now();
669
1093
  const workflowCode = \`${workflowBundleCode.replace(/[\\`$]/g, '\\$&')}\`;
670
1094
 
671
- export const POST = workflowEntrypoint(workflowCode);`;
1095
+ ${createWorkflowRouteHandlersCode(`workflowEntrypoint(workflowCode${workflowEntrypointOptionsCode})`)}`;
672
1096
  // we skip the final bundling step for Next.js so it can bundle itself
673
1097
  if (!bundleFinalOutput) {
674
1098
  if (!outfile) {
@@ -677,11 +1101,7 @@ export const POST = workflowEntrypoint(workflowCode);`;
677
1101
  // Ensure the output directory exists
678
1102
  const outputDir = dirname(outfile);
679
1103
  await mkdir(outputDir, { recursive: true });
680
- // Atomic write: write to temp file then rename to prevent
681
- // file watchers from reading partial file during write
682
- const tempPath = `${outfile}.${randomUUID()}.tmp`;
683
- await writeFile(tempPath, workflowFunctionCode);
684
- await rename(tempPath, outfile);
1104
+ await this.writeGeneratedFile(outfile, workflowFunctionCode);
685
1105
  return;
686
1106
  }
687
1107
  const bundleStartTime = Date.now();
@@ -701,7 +1121,7 @@ export const POST = workflowEntrypoint(workflowCode);`;
701
1121
  outfile,
702
1122
  // Source maps for the final workflow bundle wrapper (not important since this code
703
1123
  // doesn't run in the VM - only the intermediate bundle sourcemap is relevant)
704
- sourcemap: EMIT_SOURCEMAPS_FOR_DEBUGGING,
1124
+ sourcemap: this.resolveSourcemap(EMIT_SOURCEMAPS_FOR_DEBUGGING),
705
1125
  absWorkingDir: this.config.workingDir,
706
1126
  bundle: true,
707
1127
  format,
@@ -717,16 +1137,18 @@ export const POST = workflowEntrypoint(workflowCode);`;
717
1137
  });
718
1138
  this.logCreateWorkflowsBundleInfo('Created final workflow bundle', `${Date.now() - bundleStartTime}ms`);
719
1139
  };
720
- await bundleFinal(interimBundle.outputFiles[0].text);
1140
+ const interimBundleText = interimBundle.outputFiles[0].text;
1141
+ await bundleFinal(interimBundleText);
721
1142
  if (keepInterimBundleContext) {
722
1143
  shouldDisposeInterimBundleCtx = false;
723
1144
  return {
724
1145
  manifest: workflowManifest,
725
1146
  interimBundleCtx,
726
1147
  bundleFinal,
1148
+ interimBundleText,
727
1149
  };
728
1150
  }
729
- return { manifest: workflowManifest };
1151
+ return { manifest: workflowManifest, interimBundleText };
730
1152
  }
731
1153
  catch (error) {
732
1154
  shouldDisposeInterimBundleCtx = true;
@@ -743,6 +1165,172 @@ export const POST = workflowEntrypoint(workflowCode);`;
743
1165
  }
744
1166
  }
745
1167
  }
1168
+ /**
1169
+ * V2: Creates a combined bundle that includes both step registrations and
1170
+ * workflow orchestration in a single route. The combined entrypoint executes
1171
+ * steps inline when possible, reducing function invocations and queue overhead.
1172
+ *
1173
+ * This method reuses createStepsBundle (for step registrations) and
1174
+ * createWorkflowsBundle (for workflow VM code), then combines them into
1175
+ * a single route file using workflowEntrypoint().
1176
+ */
1177
+ async createCombinedBundle({ inputFiles, stepsOutfile, flowOutfile, format = 'esm', bundleFinalOutput = true, tsconfigPath, externalizeNonSteps, bundleTransitiveLocalStepDependencies, sourceStepRegistrationImports, discoveredEntries, }) {
1178
+ this.startWorkflowBuildTimer();
1179
+ const effectiveDiscoveredEntries = discoveredEntries ??
1180
+ (await this.discoverEntries(inputFiles, dirname(flowOutfile), tsconfigPath));
1181
+ // 1. Build step registrations bundle (used as separate file for
1182
+ // bundleFinalOutput: false, or read back for inline content when true)
1183
+ const { context: stepsContext, manifest: stepsManifest } = await this.createStepsBundle({
1184
+ inputFiles,
1185
+ outfile: stepsOutfile,
1186
+ // When bundleFinalOutput is true, use ESM for the steps bundle
1187
+ // regardless of the final output format. The final esbuild pass
1188
+ // converts everything to the target format. Using CJS here causes
1189
+ // a module.exports collision: the steps bundle's top-level
1190
+ // module.exports overwrites the combined route's module.exports
1191
+ // when esbuild inlines the steps without a __commonJS wrapper.
1192
+ format: bundleFinalOutput ? 'esm' : format,
1193
+ externalizeNonSteps,
1194
+ bundleTransitiveLocalStepDependencies,
1195
+ sourceStepRegistrationImports,
1196
+ tsconfigPath,
1197
+ discoveredEntries: effectiveDiscoveredEntries,
1198
+ // Skip the createRequire banner here — when bundleFinalOutput is true
1199
+ // the outer esbuild pass will inline this bundle and add its own
1200
+ // banner. Emitting it twice declares __createRequire twice.
1201
+ skipEsmRequireBanner: bundleFinalOutput,
1202
+ });
1203
+ // 2. Build workflow VM code
1204
+ const tempWorkflowOutfile = `${flowOutfile}.__wf_tmp.js`;
1205
+ const workflowsResult = await this.createWorkflowsBundle({
1206
+ inputFiles,
1207
+ outfile: tempWorkflowOutfile,
1208
+ format,
1209
+ bundleFinalOutput: false,
1210
+ tsconfigPath,
1211
+ discoveredEntries: effectiveDiscoveredEntries,
1212
+ });
1213
+ const workflowVMCode = workflowsResult.interimBundleText;
1214
+ if (!workflowVMCode) {
1215
+ throw new Error('createWorkflowsBundle did not return interimBundleText');
1216
+ }
1217
+ // Clean up the wrapper file
1218
+ try {
1219
+ const { unlink } = await import('node:fs/promises');
1220
+ await unlink(tempWorkflowOutfile);
1221
+ }
1222
+ catch {
1223
+ // Ignore cleanup errors
1224
+ }
1225
+ // 3. Generate combined route file
1226
+ const stepsRelativePath = `./${basename(stepsOutfile).replace(/\\/g, '/')}`;
1227
+ const escapedVMCode = workflowVMCode.replace(/[\\`$]/g, '\\$&');
1228
+ const workflowEntrypointOptionsCode = createWorkflowEntrypointOptionsCode({
1229
+ basePath: this.config.basePath,
1230
+ routeModuleBodyStartedAt: 'workflowRouteModuleBodyStartedAt',
1231
+ });
1232
+ const combinedFunctionCode = `// biome-ignore-all lint: generated file
1233
+ /* eslint-disable */
1234
+ import { __steps_registered } from '${stepsRelativePath}';
1235
+ import { workflowEntrypoint } from 'workflow/runtime';
1236
+
1237
+ const workflowRouteModuleBodyStartedAt = Date.now();
1238
+
1239
+ // Prevent rollup from tree-shaking the steps side-effect import
1240
+ void __steps_registered;
1241
+
1242
+ const workflowCode = \`${escapedVMCode}\`;
1243
+
1244
+ ${createWorkflowRouteHandlersCode(`workflowEntrypoint(workflowCode${workflowEntrypointOptionsCode})`)}`;
1245
+ if (!bundleFinalOutput) {
1246
+ await this.writeGeneratedFile(flowOutfile, combinedFunctionCode);
1247
+ }
1248
+ else {
1249
+ // Bundle the combined code for standalone use
1250
+ const bundleStartTime = Date.now();
1251
+ const { banner: importMetaBanner, define: importMetaDefine } = this.getCjsImportMetaPolyfill(format);
1252
+ // ESM banner provides `require` via createRequire(import.meta.url) so
1253
+ // CJS dependencies that call require() for Node.js builtins keep working
1254
+ // in the ESM output produced by bundleFinalOutput: true.
1255
+ const finalEsmRequireBanner = this.getEsmRequireBanner(format);
1256
+ const finalResult = await esbuild.build({
1257
+ banner: {
1258
+ js: `// biome-ignore-all lint: generated file\n/* eslint-disable */\n${importMetaBanner}${finalEsmRequireBanner}`,
1259
+ },
1260
+ stdin: {
1261
+ contents: combinedFunctionCode,
1262
+ resolveDir: dirname(flowOutfile),
1263
+ sourcefile: 'virtual-entry.js',
1264
+ loader: 'js',
1265
+ },
1266
+ outfile: flowOutfile,
1267
+ absWorkingDir: this.config.workingDir,
1268
+ bundle: true,
1269
+ format,
1270
+ platform: 'node',
1271
+ target: 'es2022',
1272
+ write: true,
1273
+ keepNames: true,
1274
+ minify: false,
1275
+ define: importMetaDefine,
1276
+ external: ['@aws-sdk/credential-provider-web-identity'],
1277
+ });
1278
+ this.logEsbuildMessages(finalResult, 'combined bundle', true);
1279
+ this.logBaseBuilderInfo('Created combined bundle', `${Date.now() - bundleStartTime}ms`);
1280
+ }
1281
+ // Merge manifests
1282
+ const manifest = {
1283
+ ...stepsManifest,
1284
+ workflows: {
1285
+ ...stepsManifest.workflows,
1286
+ ...workflowsResult.manifest.workflows,
1287
+ },
1288
+ classes: {
1289
+ ...stepsManifest.classes,
1290
+ ...workflowsResult.manifest.classes,
1291
+ },
1292
+ };
1293
+ // Create a custom bundleFinal for watch mode that uses workflowEntrypoint
1294
+ const combinedBundleFinal = async (interimBundleText) => {
1295
+ const escaped = interimBundleText.replace(/[\\`$]/g, '\\$&');
1296
+ const workflowEntrypointOptionsCode = createWorkflowEntrypointOptionsCode({
1297
+ basePath: this.config.basePath,
1298
+ routeModuleBodyStartedAt: 'workflowRouteModuleBodyStartedAt',
1299
+ });
1300
+ const code = `// biome-ignore-all lint: generated file
1301
+ /* eslint-disable */
1302
+ import { __steps_registered } from '${stepsRelativePath}';
1303
+ import { workflowEntrypoint } from 'workflow/runtime';
1304
+
1305
+ const workflowRouteModuleBodyStartedAt = Date.now();
1306
+
1307
+ void __steps_registered;
1308
+
1309
+ const workflowCode = \`${escaped}\`;
1310
+
1311
+ ${createWorkflowRouteHandlersCode(`workflowEntrypoint(workflowCode${workflowEntrypointOptionsCode})`)}`;
1312
+ const outputDir = dirname(flowOutfile);
1313
+ await mkdir(outputDir, { recursive: true });
1314
+ await this.writeGeneratedFile(flowOutfile, code);
1315
+ };
1316
+ if (this.config.watch) {
1317
+ return {
1318
+ manifest,
1319
+ stepsContext,
1320
+ interimBundleCtx: workflowsResult.interimBundleCtx,
1321
+ bundleFinal: combinedBundleFinal,
1322
+ discoveredEntries: effectiveDiscoveredEntries,
1323
+ stepsManifest,
1324
+ workflowsManifest: workflowsResult.manifest,
1325
+ };
1326
+ }
1327
+ return {
1328
+ manifest,
1329
+ discoveredEntries: effectiveDiscoveredEntries,
1330
+ stepsManifest,
1331
+ workflowsManifest: workflowsResult.manifest,
1332
+ };
1333
+ }
746
1334
  /**
747
1335
  * Creates a client library bundle for workflow execution.
748
1336
  * The client library allows importing and calling workflows from application code.
@@ -832,13 +1420,13 @@ export const POST = workflowEntrypoint(workflowCode);`;
832
1420
  createSwcPlugin({
833
1421
  mode: 'step',
834
1422
  projectRoot: this.transformProjectRoot,
1423
+ moduleSpecifierRoot: this.moduleSpecifierRoot,
835
1424
  sideEffectEntries: normalizedClientSideEffectEntries,
836
1425
  }),
837
1426
  ],
838
1427
  });
839
1428
  this.logEsbuildMessages(clientResult, 'client library bundle');
840
- // Create .gitignore in .swc directory
841
- await this.createSwcGitignore();
1429
+ await this.ensureSwcIgnored();
842
1430
  }
843
1431
  /**
844
1432
  * Creates a webhook handler bundle for resuming workflows via HTTP callbacks.
@@ -850,7 +1438,10 @@ export const POST = workflowEntrypoint(workflowCode);`;
850
1438
  await mkdir(dirname(outfile), { recursive: true });
851
1439
  // Create a static route that calls resumeWebhook
852
1440
  // This route works for both Next.js and Vercel Build Output API
853
- const routeContent = `import { resumeWebhook } from 'workflow/api';
1441
+ // Bundled Build Output API webhook functions need world.ts statically
1442
+ // present so getWorldLazy() can use the global getWorld registration
1443
+ // instead of falling back to a missing sibling import("./world.js").
1444
+ const routeContent = `${bundle ? "import 'workflow/runtime';\n" : ''}import { resumeWebhook } from 'workflow/api';
854
1445
 
855
1446
  async function handler(request) {
856
1447
  const url = new URL(request.url);
@@ -919,7 +1510,7 @@ export const OPTIONS = handler;`;
919
1510
  '.mjs',
920
1511
  '.cjs',
921
1512
  ],
922
- sourcemap: EMIT_SOURCEMAPS_FOR_DEBUGGING,
1513
+ sourcemap: this.resolveSourcemap(EMIT_SOURCEMAPS_FOR_DEBUGGING),
923
1514
  mainFields: ['module', 'main'],
924
1515
  // Don't externalize anything - bundle everything including workflow packages
925
1516
  external: [],
@@ -968,7 +1559,40 @@ export const OPTIONS = handler;`;
968
1559
  async ensureDirectory(filePath) {
969
1560
  await mkdir(dirname(filePath), { recursive: true });
970
1561
  }
971
- async createSwcGitignore() {
1562
+ async ensureSwcIgnored() {
1563
+ await this.ensureProjectSwcGitignoreEntry();
1564
+ await this.createSwcDirectoryGitignore();
1565
+ }
1566
+ async ensureProjectSwcGitignoreEntry() {
1567
+ const gitignorePath = join(this.config.workingDir, '.gitignore');
1568
+ try {
1569
+ let content = '';
1570
+ try {
1571
+ content = await readFile(gitignorePath, 'utf-8');
1572
+ }
1573
+ catch (error) {
1574
+ if (error.code !== 'ENOENT') {
1575
+ return;
1576
+ }
1577
+ }
1578
+ const hasSwcEntry = content.split(/\r?\n/).some((line) => {
1579
+ const trimmed = line.trim();
1580
+ return (trimmed === '.swc' ||
1581
+ trimmed === '.swc/' ||
1582
+ trimmed === '/.swc' ||
1583
+ trimmed === '/.swc/');
1584
+ });
1585
+ if (hasSwcEntry) {
1586
+ return;
1587
+ }
1588
+ const separator = content.length > 0 && !content.endsWith('\n') ? '\n' : '';
1589
+ await writeFile(gitignorePath, `${content}${separator}/.swc\n`);
1590
+ }
1591
+ catch {
1592
+ // We're intentionally silently ignoring this error - updating .gitignore isn't critical
1593
+ }
1594
+ }
1595
+ async createSwcDirectoryGitignore() {
972
1596
  try {
973
1597
  await writeFile(join(this.config.workingDir, '.swc', '.gitignore'), '*\n');
974
1598
  }
@@ -995,6 +1619,67 @@ export const OPTIONS = handler;`;
995
1619
  return this.resolvePath('.vercel/output/diagnostics/workflows-manifest.json');
996
1620
  }
997
1621
  }
1622
+ /**
1623
+ * Whether this is a development/watch build (e.g. `next dev`, `nitro dev`,
1624
+ * or a Vite-based dev server for astro/sveltekit/vite). `config.watch` is
1625
+ * plumbed by the builders that own a dev server (next, nitro, nest); the
1626
+ * Vite-based integrations don't set it but run with
1627
+ * `NODE_ENV === 'development'`. When neither signal is present we treat the
1628
+ * build as production, so CLI/Vercel production builds default to off.
1629
+ */
1630
+ get isDevelopmentBuild() {
1631
+ return this.config.watch === true || process.env.NODE_ENV === 'development';
1632
+ }
1633
+ /**
1634
+ * Default source map mode for the stack-relevant bundles (steps + the
1635
+ * intermediate workflow VM bundle): inline source maps in development so
1636
+ * stack traces point at source files, and off in production so function
1637
+ * bundles stay small (helps stay under the Vercel 250MB function limit) and
1638
+ * skip the source-map-support runtime shim. The `sourcemap` config option
1639
+ * and `WORKFLOW_SOURCEMAP` env var override this in either environment.
1640
+ */
1641
+ get defaultSourcemapMode() {
1642
+ return this.isDevelopmentBuild ? 'inline' : false;
1643
+ }
1644
+ /**
1645
+ * Resolve the effective source map mode for a given call site. Precedence:
1646
+ * explicit `sourcemap` config > `WORKFLOW_SOURCEMAP` env var > the call
1647
+ * site's default. Returned value is passed directly to esbuild's
1648
+ * `sourcemap` option.
1649
+ */
1650
+ resolveSourcemap(defaultMode) {
1651
+ if (this.config.sourcemap !== undefined)
1652
+ return this.config.sourcemap;
1653
+ const envMode = parseSourcemapEnv(process.env.WORKFLOW_SOURCEMAP);
1654
+ if (envMode !== undefined)
1655
+ return envMode;
1656
+ return defaultMode;
1657
+ }
1658
+ /**
1659
+ * Resolve whether workflow/step files under `node_modules` are discovered.
1660
+ * Precedence: explicit `discoverWorkflowsInNodeModules` config > the
1661
+ * `WORKFLOW_DISCOVER_NODE_MODULES` env var (`0`/`false` disables) > the
1662
+ * default (`true`, discover them).
1663
+ */
1664
+ resolveDiscoverWorkflowsInNodeModules() {
1665
+ if (this.config.discoverWorkflowsInNodeModules !== undefined) {
1666
+ return this.config.discoverWorkflowsInNodeModules;
1667
+ }
1668
+ const envValue = parseDiscoverNodeModulesEnv(process.env.WORKFLOW_DISCOVER_NODE_MODULES);
1669
+ if (envValue !== undefined)
1670
+ return envValue;
1671
+ return true;
1672
+ }
1673
+ /**
1674
+ * Whether the resolved source map mode emits any source maps at all.
1675
+ * Used by consumers like the Vercel builder to decide whether to include
1676
+ * the source-map-support runtime shim in generated functions. Uses the same
1677
+ * environment-aware default (`defaultSourcemapMode`) as the step/workflow
1678
+ * bundles, so a production build with no override omits the shim.
1679
+ */
1680
+ get sourcemapsEnabled() {
1681
+ return this.resolveSourcemap(this.defaultSourcemapMode) !== false;
1682
+ }
998
1683
  /**
999
1684
  * Creates a manifest JSON file containing step/workflow/class metadata
1000
1685
  * and graph data for visualization.
@@ -1022,10 +1707,18 @@ export const OPTIONS = handler;`;
1022
1707
  const workflowCount = Object.values(workflows).reduce((acc, w) => acc + Object.keys(w).length, 0);
1023
1708
  const classCount = Object.values(classes).reduce((acc, c) => acc + Object.keys(c).length, 0);
1024
1709
  this.logCreateManifestInfo(`Created manifest with ${stepCount} ${pluralize('step', 'steps', stepCount)}, ${workflowCount} ${pluralize('workflow', 'workflows', workflowCount)}, and ${classCount} ${pluralize('class', 'classes', classCount)}`, `${Date.now() - buildStart}ms`);
1710
+ if (!this.config.suppressCreateManifestLogs) {
1711
+ console.log(this.getWorkflowBuildSummary({
1712
+ stepCount,
1713
+ workflowCount,
1714
+ }));
1715
+ }
1716
+ this.resetWorkflowBuildTimer();
1025
1717
  return manifestJson;
1026
1718
  }
1027
1719
  catch (error) {
1028
1720
  console.warn('Failed to create manifest:', error instanceof Error ? error.message : String(error));
1721
+ this.resetWorkflowBuildTimer();
1029
1722
  return undefined;
1030
1723
  }
1031
1724
  }
@@ -1085,4 +1778,4 @@ export const OPTIONS = handler;`;
1085
1778
  return result;
1086
1779
  }
1087
1780
  }
1088
- //# sourceMappingURL=base-builder.js.map
1781
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2Jhc2UtYnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3pDLE9BQU8sRUFDTCxLQUFLLEVBQ0wsUUFBUSxFQUNSLFFBQVEsRUFDUixNQUFNLEVBQ04sRUFBRSxFQUNGLElBQUksRUFDSixTQUFTLEdBQ1YsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzVDLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDdEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM1QyxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFDMUIsT0FBTyx1QkFBdUIsTUFBTSxrQkFBa0IsQ0FBQztBQUN2RCxPQUFPLEtBQUssT0FBTyxNQUFNLFNBQVMsQ0FBQztBQUNuQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDbEMsT0FBTyxFQUNMLGlCQUFpQixHQUVsQixNQUFNLDBCQUEwQixDQUFDO0FBQ2xDLE9BQU8sRUFDTCxtQ0FBbUMsRUFDbkMsK0JBQStCLEdBQ2hDLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDbEUsT0FBTyxFQUVM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RUFBRSxLQUFLLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUU7aUJBQy9ELENBQUM7WUFDSixDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFTyxzQkFBc0IsQ0FDNUIsT0FBb0M7UUFFcEMsTUFBTSxNQUFNLEdBQXdELEVBQUUsQ0FBQztRQUN2RSxJQUFJLENBQUMsT0FBTztZQUFFLE9BQU8sTUFBTSxDQUFDO1FBRTVCLEtBQUssTUFBTSxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDMUQsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUN0QixLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNuRCxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3JELENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tICdub2RlOmNyeXB0byc7XG5pbXBvcnQge1xuICBta2RpcixcbiAgcmVhZEZpbGUsXG4gIHJlYWxwYXRoLFxuICByZW5hbWUsXG4gIHJtLFxuICBzdGF0LFxuICB3cml0ZUZpbGUsXG59IGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnO1xuaW1wb3J0IHsgY3JlYXRlUmVxdWlyZSB9IGZyb20gJ25vZGU6bW9kdWxlJztcbmltcG9ydCB7IGJhc2VuYW1lLCBkaXJuYW1lLCBqb2luLCByZWxhdGl2ZSwgcmVzb2x2ZSB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICdub2RlOnV0aWwnO1xuaW1wb3J0IHsgYnVpbGRMb2dnZXIgfSBmcm9tICdAd29ya2Zsb3cvY29yZS9sb2dnZXInO1xuaW1wb3J0IHsgV29ya2Zsb3dCdWlsZEVycm9yIH0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQgeyBwbHVyYWxpemUgfSBmcm9tICdAd29ya2Zsb3cvdXRpbHMnO1xuaW1wb3J0IGNoYWxrIGZyb20gJ2NoYWxrJztcbmltcG9ydCBlbmhhbmNlZFJlc29sdmVPcmlnaW5hbCBmcm9tICdlbmhhbmNlZC1yZXNvbHZlJztcbmltcG9ydCAqIGFzIGVzYnVpbGQgZnJvbSAnZXNidWlsZCc7XG5pbXBvcnQgeyBmaW5kVXAgfSBmcm9tICdmaW5kLXVwJztcbmltcG9ydCB7IGdsb2IgfSBmcm9tICd0aW55Z2xvYmJ5JztcbmltcG9ydCB7XG4gIGFwcGx5U3djVHJhbnNmb3JtLFxuICB0eXBlIFdvcmtmbG93TWFuaWZlc3QsXG59IGZyb20gJy4vYXBwbHktc3djLXRyYW5zZm9ybS5qcyc7XG5pbXBvcnQge1xuICBjcmVhdGVXb3JrZmxvd0VudHJ5cG9pbnRPcHRpb25zQ29kZSxcbiAgY3JlYXRlV29ya2Zsb3dSb3V0ZUhhbmRsZXJzQ29kZSxcbn0gZnJvbSAnLi9jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgZ2V0RXNidWlsZFRzY29uZmlnT3B0aW9ucyB9IGZyb20gJy4vZXNidWlsZC10c2NvbmZpZy5qcyc7XG5pbXBvcnQge1xuICB0eXBlIERpc2NvdmVyZWRFbnRyaWVzLFxuICBmYXN0RGlzY292ZXJFbnRyaWVzLFxufSBmcm9tICcuL2Zhc3QtZGlzY292ZXJ5LmpzJztcbmltcG9ydCB7XG4gIGdldEltcG9ydFBhdGgsXG4gIHJlc29sdmVNb2R1bGVTcGVjaWZpZXIsXG4gIHN0cmlwUGFja2FnZVZlcnNpb24sXG59IGZyb20gJy4vbW9kdWxlLXNwZWNpZmllci5qcyc7XG5pbXBvcnQgeyBjcmVhdGVOb2RlTW9kdWxlRXJyb3JQbHVnaW4gfSBmcm9tICcuL25vZGUtbW9kdWxlLWVzYnVpbGQtcGx1Z2luLmpzJztcbmltcG9ydCB7IGNyZWF0ZVBzZXVkb1BhY2thZ2VQbHVnaW4gfSBmcm9tICcuL3BzZXVkby1wYWNrYWdlLWVzYnVpbGQtcGx1Z2luLmpzJztcbmltcG9ydCB7IGNyZWF0ZVN3Y1BsdWdpbiB9IGZyb20gJy4vc3djLWVzYnVpbGQtcGx1Z2luLmpzJztcbmltcG9ydCB7IGRldGVjdFdvcmtmbG93UGF0dGVybnMgfSBmcm9tICcuL3RyYW5zZm9ybS11dGlscy5qcyc7XG5pbXBvcnQgdHlwZSB7IFNvdXJjZW1hcE1vZGUsIFdvcmtmbG93Q29uZmlnIH0gZnJvbSAnLi90eXBlcy5qcyc7XG5pbXBvcnQgeyBleHRyYWN0V29ya2Zsb3dHcmFwaHMgfSBmcm9tICcuL3dvcmtmbG93cy1leHRyYWN0b3IuanMnO1xuXG5jb25zdCBlbmhhbmNlZFJlc29sdmUgPSBwcm9taXNpZnkoZW5oYW5jZWRSZXNvbHZlT3JpZ2luYWwpO1xuY29uc3QgcmVxdWlyZSA9IGNyZWF0ZVJlcXVpcmUoaW1wb3J0Lm1ldGEudXJsKTtcblxuZXhwb3J0IHR5cGUgeyBEaXNjb3ZlcmVkRW50cmllcyB9IGZyb20gJy4vZmFzdC1kaXNjb3ZlcnkuanMnO1xuXG4vKipcbiAqIExlZ2FjeSBvcHQtaW4gZm9yIHNvdXJjZSBtYXBzIG9uIHRoZSBmaW5hbCB3b3JrZmxvdyB3cmFwcGVyICsgd2ViaG9va1xuICogYnVuZGxlcyAod2hpY2ggZGVmYXVsdCB0byBvZmYsIHVubGlrZSB0aGUgc3RlcC9pbnRlcmltIHdvcmtmbG93IGJ1bmRsZXNcbiAqIHRoYXQgZGVmYXVsdCB0byBpbmxpbmUpLiBTdXBlcnNlZGVkIGJ5IHRoZSBgc291cmNlbWFwYCBjb25maWcgb3B0aW9uIGFuZFxuICogdGhlIGBXT1JLRkxPV19TT1VSQ0VNQVBgIGVudmlyb25tZW50IHZhcmlhYmxlOyBrZXB0IGZvciBiYWNrLWNvbXBhdC5cbiAqL1xuY29uc3QgRU1JVF9TT1VSQ0VNQVBTX0ZPUl9ERUJVR0dJTkcgPVxuICBwcm9jZXNzLmVudi5XT1JLRkxPV19FTUlUX1NPVVJDRU1BUFNfRk9SX0RFQlVHR0lORyA9PT0gJzEnO1xuXG5jb25zdCBWQUxJRF9TT1VSQ0VNQVBfU1RSSU5HUyA9IG5ldyBTZXQoW1xuICAnaW5saW5lJyxcbiAgJ2xpbmtlZCcsXG4gICdleHRlcm5hbCcsXG4gICdib3RoJyxcbl0pO1xuXG4vKipcbiAqIFBhcnNlIHRoZSB2YWx1ZSBvZiB0aGUgYFdPUktGTE9XX1NPVVJDRU1BUGAgZW52aXJvbm1lbnQgdmFyaWFibGUgaW50byBhXG4gKiBgU291cmNlbWFwTW9kZWAuIFJldHVybnMgYHVuZGVmaW5lZGAgaWYgdGhlIGVudiB2YXIgaXMgdW5zZXQsIGVtcHR5LCBvclxuICogdW5yZWNvZ25pemVkIChhIHdhcm5pbmcgaXMgZW1pdHRlZCBmb3IgdW5yZWNvZ25pemVkIHZhbHVlcykuXG4gKi9cbmZ1bmN0aW9uIHBhcnNlU291cmNlbWFwRW52KFxuICB2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkXG4pOiBTb3VyY2VtYXBNb2RlIHwgdW5kZWZpbmVkIHtcbiAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09ICcnKSByZXR1cm4gdW5kZWZpbmVkO1xuICBzd2l0Y2ggKHZhbHVlKSB7XG4gICAgY2FzZSAnMCc6XG4gICAgY2FzZSAnZmFsc2UnOlxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIGNhc2UgJzEnOlxuICAgIGNhc2UgJ3RydWUnOlxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgZGVmYXVsdDpcbiAgICAgIGlmIChWQUxJRF9TT1VSQ0VNQVBfU1RSSU5HUy5oYXModmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZSBhcyBTb3VyY2VtYXBNb2RlO1xuICAgICAgfVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgSWdub3JpbmcgdW5yZWNvZ25pemVkIFdPUktGTE9XX1NPVVJDRU1BUD0ke3ZhbHVlfS4gYCArXG4gICAgICAgICAgYEV4cGVjdGVkIG9uZSBvZjogdHJ1ZSwgZmFsc2UsIDAsIDEsIGlubGluZSwgbGlua2VkLCBleHRlcm5hbCwgYm90aC5gXG4gICAgICApO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vKipcbiAqIFBhcnNlIHRoZSB2YWx1ZSBvZiB0aGUgYFdPUktGTE9XX0RJU0NPVkVSX05PREVfTU9EVUxFU2AgZW52aXJvbm1lbnQgdmFyaWFibGVcbiAqIGludG8gYSBib29sZWFuLiBSZXR1cm5zIGB1bmRlZmluZWRgIGlmIHRoZSBlbnYgdmFyIGlzIHVuc2V0IG9yIGVtcHR5IHNvXG4gKiBjYWxsZXJzIGNhbiBmYWxsIGJhY2sgdG8gY29uZmlnL2RlZmF1bHQuXG4gKi9cbmZ1bmN0aW9uIHBhcnNlRGlzY292ZXJOb2RlTW9kdWxlc0VudihcbiAgdmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZFxuKTogYm9vbGVhbiB8IHVuZGVmaW5lZCB7XG4gIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSAnJykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgcmV0dXJuIHZhbHVlICE9PSAnMCcgJiYgdmFsdWUgIT09ICdmYWxzZSc7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdEJ1aWxkRHVyYXRpb24oZHVyYXRpb25NczogbnVtYmVyKTogc3RyaW5nIHtcbiAgaWYgKGR1cmF0aW9uTXMgPCAxMDAwKSB7XG4gICAgcmV0dXJuIGAke2R1cmF0aW9uTXN9bXNgO1xuICB9XG5cbiAgcmV0dXJuIGAkeyhkdXJhdGlvbk1zIC8gMTAwMCkudG9GaXhlZCgxKX1zYDtcbn1cblxuLyoqXG4gKiBOb3JtYWxpemUgYW4gYXJyYXkgb2YgZmlsZSBwYXRocyBieSBhcHBlbmRpbmcgdGhlIGByZWFscGF0aCgpYCBvZiBlYWNoIGVudHJ5XG4gKiAodG8gaGFuZGxlIHN5bWxpbmtzLCBlLmcuIHBucG0vd29ya3NwYWNlIGxheW91dHMpIGFuZCBkZWR1cGxpY2F0aW5nLlxuICovXG5hc3luYyBmdW5jdGlvbiB3aXRoUmVhbHBhdGhzKGVudHJpZXM6IHN0cmluZ1tdKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICByZXR1cm4gQXJyYXkuZnJvbShcbiAgICBuZXcgU2V0KFxuICAgICAgKFxuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICBlbnRyaWVzLm1hcChhc3luYyAoZW50cnkpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkID0gYXdhaXQgcmVhbHBhdGgoZW50cnkpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZWQgPyBbZW50cnksIHJlc29sdmVkXSA6IFtlbnRyeV07XG4gICAgICAgICAgfSlcbiAgICAgICAgKVxuICAgICAgKS5mbGF0KClcbiAgICApXG4gICk7XG59XG5cbi8qKlxuICogQ2Fub25pY2FsIFwid2hhdCBtb2R1bGUgZG9lcyB0aGlzIGZpbGUgcmVwcmVzZW50P1wiIGtleSB1c2VkIHRvIGRlZHVwZVxuICogdmlydHVhbC1lbnRyeSBpbXBvcnRzLlxuICpcbiAqIElmIHRoZSBmaWxlIHJlc29sdmVzIHRvIGEgcmVhbCBwYWNrYWdlIHNwZWNpZmllciAoYHdvcmtmbG93L2ludGVybmFsL2J1aWx0aW5zYCxcbiAqIGBAaW50ZXJuYWwvYWdlbnQvc2VydmVyYCwgZXRjLiksIHdlIHJldHVybiB0aGUgYmFyZSBzcGVjaWZpZXIg4oCUIHZlcnNpb25cbiAqIHN0cmlwcGVkIOKAlCBiZWNhdXNlIGVzYnVpbGQncyBwYWNrYWdlIHJlc29sdXRpb24gd2lsbCBjb2xsYXBzZSBhbGxcbiAqIGltcG9ydGVycyBvZiB0aGF0IHNwZWNpZmllciB0byB0aGUgc2FtZSBwaHlzaWNhbCBtb2R1bGUgcmVnYXJkbGVzcyBvZlxuICogd2hpY2ggb24tZGlzayBjb3B5IChzcmMgdnMgZGlzdCkgYW55IG9uZSBpbXBvcnRlciB3cm90ZS5cbiAqXG4gKiBPdGhlcndpc2Ugd2UgZmFsbCBiYWNrIHRvIHRoZSBhYnNvbHV0ZSBmaWxlIHBhdGguIERpc3RpbmN0IGxvY2FsLWFwcFxuICogZmlsZXMgaGF2ZSBkaXN0aW5jdCBwYXRocywgc28gdGhpcyBzdGlsbCBkZWR1cGVzIGEgZmlsZSBhZ2FpbnN0IGl0c2VsZlxuICogKGUuZy4gaWYgaXQgc2hvd3MgdXAgaW4gYm90aCBgc3RlcEZpbGVzYCBhbmQgYHNlcmRlT25seUZpbGVzYCkgd2l0aG91dFxuICogY29uZmxhdGluZyB1bnJlbGF0ZWQgZmlsZXMuXG4gKi9cbmZ1bmN0aW9uIG1vZHVsZUlkZW50aXR5S2V5KGZpbGU6IHN0cmluZywgbW9kdWxlU3BlY2lmaWVyUm9vdDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgeyBtb2R1bGVTcGVjaWZpZXIgfSA9IHJlc29sdmVNb2R1bGVTcGVjaWZpZXIoZmlsZSwgbW9kdWxlU3BlY2lmaWVyUm9vdCk7XG4gIGlmIChtb2R1bGVTcGVjaWZpZXIpIHtcbiAgICAvLyBTdHJpcCB0aGUgXCJAPHZlcnNpb24+XCIgc3VmZml4IHNvIHNvdXJjZSBhbmQgZGlzdCBjb3BpZXMgb2YgdGhlIHNhbWVcbiAgICAvLyBleHBvcnQgY29sbGFwc2UgdG8gdGhlIHNhbWUga2V5LlxuICAgIHJldHVybiBzdHJpcFBhY2thZ2VWZXJzaW9uKG1vZHVsZVNwZWNpZmllcik7XG4gIH1cbiAgcmV0dXJuIGZpbGUucmVwbGFjZSgvXFxcXC9nLCAnLycpO1xufVxuXG50eXBlIE1hbmlmZXN0RW50cnlMb2NhdGlvbiA9IHtcbiAgZmlsZVBhdGg6IHN0cmluZztcbiAgbmFtZTogc3RyaW5nO1xufTtcblxudHlwZSBDYWNoZWRNYW5pZmVzdFRyYW5zZm9ybSA9IHtcbiAgc2l6ZTogbnVtYmVyO1xuICBtdGltZU1zOiBudW1iZXI7XG4gIG1hbmlmZXN0OiBXb3JrZmxvd01hbmlmZXN0O1xufTtcblxuZnVuY3Rpb24gZm9ybWF0SWRMb2NhdGlvbihsb2NhdGlvbjogTWFuaWZlc3RFbnRyeUxvY2F0aW9uKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke2xvY2F0aW9uLmZpbGVQYXRofSMke2xvY2F0aW9uLm5hbWV9YDtcbn1cblxuZnVuY3Rpb24gYXNzZXJ0VW5pcXVlTWFuaWZlc3RJZHM8VEVudHJ5PihcbiAgZW50cmllc0J5RmlsZTogUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgVEVudHJ5Pj4gfCB1bmRlZmluZWQsXG4gIGlkczogTWFwPHN0cmluZywgTWFuaWZlc3RFbnRyeUxvY2F0aW9uPixcbiAgZ2V0SWQ6IChlbnRyeTogVEVudHJ5KSA9PiBzdHJpbmcsXG4gIGxhYmVsOiAnc3RlcCcgfCAnd29ya2Zsb3cnXG4pOiB2b2lkIHtcbiAgZm9yIChjb25zdCBbZmlsZVBhdGgsIGVudHJpZXNdIG9mIE9iamVjdC5lbnRyaWVzKGVudHJpZXNCeUZpbGUgfHwge30pKSB7XG4gICAgZm9yIChjb25zdCBbbmFtZSwgZGF0YV0gb2YgT2JqZWN0LmVudHJpZXMoZW50cmllcykpIHtcbiAgICAgIGNvbnN0IGlkID0gZ2V0SWQoZGF0YSk7XG4gICAgICBjb25zdCBleGlzdGluZyA9IGlkcy5nZXQoaWQpO1xuICAgICAgY29uc3QgY3VycmVudCA9IHsgZmlsZVBhdGgsIG5hbWUgfTtcbiAgICAgIGlmIChcbiAgICAgICAgZXhpc3RpbmcgJiZcbiAgICAgICAgKGV4aXN0aW5nLmZpbGVQYXRoICE9PSBjdXJyZW50LmZpbGVQYXRoIHx8XG4gICAgICAgICAgZXhpc3RpbmcubmFtZSAhPT0gY3VycmVudC5uYW1lKVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IGlkTmFtZSA9IGxhYmVsID09PSAnc3RlcCcgPyAnd29ya2Zsb3cgc3RlcCBJRCcgOiAnd29ya2Zsb3cgSUQnO1xuICAgICAgICBjb25zdCBmdW5jdGlvbk5hbWUgPSBgJHtsYWJlbH0gZnVuY3Rpb25gO1xuICAgICAgICBjb25zdCBjYXBpdGFsaXplZExhYmVsID0gbGFiZWwgPT09ICdzdGVwJyA/ICdTdGVwJyA6ICdXb3JrZmxvdyc7XG4gICAgICAgIHRocm93IG5ldyBXb3JrZmxvd0J1aWxkRXJyb3IoXG4gICAgICAgICAgYER1cGxpY2F0ZSAke2lkTmFtZX0gXCIke2lkfVwiIGdlbmVyYXRlZCBmb3IgJHtmb3JtYXRJZExvY2F0aW9uKGV4aXN0aW5nKX0gYW5kICR7Zm9ybWF0SWRMb2NhdGlvbihjdXJyZW50KX0uYCxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBoaW50OlxuICAgICAgICAgICAgICBgJHtjYXBpdGFsaXplZExhYmVsfSBJRHMgbXVzdCBiZSB1bmlxdWUgYWNyb3NzIGEgYnVpbGQuIGAgK1xuICAgICAgICAgICAgICBgSWYgeW91IG93biBvbmUgb2YgdGhlIGNvbGxpZGluZyBmaWxlcywgcmVuYW1lIHRoZSAke2Z1bmN0aW9uTmFtZX0gb3IgZXhwb3J0IGAgK1xuICAgICAgICAgICAgICBgdGhlIHBhY2thZ2UgZmlsZSB0aHJvdWdoIGEgdW5pcXVlIHBhY2thZ2Ugc3VicGF0aC4gSWYgdGhlIGNvbGxpc2lvbiBpcyBpbiBhIGAgK1xuICAgICAgICAgICAgICBgdHJhbnNpdGl2ZSBkZXBlbmRlbmN5IHlvdSBkb24ndCBjb250cm9sLCBmaWxlIGFuIGlzc3VlIHdpdGggdGhlIHVwc3RyZWFtIGAgK1xuICAgICAgICAgICAgICBgcGFja2FnZSBvciBwaW4gdG8gYSBub24tY29sbGlkaW5nIHZlcnNpb24uYCxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZHMuc2V0KGlkLCBjdXJyZW50KTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gbWVyZ2VXb3JrZmxvd01hbmlmZXN0KFxuICB0YXJnZXQ6IFdvcmtmbG93TWFuaWZlc3QsXG4gIGluY29taW5nOiBXb3JrZmxvd01hbmlmZXN0LFxuICBzdGVwSWRzOiBNYXA8c3RyaW5nLCBNYW5pZmVzdEVudHJ5TG9jYXRpb24+LFxuICB3b3JrZmxvd0lkczogTWFwPHN0cmluZywgTWFuaWZlc3RFbnRyeUxvY2F0aW9uPlxuKTogdm9pZCB7XG4gIGFzc2VydFVuaXF1ZU1hbmlmZXN0SWRzKFxuICAgIGluY29taW5nLnN0ZXBzLFxuICAgIHN0ZXBJZHMsXG4gICAgKGRhdGEpID0+IGRhdGEuc3RlcElkLFxuICAgICdzdGVwJ1xuICApO1xuICBhc3NlcnRVbmlxdWVNYW5pZmVzdElkcyhcbiAgICBpbmNvbWluZy53b3JrZmxvd3MsXG4gICAgd29ya2Zsb3dJZHMsXG4gICAgKGRhdGEpID0+IGRhdGEud29ya2Zsb3dJZCxcbiAgICAnd29ya2Zsb3cnXG4gICk7XG5cbiAgdGFyZ2V0LndvcmtmbG93cyA9IE9iamVjdC5hc3NpZ24odGFyZ2V0LndvcmtmbG93cyB8fCB7fSwgaW5jb21pbmcud29ya2Zsb3dzKTtcbiAgdGFyZ2V0LnN0ZXBzID0gT2JqZWN0LmFzc2lnbih0YXJnZXQuc3RlcHMgfHwge30sIGluY29taW5nLnN0ZXBzKTtcbiAgdGFyZ2V0LmNsYXNzZXMgPSBPYmplY3QuYXNzaWduKHRhcmdldC5jbGFzc2VzIHx8IHt9LCBpbmNvbWluZy5jbGFzc2VzKTtcbn1cblxuLyoqXG4gKiBCYXNlIGNsYXNzIGZvciB3b3JrZmxvdyBidWlsZGVycy4gUHJvdmlkZXMgY29tbW9uIGJ1aWxkIGxvZ2ljIGZvciB0cmFuc2Zvcm1pbmdcbiAqIHdvcmtmbG93IHNvdXJjZSBmaWxlcyBpbnRvIGRlcGxveWFibGUgYnVuZGxlcyB1c2luZyBlc2J1aWxkIGFuZCBTV0MuXG4gKlxuICogU3ViY2xhc3NlcyBtdXN0IGltcGxlbWVudCB0aGUgYnVpbGQoKSBtZXRob2QgdG8gZGVmaW5lIGJ1aWxkZXItc3BlY2lmaWMgbG9naWMuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCYXNlQnVpbGRlciB7XG4gIHByb3RlY3RlZCBjb25maWc6IFdvcmtmbG93Q29uZmlnO1xuXG4gIC8qKlxuICAgKiBUcmFja3Mgd2hpY2ggZXh0ZXJuYWwgcGFja2FnZXMgaGF2ZSBhbHJlYWR5IGJlZW4gd2FybmVkIGFib3V0XG4gICAqIHRvIGF2b2lkIGR1cGxpY2F0ZSB3YXJuaW5ncyBhY3Jvc3MgbXVsdGlwbGUgZGlzY292ZXJFbnRyaWVzKCkgY2FsbHMuXG4gICAqL1xuICBwcml2YXRlIHdhcm5lZEV4dGVybmFsUGFja2FnZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgcHJpdmF0ZSB3b3JrZmxvd0J1aWxkU3RhcnRUaW1lOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgbWFuaWZlc3RUcmFuc2Zvcm1DYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBDYWNoZWRNYW5pZmVzdFRyYW5zZm9ybT4oKTtcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IFdvcmtmbG93Q29uZmlnKSB7XG4gICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IHRyYW5zZm9ybVByb2plY3RSb290KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLnByb2plY3RSb290IHx8IHRoaXMuY29uZmlnLndvcmtpbmdEaXI7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IG1vZHVsZVNwZWNpZmllclJvb3QoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWcubW9kdWxlU3BlY2lmaWVyUm9vdCB8fCB0aGlzLnRyYW5zZm9ybVByb2plY3RSb290O1xuICB9XG5cbiAgcHJvdGVjdGVkIGxvZ0Jhc2VCdWlsZGVySW5mbyguLi5hcmdzOiB1bmtub3duW10pOiB2b2lkIHtcbiAgICBidWlsZExvZ2dlci5kZWJ1ZyhhcmdzLm1hcChTdHJpbmcpLmpvaW4oJyAnKSk7XG4gIH1cblxuICBwcml2YXRlIHN0YXJ0V29ya2Zsb3dCdWlsZFRpbWVyKCk6IHZvaWQge1xuICAgIHRoaXMud29ya2Zsb3dCdWlsZFN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gIH1cblxuICBwcml2YXRlIGdldFdvcmtmbG93QnVpbGREdXJhdGlvbigpOiBudW1iZXIge1xuICAgIHJldHVybiBEYXRlLm5vdygpIC0gKHRoaXMud29ya2Zsb3dCdWlsZFN0YXJ0VGltZSA/PyBEYXRlLm5vdygpKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVzZXRXb3JrZmxvd0J1aWxkVGltZXIoKTogdm9pZCB7XG4gICAgdGhpcy53b3JrZmxvd0J1aWxkU3RhcnRUaW1lID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRXb3JrZmxvd0J1aWxkU3VtbWFyeSh7XG4gICAgc3RlcENvdW50LFxuICAgIHdvcmtmbG93Q291bnQsXG4gIH06IHtcbiAgICBzdGVwQ291bnQ6IG51bWJlcjtcbiAgICB3b3JrZmxvd0NvdW50OiBudW1iZXI7XG4gIH0pOiBzdHJpbmcge1xuICAgIGNvbnN0IGNvdW50cyA9IGAke3N0ZXBDb3VudH0gJHtwbHVyYWxpemUoJ3N0ZXAnLCAnc3RlcHMnLCBzdGVwQ291bnQpfSwgJHt3b3JrZmxvd0NvdW50fSAke3BsdXJhbGl6ZSgnd29ya2Zsb3cnLCAnd29ya2Zsb3dzJywgd29ya2Zsb3dDb3VudCl9YDtcbiAgICByZXR1cm4gYOKckyBDb21waWxlZCB3b3JrZmxvd3MgaW4gJHtmb3JtYXRCdWlsZER1cmF0aW9uKHRoaXMuZ2V0V29ya2Zsb3dCdWlsZER1cmF0aW9uKCkpfSAoJHtjb3VudHN9KWA7XG4gIH1cblxuICBwcml2YXRlIGxvZ0NyZWF0ZVdvcmtmbG93c0J1bmRsZUluZm8oLi4uYXJnczogdW5rbm93bltdKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5zdXBwcmVzc0NyZWF0ZVdvcmtmbG93c0J1bmRsZUxvZ3MpIHtcbiAgICAgIHRoaXMubG9nQmFzZUJ1aWxkZXJJbmZvKC4uLmFyZ3MpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbG9nQ3JlYXRlV2ViaG9va0J1bmRsZUluZm8oLi4uYXJnczogdW5rbm93bltdKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5zdXBwcmVzc0NyZWF0ZVdlYmhvb2tCdW5kbGVMb2dzKSB7XG4gICAgICB0aGlzLmxvZ0Jhc2VCdWlsZGVySW5mbyguLi5hcmdzKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGxvZ0NyZWF0ZU1hbmlmZXN0SW5mbyguLi5hcmdzOiB1bmtub3duW10pOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnLnN1cHByZXNzQ3JlYXRlTWFuaWZlc3RMb2dzKSB7XG4gICAgICB0aGlzLmxvZ0Jhc2VCdWlsZGVySW5mbyguLi5hcmdzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogV2hlbiBvdXRwdXR0aW5nIENKUywgZXNidWlsZCByZXBsYWNlcyBgaW1wb3J0Lm1ldGFgIHdpdGggYW4gZW1wdHkgb2JqZWN0LFxuICAgKiBtYWtpbmcgYGltcG9ydC5tZXRhLnVybGAgKGFuZCBgaW1wb3J0Lm1ldGEucmVzb2x2ZWApIHVuZGVmaW5lZC4gVGhpcyBtZXRob2RcbiAgICogcmV0dXJucyBiYW5uZXIgY29kZSBhbmQgYGRlZmluZWAgZW50cmllcyB0aGF0IHBvbHlmaWxsIHRoZW0gdXNpbmcgQ0pTXG4gICAqIGVxdWl2YWxlbnRzIChgX19maWxlbmFtZWAsIGByZXF1aXJlLnJlc29sdmVgKSBzbyB1c2VyIGNvZGUgKGUuZy4gUHJpc21hKVxuICAgKiB0aGF0IHJlbGllcyBvbiBgaW1wb3J0Lm1ldGEudXJsYCB3b3JrcyBjb3JyZWN0bHkgaW4gYnVuZGxlZCBDSlMgb3V0cHV0LlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRDanNJbXBvcnRNZXRhUG9seWZpbGwoZm9ybWF0OiBzdHJpbmcpOiB7XG4gICAgYmFubmVyOiBzdHJpbmc7XG4gICAgZGVmaW5lOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICB9IHtcbiAgICBpZiAoZm9ybWF0ICE9PSAnY2pzJykgcmV0dXJuIHsgYmFubmVyOiAnJywgZGVmaW5lOiB7fSB9O1xuICAgIHJldHVybiB7XG4gICAgICBiYW5uZXI6XG4gICAgICAgICd2YXIgX19pbXBvcnRfbWV0YV91cmwgPSB0eXBlb2YgX19maWxlbmFtZSAhPT0gXCJ1bmRlZmluZWRcIiA/IHJlcXVpcmUoXCJ1cmxcIikucGF0aFRvRmlsZVVSTChfX2ZpbGVuYW1lKS5ocmVmIDogdW5kZWZpbmVkO1xcbicgK1xuICAgICAgICAndmFyIF9faW1wb3J0X21ldGFfcmVzb2x2ZSA9IHR5cGVvZiByZXF1aXJlICE9PSBcInVuZGVmaW5lZFwiICYmIHR5cGVvZiBfX2ZpbGVuYW1lICE9PSBcInVuZGVmaW5lZFwiICcgK1xuICAgICAgICAnPyAocykgPT4gcmVxdWlyZShcInVybFwiKS5wYXRoVG9GaWxlVVJMKHJlcXVpcmUucmVzb2x2ZShzKSkuaHJlZiA6IHVuZGVmaW5lZDtcXG4nLFxuICAgICAgZGVmaW5lOiB7XG4gICAgICAgICdpbXBvcnQubWV0YS51cmwnOiAnX19pbXBvcnRfbWV0YV91cmwnLFxuICAgICAgICAnaW1wb3J0Lm1ldGEucmVzb2x2ZSc6ICdfX2ltcG9ydF9tZXRhX3Jlc29sdmUnLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZW4gb3V0cHV0dGluZyBmdWxseS1idW5kbGVkIEVTTSwgQ0pTIGRlcGVuZGVuY2llcyB0aGF0IGNhbGwgcmVxdWlyZSgpXG4gICAqIGZvciBOb2RlLmpzIGJ1aWx0aW5zIChlLmcuIGRlYnVnIOKGkiByZXF1aXJlKCd0dHknKSkgYnJlYWsgYmVjYXVzZSBlc2J1aWxkJ3NcbiAgICogQ0pTLXRvLUVTTSBfX3JlcXVpcmUgc2hpbSBkb2Vzbid0IGhhdmUgYWNjZXNzIHRvIGEgcmVhbCByZXF1aXJlIGZ1bmN0aW9uLlxuICAgKiBUaGlzIGJhbm5lciBwcm92aWRlcyBvbmUgdmlhIGNyZWF0ZVJlcXVpcmUgc28gYnVuZGxlZCBDSlMgY29kZSB3b3JrcyBpbiBFU00uXG4gICAqL1xuICBwcml2YXRlIGdldEVzbVJlcXVpcmVCYW5uZXIoZm9ybWF0OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmIChmb3JtYXQgIT09ICdlc20nKSByZXR1cm4gJyc7XG4gICAgcmV0dXJuICdpbXBvcnQgeyBjcmVhdGVSZXF1aXJlIGFzIF9fY3JlYXRlUmVxdWlyZSB9IGZyb20gXCJub2RlOm1vZHVsZVwiO1xcbnZhciByZXF1aXJlID0gX19jcmVhdGVSZXF1aXJlKGltcG9ydC5tZXRhLnVybCk7XFxuJztcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyB0aGUgY29tcGxldGUgYnVpbGQgcHJvY2VzcyBmb3Igd29ya2Zsb3dzLlxuICAgKiBTdWJjbGFzc2VzIG11c3QgaW1wbGVtZW50IHRoaXMgdG8gZGVmaW5lIHRoZWlyIHNwZWNpZmljIGJ1aWxkIHN0ZXBzLlxuICAgKi9cbiAgYWJzdHJhY3QgYnVpbGQoKTogUHJvbWlzZTx2b2lkPjtcblxuICAvKipcbiAgICogRmluZHMgdHNjb25maWcuanNvbi9qc2NvbmZpZy5qc29uIGZvciB0aGUgcHJvamVjdC5cbiAgICogVXNlZCBieSBlc2J1aWxkIHRvIHByb3Blcmx5IHJlc29sdmUgbW9kdWxlIGltcG9ydHMgZHVyaW5nIGJ1bmRsaW5nLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGZpbmRUc0NvbmZpZ1BhdGgoKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCBjd2QgPSB0aGlzLmNvbmZpZy53b3JraW5nRGlyIHx8IHByb2Nlc3MuY3dkKCk7XG4gICAgcmV0dXJuIGZpbmRVcChbJ3RzY29uZmlnLmpzb24nLCAnanNjb25maWcuanNvbiddLCB7IGN3ZCB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNjb3ZlcnMgYWxsIHNvdXJjZSBmaWxlcyBpbiB0aGUgY29uZmlndXJlZCBkaXJlY3Rvcmllcy5cbiAgICogU2VhcmNoZXMgZm9yIFR5cGVTY3JpcHQgYW5kIEphdmFTY3JpcHQgZmlsZXMgd2hpbGUgZXhjbHVkaW5nIGNvbW1vbiBidWlsZFxuICAgKiBhbmQgZGVwZW5kZW5jeSBkaXJlY3Rvcmllcy5cbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBnZXRJbnB1dEZpbGVzKCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCBpZ25vcmUgPSBbXG4gICAgICAnKiovbm9kZV9tb2R1bGVzLyoqJyxcbiAgICAgICcqKi8uZ2l0LyoqJyxcbiAgICAgICcqKi8ubmV4dC8qKicsXG4gICAgICAnKiovLm5pdHJvLyoqJyxcbiAgICAgICcqKi8ubnV4dC8qKicsXG4gICAgICAnKiovLm91dHB1dC8qKicsXG4gICAgICAnKiovLnZlcmNlbC8qKicsXG4gICAgICAnKiovLndvcmtmbG93LWRhdGEvKionLFxuICAgICAgJyoqLy53b3JrZmxvdy12aXRlc3QvKionLFxuICAgICAgJyoqLy53ZWxsLWtub3duL3dvcmtmbG93LyoqJyxcbiAgICAgICcqKi8uc3djLyoqJyxcbiAgICAgICcqKi8uc3ZlbHRlLWtpdC8qKicsXG4gICAgICAnKiovLnR1cmJvLyoqJyxcbiAgICAgICcqKi8uY2FjaGUvKionLFxuICAgICAgJyoqLy55YXJuLyoqJyxcbiAgICAgICcqKi8ucG5wbS1zdG9yZS8qKicsXG4gICAgXTtcblxuICAgIC8vIFVzZSByZWxhdGl2ZSBwYXR0ZXJucyB3aXRoIGBjd2RgIHBlciBkaXJlY3Rvcnkgc28gdGhhdCBgZG90OiB0cnVlYFxuICAgIC8vIGFwcGxpZXMgY29uc2lzdGVudGx5IHRvIGJvdGggdGhlIHNlYXJjaCBwYXR0ZXJuICphbmQqIHRoZSBpZ25vcmVcbiAgICAvLyBwYXR0ZXJucy4gV2hlbiBhYnNvbHV0ZSBwYXR0ZXJucyBhcmUgdXNlZCB3aXRoIHRpbnlnbG9iYnksIHRoZSBgKipgXG4gICAgLy8gaW4gaWdub3JlIHBhdHRlcm5zIGRvZXMgbm90IG1hdGNoIGRvdC1wcmVmaXhlZCBwYXRoIHNlZ21lbnRzLlxuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHRoaXMuY29uZmlnLmRpcnMubWFwKChkaXIpID0+IHtcbiAgICAgICAgY29uc3QgY3dkID0gcmVzb2x2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCBkaXIpO1xuICAgICAgICByZXR1cm4gZ2xvYihbJyoqLyoue3RzLHRzeCxtdHMsY3RzLGpzLGpzeCxtanMsY2pzfSddLCB7XG4gICAgICAgICAgY3dkLFxuICAgICAgICAgIGlnbm9yZSxcbiAgICAgICAgICBhYnNvbHV0ZTogdHJ1ZSxcbiAgICAgICAgICBkb3Q6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIHJlc3VsdHMuZmxhdCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIENhY2hlcyBkaXNjb3ZlcmVkIHdvcmtmbG93IGVudHJpZXMgYnkgaW5wdXQgYXJyYXkgcmVmZXJlbmNlLlxuICAgKiBVc2VzIFdlYWtNYXAgdG8gYWxsb3cgZ2FyYmFnZSBjb2xsZWN0aW9uIHdoZW4gaW5wdXQgYXJyYXlzIGFyZSBubyBsb25nZXIgcmVmZXJlbmNlZC5cbiAgICogVGhpcyBjYWNoZSBpcyBpbnZhbGlkYXRlZCBhdXRvbWF0aWNhbGx5IHdoZW4gdGhlIGlucHV0cyBhcnJheSByZWZlcmVuY2UgY2hhbmdlc1xuICAgKiAoZS5nLiwgd2hlbiBmaWxlcyBhcmUgYWRkZWQvcmVtb3ZlZCBkdXJpbmcgd2F0Y2ggbW9kZSkuXG4gICAqL1xuICBwcml2YXRlIGRpc2NvdmVyZWRFbnRyaWVzOiBXZWFrTWFwPHN0cmluZ1tdLCBEaXNjb3ZlcmVkRW50cmllcz4gPVxuICAgIG5ldyBXZWFrTWFwKCk7XG5cbiAgcHVibGljIGNsZWFyRGlzY292ZXJlZEVudHJpZXNDYWNoZSgpOiB2b2lkIHtcbiAgICB0aGlzLmRpc2NvdmVyZWRFbnRyaWVzID0gbmV3IFdlYWtNYXAoKTtcbiAgfVxuXG4gIHB1YmxpYyBjbGVhck1hbmlmZXN0VHJhbnNmb3JtQ2FjaGUoKTogdm9pZCB7XG4gICAgdGhpcy5tYW5pZmVzdFRyYW5zZm9ybUNhY2hlLmNsZWFyKCk7XG4gIH1cblxuICAvKipcbiAgICogUHNldWRvLXBhY2thZ2VzIHRoYXQgc2hvdWxkIG5vdCBiZSBjaGVja2VkIGZvciB3b3JrZmxvdyBwYXR0ZXJucy5cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IFBTRVVET19QQUNLQUdFUyA9IG5ldyBTZXQoW1xuICAgICdzZXJ2ZXItb25seScsXG4gICAgJ2NsaWVudC1vbmx5JyxcbiAgXSk7XG5cbiAgLyoqXG4gICAqIENoZWNrcyBlYWNoIHBhY2thZ2UgaW4gZXh0ZXJuYWxQYWNrYWdlcyBmb3Igd29ya2Zsb3cgcGF0dGVybnMgYW5kIGVtaXRzXG4gICAqIHdhcm5pbmdzIGlmIGFueSBjb250YWluIFwidXNlIHN0ZXBcIiwgXCJ1c2Ugd29ya2Zsb3dcIiBkaXJlY3RpdmVzLCBvclxuICAgKiBzZXJpYWxpemF0aW9uIGNsYXNzZXMuIFRoZXNlIHBhdHRlcm5zIHdpbGwgbm90IGJlIHRyYW5zZm9ybWVkIGJ5IHRoZVxuICAgKiB3b3JrZmxvdyBjb21waWxlciB3aGVuIHRoZSBwYWNrYWdlIGlzIGV4dGVybmFsaXplZC5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgd2FybkFib3V0RXh0ZXJuYWxXb3JrZmxvd1BhY2thZ2VzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGV4dGVybmFsUGFja2FnZXMgPSB0aGlzLmNvbmZpZy5leHRlcm5hbFBhY2thZ2VzO1xuICAgIGlmICghZXh0ZXJuYWxQYWNrYWdlcz8ubGVuZ3RoKSByZXR1cm47XG5cbiAgICBmb3IgKGNvbnN0IHBrZyBvZiBleHRlcm5hbFBhY2thZ2VzKSB7XG4gICAgICBpZiAoQmFzZUJ1aWxkZXIuUFNFVURPX1BBQ0tBR0VTLmhhcyhwa2cpKSBjb250aW51ZTtcbiAgICAgIGlmICh0aGlzLndhcm5lZEV4dGVybmFsUGFja2FnZXMuaGFzKHBrZykpIGNvbnRpbnVlO1xuXG4gICAgICBpZiAoXG4gICAgICAgIHBrZy5zdGFydHNXaXRoKCcuJykgfHxcbiAgICAgICAgcGtnLnN0YXJ0c1dpdGgoJy8nKSB8fFxuICAgICAgICBwa2cuc3RhcnRzV2l0aCgnJCcpIHx8XG4gICAgICAgIHBrZy5pbmNsdWRlcygnKicpIHx8XG4gICAgICAgIHBrZy5pbmNsdWRlcygnOicpXG4gICAgICApIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIENoZWNrIHBhY2thZ2UuanNvbiBkZXBlbmRlbmNpZXMgZm9yIEB3b3JrZmxvdy9zZXJkZSAoZmFzdCBwYXRoKVxuICAgICAgICBsZXQgaGFzV29ya2Zsb3dTZXJkZURlcCA9IGZhbHNlO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHBrZ0pzb25QYXRoID0gcmVxdWlyZS5yZXNvbHZlKGAke3BrZ30vcGFja2FnZS5qc29uYCwge1xuICAgICAgICAgICAgcGF0aHM6IFt0aGlzLmNvbmZpZy53b3JraW5nRGlyXSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjb25zdCBwa2dKc29uU291cmNlID0gYXdhaXQgcmVhZEZpbGUocGtnSnNvblBhdGgsICd1dGYtOCcpO1xuICAgICAgICAgIGNvbnN0IHBrZ0pzb24gPSBKU09OLnBhcnNlKHBrZ0pzb25Tb3VyY2UpIGFzIHtcbiAgICAgICAgICAgIGRlcGVuZGVuY2llcz86IHVua25vd247XG4gICAgICAgICAgICBwZWVyRGVwZW5kZW5jaWVzPzogdW5rbm93bjtcbiAgICAgICAgICB9O1xuICAgICAgICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9XG4gICAgICAgICAgICB0eXBlb2YgcGtnSnNvbi5kZXBlbmRlbmNpZXMgPT09ICdvYmplY3QnICYmXG4gICAgICAgICAgICBwa2dKc29uLmRlcGVuZGVuY2llcyAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgIUFycmF5LmlzQXJyYXkocGtnSnNvbi5kZXBlbmRlbmNpZXMpXG4gICAgICAgICAgICAgID8gKHBrZ0pzb24uZGVwZW5kZW5jaWVzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVxuICAgICAgICAgICAgICA6IHt9O1xuICAgICAgICAgIGNvbnN0IHBlZXJEZXBlbmRlbmNpZXMgPVxuICAgICAgICAgICAgdHlwZW9mIHBrZ0pzb24ucGVlckRlcGVuZGVuY2llcyA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgICAgIHBrZ0pzb24ucGVlckRlcGVuZGVuY2llcyAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgIUFycmF5LmlzQXJyYXkocGtnSnNvbi5wZWVyRGVwZW5kZW5jaWVzKVxuICAgICAgICAgICAgICA/IChwa2dKc29uLnBlZXJEZXBlbmRlbmNpZXMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pXG4gICAgICAgICAgICAgIDoge307XG4gICAgICAgICAgaGFzV29ya2Zsb3dTZXJkZURlcCA9XG4gICAgICAgICAgICBPYmplY3QuaGFzT3duKGRlcGVuZGVuY2llcywgJ0B3b3JrZmxvdy9zZXJkZScpIHx8XG4gICAgICAgICAgICBPYmplY3QuaGFzT3duKHBlZXJEZXBlbmRlbmNpZXMsICdAd29ya2Zsb3cvc2VyZGUnKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgLy8gcGFja2FnZS5qc29uIG5vdCByZXNvbHZhYmxlIC0gY29udGludWUgdG8gc291cmNlIGNoZWNrXG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayBzb3VyY2UgcGF0dGVybnMgKHRob3JvdWdoIHBhdGgpLlxuICAgICAgICAvLyBOb3RlOiByZXF1aXJlLnJlc29sdmUgb25seSBpbnNwZWN0cyB0aGUgcGFja2FnZSdzIG1haW4gZW50cnkgcG9pbnQuXG4gICAgICAgIC8vIElmIHdvcmtmbG93IGNvbnN0cnVjdHMgbGl2ZSBpbiBzdWItcGF0aHMgKGUuZy4gYG15LXBrZy93b3JrZmxvd3NgKSxcbiAgICAgICAgLy8gdGhleSB3b24ndCBiZSBkZXRlY3RlZCBoZXJlLiBUaGUgQHdvcmtmbG93L3NlcmRlIGRlcCBjaGVjayBhYm92ZVxuICAgICAgICAvLyBwYXJ0aWFsbHkgY292ZXJzIHNlcmRlIGNhc2VzLiBUaGlzIGlzIGFjY2VwdGFibGUgYXMgYSBiZXN0LWVmZm9ydFxuICAgICAgICAvLyBoZXVyaXN0aWMg4oCUIHRoZSBwcmltYXJ5IGZpeCBpcyBhdXRvLXJlbW92YWwgaW4gd2l0aFdvcmtmbG93KCkuXG4gICAgICAgIGxldCBoYXNVc2VTdGVwID0gZmFsc2U7XG4gICAgICAgIGxldCBoYXNVc2VXb3JrZmxvdyA9IGZhbHNlO1xuICAgICAgICBsZXQgaGFzU2VyZGUgPSBoYXNXb3JrZmxvd1NlcmRlRGVwO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGVudHJ5UGF0aCA9IHJlcXVpcmUucmVzb2x2ZShwa2csIHtcbiAgICAgICAgICAgIHBhdGhzOiBbdGhpcy5jb25maWcud29ya2luZ0Rpcl0sXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgcmVhZEZpbGUoZW50cnlQYXRoLCAndXRmLTgnKTtcbiAgICAgICAgICBjb25zdCBwYXR0ZXJucyA9IGRldGVjdFdvcmtmbG93UGF0dGVybnMoc291cmNlKTtcbiAgICAgICAgICBoYXNVc2VTdGVwID0gcGF0dGVybnMuaGFzVXNlU3RlcDtcbiAgICAgICAgICBoYXNVc2VXb3JrZmxvdyA9IHBhdHRlcm5zLmhhc1VzZVdvcmtmbG93O1xuICAgICAgICAgIGlmICghaGFzU2VyZGUpIHtcbiAgICAgICAgICAgIGhhc1NlcmRlID0gcGF0dGVybnMuaGFzU2VyZGU7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAvLyBFbnRyeSBmaWxlIG5vdCByZXNvbHZhYmxlIG9yIG5vdCByZWFkYWJsZSAtIHVzZSB3aGF0IHdlIGhhdmVcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaGFzVXNlU3RlcCAmJiAhaGFzVXNlV29ya2Zsb3cgJiYgIWhhc1NlcmRlKSBjb250aW51ZTtcblxuICAgICAgICAvLyBCdWlsZCBhIHNwZWNpZmljIGRlc2NyaXB0aW9uIG9mIHdoYXQgd2FzIGZvdW5kXG4gICAgICAgIGNvbnN0IGlzc3Vlczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgaWYgKGhhc1VzZVdvcmtmbG93KSBpc3N1ZXMucHVzaCgnXCJ1c2Ugd29ya2Zsb3dcIiBmdW5jdGlvbnMnKTtcbiAgICAgICAgaWYgKGhhc1VzZVN0ZXApIGlzc3Vlcy5wdXNoKCdcInVzZSBzdGVwXCIgZnVuY3Rpb25zJyk7XG4gICAgICAgIGlmIChoYXNTZXJkZSkgaXNzdWVzLnB1c2goJ3NlcmlhbGl6YXRpb24gY2xhc3NlcycpO1xuXG4gICAgICAgIHRoaXMud2FybmVkRXh0ZXJuYWxQYWNrYWdlcy5hZGQocGtnKTtcblxuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgYFxcbiR7Y2hhbGsueWVsbG93KCfimqAnKX0gV2FybmluZzogJHtjaGFsay5ib2xkKGBcIiR7cGtnfVwiYCl9IGlzIGxpc3RlZCBpbiAke2NoYWxrLmJvbGQoJ2V4dGVybmFsUGFja2FnZXMnKX0gKCR7Y2hhbGsuYm9sZCgnc2VydmVyRXh0ZXJuYWxQYWNrYWdlcycpfSBpbiBOZXh0LmpzKSBidXQgY29udGFpbnMgd29ya2Zsb3cgY29kZSAoJHtpc3N1ZXMuam9pbignLCAnKX0pLmAgK1xuICAgICAgICAgICAgYFxcbiAgVGhpcyBjb2RlIHdpbGwgJHtjaGFsay5ib2xkKCdub3QnKX0gYmUgdHJhbnNmb3JtZWQgYnkgdGhlIHdvcmtmbG93IGNvbXBpbGVyLCB3aGljaCBjYW4gY2F1c2UgcnVudGltZSBmYWlsdXJlcy5gICtcbiAgICAgICAgICAgIGBcXG4gIFJlbW92ZSAke2NoYWxrLmJvbGQoYFwiJHtwa2d9XCJgKX0gZnJvbSAke2NoYWxrLmJvbGQoJ2V4dGVybmFsUGFja2FnZXMnKX0gKCR7Y2hhbGsuYm9sZCgnc2VydmVyRXh0ZXJuYWxQYWNrYWdlcycpfSBpbiBOZXh0LmpzKSB0byBmaXggdGhpcy5cXG5gXG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gQmVzdC1lZmZvcnQ6IGlmIGFueXRoaW5nIGdvZXMgd3JvbmcsIHNraXAgdGhpcyBwYWNrYWdlIHNpbGVudGx5XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGRpc2NvdmVyRW50cmllcyhcbiAgICBpbnB1dHM6IHN0cmluZ1tdLFxuICAgIG91dGRpcjogc3RyaW5nLFxuICAgIHRzY29uZmlnUGF0aD86IHN0cmluZ1xuICApOiBQcm9taXNlPERpc2NvdmVyZWRFbnRyaWVzPiB7XG4gICAgY29uc3QgcHJldmlvdXNSZXN1bHQgPSB0aGlzLmRpc2NvdmVyZWRFbnRyaWVzLmdldChpbnB1dHMpO1xuXG4gICAgaWYgKHByZXZpb3VzUmVzdWx0KSB7XG4gICAgICByZXR1cm4gcHJldmlvdXNSZXN1bHQ7XG4gICAgfVxuICAgIGNvbnN0IHN0YXRlOiBEaXNjb3ZlcmVkRW50cmllcyA9IHtcbiAgICAgIGRpc2NvdmVyZWRTdGVwczogbmV3IFNldCgpLFxuICAgICAgZGlzY292ZXJlZFdvcmtmbG93czogbmV3IFNldCgpLFxuICAgICAgZGlzY292ZXJlZFNlcmRlRmlsZXM6IG5ldyBTZXQoKSxcbiAgICAgIGRpc2NvdmVyZWRGaWxlczogbmV3IFNldCgpLFxuICAgIH07XG5cbiAgICBjb25zdCBkaXNjb3ZlclN0YXJ0ID0gRGF0ZS5ub3coKTtcblxuICAgIC8vIFJlc29sdmUgdGhlIFNESyBydW50aW1lIHNlcmRlIGVudHJ5IHBvaW50IHNvIHRoYXQgdGhlIGRpc2NvdmVyeSBwYXNzXG4gICAgLy8gZGlzY292ZXJzIGNsYXNzZXMgbGlrZSBgUnVuYCB0aGF0IGxpdmUgaW5zaWRlIFNESyBwYWNrYWdlcy4gV2l0aG91dCB0aGlzLFxuICAgIC8vIGZpbGVzIGxpa2UgYHJ1bi5qc2AgYXJlIG9ubHkgZGlzY292ZXJlZCB3aGVuIHVzZXIgY29kZSBpbXBvcnRzIHRoZW0uXG4gICAgLy8gVGhpcyBpcyByZXNvbHZlZCBoZXJlIChyYXRoZXIgdGhhbiBpbiBjYWxsZXJzKSBzbyB0aGF0IHRoZSBvcmlnaW5hbFxuICAgIC8vIGBpbnB1dHNgIGFycmF5IHJlZmVyZW5jZSBpcyBwcmVzZXJ2ZWQgZm9yIFdlYWtNYXAgY2FjaGluZyDigJQgY2FsbGVyc1xuICAgIC8vIGxpa2UgY3JlYXRlV29ya2Zsb3dzQnVuZGxlIGFuZCBjcmVhdGVTdGVwc0J1bmRsZSBjYW4gc2hhcmUgdGhlIHNhbWVcbiAgICAvLyBjYWNoZSBlbnRyeSB3aGVuIHRoZXkgcGFzcyB0aGUgc2FtZSBpbnB1dEZpbGVzIGFycmF5LlxuICAgIGNvbnN0IHJlc29sdmVkV29ya2Zsb3dSdW50aW1lID0gYXdhaXQgZW5oYW5jZWRSZXNvbHZlKFxuICAgICAgb3V0ZGlyLFxuICAgICAgJ0B3b3JrZmxvdy9jb3JlL3J1bnRpbWUvcnVuJ1xuICAgICkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICBjb25zdCBlbnRyeVBvaW50cyA9IHJlc29sdmVkV29ya2Zsb3dSdW50aW1lXG4gICAgICA/IFsuLi5pbnB1dHMsIHJlc29sdmVkV29ya2Zsb3dSdW50aW1lXVxuICAgICAgOiBpbnB1dHM7XG5cbiAgICBjb25zdCBlZmZlY3RpdmVUc2NvbmZpZ1BhdGggPVxuICAgICAgdHNjb25maWdQYXRoID8/IChhd2FpdCB0aGlzLmZpbmRUc0NvbmZpZ1BhdGgoKSk7XG5cbiAgICBhd2FpdCBmYXN0RGlzY292ZXJFbnRyaWVzKHtcbiAgICAgIGVudHJ5UG9pbnRzLFxuICAgICAgc3RhdGUsXG4gICAgICBkZWZhdWx0VHNjb25maWdQYXRoOiBlZmZlY3RpdmVUc2NvbmZpZ1BhdGgsXG4gICAgICB3b3JraW5nRGlyOiB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgZGlzY292ZXJXb3JrZmxvd3NJbk5vZGVNb2R1bGVzOlxuICAgICAgICB0aGlzLnJlc29sdmVEaXNjb3ZlcldvcmtmbG93c0luTm9kZU1vZHVsZXMoKSxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nQmFzZUJ1aWxkZXJJbmZvKFxuICAgICAgYERpc2NvdmVyaW5nIHdvcmtmbG93IGRpcmVjdGl2ZXNgLFxuICAgICAgYCR7RGF0ZS5ub3coKSAtIGRpc2NvdmVyU3RhcnR9bXNgXG4gICAgKTtcblxuICAgIC8vIFdhcm4gYWJvdXQgZXh0ZXJuYWwgcGFja2FnZXMgdGhhdCBjb250YWluIHdvcmtmbG93IGNvZGVcbiAgICBhd2FpdCB0aGlzLndhcm5BYm91dEV4dGVybmFsV29ya2Zsb3dQYWNrYWdlcygpO1xuXG4gICAgdGhpcy5kaXNjb3ZlcmVkRW50cmllcy5zZXQoaW5wdXRzLCBzdGF0ZSk7XG4gICAgcmV0dXJuIHN0YXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIFdyaXRlcyBnZW5lcmF0ZWQgZmlsZXMgYXRvbWljYWxseSB3aGVyZSBwb3NzaWJsZS4gT24gV2luZG93cywgTmV4dC5qcyBjYW5cbiAgICogYnJpZWZseSBob2xkIGdlbmVyYXRlZCByb3V0ZSBmaWxlcyBvcGVuIHdoaWxlIGNvbXBpbGluZyB0aGVtLCB3aGljaCBtYWtlc1xuICAgKiByZW5hbWUtb3Zlci1leGlzdGluZyBmYWlsIHdpdGggRVBFUk0vRUFDQ0VTLiBJbiB0aGF0IGNhc2UsIGZhbGwgYmFjayB0byBhXG4gICAqIGRpcmVjdCBvdmVyd3JpdGUgc28gd2F0Y2ggcmVidWlsZHMgY2FuIHN0aWxsIG1ha2UgcHJvZ3Jlc3MuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHdyaXRlR2VuZXJhdGVkRmlsZShcbiAgICB0YXJnZXRQYXRoOiBzdHJpbmcsXG4gICAgY29udGVudDogc3RyaW5nXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHRlbXBQYXRoID0gYCR7dGFyZ2V0UGF0aH0uJHtyYW5kb21VVUlEKCl9LnRtcGA7XG4gICAgYXdhaXQgd3JpdGVGaWxlKHRlbXBQYXRoLCBjb250ZW50KTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgcmVuYW1lKHRlbXBQYXRoLCB0YXJnZXRQYXRoKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc3QgZXJyb3JDb2RlID1cbiAgICAgICAgZXJyb3IgJiYgdHlwZW9mIGVycm9yID09PSAnb2JqZWN0JyAmJiAnY29kZScgaW4gZXJyb3JcbiAgICAgICAgICA/IChlcnJvciBhcyBOb2RlSlMuRXJybm9FeGNlcHRpb24pLmNvZGVcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgIGlmIChcbiAgICAgICAgcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJyAmJlxuICAgICAgICAoZXJyb3JDb2RlID09PSAnRVBFUk0nIHx8IGVycm9yQ29kZSA9PT0gJ0VBQ0NFUycpXG4gICAgICApIHtcbiAgICAgICAgYXdhaXQgd3JpdGVGaWxlKHRhcmdldFBhdGgsIGNvbnRlbnQpO1xuICAgICAgICBhd2FpdCBybSh0ZW1wUGF0aCwgeyBmb3JjZTogdHJ1ZSB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFdyaXRlcyBkZWJ1ZyBpbmZvcm1hdGlvbiB0byBhIEpTT04gZmlsZSBmb3IgdHJvdWJsZXNob290aW5nIGJ1aWxkIGlzc3Vlcy5cbiAgICogVXNlcyBhdG9taWMgd3JpdGUgKHRlbXAgZmlsZSArIHJlbmFtZSkgdG8gcHJldmVudCByYWNlIGNvbmRpdGlvbnMgd2hlblxuICAgKiBtdWx0aXBsZSBidWlsZHMgcnVuIGNvbmN1cnJlbnRseS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgd3JpdGVEZWJ1Z0ZpbGUoXG4gICAgb3V0ZmlsZTogc3RyaW5nLFxuICAgIGRlYnVnRGF0YTogb2JqZWN0LFxuICAgIG1lcmdlPzogYm9vbGVhblxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmNvbmZpZy5kZWJ1Z0ZpbGVQcmVmaXggfHwgJyc7XG4gICAgY29uc3QgdGFyZ2V0UGF0aCA9IGAke2Rpcm5hbWUob3V0ZmlsZSl9LyR7cHJlZml4fSR7YmFzZW5hbWUob3V0ZmlsZSl9LmRlYnVnLmpzb25gO1xuICAgIGxldCBleGlzdGluZyA9IHt9O1xuXG4gICAgdHJ5IHtcbiAgICAgIGlmIChtZXJnZSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCByZWFkRmlsZSh0YXJnZXRQYXRoLCAndXRmOCcpO1xuICAgICAgICAgIGV4aXN0aW5nID0gSlNPTi5wYXJzZShjb250ZW50KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIC8vIEZpbGUgZG9lc24ndCBleGlzdCB5ZXQgb3IgaXMgY29ycnVwdGVkIC0gc3RhcnQgZnJlc2guXG4gICAgICAgICAgLy8gRG9uJ3QgbG9nIGVycm9yIGZvciBFTk9FTlQgKGZpbGUgbm90IGZvdW5kKSBhcyB0aGF0J3MgZXhwZWN0ZWQgb24gZmlyc3QgcnVuLlxuICAgICAgICAgIGlmICgoZSBhcyBOb2RlSlMuRXJybm9FeGNlcHRpb24pLmNvZGUgIT09ICdFTk9FTlQnKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Vycm9yIHJlYWRpbmcgZGVidWcgZmlsZSwgc3RhcnRpbmcgZnJlc2g6JywgZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1lcmdlZERhdGEgPSBKU09OLnN0cmluZ2lmeShcbiAgICAgICAge1xuICAgICAgICAgIC4uLmV4aXN0aW5nLFxuICAgICAgICAgIC4uLmRlYnVnRGF0YSxcbiAgICAgICAgfSxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgMlxuICAgICAgKTtcblxuICAgICAgYXdhaXQgdGhpcy53cml0ZUdlbmVyYXRlZEZpbGUodGFyZ2V0UGF0aCwgbWVyZ2VkRGF0YSk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIGNvbnNvbGUud2FybignRmFpbGVkIHRvIHdyaXRlIGRlYnVnIGZpbGU6JywgZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMb2dzIGFuZCBvcHRpb25hbGx5IHRocm93cyBvbiBlc2J1aWxkIGVycm9ycyBhbmQgd2FybmluZ3MuXG4gICAqIEBwYXJhbSB0aHJvd09uRXJyb3IgLSBJZiB0cnVlLCB0aHJvd3MgYW4gZXJyb3Igd2hlbiBlc2J1aWxkIGVycm9ycyBhcmUgcHJlc2VudFxuICAgKi9cbiAgcHJpdmF0ZSBsb2dFc2J1aWxkTWVzc2FnZXMoXG4gICAgcmVzdWx0OiB7IGVycm9ycz86IGFueVtdOyB3YXJuaW5ncz86IGFueVtdIH0sXG4gICAgcGhhc2U6IHN0cmluZyxcbiAgICB0aHJvd09uRXJyb3IgPSB0cnVlLFxuICAgIG9wdGlvbnM/OiB7XG4gICAgICBzdXBwcmVzc1dhcm5pbmdzPzogYm9vbGVhbjtcbiAgICB9XG4gICk6IHZvaWQge1xuICAgIGlmIChyZXN1bHQuZXJyb3JzICYmIHJlc3VsdC5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc29sZS5lcnJvcihg4p2MIGVzYnVpbGQgZXJyb3JzIGluICR7cGhhc2V9OmApO1xuICAgICAgY29uc3QgZXJyb3JNZXNzYWdlczogc3RyaW5nW10gPSBbXTtcbiAgICAgIGZvciAoY29uc3QgZXJyb3Igb2YgcmVzdWx0LmVycm9ycykge1xuICAgICAgICBjb25zb2xlLmVycm9yKGAgICR7ZXJyb3IudGV4dH1gKTtcbiAgICAgICAgZXJyb3JNZXNzYWdlcy5wdXNoKGVycm9yLnRleHQpO1xuICAgICAgICBpZiAoZXJyb3IubG9jYXRpb24pIHtcbiAgICAgICAgICBjb25zdCBsb2NhdGlvbiA9IGAgICAgYXQgJHtlcnJvci5sb2NhdGlvbi5maWxlfToke2Vycm9yLmxvY2F0aW9uLmxpbmV9OiR7ZXJyb3IubG9jYXRpb24uY29sdW1ufWA7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihsb2NhdGlvbik7XG4gICAgICAgICAgZXJyb3JNZXNzYWdlcy5wdXNoKGxvY2F0aW9uKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodGhyb3dPbkVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBXb3JrZmxvd0J1aWxkRXJyb3IoXG4gICAgICAgICAgYEJ1aWxkIGZhaWxlZCBkdXJpbmcgJHtwaGFzZX06XFxuJHtlcnJvck1lc3NhZ2VzLmpvaW4oJ1xcbicpfWAsXG4gICAgICAgICAge1xuICAgICAgICAgICAgaGludDogYFJldmlldyB0aGUgZXNidWlsZCBlcnJvcnMgYWJvdmUg4oCUIHRoZXkgY29tZSBmcm9tIHRoZSAke3BoYXNlfSBidW5kbGUuIEZpeCB0aGUgb2ZmZW5kaW5nIHNvdXJjZSBmaWxlcyBhbmQgcmUtcnVuIHRoZSBidWlsZC5gLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICAhb3B0aW9ucz8uc3VwcHJlc3NXYXJuaW5ncyAmJlxuICAgICAgcmVzdWx0Lndhcm5pbmdzICYmXG4gICAgICByZXN1bHQud2FybmluZ3MubGVuZ3RoID4gMFxuICAgICkge1xuICAgICAgY29uc29sZS53YXJuKGAhICBlc2J1aWxkIHdhcm5pbmdzIGluICR7cGhhc2V9OmApO1xuICAgICAgZm9yIChjb25zdCB3YXJuaW5nIG9mIHJlc3VsdC53YXJuaW5ncykge1xuICAgICAgICBjb25zb2xlLndhcm4oYCAgJHt3YXJuaW5nLnRleHR9YCk7XG4gICAgICAgIGlmICh3YXJuaW5nLmxvY2F0aW9uKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgYCAgICBhdCAke3dhcm5pbmcubG9jYXRpb24uZmlsZX06JHt3YXJuaW5nLmxvY2F0aW9uLmxpbmV9OiR7d2FybmluZy5sb2NhdGlvbi5jb2x1bW59YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYW4gYWJzb2x1dGUgZmlsZSBwYXRoIHRvIGEgbm9ybWFsaXplZCByZWxhdGl2ZSBwYXRoIGZvciB0aGUgbWFuaWZlc3QuXG4gICAqL1xuICBwcml2YXRlIGdldFJlbGF0aXZlRmlsZXBhdGgoYWJzb2x1dGVQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IG5vcm1hbGl6ZWRGaWxlID0gYWJzb2x1dGVQYXRoLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICBjb25zdCBub3JtYWxpemVkV29ya2luZ0RpciA9IHRoaXMuY29uZmlnLndvcmtpbmdEaXIucmVwbGFjZSgvXFxcXC9nLCAnLycpO1xuICAgIGxldCByZWxhdGl2ZVBhdGggPSByZWxhdGl2ZShub3JtYWxpemVkV29ya2luZ0Rpciwgbm9ybWFsaXplZEZpbGUpLnJlcGxhY2UoXG4gICAgICAvXFxcXC9nLFxuICAgICAgJy8nXG4gICAgKTtcbiAgICAvLyBIYW5kbGUgZmlsZXMgZGlzY292ZXJlZCBvdXRzaWRlIHRoZSB3b3JraW5nIGRpcmVjdG9yeVxuICAgIGlmIChyZWxhdGl2ZVBhdGguc3RhcnRzV2l0aCgnLi4vJykpIHtcbiAgICAgIHJlbGF0aXZlUGF0aCA9IHJlbGF0aXZlUGF0aFxuICAgICAgICAuc3BsaXQoJy8nKVxuICAgICAgICAuZmlsdGVyKChwYXJ0KSA9PiBwYXJ0ICE9PSAnLi4nKVxuICAgICAgICAuam9pbignLycpO1xuICAgIH1cbiAgICByZXR1cm4gcmVsYXRpdmVQYXRoO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRDYWNoZWRNYW5pZmVzdFRyYW5zZm9ybShcbiAgICBmaWxlOiBzdHJpbmcsXG4gICAgbW9kZTogJ3dvcmtmbG93JyB8ICdzdGVwJ1xuICApOiBQcm9taXNlPFdvcmtmbG93TWFuaWZlc3Q+IHtcbiAgICBjb25zdCBzdGF0cyA9IGF3YWl0IHN0YXQoZmlsZSk7XG4gICAgY29uc3QgY2FjaGVLZXkgPSBgJHttb2RlfToke2ZpbGV9YDtcbiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLm1hbmlmZXN0VHJhbnNmb3JtQ2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgICBpZiAoXG4gICAgICBjYWNoZWQgJiZcbiAgICAgIGNhY2hlZC5zaXplID09PSBzdGF0cy5zaXplICYmXG4gICAgICBjYWNoZWQubXRpbWVNcyA9PT0gc3RhdHMubXRpbWVNc1xuICAgICkge1xuICAgICAgcmV0dXJuIGNhY2hlZC5tYW5pZmVzdDtcbiAgICB9XG5cbiAgICBjb25zdCBzb3VyY2UgPSBhd2FpdCByZWFkRmlsZShmaWxlLCAndXRmOCcpO1xuICAgIGNvbnN0IHJlbGF0aXZlRmlsZXBhdGggPSB0aGlzLmdldFJlbGF0aXZlRmlsZXBhdGgoZmlsZSk7XG4gICAgY29uc3QgeyB3b3JrZmxvd01hbmlmZXN0IH0gPSBhd2FpdCBhcHBseVN3Y1RyYW5zZm9ybShcbiAgICAgIHJlbGF0aXZlRmlsZXBhdGgsXG4gICAgICBzb3VyY2UsXG4gICAgICBtb2RlLFxuICAgICAgZmlsZSxcbiAgICAgIHRoaXMudHJhbnNmb3JtUHJvamVjdFJvb3QsXG4gICAgICB0aGlzLm1vZHVsZVNwZWNpZmllclJvb3RcbiAgICApO1xuICAgIHRoaXMubWFuaWZlc3RUcmFuc2Zvcm1DYWNoZS5zZXQoY2FjaGVLZXksIHtcbiAgICAgIHNpemU6IHN0YXRzLnNpemUsXG4gICAgICBtdGltZU1zOiBzdGF0cy5tdGltZU1zLFxuICAgICAgbWFuaWZlc3Q6IHdvcmtmbG93TWFuaWZlc3QsXG4gICAgfSk7XG4gICAgcmV0dXJuIHdvcmtmbG93TWFuaWZlc3Q7XG4gIH1cblxuICBwcm90ZWN0ZWQgY3JlYXRlUm91dGVJbXBvcnRTcGVjaWZpZXIoZmlsZTogc3RyaW5nLCByb3V0ZURpcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCB7IGltcG9ydFBhdGgsIGlzUGFja2FnZSB9ID0gZ2V0SW1wb3J0UGF0aChcbiAgICAgIGZpbGUsXG4gICAgICB0aGlzLmNvbmZpZy53b3JraW5nRGlyXG4gICAgKTtcbiAgICBpZiAoaXNQYWNrYWdlKSB7XG4gICAgICByZXR1cm4gaW1wb3J0UGF0aDtcbiAgICB9XG5cbiAgICBsZXQgcmVsYXRpdmVQYXRoID0gcmVsYXRpdmUocm91dGVEaXIsIGZpbGUpLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICBpZiAoIXJlbGF0aXZlUGF0aC5zdGFydHNXaXRoKCcuLycpICYmICFyZWxhdGl2ZVBhdGguc3RhcnRzV2l0aCgnLi4vJykpIHtcbiAgICAgIHJlbGF0aXZlUGF0aCA9IGAuLyR7cmVsYXRpdmVQYXRofWA7XG4gICAgfVxuICAgIHJldHVybiByZWxhdGl2ZVBhdGg7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlU3RlcFNvdXJjZVJlZ2lzdHJhdGlvbkZpbGUoe1xuICAgIGlucHV0RmlsZXMsXG4gICAgb3V0ZmlsZSxcbiAgICB0c2NvbmZpZ1BhdGgsXG4gICAgZGlzY292ZXJlZEVudHJpZXMsXG4gIH06IHtcbiAgICBpbnB1dEZpbGVzOiBzdHJpbmdbXTtcbiAgICBvdXRmaWxlOiBzdHJpbmc7XG4gICAgdHNjb25maWdQYXRoPzogc3RyaW5nO1xuICAgIGRpc2NvdmVyZWRFbnRyaWVzPzogRGlzY292ZXJlZEVudHJpZXM7XG4gIH0pOiBQcm9taXNlPFdvcmtmbG93TWFuaWZlc3Q+IHtcbiAgICBjb25zdCBzdGVwc0J1bmRsZVN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCB3b3JrZmxvd01hbmlmZXN0OiBXb3JrZmxvd01hbmlmZXN0ID0ge307XG4gICAgY29uc3QgYnVpbHRJblN0ZXBzID0gJ3dvcmtmbG93L2ludGVybmFsL2J1aWx0aW5zJztcbiAgICBjb25zdCByZXNvbHZlZEJ1aWx0SW5TdGVwcyA9IChhd2FpdCBlbmhhbmNlZFJlc29sdmUoXG4gICAgICBkaXJuYW1lKG91dGZpbGUpLFxuICAgICAgYnVpbHRJblN0ZXBzXG4gICAgKS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dCdWlsZEVycm9yKFxuICAgICAgICBgRmFpbGVkIHRvIHJlc29sdmUgYnVpbHQtaW4gc3RlcHMgc291cmNlcy5cXG5cXG5DYXVzZWQgYnk6ICR7U3RyaW5nKGVycil9YCxcbiAgICAgICAge1xuICAgICAgICAgIGhpbnQ6ICdydW4gYHBucG0gaW5zdGFsbCB3b3JrZmxvd2AgdG8gcmVzb2x2ZSB0aGlzIGlzc3VlLicsXG4gICAgICAgICAgY2F1c2U6IGVycixcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KSkgYXMgc3RyaW5nO1xuXG4gICAgY29uc3QgZGlzY292ZXJlZCA9XG4gICAgICBkaXNjb3ZlcmVkRW50cmllcyA/P1xuICAgICAgKGF3YWl0IHRoaXMuZGlzY292ZXJFbnRyaWVzKGlucHV0RmlsZXMsIGRpcm5hbWUob3V0ZmlsZSksIHRzY29uZmlnUGF0aCkpO1xuICAgIGNvbnN0IHN0ZXBGaWxlcyA9IFsuLi5kaXNjb3ZlcmVkLmRpc2NvdmVyZWRTdGVwc10uc29ydCgpO1xuICAgIGNvbnN0IHdvcmtmbG93RmlsZXMgPSBbLi4uZGlzY292ZXJlZC5kaXNjb3ZlcmVkV29ya2Zsb3dzXS5zb3J0KCk7XG4gICAgY29uc3Qgc2VyZGVGaWxlcyA9IFsuLi5kaXNjb3ZlcmVkLmRpc2NvdmVyZWRTZXJkZUZpbGVzXS5zb3J0KCk7XG4gICAgY29uc3Qgc3RlcEZpbGVzU2V0ID0gbmV3IFNldChzdGVwRmlsZXMpO1xuICAgIGNvbnN0IHNlcmRlT25seUZpbGVzID0gc2VyZGVGaWxlcy5maWx0ZXIoKGYpID0+ICFzdGVwRmlsZXNTZXQuaGFzKGYpKTtcblxuICAgIGF3YWl0IHRoaXMud3JpdGVEZWJ1Z0ZpbGUob3V0ZmlsZSwge1xuICAgICAgc3RlcEZpbGVzLFxuICAgICAgd29ya2Zsb3dGaWxlcyxcbiAgICAgIHNlcmRlT25seUZpbGVzLFxuICAgICAgc291cmNlSW1wb3J0czogdHJ1ZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGVtaXR0ZWRJbXBvcnRJZGVudGl0aWVzID0gbmV3IFNldDxzdHJpbmc+KFtidWlsdEluU3RlcHNdKTtcbiAgICBjb25zdCBpbXBvcnRTdGF0ZW1lbnRzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IHJvdXRlRGlyID0gZGlybmFtZShvdXRmaWxlKTtcbiAgICBjb25zdCBhZGRSZWdpc3RyYXRpb25JbXBvcnQgPSAoc3BlY2lmaWVyOiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgICAgIGltcG9ydFN0YXRlbWVudHMucHVzaChgaW1wb3J0ICR7SlNPTi5zdHJpbmdpZnkoc3BlY2lmaWVyKX07YCk7XG4gICAgfTtcbiAgICBjb25zdCBhZGRSZWdpc3RyYXRpb25GaWxlSW1wb3J0ID0gKGZpbGU6IHN0cmluZyk6IHZvaWQgPT4ge1xuICAgICAgY29uc3QgaWRlbnRpdHkgPSBtb2R1bGVJZGVudGl0eUtleShmaWxlLCB0aGlzLm1vZHVsZVNwZWNpZmllclJvb3QpO1xuICAgICAgaWYgKGVtaXR0ZWRJbXBvcnRJZGVudGl0aWVzLmhhcyhpZGVudGl0eSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZW1pdHRlZEltcG9ydElkZW50aXRpZXMuYWRkKGlkZW50aXR5KTtcbiAgICAgIGFkZFJlZ2lzdHJhdGlvbkltcG9ydCh0aGlzLmNyZWF0ZVJvdXRlSW1wb3J0U3BlY2lmaWVyKGZpbGUsIHJvdXRlRGlyKSk7XG4gICAgfTtcblxuICAgIGFkZFJlZ2lzdHJhdGlvbkltcG9ydChidWlsdEluU3RlcHMpO1xuICAgIGZvciAoY29uc3QgZmlsZSBvZiBzdGVwRmlsZXMpIHtcbiAgICAgIGFkZFJlZ2lzdHJhdGlvbkZpbGVJbXBvcnQoZmlsZSk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgZmlsZSBvZiBzZXJkZU9ubHlGaWxlcykge1xuICAgICAgYWRkUmVnaXN0cmF0aW9uRmlsZUltcG9ydChmaWxlKTtcbiAgICB9XG5cbiAgICBjb25zdCBvdXRwdXQgPSBgLy8gYmlvbWUtaWdub3JlLWFsbCBsaW50OiBnZW5lcmF0ZWQgZmlsZVxuLyogZXNsaW50LWRpc2FibGUgKi9cbiR7aW1wb3J0U3RhdGVtZW50cy5qb2luKCdcXG4nKX1cblxuZXhwb3J0IGNvbnN0IF9fc3RlcHNfcmVnaXN0ZXJlZCA9IHRydWU7XG5gO1xuICAgIGF3YWl0IG1rZGlyKGRpcm5hbWUob3V0ZmlsZSksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIGF3YWl0IHRoaXMud3JpdGVHZW5lcmF0ZWRGaWxlKG91dGZpbGUsIG91dHB1dCk7XG5cbiAgICBjb25zdCBtYW5pZmVzdEZpbGVzID0gQXJyYXkuZnJvbShcbiAgICAgIG5ldyBTZXQoWy4uLnN0ZXBGaWxlcywgLi4uc2VyZGVPbmx5RmlsZXMsIHJlc29sdmVkQnVpbHRJblN0ZXBzXSlcbiAgICApLnNvcnQoKTtcbiAgICBjb25zdCBzdGVwSWRzID0gbmV3IE1hcDxzdHJpbmcsIE1hbmlmZXN0RW50cnlMb2NhdGlvbj4oKTtcbiAgICBjb25zdCB3b3JrZmxvd0lkcyA9IG5ldyBNYXA8c3RyaW5nLCBNYW5pZmVzdEVudHJ5TG9jYXRpb24+KCk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtYW5pZmVzdEZpbGVzLm1hcChhc3luYyAoZmlsZSkgPT4ge1xuICAgICAgICBjb25zdCBmaWxlTWFuaWZlc3QgPSBhd2FpdCB0aGlzLmdldENhY2hlZE1hbmlmZXN0VHJhbnNmb3JtKFxuICAgICAgICAgIGZpbGUsXG4gICAgICAgICAgJ3N0ZXAnXG4gICAgICAgICk7XG4gICAgICAgIG1lcmdlV29ya2Zsb3dNYW5pZmVzdChcbiAgICAgICAgICB3b3JrZmxvd01hbmlmZXN0LFxuICAgICAgICAgIGZpbGVNYW5pZmVzdCxcbiAgICAgICAgICBzdGVwSWRzLFxuICAgICAgICAgIHdvcmtmbG93SWRzXG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICBhd2FpdCB0aGlzLmVuc3VyZVN3Y0lnbm9yZWQoKTtcbiAgICB0aGlzLmxvZ0Jhc2VCdWlsZGVySW5mbyhcbiAgICAgICdDcmVhdGVkIHN0ZXAgcmVnaXN0cmF0aW9ucycsXG4gICAgICBgJHtEYXRlLm5vdygpIC0gc3RlcHNCdW5kbGVTdGFydH1tc2BcbiAgICApO1xuICAgIHJldHVybiB3b3JrZmxvd01hbmlmZXN0O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBidW5kbGUgZm9yIHdvcmtmbG93IHN0ZXAgZnVuY3Rpb25zLlxuICAgKiBTdGVwcyBoYXZlIGZ1bGwgTm9kZS5qcyBydW50aW1lIGFjY2VzcyBhbmQgaGFuZGxlIHNpZGUgZWZmZWN0cywgQVBJIGNhbGxzLCBldGMuXG4gICAqXG4gICAqIEBwYXJhbSBleHRlcm5hbGl6ZU5vblN0ZXBzIC0gSWYgdHJ1ZSwgb25seSBidW5kbGVzIHN0ZXAgZW50cnkgcG9pbnRzIGFuZCBleHRlcm5hbGl6ZXMgb3RoZXIgY29kZVxuICAgKiBAcGFyYW0gc291cmNlU3RlcFJlZ2lzdHJhdGlvbkltcG9ydHMgLSBJZiB0cnVlLCBlbWl0cyBhIHNvdXJjZSBpbXBvcnQgcmVnaXN0cmF0aW9uIGZpbGUgaW5zdGVhZCBvZiBidW5kbGluZyBzdGVwIHJlZ2lzdHJhdGlvbnNcbiAgICogQHBhcmFtIGJ1bmRsZVRyYW5zaXRpdmVMb2NhbFN0ZXBEZXBlbmRlbmNpZXMgLSBJZiB0cnVlLCBhbHNvIGJ1bmRsZXMgcHJvamVjdC1sb2NhbCBmaWxlcyBpbXBvcnRlZCBieSBzdGVwIGVudHJpZXMgZm9yIGRpcmVjdCBydW50aW1lIGxvYWRpbmdcbiAgICogQHJldHVybnMgQnVpbGQgY29udGV4dCAoZm9yIHdhdGNoIG1vZGUpIGFuZCB0aGUgY29sbGVjdGVkIHdvcmtmbG93IG1hbmlmZXN0XG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlU3RlcHNCdW5kbGUoe1xuICAgIGlucHV0RmlsZXMsXG4gICAgZm9ybWF0ID0gJ2VzbScsXG4gICAgb3V0ZmlsZSxcbiAgICBleHRlcm5hbGl6ZU5vblN0ZXBzLFxuICAgIGJ1bmRsZVRyYW5zaXRpdmVMb2NhbFN0ZXBEZXBlbmRlbmNpZXMsXG4gICAgc291cmNlU3RlcFJlZ2lzdHJhdGlvbkltcG9ydHMsXG4gICAgcmV3cml0ZVRzRXh0ZW5zaW9ucyxcbiAgICB0c2NvbmZpZ1BhdGgsXG4gICAgZGlzY292ZXJlZEVudHJpZXMsXG4gICAgc2tpcEVzbVJlcXVpcmVCYW5uZXIgPSBmYWxzZSxcbiAgfToge1xuICAgIHRzY29uZmlnUGF0aD86IHN0cmluZztcbiAgICBpbnB1dEZpbGVzOiBzdHJpbmdbXTtcbiAgICBvdXRmaWxlOiBzdHJpbmc7XG4gICAgZm9ybWF0PzogJ2NqcycgfCAnZXNtJztcbiAgICBleHRlcm5hbGl6ZU5vblN0ZXBzPzogYm9vbGVhbjtcbiAgICBidW5kbGVUcmFuc2l0aXZlTG9jYWxTdGVwRGVwZW5kZW5jaWVzPzogYm9vbGVhbjtcbiAgICBzb3VyY2VTdGVwUmVnaXN0cmF0aW9uSW1wb3J0cz86IGJvb2xlYW47XG4gICAgcmV3cml0ZVRzRXh0ZW5zaW9ucz86IGJvb2xlYW47XG4gICAgZGlzY292ZXJlZEVudHJpZXM/OiBEaXNjb3ZlcmVkRW50cmllcztcbiAgICAvKipcbiAgICAgKiBXaGVuIHRydWUsIHNraXAgdGhlIGBjcmVhdGVSZXF1aXJlYCBiYW5uZXIgb24gdGhlIHN0ZXBzIGJ1bmRsZS5cbiAgICAgKiBVc2VkIGJ5IGBjcmVhdGVDb21iaW5lZEJ1bmRsZWAgd2l0aCBgYnVuZGxlRmluYWxPdXRwdXQ6IHRydWVgIHdoZXJlXG4gICAgICogdGhlIG91dGVyIGVzYnVpbGQgcGFzcyBwcm92aWRlcyBpdHMgb3duIGJhbm5lciwgcHJldmVudGluZyB0aGVcbiAgICAgKiBgX19jcmVhdGVSZXF1aXJlYCBpZGVudGlmaWVyIGZyb20gYmVpbmcgZGVjbGFyZWQgdHdpY2UgYWZ0ZXIgaW5saW5pbmcuXG4gICAgICovXG4gICAgc2tpcEVzbVJlcXVpcmVCYW5uZXI/OiBib29sZWFuO1xuICB9KTogUHJvbWlzZTx7XG4gICAgY29udGV4dDogZXNidWlsZC5CdWlsZENvbnRleHQgfCB1bmRlZmluZWQ7XG4gICAgbWFuaWZlc3Q6IFdvcmtmbG93TWFuaWZlc3Q7XG4gIH0+IHtcbiAgICBjb25zdCBzdGVwc0J1bmRsZVN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCB3b3JrZmxvd01hbmlmZXN0OiBXb3JrZmxvd01hbmlmZXN0ID0ge307XG4gICAgY29uc3QgYnVpbHRJblN0ZXBzID0gJ3dvcmtmbG93L2ludGVybmFsL2J1aWx0aW5zJztcblxuICAgIGNvbnN0IHJlc29sdmVkQnVpbHRJblN0ZXBzID0gYXdhaXQgZW5oYW5jZWRSZXNvbHZlKFxuICAgICAgZGlybmFtZShvdXRmaWxlKSxcbiAgICAgICd3b3JrZmxvdy9pbnRlcm5hbC9idWlsdGlucydcbiAgICApLmNhdGNoKChlcnIpID0+IHtcbiAgICAgIHRocm93IG5ldyBXb3JrZmxvd0J1aWxkRXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gcmVzb2x2ZSBidWlsdC1pbiBzdGVwcyBzb3VyY2VzLlxcblxcbkNhdXNlZCBieTogJHtTdHJpbmcoZXJyKX1gLFxuICAgICAgICB7XG4gICAgICAgICAgaGludDogJ3J1biBgcG5wbSBpbnN0YWxsIHdvcmtmbG93YCB0byByZXNvbHZlIHRoaXMgaXNzdWUuJyxcbiAgICAgICAgICBjYXVzZTogZXJyLFxuICAgICAgICB9XG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgLy8gRGlzY292ZXJ5IG9mIHdvcmtmbG93L3N0ZXAvc2VyZGUgZW50cmllcy4gVGhlIFNESyBydW50aW1lIGVudHJ5IHBvaW50XG4gICAgLy8gKHdvcmtmbG93L3J1bnRpbWUpIGlzIHJlc29sdmVkIGluc2lkZSBkaXNjb3ZlckVudHJpZXMoKSBpdHNlbGYgc28gdGhhdFxuICAgIC8vIGNhbGxlcnMgY2FuIHBhc3MgdGhlIG9yaWdpbmFsIGlucHV0RmlsZXMgcmVmZXJlbmNlIGFuZCBiZW5lZml0IGZyb21cbiAgICAvLyBXZWFrTWFwIGNhY2hpbmcgYWNyb3NzIGNyZWF0ZVdvcmtmbG93c0J1bmRsZSAvIGNyZWF0ZVN0ZXBzQnVuZGxlIGNhbGxzLlxuICAgIGNvbnN0IGRpc2NvdmVyZWQgPVxuICAgICAgZGlzY292ZXJlZEVudHJpZXMgPz9cbiAgICAgIChhd2FpdCB0aGlzLmRpc2NvdmVyRW50cmllcyhpbnB1dEZpbGVzLCBkaXJuYW1lKG91dGZpbGUpLCB0c2NvbmZpZ1BhdGgpKTtcbiAgICBjb25zdCBzdGVwRmlsZXMgPSBbLi4uZGlzY292ZXJlZC5kaXNjb3ZlcmVkU3RlcHNdLnNvcnQoKTtcbiAgICBjb25zdCB3b3JrZmxvd0ZpbGVzID0gWy4uLmRpc2NvdmVyZWQuZGlzY292ZXJlZFdvcmtmbG93c10uc29ydCgpO1xuICAgIGNvbnN0IHNlcmRlRmlsZXMgPSBbLi4uZGlzY292ZXJlZC5kaXNjb3ZlcmVkU2VyZGVGaWxlc10uc29ydCgpO1xuXG4gICAgLy8gSW5jbHVkZSBzZXJkZSBmaWxlcyB0aGF0IGFyZW4ndCBhbHJlYWR5IHN0ZXAgZmlsZXMgZm9yIGNyb3NzLWNvbnRleHQgY2xhc3MgcmVnaXN0cmF0aW9uLlxuICAgIC8vIENsYXNzZXMgbmVlZCB0byBiZSByZWdpc3RlcmVkIGluIHRoZSBzdGVwIGJ1bmRsZSBzbyB0aGV5IGNhbiBiZSBkZXNlcmlhbGl6ZWRcbiAgICAvLyB3aGVuIHJlY2VpdmluZyBkYXRhIGZyb20gd29ya2Zsb3dzIGFuZCBzZXJpYWxpemVkIHdoZW4gcmV0dXJuaW5nIGRhdGEgdG8gd29ya2Zsb3dzLlxuICAgIGNvbnN0IHN0ZXBGaWxlc1NldCA9IG5ldyBTZXQoc3RlcEZpbGVzKTtcbiAgICBjb25zdCBzZXJkZU9ubHlGaWxlcyA9IHNlcmRlRmlsZXMuZmlsdGVyKChmKSA9PiAhc3RlcEZpbGVzU2V0LmhhcyhmKSk7XG5cbiAgICBpZiAoXG4gICAgICBzb3VyY2VTdGVwUmVnaXN0cmF0aW9uSW1wb3J0cyAmJlxuICAgICAgZXh0ZXJuYWxpemVOb25TdGVwcyAmJlxuICAgICAgIWJ1bmRsZVRyYW5zaXRpdmVMb2NhbFN0ZXBEZXBlbmRlbmNpZXNcbiAgICApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRleHQ6IHVuZGVmaW5lZCxcbiAgICAgICAgbWFuaWZlc3Q6IGF3YWl0IHRoaXMuY3JlYXRlU3RlcFNvdXJjZVJlZ2lzdHJhdGlvbkZpbGUoe1xuICAgICAgICAgIGlucHV0RmlsZXMsXG4gICAgICAgICAgb3V0ZmlsZSxcbiAgICAgICAgICB0c2NvbmZpZ1BhdGgsXG4gICAgICAgICAgZGlzY292ZXJlZEVudHJpZXM6IGRpc2NvdmVyZWQsXG4gICAgICAgIH0pLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBsb2cgdGhlIHN0ZXAgZmlsZXMgZm9yIGRlYnVnZ2luZ1xuICAgIGF3YWl0IHRoaXMud3JpdGVEZWJ1Z0ZpbGUob3V0ZmlsZSwge1xuICAgICAgc3RlcEZpbGVzLFxuICAgICAgd29ya2Zsb3dGaWxlcyxcbiAgICAgIHNlcmRlT25seUZpbGVzLFxuICAgIH0pO1xuXG4gICAgLy8gSGVscGVyIHRvIGNyZWF0ZSBpbXBvcnQgc3RhdGVtZW50IGZyb20gZmlsZSBwYXRoXG4gICAgLy8gRm9yIHdvcmtzcGFjZS9ub2RlX21vZHVsZXMgcGFja2FnZXMsIHVzZXMgdGhlIHBhY2thZ2UgbmFtZSBzbyBlc2J1aWxkXG4gICAgLy8gd2lsbCByZXNvbHZlIHRocm91Z2ggcGFja2FnZS5qc29uIGV4cG9ydHMgd2l0aCB0aGUgYXBwcm9wcmlhdGUgY29uZGl0aW9uc1xuICAgIGNvbnN0IGNyZWF0ZUltcG9ydCA9IChmaWxlOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRXb3Jrc3BhY2VSb290ID0gdGhpcy5jb25maWcud29ya2luZ0RpclxuICAgICAgICAucmVwbGFjZSgvXFxcXC9nLCAnLycpXG4gICAgICAgIC5yZXBsYWNlKC9cXC8kLywgJycpO1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFdvcmtzcGFjZUZpbGUgPSBmaWxlLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgIC8vIE9ubHkgdXNlIHJlbGF0aXZlIHNvdXJjZSBwYXRocyBmb3Igd29ya3NwYWNlIHN5bWxpbmtzIChmaWxlc1xuICAgICAgLy8gb3V0c2lkZSBub2RlX21vZHVsZXMgaW4gYSBwYWNrYWdlcy8qL3NyYy8gZGlyZWN0b3J5KS4gRm9yIHRhcmJhbGwtXG4gICAgICAvLyBpbnN0YWxsZWQgcGFja2FnZXMgKGZpbGVzIGluc2lkZSBub2RlX21vZHVsZXMvKSwgZmFsbCB0aHJvdWdoIHRvXG4gICAgICAvLyBnZXRJbXBvcnRQYXRoIHdoaWNoIHJldHVybnMgcGFja2FnZSBzcGVjaWZpZXJzIOKAlCB0aGlzIGFsbG93cyB0aGVcbiAgICAgIC8vIFNXQyBwbHVnaW4ncyBleHRlcm5hbGl6ZU5vblN0ZXBzIHRvIHdvcmsgY29ycmVjdGx5LlxuICAgICAgY29uc3QgaXNXb3Jrc3BhY2VTb3VyY2VCYWNrZWRQYWNrYWdlRmlsZSA9XG4gICAgICAgIG5vcm1hbGl6ZWRXb3Jrc3BhY2VGaWxlLmluY2x1ZGVzKCcvcGFja2FnZXMvJykgJiZcbiAgICAgICAgbm9ybWFsaXplZFdvcmtzcGFjZUZpbGUuaW5jbHVkZXMoJy9zcmMvJykgJiZcbiAgICAgICAgIW5vcm1hbGl6ZWRXb3Jrc3BhY2VGaWxlLmluY2x1ZGVzKCcvbm9kZV9tb2R1bGVzLycpICYmXG4gICAgICAgICEoXG4gICAgICAgICAgbm9ybWFsaXplZFdvcmtzcGFjZUZpbGUgPT09IG5vcm1hbGl6ZWRXb3Jrc3BhY2VSb290IHx8XG4gICAgICAgICAgbm9ybWFsaXplZFdvcmtzcGFjZUZpbGUuc3RhcnRzV2l0aChgJHtub3JtYWxpemVkV29ya3NwYWNlUm9vdH0vYClcbiAgICAgICAgKTtcbiAgICAgIGNvbnN0IGlzU291cmNlQmFja2VkUGFja2FnZUZpbGUgPSBpc1dvcmtzcGFjZVNvdXJjZUJhY2tlZFBhY2thZ2VGaWxlO1xuXG4gICAgICBpZiAoaXNTb3VyY2VCYWNrZWRQYWNrYWdlRmlsZSkge1xuICAgICAgICBsZXQgcmVsYXRpdmVQYXRoID0gcmVsYXRpdmUoXG4gICAgICAgICAgbm9ybWFsaXplZFdvcmtzcGFjZVJvb3QsXG4gICAgICAgICAgbm9ybWFsaXplZFdvcmtzcGFjZUZpbGVcbiAgICAgICAgKS5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gICAgICAgIGlmICghcmVsYXRpdmVQYXRoLnN0YXJ0c1dpdGgoJy4vJykgJiYgIXJlbGF0aXZlUGF0aC5zdGFydHNXaXRoKCcuLi8nKSkge1xuICAgICAgICAgIHJlbGF0aXZlUGF0aCA9IGAuLyR7cmVsYXRpdmVQYXRofWA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGBpbXBvcnQgJyR7cmVsYXRpdmVQYXRofSc7YDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgeyBpbXBvcnRQYXRoLCBpc1BhY2thZ2UgfSA9IGdldEltcG9ydFBhdGgoXG4gICAgICAgIGZpbGUsXG4gICAgICAgIHRoaXMuY29uZmlnLndvcmtpbmdEaXJcbiAgICAgICk7XG5cbiAgICAgIGlmIChpc1BhY2thZ2UpIHtcbiAgICAgICAgLy8gVXNlIHBhY2thZ2UgbmFtZSAtIGVzYnVpbGQgd2lsbCByZXNvbHZlIHZpYSBwYWNrYWdlLmpzb24gZXhwb3J0c1xuICAgICAgICByZXR1cm4gYGltcG9ydCAnJHtpbXBvcnRQYXRofSc7YDtcbiAgICAgIH1cblxuICAgICAgLy8gTG9jYWwgYXBwIGZpbGUgLSB1c2UgcmVsYXRpdmUgcGF0aFxuICAgICAgLy8gTm9ybWFsaXplIGJvdGggcGF0aHMgdG8gZm9yd2FyZCBzbGFzaGVzIGJlZm9yZSBjYWxsaW5nIHJlbGF0aXZlKClcbiAgICAgIC8vIFRoaXMgaXMgY3JpdGljYWwgb24gV2luZG93cyB3aGVyZSByZWxhdGl2ZSgpIGNhbiBwcm9kdWNlIHVuZXhwZWN0ZWQgcmVzdWx0cyB3aXRoIG1peGVkIHBhdGggZm9ybWF0c1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFdvcmtpbmdEaXIgPSB0aGlzLmNvbmZpZy53b3JraW5nRGlyLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRGaWxlID0gZmlsZS5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gICAgICAvLyBDYWxjdWxhdGUgcmVsYXRpdmUgcGF0aCBmcm9tIHdvcmtpbmcgZGlyZWN0b3J5IHRvIHRoZSBmaWxlXG4gICAgICBsZXQgcmVsYXRpdmVQYXRoID0gcmVsYXRpdmUobm9ybWFsaXplZFdvcmtpbmdEaXIsIG5vcm1hbGl6ZWRGaWxlKS5yZXBsYWNlKFxuICAgICAgICAvXFxcXC9nLFxuICAgICAgICAnLydcbiAgICAgICk7XG4gICAgICAvLyBFbnN1cmUgcmVsYXRpdmUgcGF0aHMgc3RhcnQgd2l0aCAuLyBzbyBlc2J1aWxkIHJlc29sdmVzIHRoZW0gY29ycmVjdGx5LlxuICAgICAgLy8gUGF0aHMgbGlrZSBcIi5vdXRwdXQvLi4uXCIgYXJlIG5vdCB2YWxpZCByZWxhdGl2ZSBzcGVjaWZpZXJzIGFuZCBtdXN0XG4gICAgICAvLyBiZWNvbWUgXCIuLy5vdXRwdXQvLi4uXCIuXG4gICAgICBpZiAoIXJlbGF0aXZlUGF0aC5zdGFydHNXaXRoKCcuLycpICYmICFyZWxhdGl2ZVBhdGguc3RhcnRzV2l0aCgnLi4vJykpIHtcbiAgICAgICAgcmVsYXRpdmVQYXRoID0gYC4vJHtyZWxhdGl2ZVBhdGh9YDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBgaW1wb3J0ICcke3JlbGF0aXZlUGF0aH0nO2A7XG4gICAgfTtcblxuICAgIC8vIENyZWF0ZSBhIHZpcnR1YWwgZW50cnkgdGhhdCBpbXBvcnRzIGFsbCBmaWxlcy4gQWxsIHN0ZXAgZGVmaW5pdGlvbnNcbiAgICAvLyB3aWxsIGdldCByZWdpc3RlcmVkIHRoYW5rcyB0byB0aGUgc3djIHRyYW5zZm9ybS5cbiAgICAvL1xuICAgIC8vIERlZHVwZSBpbXBvcnRzIGJ5IGNhbm9uaWNhbCBtb2R1bGUgaWRlbnRpdHkgc28gd2UgbmV2ZXIgZW1pdCB0d29cbiAgICAvLyBpbXBvcnQgbGluZXMgdGhhdCByZXNvbHZlIHRvIHRoZSBzYW1lIHBoeXNpY2FsIG1vZHVsZS4gUHJlLXNlZWQgdGhlXG4gICAgLy8gc2V0IHdpdGggdGhlIGJ1aWx0LWluIHN0ZXBzIGltcG9ydCBzbyBhIHdvcmtzcGFjZSBzdGVwIGZpbGUgYXRcbiAgICAvLyBgcGFja2FnZXMvd29ya2Zsb3cvc3JjL2ludGVybmFsL2J1aWx0aW5zLnRzYCBkb2Vzbid0IGVtaXQgYSBzZWNvbmQsXG4gICAgLy8gcmVsYXRpdmUtcGF0aCBjb21wZXRpbmcgaW1wb3J0IOKAlCBlc2J1aWxkIHdvdWxkIG90aGVyd2lzZSB0cmFuc2Zvcm1cbiAgICAvLyBib3RoIGNvcGllcyBhbmQgdGhlIHN3YyBwbHVnaW4gd291bGQgZ2VuZXJhdGUgZHVwbGljYXRlIHN0ZXAgSURzLlxuICAgIGNvbnN0IGVtaXR0ZWRJbXBvcnRJZGVudGl0aWVzID0gbmV3IFNldDxzdHJpbmc+KFtidWlsdEluU3RlcHNdKTtcbiAgICBjb25zdCBidWlsZEltcG9ydHMgPSAoZmlsZXM6IHN0cmluZ1tdKTogc3RyaW5nID0+XG4gICAgICBmaWxlc1xuICAgICAgICAuZmlsdGVyKChmaWxlKSA9PiB7XG4gICAgICAgICAgY29uc3QgaWRlbnRpdHkgPSBtb2R1bGVJZGVudGl0eUtleShmaWxlLCB0aGlzLm1vZHVsZVNwZWNpZmllclJvb3QpO1xuICAgICAgICAgIGlmIChlbWl0dGVkSW1wb3J0SWRlbnRpdGllcy5oYXMoaWRlbnRpdHkpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgZW1pdHRlZEltcG9ydElkZW50aXRpZXMuYWRkKGlkZW50aXR5KTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSlcbiAgICAgICAgLm1hcChjcmVhdGVJbXBvcnQpXG4gICAgICAgIC5qb2luKCdcXG4nKTtcblxuICAgIGNvbnN0IHN0ZXBJbXBvcnRzID0gYnVpbGRJbXBvcnRzKHN0ZXBGaWxlcyk7XG5cbiAgICAvLyBJbmNsdWRlIHNlcmRlLW9ubHkgZmlsZXMgZm9yIGNsYXNzIHJlZ2lzdHJhdGlvbiBzaWRlIGVmZmVjdHNcbiAgICBjb25zdCBzZXJkZUltcG9ydHMgPSBidWlsZEltcG9ydHMoc2VyZGVPbmx5RmlsZXMpO1xuXG4gICAgY29uc3QgZW50cnlDb250ZW50ID0gYFxuICAgIC8vIEJ1aWx0IGluIHN0ZXBzXG4gICAgaW1wb3J0ICcke2J1aWx0SW5TdGVwc30nO1xuICAgIC8vIFVzZXIgc3RlcHNcbiAgICAke3N0ZXBJbXBvcnRzfVxuICAgIC8vIFNlcmRlIGZpbGVzIGZvciBjcm9zcy1jb250ZXh0IGNsYXNzIHJlZ2lzdHJhdGlvblxuICAgICR7c2VyZGVJbXBvcnRzfVxuICAgIC8vIFNlbnRpbmVsIGV4cG9ydCBzbyBidW5kbGVycyAocm9sbHVwKSBkb24ndCB0cmVlLXNoYWtlIHRoaXMgbW9kdWxlXG4gICAgLy8gd2hlbiBpdCdzIGltcG9ydGVkIGFzIGEgc2lkZS1lZmZlY3Qtb25seSBkZXBlbmRlbmN5LlxuICAgIGV4cG9ydCBjb25zdCBfX3N0ZXBzX3JlZ2lzdGVyZWQgPSB0cnVlO2A7XG5cbiAgICAvLyBCdW5kbGUgd2l0aCBlc2J1aWxkIGFuZCBvdXIgY3VzdG9tIFNXQyBwbHVnaW5cbiAgICBjb25zdCBlbnRyaWVzVG9CdW5kbGUgPSBleHRlcm5hbGl6ZU5vblN0ZXBzXG4gICAgICA/IFtcbiAgICAgICAgICAuLi5zdGVwRmlsZXMsXG4gICAgICAgICAgLi4uc2VyZGVGaWxlcyxcbiAgICAgICAgICAuLi4ocmVzb2x2ZWRCdWlsdEluU3RlcHMgPyBbcmVzb2x2ZWRCdWlsdEluU3RlcHNdIDogW10pLFxuICAgICAgICBdXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBub3JtYWxpemVkRW50cmllc1RvQnVuZGxlID0gZW50cmllc1RvQnVuZGxlXG4gICAgICA/IGF3YWl0IHdpdGhSZWFscGF0aHMoZW50cmllc1RvQnVuZGxlKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gICAgY29uc3Qgbm9ybWFsaXplZFNpZGVFZmZlY3RFbnRyaWVzID0gYXdhaXQgd2l0aFJlYWxwYXRocyhbXG4gICAgICAuLi5zdGVwRmlsZXMsXG4gICAgICAuLi5zZXJkZU9ubHlGaWxlcyxcbiAgICAgIC4uLihyZXNvbHZlZEJ1aWx0SW5TdGVwcyA/IFtyZXNvbHZlZEJ1aWx0SW5TdGVwc10gOiBbXSksXG4gICAgXSk7XG4gICAgY29uc3QgZXNidWlsZFRzY29uZmlnT3B0aW9ucyA9XG4gICAgICBhd2FpdCBnZXRFc2J1aWxkVHNjb25maWdPcHRpb25zKHRzY29uZmlnUGF0aCk7XG4gICAgY29uc3QgeyBiYW5uZXI6IGltcG9ydE1ldGFCYW5uZXIsIGRlZmluZTogaW1wb3J0TWV0YURlZmluZSB9ID1cbiAgICAgIHRoaXMuZ2V0Q2pzSW1wb3J0TWV0YVBvbHlmaWxsKGZvcm1hdCk7XG4gICAgY29uc3QgZXNtUmVxdWlyZUJhbm5lciA9IHNraXBFc21SZXF1aXJlQmFubmVyXG4gICAgICA/ICcnXG4gICAgICA6IHRoaXMuZ2V0RXNtUmVxdWlyZUJhbm5lcihmb3JtYXQpO1xuXG4gICAgY29uc3QgZXNidWlsZEN0eCA9IGF3YWl0IGVzYnVpbGQuY29udGV4dCh7XG4gICAgICBiYW5uZXI6IHtcbiAgICAgICAganM6IGAvLyBiaW9tZS1pZ25vcmUtYWxsIGxpbnQ6IGdlbmVyYXRlZCBmaWxlXFxuLyogZXNsaW50LWRpc2FibGUgKi9cXG4ke2ltcG9ydE1ldGFCYW5uZXJ9JHtlc21SZXF1aXJlQmFubmVyfWAsXG4gICAgICB9LFxuICAgICAgc3RkaW46IHtcbiAgICAgICAgY29udGVudHM6IGVudHJ5Q29udGVudCxcbiAgICAgICAgcmVzb2x2ZURpcjogdGhpcy5jb25maWcud29ya2luZ0RpcixcbiAgICAgICAgc291cmNlZmlsZTogJ3ZpcnR1YWwtZW50cnkuanMnLFxuICAgICAgICBsb2FkZXI6ICdqcycsXG4gICAgICB9LFxuICAgICAgb3V0ZmlsZSxcbiAgICAgIGFic1dvcmtpbmdEaXI6IHRoaXMuY29uZmlnLndvcmtpbmdEaXIsXG4gICAgICBidW5kbGU6IHRydWUsXG4gICAgICBmb3JtYXQsXG4gICAgICBwbGF0Zm9ybTogJ25vZGUnLFxuICAgICAgY29uZGl0aW9uczogWydub2RlJ10sXG4gICAgICB0YXJnZXQ6ICdlczIwMjInLFxuICAgICAgd3JpdGU6IHRydWUsXG4gICAgICB0cmVlU2hha2luZzogdHJ1ZSxcbiAgICAgIGtlZXBOYW1lczogdHJ1ZSxcbiAgICAgIG1pbmlmeTogZmFsc2UsXG4gICAgICBqc3g6ICdwcmVzZXJ2ZScsXG4gICAgICBsb2dMZXZlbDogJ2Vycm9yJyxcbiAgICAgIC8vIFVzZSB0c2NvbmZpZyBmb3IgcGF0aCBhbGlhcyByZXNvbHV0aW9uLlxuICAgICAgLy8gRm9yIHN5bWxpbmtlZCBjb25maWdzIHRoaXMgdXNlcyB0c2NvbmZpZ1JhdyB0byBwcmVzZXJ2ZSBjd2QtcmVsYXRpdmUgYWxpYXNlcy5cbiAgICAgIC4uLmVzYnVpbGRUc2NvbmZpZ09wdGlvbnMsXG4gICAgICBkZWZpbmU6IGltcG9ydE1ldGFEZWZpbmUsXG4gICAgICByZXNvbHZlRXh0ZW5zaW9uczogW1xuICAgICAgICAnLnRzJyxcbiAgICAgICAgJy50c3gnLFxuICAgICAgICAnLm10cycsXG4gICAgICAgICcuY3RzJyxcbiAgICAgICAgJy5qcycsXG4gICAgICAgICcuanN4JyxcbiAgICAgICAgJy5tanMnLFxuICAgICAgICAnLmNqcycsXG4gICAgICBdLFxuICAgICAgLy8gU291cmNlIG1hcHMgZm9yIGJldHRlciBzdGFjayB0cmFjZXMgaW4gc3RlcCBleGVjdXRpb24uIFN0ZXBzIGV4ZWN1dGVcbiAgICAgIC8vIGluIE5vZGUuanMgY29udGV4dCBhbmQgaW5saW5lIHNvdXJjZW1hcHMgZ2l2ZSBtZWFuaW5nZnVsIHN0YWNrIHRyYWNlc1xuICAgICAgLy8gd2l0aCBwcm9wZXIgZmlsZSBuYW1lcyBhbmQgbGluZSBudW1iZXJzIHdoZW4gZXJyb3JzIG9jY3VyIGluIGRlZXBseVxuICAgICAgLy8gbmVzdGVkIGZ1bmN0aW9uIGNhbGxzIGFjcm9zcyBtdWx0aXBsZSBmaWxlcy4gRGVmYXVsdHMgdG8gaW5saW5lIGluXG4gICAgICAvLyBkZXZlbG9wbWVudCBhbmQgb2ZmIGluIHByb2R1Y3Rpb24gKHNlZSBgZGVmYXVsdFNvdXJjZW1hcE1vZGVgKSB0byBrZWVwXG4gICAgICAvLyBwcm9kdWN0aW9uIGZ1bmN0aW9uIGJ1bmRsZXMgc21hbGw7IG92ZXJyaWRlIHdpdGggdGhlIGBzb3VyY2VtYXBgXG4gICAgICAvLyBjb25maWcgb3B0aW9uIG9yIHRoZSBgV09SS0ZMT1dfU09VUkNFTUFQYCBlbnYgdmFyLlxuICAgICAgc291cmNlbWFwOiB0aGlzLnJlc29sdmVTb3VyY2VtYXAodGhpcy5kZWZhdWx0U291cmNlbWFwTW9kZSksXG4gICAgICBwbHVnaW5zOiBbXG4gICAgICAgIC8vIEhhbmRsZSBwc2V1ZG8tcGFja2FnZXMgbGlrZSAnc2VydmVyLW9ubHknIGFuZCAnY2xpZW50LW9ubHknIGJ5IHByb3ZpZGluZ1xuICAgICAgICAvLyBlbXB0eSBtb2R1bGVzLiBNdXN0IHJ1biBmaXJzdCB0byBpbnRlcmNlcHQgdGhlc2UgYmVmb3JlIG90aGVyIHJlc29sdXRpb24uXG4gICAgICAgIGNyZWF0ZVBzZXVkb1BhY2thZ2VQbHVnaW4oKSxcbiAgICAgICAgY3JlYXRlU3djUGx1Z2luKHtcbiAgICAgICAgICBtb2RlOiAnc3RlcCcsXG4gICAgICAgICAgZW50cmllc1RvQnVuZGxlOiBub3JtYWxpemVkRW50cmllc1RvQnVuZGxlLFxuICAgICAgICAgIG91dGRpcjogb3V0ZmlsZSA/IGRpcm5hbWUob3V0ZmlsZSkgOiB1bmRlZmluZWQsXG4gICAgICAgICAgcHJvamVjdFJvb3Q6IHRoaXMudHJhbnNmb3JtUHJvamVjdFJvb3QsXG4gICAgICAgICAgbW9kdWxlU3BlY2lmaWVyUm9vdDogdGhpcy5tb2R1bGVTcGVjaWZpZXJSb290LFxuICAgICAgICAgIHdvcmtmbG93TWFuaWZlc3QsXG4gICAgICAgICAgYnVuZGxlVHJhbnNpdGl2ZUxvY2FsU3RlcERlcGVuZGVuY2llcyxcbiAgICAgICAgICByZXdyaXRlVHNFeHRlbnNpb25zLFxuICAgICAgICAgIHNpZGVFZmZlY3RFbnRyaWVzOiBub3JtYWxpemVkU2lkZUVmZmVjdEVudHJpZXMsXG4gICAgICAgIH0pLFxuICAgICAgXSxcbiAgICAgIC8vIFBsdWdpbiBzaG91bGQgY2F0Y2ggbW9zdCB0aGluZ3MsIGJ1dCB0aGlzIGxldHMgdXNlcnMgaGFyZCBvdmVycmlkZVxuICAgICAgLy8gaWYgdGhlIHBsdWdpbiBtaXNzZXMgYW55dGhpbmcgdGhhdCBzaG91bGQgYmUgZXh0ZXJuYWxpemVkXG4gICAgICBleHRlcm5hbDogWydidW4nLCAnYnVuOionLCAuLi4odGhpcy5jb25maWcuZXh0ZXJuYWxQYWNrYWdlcyB8fCBbXSldLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgc3RlcHNSZXN1bHQgPSBhd2FpdCBlc2J1aWxkQ3R4LnJlYnVpbGQoKTtcblxuICAgIHRoaXMubG9nRXNidWlsZE1lc3NhZ2VzKHN0ZXBzUmVzdWx0LCAnc3RlcHMgYnVuZGxlIGNyZWF0aW9uJyk7XG4gICAgdGhpcy5sb2dCYXNlQnVpbGRlckluZm8oXG4gICAgICAnQ3JlYXRlZCBzdGVwcyBidW5kbGUnLFxuICAgICAgYCR7RGF0ZS5ub3coKSAtIHN0ZXBzQnVuZGxlU3RhcnR9bXNgXG4gICAgKTtcblxuICAgIC8vIEhhbmRsZSB3b3JrZmxvdy1vbmx5IGZpbGVzIHRoYXQgbWF5IGhhdmUgYmVlbiB0cmVlLXNoYWtlbiBmcm9tIHRoZSBidW5kbGUuXG4gICAgLy8gVGhlc2UgZmlsZXMgaGF2ZSBubyBzdGVwcywgc28gZXNidWlsZCByZW1vdmVzIHRoZW0sIGJ1dCB3ZSBzdGlsbCBuZWVkIHRoZWlyXG4gICAgLy8gd29ya2Zsb3cgbWV0YWRhdGEgZm9yIHRoZSBtYW5pZmVzdC4gVHJhbnNmb3JtIHRoZW0gc2VwYXJhdGVseS5cbiAgICBjb25zdCB3b3JrZmxvd09ubHlGaWxlcyA9IHdvcmtmbG93RmlsZXMuZmlsdGVyKFxuICAgICAgKGYpID0+ICFzdGVwRmlsZXMuaW5jbHVkZXMoZilcbiAgICApO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgd29ya2Zsb3dPbmx5RmlsZXMubWFwKGFzeW5jICh3b3JrZmxvd0ZpbGUpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBmaWxlTWFuaWZlc3QgPSBhd2FpdCB0aGlzLmdldENhY2hlZE1hbmlmZXN0VHJhbnNmb3JtKFxuICAgICAgICAgICAgd29ya2Zsb3dGaWxlLFxuICAgICAgICAgICAgJ3dvcmtmbG93J1xuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKGZpbGVNYW5pZmVzdC53b3JrZmxvd3MpIHtcbiAgICAgICAgICAgIHdvcmtmbG93TWFuaWZlc3Qud29ya2Zsb3dzID0gT2JqZWN0LmFzc2lnbihcbiAgICAgICAgICAgICAgd29ya2Zsb3dNYW5pZmVzdC53b3JrZmxvd3MgfHwge30sXG4gICAgICAgICAgICAgIGZpbGVNYW5pZmVzdC53b3JrZmxvd3NcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChmaWxlTWFuaWZlc3QuY2xhc3Nlcykge1xuICAgICAgICAgICAgd29ya2Zsb3dNYW5pZmVzdC5jbGFzc2VzID0gT2JqZWN0LmFzc2lnbihcbiAgICAgICAgICAgICAgd29ya2Zsb3dNYW5pZmVzdC5jbGFzc2VzIHx8IHt9LFxuICAgICAgICAgICAgICBmaWxlTWFuaWZlc3QuY2xhc3Nlc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgLy8gTG9nIHdhcm5pbmcgYnV0IGNvbnRpbnVlIC0gZG9uJ3QgZmFpbCBidWlsZCBmb3Igd29ya2Zsb3ctb25seSBmaWxlIGlzc3Vlc1xuICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgIGBXYXJuaW5nOiBGYWlsZWQgdG8gZXh0cmFjdCB3b3JrZmxvdyBtZXRhZGF0YSBmcm9tICR7d29ya2Zsb3dGaWxlfTpgLFxuICAgICAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgYXdhaXQgdGhpcy5lbnN1cmVTd2NJZ25vcmVkKCk7XG5cbiAgICBpZiAodGhpcy5jb25maWcud2F0Y2gpIHtcbiAgICAgIHJldHVybiB7IGNvbnRleHQ6IGVzYnVpbGRDdHgsIG1hbmlmZXN0OiB3b3JrZmxvd01hbmlmZXN0IH07XG4gICAgfVxuICAgIGF3YWl0IGVzYnVpbGRDdHguZGlzcG9zZSgpO1xuICAgIHJldHVybiB7IGNvbnRleHQ6IHVuZGVmaW5lZCwgbWFuaWZlc3Q6IHdvcmtmbG93TWFuaWZlc3QgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgYnVuZGxlIGZvciB3b3JrZmxvdyBvcmNoZXN0cmF0aW9uIGZ1bmN0aW9ucy5cbiAgICogV29ya2Zsb3dzIHJ1biBpbiBhIHNhbmRib3hlZCBWTSBhbmQgY29vcmRpbmF0ZSBzdGVwIGV4ZWN1dGlvbi5cbiAgICpcbiAgICogQHBhcmFtIGJ1bmRsZUZpbmFsT3V0cHV0IC0gSWYgZmFsc2UsIHNraXBzIHRoZSBmaW5hbCBidW5kbGluZyBzdGVwICh1c2VkIGJ5IE5leHQuanMpXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlV29ya2Zsb3dzQnVuZGxlKHtcbiAgICBpbnB1dEZpbGVzLFxuICAgIGZvcm1hdCA9ICdlc20nLFxuICAgIG91dGZpbGUsXG4gICAgYnVuZGxlRmluYWxPdXRwdXQgPSB0cnVlLFxuICAgIGtlZXBJbnRlcmltQnVuZGxlQ29udGV4dCA9IHRoaXMuY29uZmlnLndhdGNoLFxuICAgIHRzY29uZmlnUGF0aCxcbiAgICBkaXNjb3ZlcmVkRW50cmllcyxcbiAgfToge1xuICAgIHRzY29uZmlnUGF0aD86IHN0cmluZztcbiAgICBpbnB1dEZpbGVzOiBzdHJpbmdbXTtcbiAgICBvdXRmaWxlOiBzdHJpbmc7XG4gICAgZm9ybWF0PzogJ2NqcycgfCAnZXNtJztcbiAgICBidW5kbGVGaW5hbE91dHB1dD86IGJvb2xlYW47XG4gICAga2VlcEludGVyaW1CdW5kbGVDb250ZXh0PzogYm9vbGVhbjtcbiAgICBkaXNjb3ZlcmVkRW50cmllcz86IERpc2NvdmVyZWRFbnRyaWVzO1xuICB9KTogUHJvbWlzZTx7XG4gICAgbWFuaWZlc3Q6IFdvcmtmbG93TWFuaWZlc3Q7XG4gICAgaW50ZXJpbUJ1bmRsZUN0eD86IGVzYnVpbGQuQnVpbGRDb250ZXh0O1xuICAgIGJ1bmRsZUZpbmFsPzogKGludGVyaW1CdW5kbGVSZXN1bHQ6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPjtcbiAgICAvKiogVGhlIHJhdyB3b3JrZmxvdyBWTSBjb2RlIChiZWZvcmUgd3JhcHBpbmcgd2l0aCBlbnRyeXBvaW50KSAqL1xuICAgIGludGVyaW1CdW5kbGVUZXh0Pzogc3RyaW5nO1xuICB9PiB7XG4gICAgY29uc3QgZGlzY292ZXJlZCA9XG4gICAgICBkaXNjb3ZlcmVkRW50cmllcyA/P1xuICAgICAgKGF3YWl0IHRoaXMuZGlzY292ZXJFbnRyaWVzKGlucHV0RmlsZXMsIGRpcm5hbWUob3V0ZmlsZSksIHRzY29uZmlnUGF0aCkpO1xuICAgIGNvbnN0IHdvcmtmbG93RmlsZXMgPSBbLi4uZGlzY292ZXJlZC5kaXNjb3ZlcmVkV29ya2Zsb3dzXS5zb3J0KCk7XG4gICAgY29uc3Qgc2VyZGVGaWxlcyA9IFsuLi5kaXNjb3ZlcmVkLmRpc2NvdmVyZWRTZXJkZUZpbGVzXS5zb3J0KCk7XG5cbiAgICAvLyBJbmNsdWRlIHNlcmRlIGZpbGVzIHRoYXQgYXJlbid0IGFscmVhZHkgd29ya2Zsb3cgZmlsZXMgZm9yIGNyb3NzLWNvbnRleHQgY2xhc3MgcmVnaXN0cmF0aW9uLlxuICAgIC8vIENsYXNzZXMgbmVlZCB0byBiZSByZWdpc3RlcmVkIGluIHRoZSB3b3JrZmxvdyBidW5kbGUgc28gdGhleSBjYW4gYmUgZGVzZXJpYWxpemVkXG4gICAgLy8gd2hlbiByZWNlaXZpbmcgZGF0YSBmcm9tIHN0ZXBzIG9yIHdoZW4gc2VyaWFsaXppbmcgZGF0YSB0byBzZW5kIHRvIHN0ZXBzLlxuICAgIGNvbnN0IHdvcmtmbG93RmlsZXNTZXQgPSBuZXcgU2V0KHdvcmtmbG93RmlsZXMpO1xuICAgIGNvbnN0IHNlcmRlT25seUZpbGVzID0gc2VyZGVGaWxlcy5maWx0ZXIoKGYpID0+ICF3b3JrZmxvd0ZpbGVzU2V0LmhhcyhmKSk7XG5cbiAgICAvLyBsb2cgdGhlIHdvcmtmbG93IGZpbGVzIGZvciBkZWJ1Z2dpbmdcbiAgICBhd2FpdCB0aGlzLndyaXRlRGVidWdGaWxlKG91dGZpbGUsIHsgd29ya2Zsb3dGaWxlcywgc2VyZGVPbmx5RmlsZXMgfSk7XG5cbiAgICAvLyBIZWxwZXIgdG8gY3JlYXRlIGltcG9ydCBzdGF0ZW1lbnQgZnJvbSBmaWxlIHBhdGhcbiAgICAvLyBGb3IgcGFja2FnZXMsIHVzZXMgdGhlIHBhY2thZ2UgbmFtZSBzbyBlc2J1aWxkIHdpbGwgcmVzb2x2ZSB0aHJvdWdoXG4gICAgLy8gcGFja2FnZS5qc29uIGV4cG9ydHMgd2l0aCBjb25kaXRpb25zOiBbJ3dvcmtmbG93J11cbiAgICBjb25zdCBjcmVhdGVJbXBvcnQgPSAoZmlsZTogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCB7IGltcG9ydFBhdGgsIGlzUGFja2FnZSB9ID0gZ2V0SW1wb3J0UGF0aChcbiAgICAgICAgZmlsZSxcbiAgICAgICAgdGhpcy5jb25maWcud29ya2luZ0RpclxuICAgICAgKTtcblxuICAgICAgaWYgKGlzUGFja2FnZSkge1xuICAgICAgICAvLyBVc2UgcGFja2FnZSBuYW1lIC0gZXNidWlsZCB3aWxsIHJlc29sdmUgdmlhIHBhY2thZ2UuanNvbiBleHBvcnRzXG4gICAgICAgIC8vIGFuZCBhcHBseSB0aGUgJ3dvcmtmbG93JyBjb25kaXRpb25cbiAgICAgICAgcmV0dXJuIGBpbXBvcnQgJyR7aW1wb3J0UGF0aH0nO2A7XG4gICAgICB9XG5cbiAgICAgIC8vIExvY2FsIGFwcCBmaWxlIC0gdXNlIHJlbGF0aXZlIHBhdGhcbiAgICAgIC8vIE5vcm1hbGl6ZSBib3RoIHBhdGhzIHRvIGZvcndhcmQgc2xhc2hlcyBiZWZvcmUgY2FsbGluZyByZWxhdGl2ZSgpXG4gICAgICAvLyBUaGlzIGlzIGNyaXRpY2FsIG9uIFdpbmRvd3Mgd2hlcmUgcmVsYXRpdmUoKSBjYW4gcHJvZHVjZSB1bmV4cGVjdGVkIHJlc3VsdHMgd2l0aCBtaXhlZCBwYXRoIGZvcm1hdHNcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRXb3JraW5nRGlyID0gdGhpcy5jb25maWcud29ya2luZ0Rpci5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gICAgICBjb25zdCBub3JtYWxpemVkRmlsZSA9IGZpbGUucmVwbGFjZSgvXFxcXC9nLCAnLycpO1xuICAgICAgLy8gQ2FsY3VsYXRlIHJlbGF0aXZlIHBhdGggZnJvbSB3b3JraW5nIGRpcmVjdG9yeSB0byB0aGUgZmlsZVxuICAgICAgbGV0IHJlbGF0aXZlUGF0aCA9IHJlbGF0aXZlKG5vcm1hbGl6ZWRXb3JraW5nRGlyLCBub3JtYWxpemVkRmlsZSkucmVwbGFjZShcbiAgICAgICAgL1xcXFwvZyxcbiAgICAgICAgJy8nXG4gICAgICApO1xuICAgICAgLy8gRW5zdXJlIHJlbGF0aXZlIHBhdGhzIHN0YXJ0IHdpdGggLi8gc28gZXNidWlsZCByZXNvbHZlcyB0aGVtIGNvcnJlY3RseS5cbiAgICAgIC8vIFBhdGhzIGxpa2UgXCIub3V0cHV0Ly4uLlwiIGFyZSBub3QgdmFsaWQgcmVsYXRpdmUgc3BlY2lmaWVycyBhbmQgbXVzdFxuICAgICAgLy8gYmVjb21lIFwiLi8ub3V0cHV0Ly4uLlwiLlxuICAgICAgaWYgKCFyZWxhdGl2ZVBhdGguc3RhcnRzV2l0aCgnLi8nKSAmJiAhcmVsYXRpdmVQYXRoLnN0YXJ0c1dpdGgoJy4uLycpKSB7XG4gICAgICAgIHJlbGF0aXZlUGF0aCA9IGAuLyR7cmVsYXRpdmVQYXRofWA7XG4gICAgICB9XG4gICAgICByZXR1cm4gYGltcG9ydCAnJHtyZWxhdGl2ZVBhdGh9JztgO1xuICAgIH07XG5cbiAgICAvLyBDcmVhdGUgYSB2aXJ0dWFsIGVudHJ5IHRoYXQgaW1wb3J0cyBhbGwgd29ya2Zsb3cgZmlsZXMuIERlZHVwZSBieVxuICAgIC8vIGNhbm9uaWNhbCBtb2R1bGUgaWRlbnRpdHkgc28gc291cmNlL2Rpc3QgY29waWVzIG9mIHRoZSBzYW1lIHdvcmtzcGFjZVxuICAgIC8vIHBhY2thZ2UgZXhwb3J0IGRvbid0IGJvdGggZ2V0IGltcG9ydGVkICh3aGljaCB3b3VsZCBtYWtlIHRoZSBzd2NcbiAgICAvLyBwbHVnaW4gZ2VuZXJhdGUgZHVwbGljYXRlIHdvcmtmbG93IElEcykuXG4gICAgY29uc3QgZW1pdHRlZEltcG9ydElkZW50aXRpZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBjb25zdCBidWlsZEltcG9ydHMgPSAoZmlsZXM6IHN0cmluZ1tdKTogc3RyaW5nID0+XG4gICAgICBmaWxlc1xuICAgICAgICAuZmlsdGVyKChmaWxlKSA9PiB7XG4gICAgICAgICAgY29uc3QgaWRlbnRpdHkgPSBtb2R1bGVJZGVudGl0eUtleShmaWxlLCB0aGlzLm1vZHVsZVNwZWNpZmllclJvb3QpO1xuICAgICAgICAgIGlmIChlbWl0dGVkSW1wb3J0SWRlbnRpdGllcy5oYXMoaWRlbnRpdHkpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgZW1pdHRlZEltcG9ydElkZW50aXRpZXMuYWRkKGlkZW50aXR5KTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSlcbiAgICAgICAgLm1hcChjcmVhdGVJbXBvcnQpXG4gICAgICAgIC5qb2luKCdcXG4nKTtcblxuICAgIC8vIFRoZSBTV0MgcGx1Z2luIGluIHdvcmtmbG93IG1vZGUgZW1pdHMgYGdsb2JhbFRoaXMuX19wcml2YXRlX3dvcmtmbG93cy5zZXQod29ya2Zsb3dJZCwgZm4pYFxuICAgIC8vIGNhbGxzIGRpcmVjdGx5LCBzbyB3ZSBqdXN0IG5lZWQgdG8gaW1wb3J0IHRoZSBmaWxlcyAoTWFwIGlzIGluaXRpYWxpemVkIHZpYSBiYW5uZXIpXG4gICAgY29uc3Qgd29ya2Zsb3dJbXBvcnRzID0gYnVpbGRJbXBvcnRzKHdvcmtmbG93RmlsZXMpO1xuXG4gICAgLy8gSW5jbHVkZSBzZXJkZS1vbmx5IGZpbGVzIGZvciBjbGFzcyByZWdpc3RyYXRpb24gc2lkZSBlZmZlY3RzXG4gICAgY29uc3Qgc2VyZGVJbXBvcnRzID0gYnVpbGRJbXBvcnRzKHNlcmRlT25seUZpbGVzKTtcblxuICAgIGNvbnN0IGltcG9ydHMgPSBzZXJkZUltcG9ydHNcbiAgICAgID8gYCR7d29ya2Zsb3dJbXBvcnRzfVxcbi8vIFNlcmRlIGZpbGVzIGZvciBjcm9zcy1jb250ZXh0IGNsYXNzIHJlZ2lzdHJhdGlvblxcbiR7c2VyZGVJbXBvcnRzfWBcbiAgICAgIDogd29ya2Zsb3dJbXBvcnRzO1xuXG4gICAgY29uc3QgYnVuZGxlU3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCB3b3JrZmxvd01hbmlmZXN0OiBXb3JrZmxvd01hbmlmZXN0ID0ge307XG4gICAgY29uc3QgZXNidWlsZFRzY29uZmlnT3B0aW9ucyA9XG4gICAgICBhd2FpdCBnZXRFc2J1aWxkVHNjb25maWdPcHRpb25zKHRzY29uZmlnUGF0aCk7XG4gICAgY29uc3Qgbm9ybWFsaXplZFdvcmtmbG93U2lkZUVmZmVjdEVudHJpZXMgPSBhd2FpdCB3aXRoUmVhbHBhdGhzKFtcbiAgICAgIC4uLndvcmtmbG93RmlsZXMsXG4gICAgICAuLi5zZXJkZU9ubHlGaWxlcyxcbiAgICBdKTtcblxuICAgIC8vIEJ1bmRsZSB3aXRoIGVzYnVpbGQgYW5kIG91ciBjdXN0b20gU1dDIHBsdWdpbiBpbiB3b3JrZmxvdyBtb2RlLlxuICAgIC8vIHRoaXMgYnVuZGxlIHdpbGwgYmUgcnVuIGluc2lkZSBhIHZtIGlzb2xhdGVcbiAgICBjb25zdCBpbnRlcmltQnVuZGxlQ3R4ID0gYXdhaXQgZXNidWlsZC5jb250ZXh0KHtcbiAgICAgIHN0ZGluOiB7XG4gICAgICAgIGNvbnRlbnRzOiBpbXBvcnRzLFxuICAgICAgICByZXNvbHZlRGlyOiB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgICBzb3VyY2VmaWxlOiAndmlydHVhbC1lbnRyeS5qcycsXG4gICAgICAgIGxvYWRlcjogJ2pzJyxcbiAgICAgIH0sXG4gICAgICBidW5kbGU6IHRydWUsXG4gICAgICBhYnNXb3JraW5nRGlyOiB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgZm9ybWF0OiAnY2pzJywgLy8gUnVucyBpbnNpZGUgdGhlIFZNIHdoaWNoIGV4cGVjdHMgY2pzXG4gICAgICBwbGF0Zm9ybTogJ25ldXRyYWwnLCAvLyBUaGUgcGxhdGZvcm0gaXMgbmVpdGhlciBub2RlIG5vciBicm93c2VyXG4gICAgICBtYWluRmllbGRzOiBbJ21vZHVsZScsICdtYWluJ10sIC8vIFRvIHN1cHBvcnQgbnBtIHN0eWxlIGltcG9ydHNcbiAgICAgIGNvbmRpdGlvbnM6IFsnd29ya2Zsb3cnXSwgLy8gQWxsb3cgcGFja2FnZXMgdG8gZXhwb3J0ICd3b3JrZmxvdycgY29tcGxpYW50IHZlcnNpb25zXG4gICAgICB0YXJnZXQ6ICdlczIwMjInLFxuICAgICAgd3JpdGU6IGZhbHNlLFxuICAgICAgdHJlZVNoYWtpbmc6IHRydWUsXG4gICAgICBrZWVwTmFtZXM6IHRydWUsXG4gICAgICBtaW5pZnk6IGZhbHNlLFxuICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgd29ya2Zsb3cgcmVnaXN0cnkgYXQgdGhlIHZlcnkgdG9wIG9mIHRoZSBidW5kbGVcbiAgICAgIC8vIFRoaXMgbXVzdCBiZSBpbiBiYW5uZXIgKG5vdCB0aGUgdmlydHVhbCBlbnRyeSkgYmVjYXVzZSBlc2J1aWxkJ3MgYnVuZGxpbmdcbiAgICAgIC8vIGNhbiByZW9yZGVyIGNvZGUsIGFuZCB0aGUgLnNldCgpIGNhbGxzIG5lZWQgdGhlIE1hcCB0byBleGlzdCBmaXJzdFxuICAgICAgYmFubmVyOiB7XG4gICAgICAgIGpzOiAnZ2xvYmFsVGhpcy5fX3ByaXZhdGVfd29ya2Zsb3dzID0gbmV3IE1hcCgpOycsXG4gICAgICB9LFxuICAgICAgLy8gU291cmNlIG1hcHMgZm9yIGJldHRlciBzdGFjayB0cmFjZXMgaW4gd29ya2Zsb3cgVk0gZXhlY3V0aW9uLiBUaGlzXG4gICAgICAvLyBpbnRlcm1lZGlhdGUgYnVuZGxlIGlzIGV4ZWN1dGVkIHZpYSBydW5JbkNvbnRleHQoKSBpbiBhIFZNLCBzbyBpbmxpbmVcbiAgICAgIC8vIHNvdXJjZSBtYXBzIGdpdmUgbWVhbmluZ2Z1bCBzdGFjayB0cmFjZXMgaW5zdGVhZCBvZlxuICAgICAgLy8gXCJldmFsbWFjaGluZS48YW5vbnltb3VzPlwiLiBEZWZhdWx0cyB0byBpbmxpbmUgaW4gZGV2ZWxvcG1lbnQgYW5kIG9mZiBpblxuICAgICAgLy8gcHJvZHVjdGlvbiAoc2VlIGBkZWZhdWx0U291cmNlbWFwTW9kZWApIHRvIGtlZXAgcHJvZHVjdGlvbiBmdW5jdGlvblxuICAgICAgLy8gYnVuZGxlcyBzbWFsbDsgb3ZlcnJpZGUgd2l0aCB0aGUgYHNvdXJjZW1hcGAgY29uZmlnIG9wdGlvbiBvciB0aGVcbiAgICAgIC8vIGBXT1JLRkxPV19TT1VSQ0VNQVBgIGVudiB2YXIuIFRoZSBydW50aW1lIHJlbWFwcyBzdGFja3Mgb25seSB3aGVuIGFcbiAgICAgIC8vIG1hcCBpcyBwcmVzZW50LCBzbyBkaXNhYmxpbmcgbWFwcyBkZWdyYWRlcyBncmFjZWZ1bGx5LlxuICAgICAgc291cmNlbWFwOiB0aGlzLnJlc29sdmVTb3VyY2VtYXAodGhpcy5kZWZhdWx0U291cmNlbWFwTW9kZSksXG4gICAgICAvLyBVc2UgdHNjb25maWcgZm9yIHBhdGggYWxpYXMgcmVzb2x1dGlvbi5cbiAgICAgIC8vIEZvciBzeW1saW5rZWQgY29uZmlncyB0aGlzIHVzZXMgdHNjb25maWdSYXcgdG8gcHJlc2VydmUgY3dkLXJlbGF0aXZlIGFsaWFzZXMuXG4gICAgICAuLi5lc2J1aWxkVHNjb25maWdPcHRpb25zLFxuICAgICAgcmVzb2x2ZUV4dGVuc2lvbnM6IFtcbiAgICAgICAgJy50cycsXG4gICAgICAgICcudHN4JyxcbiAgICAgICAgJy5tdHMnLFxuICAgICAgICAnLmN0cycsXG4gICAgICAgICcuanMnLFxuICAgICAgICAnLmpzeCcsXG4gICAgICAgICcubWpzJyxcbiAgICAgICAgJy5janMnLFxuICAgICAgXSxcbiAgICAgIHBsdWdpbnM6IFtcbiAgICAgICAgLy8gSGFuZGxlIHBzZXVkby1wYWNrYWdlcyBsaWtlICdzZXJ2ZXItb25seScgYW5kICdjbGllbnQtb25seScgYnkgcHJvdmlkaW5nXG4gICAgICAgIC8vIGVtcHR5IG1vZHVsZXMuIE11c3QgcnVuIGZpcnN0IHRvIGludGVyY2VwdCB0aGVzZSBiZWZvcmUgb3RoZXIgcmVzb2x1dGlvbi5cbiAgICAgICAgY3JlYXRlUHNldWRvUGFja2FnZVBsdWdpbigpLFxuICAgICAgICBjcmVhdGVTd2NQbHVnaW4oe1xuICAgICAgICAgIG1vZGU6ICd3b3JrZmxvdycsXG4gICAgICAgICAgcHJvamVjdFJvb3Q6IHRoaXMudHJhbnNmb3JtUHJvamVjdFJvb3QsXG4gICAgICAgICAgbW9kdWxlU3BlY2lmaWVyUm9vdDogdGhpcy5tb2R1bGVTcGVjaWZpZXJSb290LFxuICAgICAgICAgIHdvcmtmbG93TWFuaWZlc3QsXG4gICAgICAgICAgc2lkZUVmZmVjdEVudHJpZXM6IG5vcm1hbGl6ZWRXb3JrZmxvd1NpZGVFZmZlY3RFbnRyaWVzLFxuICAgICAgICB9KSxcbiAgICAgICAgLy8gVGhpcyBwbHVnaW4gbXVzdCBydW4gYWZ0ZXIgdGhlIHN3YyBwbHVnaW4gdG8gZW5zdXJlIGRlYWQgY29kZSBlbGltaW5hdGlvblxuICAgICAgICAvLyBoYXBwZW5zIGZpcnN0LCBwcmV2ZW50aW5nIGZhbHNlIHBvc2l0aXZlcyBvbiBOb2RlLmpzIGltcG9ydHMgaW4gdW51c2VkIGNvZGUgcGF0aHNcbiAgICAgICAgY3JlYXRlTm9kZU1vZHVsZUVycm9yUGx1Z2luKCksXG4gICAgICBdLFxuICAgICAgLy8gTk9URTogV2UgaW50ZW50aW9uYWxseSBkbyBOT1QgdXNlIHRoZSBleHRlcm5hbCBvcHRpb24gaGVyZSBmb3Igd29ya2Zsb3cgYnVuZGxlcy5cbiAgICAgIC8vIFdoZW4gcGFja2FnZXMgYXJlIG1hcmtlZCBleHRlcm5hbCB3aXRoIGZvcm1hdDogJ2NqcycsIGVzYnVpbGQgZ2VuZXJhdGVzIHJlcXVpcmUoKSBjYWxscy5cbiAgICAgIC8vIEhvd2V2ZXIsIHRoZSB3b3JrZmxvdyBWTSAodm0ucnVuSW5Db250ZXh0KSBkb2VzIG5vdCBoYXZlIHJlcXVpcmUoKSBkZWZpbmVkIC0gaXQgb25seVxuICAgICAgLy8gcHJvdmlkZXMgbW9kdWxlLmV4cG9ydHMgYW5kIGV4cG9ydHMuIEV4dGVybmFsIHBhY2thZ2VzIHdvdWxkIGZhaWwgYXQgcnVudGltZSB3aXRoOlxuICAgICAgLy8gICBSZWZlcmVuY2VFcnJvcjogcmVxdWlyZSBpcyBub3QgZGVmaW5lZFxuICAgICAgLy8gSW5zdGVhZCwgd2UgYnVuZGxlIGV2ZXJ5dGhpbmcgYW5kIHJlbHkgb246XG4gICAgICAvLyAtIGNyZWF0ZVBzZXVkb1BhY2thZ2VQbHVnaW4oKSB0byBoYW5kbGUgc2VydmVyLW9ubHkvY2xpZW50LW9ubHkgd2l0aCBlbXB0eSBtb2R1bGVzXG4gICAgICAvLyAtIGNyZWF0ZU5vZGVNb2R1bGVFcnJvclBsdWdpbigpIHRvIGNhdGNoIE5vZGUuanMgYnVpbHRpbiBpbXBvcnRzIGF0IGJ1aWxkIHRpbWVcbiAgICB9KTtcbiAgICBsZXQgc2hvdWxkRGlzcG9zZUludGVyaW1CdW5kbGVDdHggPSAha2VlcEludGVyaW1CdW5kbGVDb250ZXh0O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBpbnRlcmltQnVuZGxlID0gYXdhaXQgaW50ZXJpbUJ1bmRsZUN0eC5yZWJ1aWxkKCk7XG5cbiAgICAgIHRoaXMubG9nRXNidWlsZE1lc3NhZ2VzKFxuICAgICAgICBpbnRlcmltQnVuZGxlLFxuICAgICAgICAnaW50ZXJtZWRpYXRlIHdvcmtmbG93IGJ1bmRsZScsXG4gICAgICAgIHRydWUsXG4gICAgICAgIHtcbiAgICAgICAgICBzdXBwcmVzc1dhcm5pbmdzOiB0aGlzLmNvbmZpZy5zdXBwcmVzc0NyZWF0ZVdvcmtmbG93c0J1bmRsZVdhcm5pbmdzLFxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgdGhpcy5sb2dDcmVhdGVXb3JrZmxvd3NCdW5kbGVJbmZvKFxuICAgICAgICAnQ3JlYXRlZCBpbnRlcm1lZGlhdGUgd29ya2Zsb3cgYnVuZGxlJyxcbiAgICAgICAgYCR7RGF0ZS5ub3coKSAtIGJ1bmRsZVN0YXJ0VGltZX1tc2BcbiAgICAgICk7XG5cbiAgICAgIGlmICh0aGlzLmNvbmZpZy53b3JrZmxvd01hbmlmZXN0UGF0aCkge1xuICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPSByZXNvbHZlKFxuICAgICAgICAgIHByb2Nlc3MuY3dkKCksXG4gICAgICAgICAgdGhpcy5jb25maWcud29ya2Zsb3dNYW5pZmVzdFBhdGhcbiAgICAgICAgKTtcbiAgICAgICAgbGV0IHByZWZpeCA9ICcnO1xuXG4gICAgICAgIGlmIChyZXNvbHZlZFBhdGguZW5kc1dpdGgoJy5janMnKSkge1xuICAgICAgICAgIHByZWZpeCA9ICdtb2R1bGUuZXhwb3J0cyA9ICc7XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgcmVzb2x2ZWRQYXRoLmVuZHNXaXRoKCcuanMnKSB8fFxuICAgICAgICAgIHJlc29sdmVkUGF0aC5lbmRzV2l0aCgnLm1qcycpXG4gICAgICAgICkge1xuICAgICAgICAgIHByZWZpeCA9ICdleHBvcnQgZGVmYXVsdCAnO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgbWtkaXIoZGlybmFtZShyZXNvbHZlZFBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgYXdhaXQgd3JpdGVGaWxlKFxuICAgICAgICAgIHJlc29sdmVkUGF0aCxcbiAgICAgICAgICBwcmVmaXggKyBKU09OLnN0cmluZ2lmeSh3b3JrZmxvd01hbmlmZXN0LCBudWxsLCAyKVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCB0aGlzLmVuc3VyZVN3Y0lnbm9yZWQoKTtcblxuICAgICAgaWYgKFxuICAgICAgICAhaW50ZXJpbUJ1bmRsZS5vdXRwdXRGaWxlcyB8fFxuICAgICAgICBpbnRlcmltQnVuZGxlLm91dHB1dEZpbGVzLmxlbmd0aCA9PT0gMFxuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBXb3JrZmxvd0J1aWxkRXJyb3IoJ05vIG91dHB1dCBmaWxlcyBnZW5lcmF0ZWQgZnJvbSBlc2J1aWxkJywge1xuICAgICAgICAgIGhpbnQ6ICdUaGlzIHVzdWFsbHkgaW5kaWNhdGVzIGEgbWlzY29uZmlndXJlZCBlbnRyeSBwb2ludCBvciBhbiBlbXB0eSB3b3JrZmxvdyBkaXJlY3RvcnkuIENoZWNrIHRoYXQgeW91ciB3b3JrZmxvdyBmaWxlcyBjb250YWluIGEgYFwidXNlIHdvcmtmbG93XCJgIG9yIGBcInVzZSBzdGVwXCJgIGRpcmVjdGl2ZS4nLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gU2VyZGUgY29tcGxpYW5jZSB3YXJuaW5nczogY2hlY2sgaWYgd29ya2Zsb3cgYnVuZGxlIGhhcyBOb2RlLmpzIGltcG9ydHNcbiAgICAgIC8vIGFsb25nc2lkZSBzZXJkZS1yZWdpc3RlcmVkIGNsYXNzZXMgKHRoZXNlIHdpbGwgZmFpbCBhdCBydW50aW1lIGluIHRoZSBzYW5kYm94KVxuICAgICAgaWYgKFxuICAgICAgICB3b3JrZmxvd01hbmlmZXN0LmNsYXNzZXMgJiZcbiAgICAgICAgT2JqZWN0LmtleXMod29ya2Zsb3dNYW5pZmVzdC5jbGFzc2VzKS5sZW5ndGggPiAwXG4gICAgICApIHtcbiAgICAgICAgY29uc3QgeyBhbmFseXplU2VyZGVDb21wbGlhbmNlIH0gPSBhd2FpdCBpbXBvcnQoJy4vc2VyZGUtY2hlY2tlci5qcycpO1xuICAgICAgICBjb25zdCBidW5kbGVUZXh0ID0gaW50ZXJpbUJ1bmRsZS5vdXRwdXRGaWxlc1swXS50ZXh0O1xuICAgICAgICBjb25zdCBzZXJkZVJlc3VsdCA9IGFuYWx5emVTZXJkZUNvbXBsaWFuY2Uoe1xuICAgICAgICAgIHNvdXJjZUNvZGU6ICcnLFxuICAgICAgICAgIHdvcmtmbG93Q29kZTogYnVuZGxlVGV4dCxcbiAgICAgICAgICBtYW5pZmVzdDogd29ya2Zsb3dNYW5pZmVzdCxcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIERlLWR1cGUgd2FybmluZ3M6IGdyb3VwIGlkZW50aWNhbCBpc3N1ZXMgYWNyb3NzIGNsYXNzZXNcbiAgICAgICAgY29uc3QgaXNzdWVzVG9DbGFzc2VzID0gbmV3IE1hcDxzdHJpbmcsIFNldDxzdHJpbmc+PigpO1xuICAgICAgICBmb3IgKGNvbnN0IGNscyBvZiBzZXJkZVJlc3VsdC5jbGFzc2VzKSB7XG4gICAgICAgICAgaWYgKCFjbHMuY29tcGxpYW50KSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGlzc3VlIG9mIGNscy5pc3N1ZXMpIHtcbiAgICAgICAgICAgICAgbGV0IGFmZmVjdGVkQ2xhc3NlcyA9IGlzc3Vlc1RvQ2xhc3Nlcy5nZXQoaXNzdWUpO1xuICAgICAgICAgICAgICBpZiAoIWFmZmVjdGVkQ2xhc3Nlcykge1xuICAgICAgICAgICAgICAgIGFmZmVjdGVkQ2xhc3NlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgICAgICAgICAgIGlzc3Vlc1RvQ2xhc3Nlcy5zZXQoaXNzdWUsIGFmZmVjdGVkQ2xhc3Nlcyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgYWZmZWN0ZWRDbGFzc2VzLmFkZChjbHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBbaXNzdWUsIGFmZmVjdGVkQ2xhc3Nlc10gb2YgaXNzdWVzVG9DbGFzc2VzKSB7XG4gICAgICAgICAgY29uc3QgY2xhc3NOYW1lcyA9IFsuLi5hZmZlY3RlZENsYXNzZXNdO1xuICAgICAgICAgIGNvbnN0IGNsYXNzTGFiZWwgPVxuICAgICAgICAgICAgY2xhc3NOYW1lcy5sZW5ndGggPT09IDFcbiAgICAgICAgICAgICAgPyBgY2xhc3MgXCIke2NsYXNzTmFtZXNbMF19XCJgXG4gICAgICAgICAgICAgIDogYGNsYXNzZXMgJHtjbGFzc05hbWVzLm1hcCgobmFtZSkgPT4gYFwiJHtuYW1lfVwiYCkuam9pbignLCAnKX1gO1xuICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgIGNoYWxrLnllbGxvdyhg4pqgIFNlcmRlIHdhcm5pbmcgZm9yICR7Y2xhc3NMYWJlbH06IGApICsgaXNzdWVcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHdvcmtmbG93RW50cnlwb2ludE9wdGlvbnNDb2RlID0gY3JlYXRlV29ya2Zsb3dFbnRyeXBvaW50T3B0aW9uc0NvZGUoXG4gICAgICAgIHtcbiAgICAgICAgICBiYXNlUGF0aDogdGhpcy5jb25maWcuYmFzZVBhdGgsXG4gICAgICAgICAgcm91dGVNb2R1bGVCb2R5U3RhcnRlZEF0OiAnd29ya2Zsb3dSb3V0ZU1vZHVsZUJvZHlTdGFydGVkQXQnLFxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICBjb25zdCBidW5kbGVGaW5hbCA9IGFzeW5jIChpbnRlcmltQnVuZGxlOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3Qgd29ya2Zsb3dCdW5kbGVDb2RlID0gaW50ZXJpbUJ1bmRsZTtcblxuICAgICAgICBjb25zdCB3b3JrZmxvd0Z1bmN0aW9uQ29kZSA9IGAvLyBiaW9tZS1pZ25vcmUtYWxsIGxpbnQ6IGdlbmVyYXRlZCBmaWxlXG4vKiBlc2xpbnQtZGlzYWJsZSAqL1xuaW1wb3J0IHsgd29ya2Zsb3dFbnRyeXBvaW50IH0gZnJvbSAnd29ya2Zsb3cvcnVudGltZSc7XG5cbmNvbnN0IHdvcmtmbG93Um91dGVNb2R1bGVCb2R5U3RhcnRlZEF0ID0gRGF0ZS5ub3coKTtcbmNvbnN0IHdvcmtmbG93Q29kZSA9IFxcYCR7d29ya2Zsb3dCdW5kbGVDb2RlLnJlcGxhY2UoL1tcXFxcYCRdL2csICdcXFxcJCYnKX1cXGA7XG5cbiR7Y3JlYXRlV29ya2Zsb3dSb3V0ZUhhbmRsZXJzQ29kZShgd29ya2Zsb3dFbnRyeXBvaW50KHdvcmtmbG93Q29kZSR7d29ya2Zsb3dFbnRyeXBvaW50T3B0aW9uc0NvZGV9KWApfWA7XG5cbiAgICAgICAgLy8gd2Ugc2tpcCB0aGUgZmluYWwgYnVuZGxpbmcgc3RlcCBmb3IgTmV4dC5qcyBzbyBpdCBjYW4gYnVuZGxlIGl0c2VsZlxuICAgICAgICBpZiAoIWJ1bmRsZUZpbmFsT3V0cHV0KSB7XG4gICAgICAgICAgaWYgKCFvdXRmaWxlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFyaWFudDogbWlzc2luZyBvdXRmaWxlIGZvciB3b3JrZmxvdyBidW5kbGVgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gRW5zdXJlIHRoZSBvdXRwdXQgZGlyZWN0b3J5IGV4aXN0c1xuICAgICAgICAgIGNvbnN0IG91dHB1dERpciA9IGRpcm5hbWUob3V0ZmlsZSk7XG4gICAgICAgICAgYXdhaXQgbWtkaXIob3V0cHV0RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICAgICAgICAgIGF3YWl0IHRoaXMud3JpdGVHZW5lcmF0ZWRGaWxlKG91dGZpbGUsIHdvcmtmbG93RnVuY3Rpb25Db2RlKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBidW5kbGVTdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIC8vIE5vdyBidW5kbGUgdGhpcyBzbyB3ZSBjYW4gcmVzb2x2ZSB0aGUgQHdvcmtmbG93L2NvcmUgZGVwZW5kZW5jeVxuICAgICAgICAvLyB3ZSBjb3VsZCByZW1vdmUgdGhpcyBpZiB3ZSBkbyBuZnQgdHJhY2luZyBvciBzaW1pbGFyIGluc3RlYWRcbiAgICAgICAgY29uc3QgZmluYWxFc21SZXF1aXJlQmFubmVyID0gdGhpcy5nZXRFc21SZXF1aXJlQmFubmVyKGZvcm1hdCk7XG4gICAgICAgIGNvbnN0IGZpbmFsV29ya2Zsb3dSZXN1bHQgPSBhd2FpdCBlc2J1aWxkLmJ1aWxkKHtcbiAgICAgICAgICBiYW5uZXI6IHtcbiAgICAgICAgICAgIGpzOiBgLy8gYmlvbWUtaWdub3JlLWFsbCBsaW50OiBnZW5lcmF0ZWQgZmlsZVxcbi8qIGVzbGludC1kaXNhYmxlICovXFxuJHtmaW5hbEVzbVJlcXVpcmVCYW5uZXJ9YCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHN0ZGluOiB7XG4gICAgICAgICAgICBjb250ZW50czogd29ya2Zsb3dGdW5jdGlvbkNvZGUsXG4gICAgICAgICAgICByZXNvbHZlRGlyOiB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgICAgICAgc291cmNlZmlsZTogJ3ZpcnR1YWwtZW50cnkuanMnLFxuICAgICAgICAgICAgbG9hZGVyOiAnanMnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgb3V0ZmlsZSxcbiAgICAgICAgICAvLyBTb3VyY2UgbWFwcyBmb3IgdGhlIGZpbmFsIHdvcmtmbG93IGJ1bmRsZSB3cmFwcGVyIChub3QgaW1wb3J0YW50IHNpbmNlIHRoaXMgY29kZVxuICAgICAgICAgIC8vIGRvZXNuJ3QgcnVuIGluIHRoZSBWTSAtIG9ubHkgdGhlIGludGVybWVkaWF0ZSBidW5kbGUgc291cmNlbWFwIGlzIHJlbGV2YW50KVxuICAgICAgICAgIHNvdXJjZW1hcDogdGhpcy5yZXNvbHZlU291cmNlbWFwKEVNSVRfU09VUkNFTUFQU19GT1JfREVCVUdHSU5HKSxcbiAgICAgICAgICBhYnNXb3JraW5nRGlyOiB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgICAgIGJ1bmRsZTogdHJ1ZSxcbiAgICAgICAgICBmb3JtYXQsXG4gICAgICAgICAgcGxhdGZvcm06ICdub2RlJyxcbiAgICAgICAgICB0YXJnZXQ6ICdlczIwMjInLFxuICAgICAgICAgIHdyaXRlOiB0cnVlLFxuICAgICAgICAgIGtlZXBOYW1lczogdHJ1ZSxcbiAgICAgICAgICBtaW5pZnk6IGZhbHNlLFxuICAgICAgICAgIGV4dGVybmFsOiBbJ0Bhd3Mtc2RrL2NyZWRlbnRpYWwtcHJvdmlkZXItd2ViLWlkZW50aXR5J10sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMubG9nRXNidWlsZE1lc3NhZ2VzKFxuICAgICAgICAgIGZpbmFsV29ya2Zsb3dSZXN1bHQsXG4gICAgICAgICAgJ2ZpbmFsIHdvcmtmbG93IGJ1bmRsZScsXG4gICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBzdXBwcmVzc1dhcm5pbmdzOiB0aGlzLmNvbmZpZy5zdXBwcmVzc0NyZWF0ZVdvcmtmbG93c0J1bmRsZVdhcm5pbmdzLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5sb2dDcmVhdGVXb3JrZmxvd3NCdW5kbGVJbmZvKFxuICAgICAgICAgICdDcmVhdGVkIGZpbmFsIHdvcmtmbG93IGJ1bmRsZScsXG4gICAgICAgICAgYCR7RGF0ZS5ub3coKSAtIGJ1bmRsZVN0YXJ0VGltZX1tc2BcbiAgICAgICAgKTtcbiAgICAgIH07XG4gICAgICBjb25zdCBpbnRlcmltQnVuZGxlVGV4dCA9IGludGVyaW1CdW5kbGUub3V0cHV0RmlsZXNbMF0udGV4dDtcbiAgICAgIGF3YWl0IGJ1bmRsZUZpbmFsKGludGVyaW1CdW5kbGVUZXh0KTtcblxuICAgICAgaWYgKGtlZXBJbnRlcmltQnVuZGxlQ29udGV4dCkge1xuICAgICAgICBzaG91bGREaXNwb3NlSW50ZXJpbUJ1bmRsZUN0eCA9IGZhbHNlO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG1hbmlmZXN0OiB3b3JrZmxvd01hbmlmZXN0LFxuICAgICAgICAgIGludGVyaW1CdW5kbGVDdHgsXG4gICAgICAgICAgYnVuZGxlRmluYWwsXG4gICAgICAgICAgaW50ZXJpbUJ1bmRsZVRleHQsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4geyBtYW5pZmVzdDogd29ya2Zsb3dNYW5pZmVzdCwgaW50ZXJpbUJ1bmRsZVRleHQgfTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgc2hvdWxkRGlzcG9zZUludGVyaW1CdW5kbGVDdHggPSB0cnVlO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmIChzaG91bGREaXNwb3NlSW50ZXJpbUJ1bmRsZUN0eCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGludGVyaW1CdW5kbGVDdHguZGlzcG9zZSgpO1xuICAgICAgICB9IGNhdGNoIChkaXNwb3NlRXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAnV2FybmluZzogRmFpbGVkIHRvIGRpc3Bvc2Ugd29ya2Zsb3cgYnVuZGxlIGNvbnRleHQnLFxuICAgICAgICAgICAgZGlzcG9zZUVycm9yXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBWMjogQ3JlYXRlcyBhIGNvbWJpbmVkIGJ1bmRsZSB0aGF0IGluY2x1ZGVzIGJvdGggc3RlcCByZWdpc3RyYXRpb25zIGFuZFxuICAgKiB3b3JrZmxvdyBvcmNoZXN0cmF0aW9uIGluIGEgc2luZ2xlIHJvdXRlLiBUaGUgY29tYmluZWQgZW50cnlwb2ludCBleGVjdXRlc1xuICAgKiBzdGVwcyBpbmxpbmUgd2hlbiBwb3NzaWJsZSwgcmVkdWNpbmcgZnVuY3Rpb24gaW52b2NhdGlvbnMgYW5kIHF1ZXVlIG92ZXJoZWFkLlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCByZXVzZXMgY3JlYXRlU3RlcHNCdW5kbGUgKGZvciBzdGVwIHJlZ2lzdHJhdGlvbnMpIGFuZFxuICAgKiBjcmVhdGVXb3JrZmxvd3NCdW5kbGUgKGZvciB3b3JrZmxvdyBWTSBjb2RlKSwgdGhlbiBjb21iaW5lcyB0aGVtIGludG9cbiAgICogYSBzaW5nbGUgcm91dGUgZmlsZSB1c2luZyB3b3JrZmxvd0VudHJ5cG9pbnQoKS5cbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBjcmVhdGVDb21iaW5lZEJ1bmRsZSh7XG4gICAgaW5wdXRGaWxlcyxcbiAgICBzdGVwc091dGZpbGUsXG4gICAgZmxvd091dGZpbGUsXG4gICAgZm9ybWF0ID0gJ2VzbScsXG4gICAgYnVuZGxlRmluYWxPdXRwdXQgPSB0cnVlLFxuICAgIHRzY29uZmlnUGF0aCxcbiAgICBleHRlcm5hbGl6ZU5vblN0ZXBzLFxuICAgIGJ1bmRsZVRyYW5zaXRpdmVMb2NhbFN0ZXBEZXBlbmRlbmNpZXMsXG4gICAgc291cmNlU3RlcFJlZ2lzdHJhdGlvbkltcG9ydHMsXG4gICAgZGlzY292ZXJlZEVudHJpZXMsXG4gIH06IHtcbiAgICBpbnB1dEZpbGVzOiBzdHJpbmdbXTtcbiAgICAvKiogT3V0cHV0IHBhdGggZm9yIHRoZSBzdGVwIHJlZ2lzdHJhdGlvbnMgYnVuZGxlIChzaWRlIGVmZmVjdHMgb25seSkgKi9cbiAgICBzdGVwc091dGZpbGU6IHN0cmluZztcbiAgICAvKiogT3V0cHV0IHBhdGggZm9yIHRoZSBjb21iaW5lZCByb3V0ZSBmaWxlICovXG4gICAgZmxvd091dGZpbGU6IHN0cmluZztcbiAgICBmb3JtYXQ/OiAnY2pzJyB8ICdlc20nO1xuICAgIGJ1bmRsZUZpbmFsT3V0cHV0PzogYm9vbGVhbjtcbiAgICB0c2NvbmZpZ1BhdGg/OiBzdHJpbmc7XG4gICAgZXh0ZXJuYWxpemVOb25TdGVwcz86IGJvb2xlYW47XG4gICAgYnVuZGxlVHJhbnNpdGl2ZUxvY2FsU3RlcERlcGVuZGVuY2llcz86IGJvb2xlYW47XG4gICAgc291cmNlU3RlcFJlZ2lzdHJhdGlvbkltcG9ydHM/OiBib29sZWFuO1xuICAgIGRpc2NvdmVyZWRFbnRyaWVzPzogRGlzY292ZXJlZEVudHJpZXM7XG4gIH0pOiBQcm9taXNlPHtcbiAgICBtYW5pZmVzdDogV29ya2Zsb3dNYW5pZmVzdDtcbiAgICBzdGVwc0NvbnRleHQ/OiBlc2J1aWxkLkJ1aWxkQ29udGV4dDtcbiAgICBpbnRlcmltQnVuZGxlQ3R4PzogZXNidWlsZC5CdWlsZENvbnRleHQ7XG4gICAgYnVuZGxlRmluYWw/OiAoaW50ZXJpbUJ1bmRsZVJlc3VsdDogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+O1xuICAgIGRpc2NvdmVyZWRFbnRyaWVzOiBEaXNjb3ZlcmVkRW50cmllcztcbiAgICBzdGVwc01hbmlmZXN0OiBXb3JrZmxvd01hbmlmZXN0O1xuICAgIHdvcmtmbG93c01hbmlmZXN0OiBXb3JrZmxvd01hbmlmZXN0O1xuICB9PiB7XG4gICAgdGhpcy5zdGFydFdvcmtmbG93QnVpbGRUaW1lcigpO1xuICAgIGNvbnN0IGVmZmVjdGl2ZURpc2NvdmVyZWRFbnRyaWVzID1cbiAgICAgIGRpc2NvdmVyZWRFbnRyaWVzID8/XG4gICAgICAoYXdhaXQgdGhpcy5kaXNjb3ZlckVudHJpZXMoXG4gICAgICAgIGlucHV0RmlsZXMsXG4gICAgICAgIGRpcm5hbWUoZmxvd091dGZpbGUpLFxuICAgICAgICB0c2NvbmZpZ1BhdGhcbiAgICAgICkpO1xuXG4gICAgLy8gMS4gQnVpbGQgc3RlcCByZWdpc3RyYXRpb25zIGJ1bmRsZSAodXNlZCBhcyBzZXBhcmF0ZSBmaWxlIGZvclxuICAgIC8vIGJ1bmRsZUZpbmFsT3V0cHV0OiBmYWxzZSwgb3IgcmVhZCBiYWNrIGZvciBpbmxpbmUgY29udGVudCB3aGVuIHRydWUpXG4gICAgY29uc3QgeyBjb250ZXh0OiBzdGVwc0NvbnRleHQsIG1hbmlmZXN0OiBzdGVwc01hbmlmZXN0IH0gPVxuICAgICAgYXdhaXQgdGhpcy5jcmVhdGVTdGVwc0J1bmRsZSh7XG4gICAgICAgIGlucHV0RmlsZXMsXG4gICAgICAgIG91dGZpbGU6IHN0ZXBzT3V0ZmlsZSxcbiAgICAgICAgLy8gV2hlbiBidW5kbGVGaW5hbE91dHB1dCBpcyB0cnVlLCB1c2UgRVNNIGZvciB0aGUgc3RlcHMgYnVuZGxlXG4gICAgICAgIC8vIHJlZ2FyZGxlc3Mgb2YgdGhlIGZpbmFsIG91dHB1dCBmb3JtYXQuIFRoZSBmaW5hbCBlc2J1aWxkIHBhc3NcbiAgICAgICAgLy8gY29udmVydHMgZXZlcnl0aGluZyB0byB0aGUgdGFyZ2V0IGZvcm1hdC4gVXNpbmcgQ0pTIGhlcmUgY2F1c2VzXG4gICAgICAgIC8vIGEgbW9kdWxlLmV4cG9ydHMgY29sbGlzaW9uOiB0aGUgc3RlcHMgYnVuZGxlJ3MgdG9wLWxldmVsXG4gICAgICAgIC8vIG1vZHVsZS5leHBvcnRzIG92ZXJ3cml0ZXMgdGhlIGNvbWJpbmVkIHJvdXRlJ3MgbW9kdWxlLmV4cG9ydHNcbiAgICAgICAgLy8gd2hlbiBlc2J1aWxkIGlubGluZXMgdGhlIHN0ZXBzIHdpdGhvdXQgYSBfX2NvbW1vbkpTIHdyYXBwZXIuXG4gICAgICAgIGZvcm1hdDogYnVuZGxlRmluYWxPdXRwdXQgPyAnZXNtJyA6IGZvcm1hdCxcbiAgICAgICAgZXh0ZXJuYWxpemVOb25TdGVwcyxcbiAgICAgICAgYnVuZGxlVHJhbnNpdGl2ZUxvY2FsU3RlcERlcGVuZGVuY2llcyxcbiAgICAgICAgc291cmNlU3RlcFJlZ2lzdHJhdGlvbkltcG9ydHMsXG4gICAgICAgIHRzY29uZmlnUGF0aCxcbiAgICAgICAgZGlzY292ZXJlZEVudHJpZXM6IGVmZmVjdGl2ZURpc2NvdmVyZWRFbnRyaWVzLFxuICAgICAgICAvLyBTa2lwIHRoZSBjcmVhdGVSZXF1aXJlIGJhbm5lciBoZXJlIOKAlCB3aGVuIGJ1bmRsZUZpbmFsT3V0cHV0IGlzIHRydWVcbiAgICAgICAgLy8gdGhlIG91dGVyIGVzYnVpbGQgcGFzcyB3aWxsIGlubGluZSB0aGlzIGJ1bmRsZSBhbmQgYWRkIGl0cyBvd25cbiAgICAgICAgLy8gYmFubmVyLiBFbWl0dGluZyBpdCB0d2ljZSBkZWNsYXJlcyBfX2NyZWF0ZVJlcXVpcmUgdHdpY2UuXG4gICAgICAgIHNraXBFc21SZXF1aXJlQmFubmVyOiBidW5kbGVGaW5hbE91dHB1dCxcbiAgICAgIH0pO1xuXG4gICAgLy8gMi4gQnVpbGQgd29ya2Zsb3cgVk0gY29kZVxuICAgIGNvbnN0IHRlbXBXb3JrZmxvd091dGZpbGUgPSBgJHtmbG93T3V0ZmlsZX0uX193Zl90bXAuanNgO1xuICAgIGNvbnN0IHdvcmtmbG93c1Jlc3VsdCA9IGF3YWl0IHRoaXMuY3JlYXRlV29ya2Zsb3dzQnVuZGxlKHtcbiAgICAgIGlucHV0RmlsZXMsXG4gICAgICBvdXRmaWxlOiB0ZW1wV29ya2Zsb3dPdXRmaWxlLFxuICAgICAgZm9ybWF0LFxuICAgICAgYnVuZGxlRmluYWxPdXRwdXQ6IGZhbHNlLFxuICAgICAgdHNjb25maWdQYXRoLFxuICAgICAgZGlzY292ZXJlZEVudHJpZXM6IGVmZmVjdGl2ZURpc2NvdmVyZWRFbnRyaWVzLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgd29ya2Zsb3dWTUNvZGUgPSB3b3JrZmxvd3NSZXN1bHQuaW50ZXJpbUJ1bmRsZVRleHQ7XG4gICAgaWYgKCF3b3JrZmxvd1ZNQ29kZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjcmVhdGVXb3JrZmxvd3NCdW5kbGUgZGlkIG5vdCByZXR1cm4gaW50ZXJpbUJ1bmRsZVRleHQnKTtcbiAgICB9XG5cbiAgICAvLyBDbGVhbiB1cCB0aGUgd3JhcHBlciBmaWxlXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgdW5saW5rIH0gPSBhd2FpdCBpbXBvcnQoJ25vZGU6ZnMvcHJvbWlzZXMnKTtcbiAgICAgIGF3YWl0IHVubGluayh0ZW1wV29ya2Zsb3dPdXRmaWxlKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIElnbm9yZSBjbGVhbnVwIGVycm9yc1xuICAgIH1cblxuICAgIC8vIDMuIEdlbmVyYXRlIGNvbWJpbmVkIHJvdXRlIGZpbGVcbiAgICBjb25zdCBzdGVwc1JlbGF0aXZlUGF0aCA9IGAuLyR7YmFzZW5hbWUoc3RlcHNPdXRmaWxlKS5yZXBsYWNlKC9cXFxcL2csICcvJyl9YDtcbiAgICBjb25zdCBlc2NhcGVkVk1Db2RlID0gd29ya2Zsb3dWTUNvZGUucmVwbGFjZSgvW1xcXFxgJF0vZywgJ1xcXFwkJicpO1xuICAgIGNvbnN0IHdvcmtmbG93RW50cnlwb2ludE9wdGlvbnNDb2RlID0gY3JlYXRlV29ya2Zsb3dFbnRyeXBvaW50T3B0aW9uc0NvZGUoe1xuICAgICAgYmFzZVBhdGg6IHRoaXMuY29uZmlnLmJhc2VQYXRoLFxuICAgICAgcm91dGVNb2R1bGVCb2R5U3RhcnRlZEF0OiAnd29ya2Zsb3dSb3V0ZU1vZHVsZUJvZHlTdGFydGVkQXQnLFxuICAgIH0pO1xuXG4gICAgY29uc3QgY29tYmluZWRGdW5jdGlvbkNvZGUgPSBgLy8gYmlvbWUtaWdub3JlLWFsbCBsaW50OiBnZW5lcmF0ZWQgZmlsZVxuLyogZXNsaW50LWRpc2FibGUgKi9cbmltcG9ydCB7IF9fc3RlcHNfcmVnaXN0ZXJlZCB9IGZyb20gJyR7c3RlcHNSZWxhdGl2ZVBhdGh9JztcbmltcG9ydCB7IHdvcmtmbG93RW50cnlwb2ludCB9IGZyb20gJ3dvcmtmbG93L3J1bnRpbWUnO1xuXG5jb25zdCB3b3JrZmxvd1JvdXRlTW9kdWxlQm9keVN0YXJ0ZWRBdCA9IERhdGUubm93KCk7XG5cbi8vIFByZXZlbnQgcm9sbHVwIGZyb20gdHJlZS1zaGFraW5nIHRoZSBzdGVwcyBzaWRlLWVmZmVjdCBpbXBvcnRcbnZvaWQgX19zdGVwc19yZWdpc3RlcmVkO1xuXG5jb25zdCB3b3JrZmxvd0NvZGUgPSBcXGAke2VzY2FwZWRWTUNvZGV9XFxgO1xuXG4ke2NyZWF0ZVdvcmtmbG93Um91dGVIYW5kbGVyc0NvZGUoYHdvcmtmbG93RW50cnlwb2ludCh3b3JrZmxvd0NvZGUke3dvcmtmbG93RW50cnlwb2ludE9wdGlvbnNDb2RlfSlgKX1gO1xuXG4gICAgaWYgKCFidW5kbGVGaW5hbE91dHB1dCkge1xuICAgICAgYXdhaXQgdGhpcy53cml0ZUdlbmVyYXRlZEZpbGUoZmxvd091dGZpbGUsIGNvbWJpbmVkRnVuY3Rpb25Db2RlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQnVuZGxlIHRoZSBjb21iaW5lZCBjb2RlIGZvciBzdGFuZGFsb25lIHVzZVxuICAgICAgY29uc3QgYnVuZGxlU3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgIGNvbnN0IHsgYmFubmVyOiBpbXBvcnRNZXRhQmFubmVyLCBkZWZpbmU6IGltcG9ydE1ldGFEZWZpbmUgfSA9XG4gICAgICAgIHRoaXMuZ2V0Q2pzSW1wb3J0TWV0YVBvbHlmaWxsKGZvcm1hdCk7XG4gICAgICAvLyBFU00gYmFubmVyIHByb3ZpZGVzIGByZXF1aXJlYCB2aWEgY3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwpIHNvXG4gICAgICAvLyBDSlMgZGVwZW5kZW5jaWVzIHRoYXQgY2FsbCByZXF1aXJlKCkgZm9yIE5vZGUuanMgYnVpbHRpbnMga2VlcCB3b3JraW5nXG4gICAgICAvLyBpbiB0aGUgRVNNIG91dHB1dCBwcm9kdWNlZCBieSBidW5kbGVGaW5hbE91dHB1dDogdHJ1ZS5cbiAgICAgIGNvbnN0IGZpbmFsRXNtUmVxdWlyZUJhbm5lciA9IHRoaXMuZ2V0RXNtUmVxdWlyZUJhbm5lcihmb3JtYXQpO1xuICAgICAgY29uc3QgZmluYWxSZXN1bHQgPSBhd2FpdCBlc2J1aWxkLmJ1aWxkKHtcbiAgICAgICAgYmFubmVyOiB7XG4gICAgICAgICAganM6IGAvLyBiaW9tZS1pZ25vcmUtYWxsIGxpbnQ6IGdlbmVyYXRlZCBmaWxlXFxuLyogZXNsaW50LWRpc2FibGUgKi9cXG4ke2ltcG9ydE1ldGFCYW5uZXJ9JHtmaW5hbEVzbVJlcXVpcmVCYW5uZXJ9YCxcbiAgICAgICAgfSxcbiAgICAgICAgc3RkaW46IHtcbiAgICAgICAgICBjb250ZW50czogY29tYmluZWRGdW5jdGlvbkNvZGUsXG4gICAgICAgICAgcmVzb2x2ZURpcjogZGlybmFtZShmbG93T3V0ZmlsZSksXG4gICAgICAgICAgc291cmNlZmlsZTogJ3ZpcnR1YWwtZW50cnkuanMnLFxuICAgICAgICAgIGxvYWRlcjogJ2pzJyxcbiAgICAgICAgfSxcbiAgICAgICAgb3V0ZmlsZTogZmxvd091dGZpbGUsXG4gICAgICAgIGFic1dvcmtpbmdEaXI6IHRoaXMuY29uZmlnLndvcmtpbmdEaXIsXG4gICAgICAgIGJ1bmRsZTogdHJ1ZSxcbiAgICAgICAgZm9ybWF0LFxuICAgICAgICBwbGF0Zm9ybTogJ25vZGUnLFxuICAgICAgICB0YXJnZXQ6ICdlczIwMjInLFxuICAgICAgICB3cml0ZTogdHJ1ZSxcbiAgICAgICAga2VlcE5hbWVzOiB0cnVlLFxuICAgICAgICBtaW5pZnk6IGZhbHNlLFxuICAgICAgICBkZWZpbmU6IGltcG9ydE1ldGFEZWZpbmUsXG4gICAgICAgIGV4dGVybmFsOiBbJ0Bhd3Mtc2RrL2NyZWRlbnRpYWwtcHJvdmlkZXItd2ViLWlkZW50aXR5J10sXG4gICAgICB9KTtcbiAgICAgIHRoaXMubG9nRXNidWlsZE1lc3NhZ2VzKGZpbmFsUmVzdWx0LCAnY29tYmluZWQgYnVuZGxlJywgdHJ1ZSk7XG4gICAgICB0aGlzLmxvZ0Jhc2VCdWlsZGVySW5mbyhcbiAgICAgICAgJ0NyZWF0ZWQgY29tYmluZWQgYnVuZGxlJyxcbiAgICAgICAgYCR7RGF0ZS5ub3coKSAtIGJ1bmRsZVN0YXJ0VGltZX1tc2BcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gTWVyZ2UgbWFuaWZlc3RzXG4gICAgY29uc3QgbWFuaWZlc3Q6IFdvcmtmbG93TWFuaWZlc3QgPSB7XG4gICAgICAuLi5zdGVwc01hbmlmZXN0LFxuICAgICAgd29ya2Zsb3dzOiB7XG4gICAgICAgIC4uLnN0ZXBzTWFuaWZlc3Qud29ya2Zsb3dzLFxuICAgICAgICAuLi53b3JrZmxvd3NSZXN1bHQubWFuaWZlc3Qud29ya2Zsb3dzLFxuICAgICAgfSxcbiAgICAgIGNsYXNzZXM6IHtcbiAgICAgICAgLi4uc3RlcHNNYW5pZmVzdC5jbGFzc2VzLFxuICAgICAgICAuLi53b3JrZmxvd3NSZXN1bHQubWFuaWZlc3QuY2xhc3NlcyxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIC8vIENyZWF0ZSBhIGN1c3RvbSBidW5kbGVGaW5hbCBmb3Igd2F0Y2ggbW9kZSB0aGF0IHVzZXMgd29ya2Zsb3dFbnRyeXBvaW50XG4gICAgY29uc3QgY29tYmluZWRCdW5kbGVGaW5hbCA9IGFzeW5jIChpbnRlcmltQnVuZGxlVGV4dDogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCBlc2NhcGVkID0gaW50ZXJpbUJ1bmRsZVRleHQucmVwbGFjZSgvW1xcXFxgJF0vZywgJ1xcXFwkJicpO1xuICAgICAgY29uc3Qgd29ya2Zsb3dFbnRyeXBvaW50T3B0aW9uc0NvZGUgPSBjcmVhdGVXb3JrZmxvd0VudHJ5cG9pbnRPcHRpb25zQ29kZShcbiAgICAgICAge1xuICAgICAgICAgIGJhc2VQYXRoOiB0aGlzLmNvbmZpZy5iYXNlUGF0aCxcbiAgICAgICAgICByb3V0ZU1vZHVsZUJvZHlTdGFydGVkQXQ6ICd3b3JrZmxvd1JvdXRlTW9kdWxlQm9keVN0YXJ0ZWRBdCcsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgICBjb25zdCBjb2RlID0gYC8vIGJpb21lLWlnbm9yZS1hbGwgbGludDogZ2VuZXJhdGVkIGZpbGVcbi8qIGVzbGludC1kaXNhYmxlICovXG5pbXBvcnQgeyBfX3N0ZXBzX3JlZ2lzdGVyZWQgfSBmcm9tICcke3N0ZXBzUmVsYXRpdmVQYXRofSc7XG5pbXBvcnQgeyB3b3JrZmxvd0VudHJ5cG9pbnQgfSBmcm9tICd3b3JrZmxvdy9ydW50aW1lJztcblxuY29uc3Qgd29ya2Zsb3dSb3V0ZU1vZHVsZUJvZHlTdGFydGVkQXQgPSBEYXRlLm5vdygpO1xuXG52b2lkIF9fc3RlcHNfcmVnaXN0ZXJlZDtcblxuY29uc3Qgd29ya2Zsb3dDb2RlID0gXFxgJHtlc2NhcGVkfVxcYDtcblxuJHtjcmVhdGVXb3JrZmxvd1JvdXRlSGFuZGxlcnNDb2RlKGB3b3JrZmxvd0VudHJ5cG9pbnQod29ya2Zsb3dDb2RlJHt3b3JrZmxvd0VudHJ5cG9pbnRPcHRpb25zQ29kZX0pYCl9YDtcblxuICAgICAgY29uc3Qgb3V0cHV0RGlyID0gZGlybmFtZShmbG93T3V0ZmlsZSk7XG4gICAgICBhd2FpdCBta2RpcihvdXRwdXREaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgYXdhaXQgdGhpcy53cml0ZUdlbmVyYXRlZEZpbGUoZmxvd091dGZpbGUsIGNvZGUpO1xuICAgIH07XG5cbiAgICBpZiAodGhpcy5jb25maWcud2F0Y2gpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG1hbmlmZXN0LFxuICAgICAgICBzdGVwc0NvbnRleHQsXG4gICAgICAgIGludGVyaW1CdW5kbGVDdHg6IHdvcmtmbG93c1Jlc3VsdC5pbnRlcmltQnVuZGxlQ3R4LFxuICAgICAgICBidW5kbGVGaW5hbDogY29tYmluZWRCdW5kbGVGaW5hbCxcbiAgICAgICAgZGlzY292ZXJlZEVudHJpZXM6IGVmZmVjdGl2ZURpc2NvdmVyZWRFbnRyaWVzLFxuICAgICAgICBzdGVwc01hbmlmZXN0LFxuICAgICAgICB3b3JrZmxvd3NNYW5pZmVzdDogd29ya2Zsb3dzUmVzdWx0Lm1hbmlmZXN0LFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgbWFuaWZlc3QsXG4gICAgICBkaXNjb3ZlcmVkRW50cmllczogZWZmZWN0aXZlRGlzY292ZXJlZEVudHJpZXMsXG4gICAgICBzdGVwc01hbmlmZXN0LFxuICAgICAgd29ya2Zsb3dzTWFuaWZlc3Q6IHdvcmtmbG93c1Jlc3VsdC5tYW5pZmVzdCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBjbGllbnQgbGlicmFyeSBidW5kbGUgZm9yIHdvcmtmbG93IGV4ZWN1dGlvbi5cbiAgICogVGhlIGNsaWVudCBsaWJyYXJ5IGFsbG93cyBpbXBvcnRpbmcgYW5kIGNhbGxpbmcgd29ya2Zsb3dzIGZyb20gYXBwbGljYXRpb24gY29kZS5cbiAgICogT25seSBnZW5lcmF0ZWQgaWYgY2xpZW50QnVuZGxlUGF0aCBpcyBzcGVjaWZpZWQgaW4gY29uZmlnLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGNyZWF0ZUNsaWVudExpYnJhcnkoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5jbGllbnRCdW5kbGVQYXRoKSB7XG4gICAgICAvLyBTaWxlbnRseSBleGl0IHNpbmNlIG5vIGNsaWVudCBidW5kbGUgd2FzIHJlcXVlc3RlZFxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMubG9nQmFzZUJ1aWxkZXJJbmZvKFxuICAgICAgJ0dlbmVyYXRpbmcgYSBjbGllbnQgbGlicmFyeSBhdCcsXG4gICAgICB0aGlzLmNvbmZpZy5jbGllbnRCdW5kbGVQYXRoXG4gICAgKTtcbiAgICB0aGlzLmxvZ0Jhc2VCdWlsZGVySW5mbyhcbiAgICAgICdOT1RFOiBUaGUgcmVjb21tZW5kZWQgd2F5IHRvIHVzZSB3b3JrZmxvdyB3aXRoIGEgZnJhbWV3b3JrIGxpa2UgTmV4dEpTIGlzIHVzaW5nIHRoZSBsb2FkZXIvcGx1Z2luIHdpdGggd2VicGFjay90dXJib2JwYWNrL3JvbGx1cCdcbiAgICApO1xuXG4gICAgLy8gRW5zdXJlIHdlIGhhdmUgdGhlIGRpcmVjdG9yeSBmb3IgdGhlIGNsaWVudCBidW5kbGVcbiAgICBjb25zdCBvdXRwdXREaXIgPSBkaXJuYW1lKHRoaXMuY29uZmlnLmNsaWVudEJ1bmRsZVBhdGgpO1xuICAgIGF3YWl0IG1rZGlyKG91dHB1dERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgICBjb25zdCBpbnB1dEZpbGVzID0gYXdhaXQgdGhpcy5nZXRJbnB1dEZpbGVzKCk7XG5cbiAgICAvLyBEaXNjb3ZlciBzZXJkZSBmaWxlcyBmcm9tIHRoZSBpbnB1dCBmaWxlcycgZGVwZW5kZW5jeSB0cmVlIGZvciBjcm9zcy1jb250ZXh0IGNsYXNzIHJlZ2lzdHJhdGlvbi5cbiAgICAvLyBDbGFzc2VzIG5lZWQgdG8gYmUgcmVnaXN0ZXJlZCBpbiB0aGUgY2xpZW50IGJ1bmRsZSBzbyB0aGV5IGNhbiBiZSBzZXJpYWxpemVkXG4gICAgLy8gd2hlbiBwYXNzaW5nIGRhdGEgdG8gd29ya2Zsb3dzIHZpYSBzdGFydCgpIGFuZCBkZXNlcmlhbGl6ZWQgd2hlbiByZWNlaXZpbmcgd29ya2Zsb3cgcmVzdWx0cy5cbiAgICBjb25zdCB7IGRpc2NvdmVyZWRTZXJkZUZpbGVzIH0gPSBhd2FpdCB0aGlzLmRpc2NvdmVyRW50cmllcyhcbiAgICAgIGlucHV0RmlsZXMsXG4gICAgICBvdXRwdXREaXJcbiAgICApO1xuXG4gICAgLy8gSWRlbnRpZnkgc2VyZGUgZmlsZXMgdGhhdCBhcmVuJ3QgaW4gdGhlIGlucHV0RmlsZXMgKGRlZHVwbGljYXRlZClcbiAgICBjb25zdCBpbnB1dEZpbGVzTm9ybWFsaXplZCA9IG5ldyBTZXQoXG4gICAgICBpbnB1dEZpbGVzLm1hcCgoZikgPT4gZi5yZXBsYWNlKC9cXFxcL2csICcvJykpXG4gICAgKTtcbiAgICBjb25zdCBzZXJkZU9ubHlGaWxlcyA9IFsuLi5kaXNjb3ZlcmVkU2VyZGVGaWxlc10uZmlsdGVyKFxuICAgICAgKGYpID0+ICFpbnB1dEZpbGVzTm9ybWFsaXplZC5oYXMoZilcbiAgICApO1xuXG4gICAgLy8gUmUtZXhwb3J0cyBmb3IgaW5wdXQgZmlsZXMgKHVzZXIncyB3b3JrZmxvdy9zdGVwIGRlZmluaXRpb25zKS5cbiAgICAvLyBUaGVzZSBtdXN0IHVzZSB2YWxpZCByZWxhdGl2ZSBzcGVjaWZpZXJzIGJlY2F1c2Ugc29tZSBmcmFtZXdvcmtzIHBhc3NcbiAgICAvLyBnZW5lcmF0ZWQgZmlsZXMgbGlrZSBcIi5vdXRwdXQvc2VydmVyL2luZGV4Lm1qc1wiIGFzIGlucHV0IGZpbGVzLlxuICAgIGNvbnN0IHJlZXhwb3J0cyA9IGlucHV0RmlsZXNcbiAgICAgIC5tYXAoKGZpbGUpID0+IHtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFdvcmtpbmdEaXIgPSB0aGlzLmNvbmZpZy53b3JraW5nRGlyLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgICAgbGV0IHJlbGF0aXZlUGF0aCA9IHJlbGF0aXZlKG5vcm1hbGl6ZWRXb3JraW5nRGlyLCBmaWxlKS5yZXBsYWNlKFxuICAgICAgICAgIC9cXFxcL2csXG4gICAgICAgICAgJy8nXG4gICAgICAgICk7XG4gICAgICAgIGlmICghcmVsYXRpdmVQYXRoLnN0YXJ0c1dpdGgoJy4vJykgJiYgIXJlbGF0aXZlUGF0aC5zdGFydHNXaXRoKCcuLi8nKSkge1xuICAgICAgICAgIHJlbGF0aXZlUGF0aCA9IGAuLyR7cmVsYXRpdmVQYXRofWA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGBleHBvcnQgKiBmcm9tICcke3JlbGF0aXZlUGF0aH0nO2A7XG4gICAgICB9KVxuICAgICAgLmpvaW4oJ1xcbicpO1xuXG4gICAgLy8gU2lkZS1lZmZlY3QgaW1wb3J0cyBmb3Igc2VyZGUgZmlsZXMgbm90IGluIGlucHV0RmlsZXMgKGZvciBjbGFzcyByZWdpc3RyYXRpb24pXG4gICAgY29uc3Qgc2VyZGVJbXBvcnRzID0gc2VyZGVPbmx5RmlsZXNcbiAgICAgIC5tYXAoKGZpbGUpID0+IHtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFdvcmtpbmdEaXIgPSB0aGlzLmNvbmZpZy53b3JraW5nRGlyLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgICAgbGV0IHJlbGF0aXZlUGF0aCA9IHJlbGF0aXZlKG5vcm1hbGl6ZWRXb3JraW5nRGlyLCBmaWxlKS5yZXBsYWNlKFxuICAgICAgICAgIC9cXFxcL2csXG4gICAgICAgICAgJy8nXG4gICAgICAgICk7XG4gICAgICAgIGlmICghcmVsYXRpdmVQYXRoLnN0YXJ0c1dpdGgoJy4vJykgJiYgIXJlbGF0aXZlUGF0aC5zdGFydHNXaXRoKCcuLi8nKSkge1xuICAgICAgICAgIHJlbGF0aXZlUGF0aCA9IGAuLyR7cmVsYXRpdmVQYXRofWA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGBpbXBvcnQgJyR7cmVsYXRpdmVQYXRofSc7YDtcbiAgICAgIH0pXG4gICAgICAuam9pbignXFxuJyk7XG5cbiAgICAvLyBDb21iaW5lOiBzZXJkZSBpbXBvcnRzIChmb3IgcmVnaXN0cmF0aW9uIHNpZGUgZWZmZWN0cykgKyByZS1leHBvcnRzXG4gICAgY29uc3QgZW50cnlDb250ZW50ID0gc2VyZGVJbXBvcnRzXG4gICAgICA/IGAvLyBTZXJkZSBmaWxlcyBmb3IgY3Jvc3MtY29udGV4dCBjbGFzcyByZWdpc3RyYXRpb25cXG4ke3NlcmRlSW1wb3J0c31cXG4ke3JlZXhwb3J0c31gXG4gICAgICA6IHJlZXhwb3J0cztcblxuICAgIC8vIEJ1bmRsZSB3aXRoIGVzYnVpbGQgYW5kIG91ciBjdXN0b20gU1dDIHBsdWdpblxuICAgIGNvbnN0IG5vcm1hbGl6ZWRDbGllbnRTaWRlRWZmZWN0RW50cmllcyA9IGF3YWl0IHdpdGhSZWFscGF0aHMoW1xuICAgICAgLi4uaW5wdXRGaWxlcyxcbiAgICAgIC4uLnNlcmRlT25seUZpbGVzLFxuICAgIF0pO1xuICAgIGNvbnN0IGNsaWVudFJlc3VsdCA9IGF3YWl0IGVzYnVpbGQuYnVpbGQoe1xuICAgICAgYmFubmVyOiB7XG4gICAgICAgIGpzOiAnLy8gYmlvbWUtaWdub3JlLWFsbCBsaW50OiBnZW5lcmF0ZWQgZmlsZVxcbi8qIGVzbGludC1kaXNhYmxlICovXFxuJyxcbiAgICAgIH0sXG4gICAgICBzdGRpbjoge1xuICAgICAgICBjb250ZW50czogZW50cnlDb250ZW50LFxuICAgICAgICByZXNvbHZlRGlyOiB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgICBzb3VyY2VmaWxlOiAndmlydHVhbC1lbnRyeS5qcycsXG4gICAgICAgIGxvYWRlcjogJ2pzJyxcbiAgICAgIH0sXG4gICAgICBvdXRmaWxlOiB0aGlzLmNvbmZpZy5jbGllbnRCdW5kbGVQYXRoLFxuICAgICAgYnVuZGxlOiB0cnVlLFxuICAgICAgZm9ybWF0OiAnZXNtJyxcbiAgICAgIHBsYXRmb3JtOiAnbm9kZScsXG4gICAgICBqc3g6ICdwcmVzZXJ2ZScsXG4gICAgICB0YXJnZXQ6ICdlczIwMjInLFxuICAgICAgd3JpdGU6IHRydWUsXG4gICAgICB0cmVlU2hha2luZzogdHJ1ZSxcbiAgICAgIGV4dGVybmFsOiBbJ0B3b3JrZmxvdy9jb3JlJ10sXG4gICAgICByZXNvbHZlRXh0ZW5zaW9uczogW1xuICAgICAgICAnLnRzJyxcbiAgICAgICAgJy50c3gnLFxuICAgICAgICAnLm10cycsXG4gICAgICAgICcuY3RzJyxcbiAgICAgICAgJy5qcycsXG4gICAgICAgICcuanN4JyxcbiAgICAgICAgJy5tanMnLFxuICAgICAgICAnLmNqcycsXG4gICAgICBdLFxuICAgICAgcGx1Z2luczogW1xuICAgICAgICBjcmVhdGVTd2NQbHVnaW4oe1xuICAgICAgICAgIG1vZGU6ICdzdGVwJyxcbiAgICAgICAgICBwcm9qZWN0Um9vdDogdGhpcy50cmFuc2Zvcm1Qcm9qZWN0Um9vdCxcbiAgICAgICAgICBtb2R1bGVTcGVjaWZpZXJSb290OiB0aGlzLm1vZHVsZVNwZWNpZmllclJvb3QsXG4gICAgICAgICAgc2lkZUVmZmVjdEVudHJpZXM6IG5vcm1hbGl6ZWRDbGllbnRTaWRlRWZmZWN0RW50cmllcyxcbiAgICAgICAgfSksXG4gICAgICBdLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2dFc2J1aWxkTWVzc2FnZXMoY2xpZW50UmVzdWx0LCAnY2xpZW50IGxpYnJhcnkgYnVuZGxlJyk7XG5cbiAgICBhd2FpdCB0aGlzLmVuc3VyZVN3Y0lnbm9yZWQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgd2ViaG9vayBoYW5kbGVyIGJ1bmRsZSBmb3IgcmVzdW1pbmcgd29ya2Zsb3dzIHZpYSBIVFRQIGNhbGxiYWNrcy5cbiAgICpcbiAgICogQHBhcmFtIGJ1bmRsZSAtIElmIHRydWUsIGJ1bmRsZXMgZGVwZW5kZW5jaWVzIChuZWVkZWQgZm9yIEJ1aWxkIE91dHB1dCBBUEkpXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlV2ViaG9va0J1bmRsZSh7XG4gICAgb3V0ZmlsZSxcbiAgICBidW5kbGUgPSBmYWxzZSxcbiAgfToge1xuICAgIG91dGZpbGU6IHN0cmluZztcbiAgICBidW5kbGU/OiBib29sZWFuO1xuICB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5sb2dDcmVhdGVXZWJob29rQnVuZGxlSW5mbygnQ3JlYXRpbmcgd2ViaG9vayByb3V0ZScpO1xuICAgIGF3YWl0IG1rZGlyKGRpcm5hbWUob3V0ZmlsZSksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gICAgLy8gQ3JlYXRlIGEgc3RhdGljIHJvdXRlIHRoYXQgY2FsbHMgcmVzdW1lV2ViaG9va1xuICAgIC8vIFRoaXMgcm91dGUgd29ya3MgZm9yIGJvdGggTmV4dC5qcyBhbmQgVmVyY2VsIEJ1aWxkIE91dHB1dCBBUElcbiAgICAvLyBCdW5kbGVkIEJ1aWxkIE91dHB1dCBBUEkgd2ViaG9vayBmdW5jdGlvbnMgbmVlZCB3b3JsZC50cyBzdGF0aWNhbGx5XG4gICAgLy8gcHJlc2VudCBzbyBnZXRXb3JsZExhenkoKSBjYW4gdXNlIHRoZSBnbG9iYWwgZ2V0V29ybGQgcmVnaXN0cmF0aW9uXG4gICAgLy8gaW5zdGVhZCBvZiBmYWxsaW5nIGJhY2sgdG8gYSBtaXNzaW5nIHNpYmxpbmcgaW1wb3J0KFwiLi93b3JsZC5qc1wiKS5cbiAgICBjb25zdCByb3V0ZUNvbnRlbnQgPSBgJHtidW5kbGUgPyBcImltcG9ydCAnd29ya2Zsb3cvcnVudGltZSc7XFxuXCIgOiAnJ31pbXBvcnQgeyByZXN1bWVXZWJob29rIH0gZnJvbSAnd29ya2Zsb3cvYXBpJztcblxuYXN5bmMgZnVuY3Rpb24gaGFuZGxlcihyZXF1ZXN0KSB7XG4gIGNvbnN0IHVybCA9IG5ldyBVUkwocmVxdWVzdC51cmwpO1xuICAvLyBFeHRyYWN0IHRva2VuIGZyb20gcGF0aG5hbWU6IC8ud2VsbC1rbm93bi93b3JrZmxvdy92MS93ZWJob29rL3t0b2tlbn1cbiAgY29uc3QgcGF0aFBhcnRzID0gdXJsLnBhdGhuYW1lLnNwbGl0KCcvJyk7XG4gIGNvbnN0IHRva2VuID0gZGVjb2RlVVJJQ29tcG9uZW50KHBhdGhQYXJ0c1twYXRoUGFydHMubGVuZ3RoIC0gMV0pO1xuXG4gIGlmICghdG9rZW4pIHtcbiAgICByZXR1cm4gbmV3IFJlc3BvbnNlKCdNaXNzaW5nIHRva2VuJywgeyBzdGF0dXM6IDQwMCB9KTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXN1bWVXZWJob29rKHRva2VuLCByZXF1ZXN0KTtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgLy8gVE9ETzogZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIGludmFsaWQgdG9rZW4gYW5kIG90aGVyIGVycm9yc1xuICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGR1cmluZyByZXN1bWVXZWJob29rJywgZXJyb3IpO1xuICAgIHJldHVybiBuZXcgUmVzcG9uc2UobnVsbCwgeyBzdGF0dXM6IDQwNCB9KTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgR0VUID0gaGFuZGxlcjtcbmV4cG9ydCBjb25zdCBQT1NUID0gaGFuZGxlcjtcbmV4cG9ydCBjb25zdCBQVVQgPSBoYW5kbGVyO1xuZXhwb3J0IGNvbnN0IFBBVENIID0gaGFuZGxlcjtcbmV4cG9ydCBjb25zdCBERUxFVEUgPSBoYW5kbGVyO1xuZXhwb3J0IGNvbnN0IEhFQUQgPSBoYW5kbGVyO1xuZXhwb3J0IGNvbnN0IE9QVElPTlMgPSBoYW5kbGVyO2A7XG5cbiAgICBpZiAoIWJ1bmRsZSkge1xuICAgICAgLy8gRm9yIE5leHQuanMsIGp1c3Qgd3JpdGUgdGhlIHVuYnVuZGxlZCBmaWxlXG4gICAgICBhd2FpdCB3cml0ZUZpbGUob3V0ZmlsZSwgcm91dGVDb250ZW50KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBGb3IgQnVpbGQgT3V0cHV0IEFQSSwgYnVuZGxlIHdpdGggZXNidWlsZCB0byByZXNvbHZlIGltcG9ydHNcblxuICAgIGNvbnN0IHdlYmhvb2tFc21SZXF1aXJlQmFubmVyID0gdGhpcy5nZXRFc21SZXF1aXJlQmFubmVyKCdlc20nKTtcbiAgICBjb25zdCB3ZWJob29rQnVuZGxlU3RhcnQgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGVzYnVpbGQuYnVpbGQoe1xuICAgICAgYmFubmVyOiB7XG4gICAgICAgIGpzOiBgLy8gYmlvbWUtaWdub3JlLWFsbCBsaW50OiBnZW5lcmF0ZWQgZmlsZVxcbi8qIGVzbGludC1kaXNhYmxlICovXFxuJHt3ZWJob29rRXNtUmVxdWlyZUJhbm5lcn1gLFxuICAgICAgfSxcbiAgICAgIHN0ZGluOiB7XG4gICAgICAgIGNvbnRlbnRzOiByb3V0ZUNvbnRlbnQsXG4gICAgICAgIHJlc29sdmVEaXI6IHRoaXMuY29uZmlnLndvcmtpbmdEaXIsXG4gICAgICAgIHNvdXJjZWZpbGU6ICd3ZWJob29rLXJvdXRlLmpzJyxcbiAgICAgICAgbG9hZGVyOiAnanMnLFxuICAgICAgfSxcbiAgICAgIG91dGZpbGUsXG4gICAgICBhYnNXb3JraW5nRGlyOiB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgYnVuZGxlOiB0cnVlLFxuICAgICAganN4OiAncHJlc2VydmUnLFxuICAgICAgZm9ybWF0OiAnZXNtJyxcbiAgICAgIHBsYXRmb3JtOiAnbm9kZScsXG4gICAgICBjb25kaXRpb25zOiBbJ2ltcG9ydCcsICdtb2R1bGUnLCAnbm9kZScsICdkZWZhdWx0J10sXG4gICAgICB0YXJnZXQ6ICdlczIwMjInLFxuICAgICAgd3JpdGU6IHRydWUsXG4gICAgICB0cmVlU2hha2luZzogdHJ1ZSxcbiAgICAgIGtlZXBOYW1lczogdHJ1ZSxcbiAgICAgIG1pbmlmeTogZmFsc2UsXG4gICAgICByZXNvbHZlRXh0ZW5zaW9uczogW1xuICAgICAgICAnLnRzJyxcbiAgICAgICAgJy50c3gnLFxuICAgICAgICAnLm10cycsXG4gICAgICAgICcuY3RzJyxcbiAgICAgICAgJy5qcycsXG4gICAgICAgICcuanN4JyxcbiAgICAgICAgJy5tanMnLFxuICAgICAgICAnLmNqcycsXG4gICAgICBdLFxuICAgICAgc291cmNlbWFwOiB0aGlzLnJlc29sdmVTb3VyY2VtYXAoRU1JVF9TT1VSQ0VNQVBTX0ZPUl9ERUJVR0dJTkcpLFxuICAgICAgbWFpbkZpZWxkczogWydtb2R1bGUnLCAnbWFpbiddLFxuICAgICAgLy8gRG9uJ3QgZXh0ZXJuYWxpemUgYW55dGhpbmcgLSBidW5kbGUgZXZlcnl0aGluZyBpbmNsdWRpbmcgd29ya2Zsb3cgcGFja2FnZXNcbiAgICAgIGV4dGVybmFsOiBbXSxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nRXNidWlsZE1lc3NhZ2VzKHJlc3VsdCwgJ3dlYmhvb2sgYnVuZGxlIGNyZWF0aW9uJyk7XG4gICAgdGhpcy5sb2dDcmVhdGVXZWJob29rQnVuZGxlSW5mbyhcbiAgICAgICdDcmVhdGVkIHdlYmhvb2sgYnVuZGxlJyxcbiAgICAgIGAke0RhdGUubm93KCkgLSB3ZWJob29rQnVuZGxlU3RhcnR9bXNgXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgcGFja2FnZS5qc29uIGZpbGUgd2l0aCB0aGUgc3BlY2lmaWVkIG1vZHVsZSB0eXBlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGNyZWF0ZVBhY2thZ2VKc29uKFxuICAgIGRpcjogc3RyaW5nLFxuICAgIHR5cGU6ICdjb21tb25qcycgfCAnbW9kdWxlJ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBwYWNrYWdlSnNvbiA9IHsgdHlwZSB9O1xuICAgIGF3YWl0IHdyaXRlRmlsZShcbiAgICAgIGpvaW4oZGlyLCAncGFja2FnZS5qc29uJyksXG4gICAgICBKU09OLnN0cmluZ2lmeShwYWNrYWdlSnNvbiwgbnVsbCwgMilcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSAudmMtY29uZmlnLmpzb24gZmlsZSBmb3IgVmVyY2VsIEJ1aWxkIE91dHB1dCBBUEkgZnVuY3Rpb25zLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGNyZWF0ZVZjQ29uZmlnKFxuICAgIGRpcjogc3RyaW5nLFxuICAgIGNvbmZpZzoge1xuICAgICAgcnVudGltZT86IHN0cmluZztcbiAgICAgIGhhbmRsZXI/OiBzdHJpbmc7XG4gICAgICBsYXVuY2hlclR5cGU/OiBzdHJpbmc7XG4gICAgICBhcmNoaXRlY3R1cmU/OiBzdHJpbmc7XG4gICAgICBzaG91bGRBZGRIZWxwZXJzPzogYm9vbGVhbjtcbiAgICAgIHNob3VsZEFkZFNvdXJjZW1hcFN1cHBvcnQ/OiBib29sZWFuO1xuICAgICAgbWF4RHVyYXRpb24/OiBudW1iZXIgfCAnbWF4JztcbiAgICAgIGV4cGVyaW1lbnRhbFRyaWdnZXJzPzogQXJyYXk8e1xuICAgICAgICB0eXBlOiAncXVldWUvdjJiZXRhJztcbiAgICAgICAgdG9waWM6IHN0cmluZztcbiAgICAgICAgY29uc3VtZXI6IHN0cmluZztcbiAgICAgICAgbWF4RGVsaXZlcmllcz86IG51bWJlcjtcbiAgICAgICAgbWF4Q29uY3VycmVuY3k/OiBudW1iZXI7XG4gICAgICAgIHJldHJ5QWZ0ZXJTZWNvbmRzPzogbnVtYmVyO1xuICAgICAgICBpbml0aWFsRGVsYXlTZWNvbmRzPzogbnVtYmVyO1xuICAgICAgfT47XG4gICAgfVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB2Y0NvbmZpZyA9IHtcbiAgICAgIHJ1bnRpbWU6IGNvbmZpZy5ydW50aW1lID8/ICdub2RlanMyMi54JyxcbiAgICAgIGhhbmRsZXI6IGNvbmZpZy5oYW5kbGVyID8/ICdpbmRleC5tanMnLFxuICAgICAgbGF1bmNoZXJUeXBlOiBjb25maWcubGF1bmNoZXJUeXBlID8/ICdOb2RlanMnLFxuICAgICAgYXJjaGl0ZWN0dXJlOiBjb25maWcuYXJjaGl0ZWN0dXJlID8/ICdhcm02NCcsXG4gICAgICBzaG91bGRBZGRIZWxwZXJzOiBjb25maWcuc2hvdWxkQWRkSGVscGVycyA/PyB0cnVlLFxuICAgICAgLi4uKGNvbmZpZy5tYXhEdXJhdGlvbiAhPT0gdW5kZWZpbmVkICYmIHtcbiAgICAgICAgbWF4RHVyYXRpb246IGNvbmZpZy5tYXhEdXJhdGlvbixcbiAgICAgIH0pLFxuICAgICAgLi4uKGNvbmZpZy5zaG91bGRBZGRTb3VyY2VtYXBTdXBwb3J0ICE9PSB1bmRlZmluZWQgJiYge1xuICAgICAgICBzaG91bGRBZGRTb3VyY2VtYXBTdXBwb3J0OiBjb25maWcuc2hvdWxkQWRkU291cmNlbWFwU3VwcG9ydCxcbiAgICAgIH0pLFxuICAgICAgLi4uKGNvbmZpZy5leHBlcmltZW50YWxUcmlnZ2VycyAmJiB7XG4gICAgICAgIGV4cGVyaW1lbnRhbFRyaWdnZXJzOiBjb25maWcuZXhwZXJpbWVudGFsVHJpZ2dlcnMsXG4gICAgICB9KSxcbiAgICB9O1xuXG4gICAgYXdhaXQgd3JpdGVGaWxlKFxuICAgICAgam9pbihkaXIsICcudmMtY29uZmlnLmpzb24nKSxcbiAgICAgIEpTT04uc3RyaW5naWZ5KHZjQ29uZmlnLCBudWxsLCAyKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgYSBwYXRoIHJlbGF0aXZlIHRvIHRoZSB3b3JraW5nIGRpcmVjdG9yeS5cbiAgICovXG4gIHByb3RlY3RlZCByZXNvbHZlUGF0aChwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiByZXNvbHZlKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsIHBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuc3VyZXMgdGhlIGRpcmVjdG9yeSBmb3IgYSBmaWxlIHBhdGggZXhpc3RzLCBjcmVhdGluZyBpdCBpZiBuZWNlc3NhcnkuXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgZW5zdXJlRGlyZWN0b3J5KGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCBta2RpcihkaXJuYW1lKGZpbGVQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZW5zdXJlU3djSWdub3JlZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVByb2plY3RTd2NHaXRpZ25vcmVFbnRyeSgpO1xuICAgIGF3YWl0IHRoaXMuY3JlYXRlU3djRGlyZWN0b3J5R2l0aWdub3JlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGVuc3VyZVByb2plY3RTd2NHaXRpZ25vcmVFbnRyeSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBnaXRpZ25vcmVQYXRoID0gam9pbih0aGlzLmNvbmZpZy53b3JraW5nRGlyLCAnLmdpdGlnbm9yZScpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGxldCBjb250ZW50ID0gJyc7XG4gICAgICB0cnkge1xuICAgICAgICBjb250ZW50ID0gYXdhaXQgcmVhZEZpbGUoZ2l0aWdub3JlUGF0aCwgJ3V0Zi04Jyk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBpZiAoKGVycm9yIGFzIE5vZGVKUy5FcnJub0V4Y2VwdGlvbikuY29kZSAhPT0gJ0VOT0VOVCcpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgaGFzU3djRW50cnkgPSBjb250ZW50LnNwbGl0KC9cXHI/XFxuLykuc29tZSgobGluZSkgPT4ge1xuICAgICAgICBjb25zdCB0cmltbWVkID0gbGluZS50cmltKCk7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgdHJpbW1lZCA9PT0gJy5zd2MnIHx8XG4gICAgICAgICAgdHJpbW1lZCA9PT0gJy5zd2MvJyB8fFxuICAgICAgICAgIHRyaW1tZWQgPT09ICcvLnN3YycgfHxcbiAgICAgICAgICB0cmltbWVkID09PSAnLy5zd2MvJ1xuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGlmIChoYXNTd2NFbnRyeSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNlcGFyYXRvciA9XG4gICAgICAgIGNvbnRlbnQubGVuZ3RoID4gMCAmJiAhY29udGVudC5lbmRzV2l0aCgnXFxuJykgPyAnXFxuJyA6ICcnO1xuICAgICAgYXdhaXQgd3JpdGVGaWxlKGdpdGlnbm9yZVBhdGgsIGAke2NvbnRlbnR9JHtzZXBhcmF0b3J9Ly5zd2NcXG5gKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIFdlJ3JlIGludGVudGlvbmFsbHkgc2lsZW50bHkgaWdub3JpbmcgdGhpcyBlcnJvciAtIHVwZGF0aW5nIC5naXRpZ25vcmUgaXNuJ3QgY3JpdGljYWxcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNyZWF0ZVN3Y0RpcmVjdG9yeUdpdGlnbm9yZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgd3JpdGVGaWxlKFxuICAgICAgICBqb2luKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsICcuc3djJywgJy5naXRpZ25vcmUnKSxcbiAgICAgICAgJypcXG4nXG4gICAgICApO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gV2UncmUgaW50ZW50aW9uYWxseSBzaWxlbnRseSBpZ25vcmluZyB0aGlzIGVycm9yIC0gY3JlYXRpbmcgLmdpdGlnbm9yZSBpc24ndCBjcml0aWNhbFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBtYW5pZmVzdCBzaG91bGQgYmUgZXhwb3NlZCBhcyBhIHB1YmxpYyBIVFRQIHJvdXRlLlxuICAgKiBDb250cm9sbGVkIGJ5IHRoZSBgV09SS0ZMT1dfUFVCTElDX01BTklGRVNUYCBlbnZpcm9ubWVudCB2YXJpYWJsZS5cbiAgICovXG4gIHByb3RlY3RlZCBnZXQgc2hvdWxkRXhwb3NlUHVibGljTWFuaWZlc3QoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHByb2Nlc3MuZW52LldPUktGTE9XX1BVQkxJQ19NQU5JRkVTVCA9PT0gJzEnO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIHRoZSB3b3JrZmxvdyBtYW5pZmVzdCBkaWFnbm9zdGljcyBwYXRoLCB3aGVuIHRoaXMgYnVpbGRlciBzaG91bGRcbiAgICogZW1pdCBvbmUuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0RGlhZ25vc3RpY3NNYW5pZmVzdFBhdGgoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodGhpcy5jb25maWcuZGlhZ25vc3RpY3NEaXIpIHtcbiAgICAgIHJldHVybiByZXNvbHZlKFxuICAgICAgICB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgICB0aGlzLmNvbmZpZy5kaWFnbm9zdGljc0RpcixcbiAgICAgICAgJ3dvcmtmbG93cy1tYW5pZmVzdC5qc29uJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jb25maWcuYnVpbGRUYXJnZXQgPT09ICd2ZXJjZWwtYnVpbGQtb3V0cHV0LWFwaScpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlc29sdmVQYXRoKFxuICAgICAgICAnLnZlcmNlbC9vdXRwdXQvZGlhZ25vc3RpY3Mvd29ya2Zsb3dzLW1hbmlmZXN0Lmpzb24nXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgaXMgYSBkZXZlbG9wbWVudC93YXRjaCBidWlsZCAoZS5nLiBgbmV4dCBkZXZgLCBgbml0cm8gZGV2YCxcbiAgICogb3IgYSBWaXRlLWJhc2VkIGRldiBzZXJ2ZXIgZm9yIGFzdHJvL3N2ZWx0ZWtpdC92aXRlKS4gYGNvbmZpZy53YXRjaGAgaXNcbiAgICogcGx1bWJlZCBieSB0aGUgYnVpbGRlcnMgdGhhdCBvd24gYSBkZXYgc2VydmVyIChuZXh0LCBuaXRybywgbmVzdCk7IHRoZVxuICAgKiBWaXRlLWJhc2VkIGludGVncmF0aW9ucyBkb24ndCBzZXQgaXQgYnV0IHJ1biB3aXRoXG4gICAqIGBOT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50J2AuIFdoZW4gbmVpdGhlciBzaWduYWwgaXMgcHJlc2VudCB3ZSB0cmVhdCB0aGVcbiAgICogYnVpbGQgYXMgcHJvZHVjdGlvbiwgc28gQ0xJL1ZlcmNlbCBwcm9kdWN0aW9uIGJ1aWxkcyBkZWZhdWx0IHRvIG9mZi5cbiAgICovXG4gIHByb3RlY3RlZCBnZXQgaXNEZXZlbG9wbWVudEJ1aWxkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZy53YXRjaCA9PT0gdHJ1ZSB8fCBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50JztcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWZhdWx0IHNvdXJjZSBtYXAgbW9kZSBmb3IgdGhlIHN0YWNrLXJlbGV2YW50IGJ1bmRsZXMgKHN0ZXBzICsgdGhlXG4gICAqIGludGVybWVkaWF0ZSB3b3JrZmxvdyBWTSBidW5kbGUpOiBpbmxpbmUgc291cmNlIG1hcHMgaW4gZGV2ZWxvcG1lbnQgc29cbiAgICogc3RhY2sgdHJhY2VzIHBvaW50IGF0IHNvdXJjZSBmaWxlcywgYW5kIG9mZiBpbiBwcm9kdWN0aW9uIHNvIGZ1bmN0aW9uXG4gICAqIGJ1bmRsZXMgc3RheSBzbWFsbCAoaGVscHMgc3RheSB1bmRlciB0aGUgVmVyY2VsIDI1ME1CIGZ1bmN0aW9uIGxpbWl0KSBhbmRcbiAgICogc2tpcCB0aGUgc291cmNlLW1hcC1zdXBwb3J0IHJ1bnRpbWUgc2hpbS4gVGhlIGBzb3VyY2VtYXBgIGNvbmZpZyBvcHRpb25cbiAgICogYW5kIGBXT1JLRkxPV19TT1VSQ0VNQVBgIGVudiB2YXIgb3ZlcnJpZGUgdGhpcyBpbiBlaXRoZXIgZW52aXJvbm1lbnQuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0IGRlZmF1bHRTb3VyY2VtYXBNb2RlKCk6IFNvdXJjZW1hcE1vZGUge1xuICAgIHJldHVybiB0aGlzLmlzRGV2ZWxvcG1lbnRCdWlsZCA/ICdpbmxpbmUnIDogZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSB0aGUgZWZmZWN0aXZlIHNvdXJjZSBtYXAgbW9kZSBmb3IgYSBnaXZlbiBjYWxsIHNpdGUuIFByZWNlZGVuY2U6XG4gICAqIGV4cGxpY2l0IGBzb3VyY2VtYXBgIGNvbmZpZyA+IGBXT1JLRkxPV19TT1VSQ0VNQVBgIGVudiB2YXIgPiB0aGUgY2FsbFxuICAgKiBzaXRlJ3MgZGVmYXVsdC4gUmV0dXJuZWQgdmFsdWUgaXMgcGFzc2VkIGRpcmVjdGx5IHRvIGVzYnVpbGQnc1xuICAgKiBgc291cmNlbWFwYCBvcHRpb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVzb2x2ZVNvdXJjZW1hcChkZWZhdWx0TW9kZTogU291cmNlbWFwTW9kZSk6IFNvdXJjZW1hcE1vZGUge1xuICAgIGlmICh0aGlzLmNvbmZpZy5zb3VyY2VtYXAgIT09IHVuZGVmaW5lZCkgcmV0dXJuIHRoaXMuY29uZmlnLnNvdXJjZW1hcDtcbiAgICBjb25zdCBlbnZNb2RlID0gcGFyc2VTb3VyY2VtYXBFbnYocHJvY2Vzcy5lbnYuV09SS0ZMT1dfU09VUkNFTUFQKTtcbiAgICBpZiAoZW52TW9kZSAhPT0gdW5kZWZpbmVkKSByZXR1cm4gZW52TW9kZTtcbiAgICByZXR1cm4gZGVmYXVsdE1vZGU7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSB3aGV0aGVyIHdvcmtmbG93L3N0ZXAgZmlsZXMgdW5kZXIgYG5vZGVfbW9kdWxlc2AgYXJlIGRpc2NvdmVyZWQuXG4gICAqIFByZWNlZGVuY2U6IGV4cGxpY2l0IGBkaXNjb3ZlcldvcmtmbG93c0luTm9kZU1vZHVsZXNgIGNvbmZpZyA+IHRoZVxuICAgKiBgV09SS0ZMT1dfRElTQ09WRVJfTk9ERV9NT0RVTEVTYCBlbnYgdmFyIChgMGAvYGZhbHNlYCBkaXNhYmxlcykgPiB0aGVcbiAgICogZGVmYXVsdCAoYHRydWVgLCBkaXNjb3ZlciB0aGVtKS5cbiAgICovXG4gIHByb3RlY3RlZCByZXNvbHZlRGlzY292ZXJXb3JrZmxvd3NJbk5vZGVNb2R1bGVzKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmNvbmZpZy5kaXNjb3ZlcldvcmtmbG93c0luTm9kZU1vZHVsZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmRpc2NvdmVyV29ya2Zsb3dzSW5Ob2RlTW9kdWxlcztcbiAgICB9XG4gICAgY29uc3QgZW52VmFsdWUgPSBwYXJzZURpc2NvdmVyTm9kZU1vZHVsZXNFbnYoXG4gICAgICBwcm9jZXNzLmVudi5XT1JLRkxPV19ESVNDT1ZFUl9OT0RFX01PRFVMRVNcbiAgICApO1xuICAgIGlmIChlbnZWYWx1ZSAhPT0gdW5kZWZpbmVkKSByZXR1cm4gZW52VmFsdWU7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGUgcmVzb2x2ZWQgc291cmNlIG1hcCBtb2RlIGVtaXRzIGFueSBzb3VyY2UgbWFwcyBhdCBhbGwuXG4gICAqIFVzZWQgYnkgY29uc3VtZXJzIGxpa2UgdGhlIFZlcmNlbCBidWlsZGVyIHRvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGVcbiAgICogdGhlIHNvdXJjZS1tYXAtc3VwcG9ydCBydW50aW1lIHNoaW0gaW4gZ2VuZXJhdGVkIGZ1bmN0aW9ucy4gVXNlcyB0aGUgc2FtZVxuICAgKiBlbnZpcm9ubWVudC1hd2FyZSBkZWZhdWx0IChgZGVmYXVsdFNvdXJjZW1hcE1vZGVgKSBhcyB0aGUgc3RlcC93b3JrZmxvd1xuICAgKiBidW5kbGVzLCBzbyBhIHByb2R1Y3Rpb24gYnVpbGQgd2l0aCBubyBvdmVycmlkZSBvbWl0cyB0aGUgc2hpbS5cbiAgICovXG4gIHByb3RlY3RlZCBnZXQgc291cmNlbWFwc0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucmVzb2x2ZVNvdXJjZW1hcCh0aGlzLmRlZmF1bHRTb3VyY2VtYXBNb2RlKSAhPT0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG1hbmlmZXN0IEpTT04gZmlsZSBjb250YWluaW5nIHN0ZXAvd29ya2Zsb3cvY2xhc3MgbWV0YWRhdGFcbiAgICogYW5kIGdyYXBoIGRhdGEgZm9yIHZpc3VhbGl6YXRpb24uXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSBtYW5pZmVzdCBKU09OIHN0cmluZywgb3IgdW5kZWZpbmVkIGlmIG1hbmlmZXN0IGNyZWF0aW9uIGZhaWxlZC5cbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBjcmVhdGVNYW5pZmVzdCh7XG4gICAgd29ya2Zsb3dCdW5kbGVQYXRoLFxuICAgIG1hbmlmZXN0RGlyLFxuICAgIG1hbmlmZXN0LFxuICB9OiB7XG4gICAgd29ya2Zsb3dCdW5kbGVQYXRoOiBzdHJpbmc7XG4gICAgbWFuaWZlc3REaXI6IHN0cmluZztcbiAgICBtYW5pZmVzdDogV29ya2Zsb3dNYW5pZmVzdDtcbiAgfSk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3QgYnVpbGRTdGFydCA9IERhdGUubm93KCk7XG4gICAgdGhpcy5sb2dDcmVhdGVNYW5pZmVzdEluZm8oJ0NyZWF0aW5nIG1hbmlmZXN0Li4uJyk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgd29ya2Zsb3dHcmFwaHMgPSBhd2FpdCBleHRyYWN0V29ya2Zsb3dHcmFwaHMod29ya2Zsb3dCdW5kbGVQYXRoKTtcblxuICAgICAgY29uc3Qgc3RlcHMgPSB0aGlzLmNvbnZlcnRTdGVwc01hbmlmZXN0KG1hbmlmZXN0LnN0ZXBzKTtcbiAgICAgIGNvbnN0IHdvcmtmbG93cyA9IHRoaXMuY29udmVydFdvcmtmbG93c01hbmlmZXN0KFxuICAgICAgICBtYW5pZmVzdC53b3JrZmxvd3MsXG4gICAgICAgIHdvcmtmbG93R3JhcGhzXG4gICAgICApO1xuICAgICAgY29uc3QgY2xhc3NlcyA9IHRoaXMuY29udmVydENsYXNzZXNNYW5pZmVzdChtYW5pZmVzdC5jbGFzc2VzKTtcblxuICAgICAgY29uc3Qgb3V0cHV0ID0geyB2ZXJzaW9uOiAnMS4wLjAnLCBzdGVwcywgd29ya2Zsb3dzLCBjbGFzc2VzIH07XG4gICAgICBjb25zdCBtYW5pZmVzdEpzb24gPSBKU09OLnN0cmluZ2lmeShvdXRwdXQsIG51bGwsIDIpO1xuXG4gICAgICBhd2FpdCBta2RpcihtYW5pZmVzdERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBhd2FpdCB3cml0ZUZpbGUoam9pbihtYW5pZmVzdERpciwgJ21hbmlmZXN0Lmpzb24nKSwgbWFuaWZlc3RKc29uKTtcblxuICAgICAgY29uc3QgZGlhZ25vc3RpY3NNYW5pZmVzdFBhdGggPSB0aGlzLmdldERpYWdub3N0aWNzTWFuaWZlc3RQYXRoKCk7XG4gICAgICBpZiAoZGlhZ25vc3RpY3NNYW5pZmVzdFBhdGgpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5lbnN1cmVEaXJlY3RvcnkoZGlhZ25vc3RpY3NNYW5pZmVzdFBhdGgpO1xuICAgICAgICBhd2FpdCB3cml0ZUZpbGUoZGlhZ25vc3RpY3NNYW5pZmVzdFBhdGgsIG1hbmlmZXN0SnNvbik7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN0ZXBDb3VudCA9IE9iamVjdC52YWx1ZXMoc3RlcHMpLnJlZHVjZShcbiAgICAgICAgKGFjYywgcykgPT4gYWNjICsgT2JqZWN0LmtleXMocykubGVuZ3RoLFxuICAgICAgICAwXG4gICAgICApO1xuICAgICAgY29uc3Qgd29ya2Zsb3dDb3VudCA9IE9iamVjdC52YWx1ZXMod29ya2Zsb3dzKS5yZWR1Y2UoXG4gICAgICAgIChhY2MsIHcpID0+IGFjYyArIE9iamVjdC5rZXlzKHcpLmxlbmd0aCxcbiAgICAgICAgMFxuICAgICAgKTtcbiAgICAgIGNvbnN0IGNsYXNzQ291bnQgPSBPYmplY3QudmFsdWVzKGNsYXNzZXMpLnJlZHVjZShcbiAgICAgICAgKGFjYywgYykgPT4gYWNjICsgT2JqZWN0LmtleXMoYykubGVuZ3RoLFxuICAgICAgICAwXG4gICAgICApO1xuXG4gICAgICB0aGlzLmxvZ0NyZWF0ZU1hbmlmZXN0SW5mbyhcbiAgICAgICAgYENyZWF0ZWQgbWFuaWZlc3Qgd2l0aCAke3N0ZXBDb3VudH0gJHtwbHVyYWxpemUoJ3N0ZXAnLCAnc3RlcHMnLCBzdGVwQ291bnQpfSwgJHt3b3JrZmxvd0NvdW50fSAke3BsdXJhbGl6ZSgnd29ya2Zsb3cnLCAnd29ya2Zsb3dzJywgd29ya2Zsb3dDb3VudCl9LCBhbmQgJHtjbGFzc0NvdW50fSAke3BsdXJhbGl6ZSgnY2xhc3MnLCAnY2xhc3NlcycsIGNsYXNzQ291bnQpfWAsXG4gICAgICAgIGAke0RhdGUubm93KCkgLSBidWlsZFN0YXJ0fW1zYFxuICAgICAgKTtcblxuICAgICAgaWYgKCF0aGlzLmNvbmZpZy5zdXBwcmVzc0NyZWF0ZU1hbmlmZXN0TG9ncykge1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICB0aGlzLmdldFdvcmtmbG93QnVpbGRTdW1tYXJ5KHtcbiAgICAgICAgICAgIHN0ZXBDb3VudCxcbiAgICAgICAgICAgIHdvcmtmbG93Q291bnQsXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHRoaXMucmVzZXRXb3JrZmxvd0J1aWxkVGltZXIoKTtcblxuICAgICAgcmV0dXJuIG1hbmlmZXN0SnNvbjtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAnRmFpbGVkIHRvIGNyZWF0ZSBtYW5pZmVzdDonLFxuICAgICAgICBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcilcbiAgICAgICk7XG4gICAgICB0aGlzLnJlc2V0V29ya2Zsb3dCdWlsZFRpbWVyKCk7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY29udmVydFN0ZXBzTWFuaWZlc3QoXG4gICAgc3RlcHM6IFdvcmtmbG93TWFuaWZlc3RbJ3N0ZXBzJ11cbiAgKTogUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgeyBzdGVwSWQ6IHN0cmluZyB9Pj4ge1xuICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgeyBzdGVwSWQ6IHN0cmluZyB9Pj4gPSB7fTtcbiAgICBpZiAoIXN0ZXBzKSByZXR1cm4gcmVzdWx0O1xuXG4gICAgZm9yIChjb25zdCBbZmlsZVBhdGgsIGVudHJpZXNdIG9mIE9iamVjdC5lbnRyaWVzKHN0ZXBzKSkge1xuICAgICAgcmVzdWx0W2ZpbGVQYXRoXSA9IHt9O1xuICAgICAgZm9yIChjb25zdCBbbmFtZSwgZGF0YV0gb2YgT2JqZWN0LmVudHJpZXMoZW50cmllcykpIHtcbiAgICAgICAgcmVzdWx0W2ZpbGVQYXRoXVtuYW1lXSA9IHsgc3RlcElkOiBkYXRhLnN0ZXBJZCB9O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHJpdmF0ZSBjb252ZXJ0V29ya2Zsb3dzTWFuaWZlc3QoXG4gICAgd29ya2Zsb3dzOiBXb3JrZmxvd01hbmlmZXN0Wyd3b3JrZmxvd3MnXSxcbiAgICBncmFwaHM6IFJlY29yZDxcbiAgICAgIHN0cmluZyxcbiAgICAgIFJlY29yZDxzdHJpbmcsIHsgZ3JhcGg6IHsgbm9kZXM6IGFueVtdOyBlZGdlczogYW55W10gfSB9PlxuICAgID5cbiAgKTogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBSZWNvcmQ8XG4gICAgICBzdHJpbmcsXG4gICAgICB7IHdvcmtmbG93SWQ6IHN0cmluZzsgZ3JhcGg6IHsgbm9kZXM6IGFueVtdOyBlZGdlczogYW55W10gfSB9XG4gICAgPlxuICA+IHtcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxcbiAgICAgIHN0cmluZyxcbiAgICAgIFJlY29yZDxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICB7IHdvcmtmbG93SWQ6IHN0cmluZzsgZ3JhcGg6IHsgbm9kZXM6IGFueVtdOyBlZGdlczogYW55W10gfSB9XG4gICAgICA+XG4gICAgPiA9IHt9O1xuICAgIGlmICghd29ya2Zsb3dzKSByZXR1cm4gcmVzdWx0O1xuXG4gICAgLy8gQnVpbGQgYSBub3JtYWxpemVkIGxvb2t1cCBmb3IgZ3JhcGhzIHNpbmNlIHRoZSBncmFwaCBleHRyYWN0b3IgdXNlc1xuICAgIC8vIHBhdGhzIGZyb20gd29ya2Zsb3dJZCAoZS5nLiBcIi4vd29ya2Zsb3dzL2hlbGxvLWFnZW50XCIpIHdoaWxlIHRoZVxuICAgIC8vIG1hbmlmZXN0IHVzZXMgc291cmNlIGZpbGUgcGF0aHMgKGUuZy4gXCJ3b3JrZmxvd3MvaGVsbG8tYWdlbnQudHNcIikuXG4gICAgLy8gTm9ybWFsaXplIGJ5IHN0cmlwcGluZyBsZWFkaW5nIFwiLi9cIiBhbmQgZmlsZSBleHRlbnNpb25zLlxuICAgIGNvbnN0IG5vcm1hbGl6ZWRHcmFwaHMgPSBuZXcgTWFwPFxuICAgICAgc3RyaW5nLFxuICAgICAgUmVjb3JkPHN0cmluZywgeyBncmFwaDogeyBub2RlczogYW55W107IGVkZ2VzOiBhbnlbXSB9IH0+XG4gICAgPigpO1xuICAgIGZvciAoY29uc3QgW2dyYXBoUGF0aCwgZ3JhcGhFbnRyaWVzXSBvZiBPYmplY3QuZW50cmllcyhncmFwaHMpKSB7XG4gICAgICBjb25zdCBub3JtYWxpemVkID0gZ3JhcGhQYXRoXG4gICAgICAgIC5yZXBsYWNlKC9eXFwuXFwvLywgJycpXG4gICAgICAgIC5yZXBsYWNlKC9cXC5bXi8uXSskLywgJycpO1xuICAgICAgbm9ybWFsaXplZEdyYXBocy5zZXQobm9ybWFsaXplZCwgZ3JhcGhFbnRyaWVzKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IFtmaWxlUGF0aCwgZW50cmllc10gb2YgT2JqZWN0LmVudHJpZXMod29ya2Zsb3dzKSkge1xuICAgICAgcmVzdWx0W2ZpbGVQYXRoXSA9IHt9O1xuICAgICAgLy8gTm9ybWFsaXplIHRoZSBtYW5pZmVzdCBmaWxlIHBhdGggZm9yIGxvb2t1cFxuICAgICAgY29uc3Qgbm9ybWFsaXplZEZpbGVQYXRoID0gZmlsZVBhdGhcbiAgICAgICAgLnJlcGxhY2UoL15cXC5cXC8vLCAnJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLlteLy5dKyQvLCAnJyk7XG5cbiAgICAgIGNvbnN0IGdyYXBoRW50cmllcyA9XG4gICAgICAgIGdyYXBoc1tmaWxlUGF0aF0gfHwgbm9ybWFsaXplZEdyYXBocy5nZXQobm9ybWFsaXplZEZpbGVQYXRoKTtcblxuICAgICAgZm9yIChjb25zdCBbbmFtZSwgZGF0YV0gb2YgT2JqZWN0LmVudHJpZXMoZW50cmllcykpIHtcbiAgICAgICAgcmVzdWx0W2ZpbGVQYXRoXVtuYW1lXSA9IHtcbiAgICAgICAgICB3b3JrZmxvd0lkOiBkYXRhLndvcmtmbG93SWQsXG4gICAgICAgICAgZ3JhcGg6IGdyYXBoRW50cmllcz8uW25hbWVdPy5ncmFwaCB8fCB7IG5vZGVzOiBbXSwgZWRnZXM6IFtdIH0sXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwcml2YXRlIGNvbnZlcnRDbGFzc2VzTWFuaWZlc3QoXG4gICAgY2xhc3NlczogV29ya2Zsb3dNYW5pZmVzdFsnY2xhc3NlcyddXG4gICk6IFJlY29yZDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIHsgY2xhc3NJZDogc3RyaW5nIH0+PiB7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBSZWNvcmQ8c3RyaW5nLCB7IGNsYXNzSWQ6IHN0cmluZyB9Pj4gPSB7fTtcbiAgICBpZiAoIWNsYXNzZXMpIHJldHVybiByZXN1bHQ7XG5cbiAgICBmb3IgKGNvbnN0IFtmaWxlUGF0aCwgZW50cmllc10gb2YgT2JqZWN0LmVudHJpZXMoY2xhc3NlcykpIHtcbiAgICAgIHJlc3VsdFtmaWxlUGF0aF0gPSB7fTtcbiAgICAgIGZvciAoY29uc3QgW25hbWUsIGRhdGFdIG9mIE9iamVjdC5lbnRyaWVzKGVudHJpZXMpKSB7XG4gICAgICAgIHJlc3VsdFtmaWxlUGF0aF1bbmFtZV0gPSB7IGNsYXNzSWQ6IGRhdGEuY2xhc3NJZCB9O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG4iXX0=