@workflow/next 4.0.10 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1417 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getNextBuilderDeferred = getNextBuilderDeferred;
7
- const node_crypto_1 = require("node:crypto");
8
- const node_fs_1 = require("node:fs");
9
- const promises_1 = require("node:fs/promises");
10
- const node_os_1 = __importDefault(require("node:os"));
11
- const node_path_1 = require("node:path");
12
- const socket_server_js_1 = require("./socket-server.js");
13
- const step_copy_utils_js_1 = require("./step-copy-utils.js");
14
- const ROUTE_STUB_FILE_MARKER = 'WORKFLOW_ROUTE_STUB_FILE';
15
- let CachedNextBuilderDeferred;
16
- // Create the deferred Next builder dynamically by extending the ESM BaseBuilder.
17
- // Exported as getNextBuilderDeferred() to allow CommonJS modules to import from
18
- // the ESM @workflow/builders package via dynamic import at runtime.
19
- async function getNextBuilderDeferred() {
20
- if (CachedNextBuilderDeferred) {
21
- return CachedNextBuilderDeferred;
22
- }
23
- const { BaseBuilder: BaseBuilderClass, STEP_QUEUE_TRIGGER, WORKFLOW_QUEUE_TRIGGER, applySwcTransform, detectWorkflowPatterns, getImportPath, isWorkflowSdkFile, resolveWorkflowAliasRelativePath,
24
- // biome-ignore lint/security/noGlobalEval: Need to use eval here to avoid TypeScript from transpiling the import statement into `require()`
25
- } = (await eval('import("@workflow/builders")'));
26
- class NextDeferredBuilder extends BaseBuilderClass {
27
- socketIO;
28
- discoveredWorkflowFiles = new Set();
29
- discoveredStepFiles = new Set();
30
- discoveredSerdeFiles = new Set();
31
- trackedDependencyFiles = new Set();
32
- deferredBuildQueue = Promise.resolve();
33
- cacheInitialized = false;
34
- cacheWriteTimer = null;
35
- deferredRebuildTimer = null;
36
- lastDeferredBuildSignature = null;
37
- async build() {
38
- const outputDir = await this.findAppDirectory();
39
- await this.initializeDiscoveryState();
40
- await this.cleanupGeneratedArtifactsOnBoot(outputDir);
41
- await this.writeStubFiles(outputDir);
42
- await this.createDiscoverySocketServer();
43
- }
44
- async onBeforeDeferredEntries() {
45
- await this.initializeDiscoveryState();
46
- await this.validateDiscoveredEntryFiles();
47
- const implicitStepFiles = await this.resolveImplicitStepFiles();
48
- const pendingBuild = this.deferredBuildQueue.then(() => this.buildDeferredEntriesUntilStable(implicitStepFiles));
49
- // Keep the queue chain alive even when the current build fails so future
50
- // callbacks can enqueue another attempt without triggering unhandled
51
- // rejection warnings.
52
- this.deferredBuildQueue = pendingBuild.catch(() => {
53
- // Error is surfaced through `pendingBuild` below.
54
- });
55
- await pendingBuild;
56
- }
57
- getCurrentInputFiles(implicitStepFiles) {
58
- return Array.from(new Set([
59
- ...this.discoveredWorkflowFiles,
60
- ...this.discoveredStepFiles,
61
- ...this.discoveredSerdeFiles,
62
- ...implicitStepFiles,
63
- ])).sort();
64
- }
65
- async buildDeferredEntriesUntilStable(implicitStepFiles) {
66
- // A successful build can discover additional transitive dependency files
67
- // (via source maps), which changes the signature and may require one more
68
- // build pass to include newly discovered serde files.
69
- const maxBuildPasses = 3;
70
- for (let buildPass = 0; buildPass < maxBuildPasses; buildPass++) {
71
- const inputFiles = this.getCurrentInputFiles(implicitStepFiles);
72
- const buildSignature = await this.createDeferredBuildSignature(inputFiles);
73
- if (buildSignature === this.lastDeferredBuildSignature) {
74
- return;
75
- }
76
- try {
77
- await this.buildDiscoveredFiles(inputFiles, implicitStepFiles);
78
- }
79
- catch (error) {
80
- if (this.config.watch) {
81
- await this.validateDiscoveredEntryFiles();
82
- const recoveredInputFiles = this.getCurrentInputFiles(implicitStepFiles);
83
- const recoveredSignature = await this.createDeferredBuildSignature(recoveredInputFiles);
84
- if (recoveredSignature !== buildSignature) {
85
- // A file was added/removed while this build was running; retry
86
- // immediately with the refreshed discovered-entry state.
87
- continue;
88
- }
89
- console.warn('[workflow] Deferred entries build failed. Will retry only after inputs change.', error);
90
- this.lastDeferredBuildSignature = buildSignature;
91
- return;
92
- }
93
- else {
94
- throw error;
95
- }
96
- }
97
- this.lastDeferredBuildSignature = buildSignature;
98
- const postBuildInputFiles = this.getCurrentInputFiles(implicitStepFiles);
99
- const postBuildSignature = await this.createDeferredBuildSignature(postBuildInputFiles);
100
- if (postBuildSignature === buildSignature) {
101
- return;
102
- }
103
- }
104
- console.warn('[workflow] Deferred entries build signature did not stabilize after 3 passes.');
105
- }
106
- async resolveImplicitStepFiles() {
107
- const workflowStdlibPath = this.resolveWorkflowStdlibStepFilePath();
108
- return workflowStdlibPath ? [workflowStdlibPath] : [];
109
- }
110
- resolveWorkflowStdlibStepFilePath() {
111
- let workflowCjsEntry;
112
- try {
113
- workflowCjsEntry = require.resolve('workflow', {
114
- paths: [this.config.workingDir],
115
- });
116
- }
117
- catch {
118
- return null;
119
- }
120
- const workflowDistDir = (0, node_path_1.dirname)(workflowCjsEntry);
121
- const workflowStdlibPath = this.normalizeDiscoveredFilePath((0, node_path_1.join)(workflowDistDir, 'stdlib.js'));
122
- return (0, node_fs_1.existsSync)(workflowStdlibPath) ? workflowStdlibPath : null;
123
- }
124
- async reconcileDiscoveredEntries({ workflowCandidates, stepCandidates, serdeCandidates, validatePatterns, }) {
125
- const candidatesByFile = new Map();
126
- for (const filePath of workflowCandidates) {
127
- const normalizedPath = this.normalizeDiscoveredFilePath(filePath);
128
- const existing = candidatesByFile.get(normalizedPath);
129
- if (existing) {
130
- existing.hasWorkflowCandidate = true;
131
- }
132
- else {
133
- candidatesByFile.set(normalizedPath, {
134
- hasWorkflowCandidate: true,
135
- hasStepCandidate: false,
136
- hasSerdeCandidate: false,
137
- });
138
- }
139
- }
140
- for (const filePath of stepCandidates) {
141
- const normalizedPath = this.normalizeDiscoveredFilePath(filePath);
142
- const existing = candidatesByFile.get(normalizedPath);
143
- if (existing) {
144
- existing.hasStepCandidate = true;
145
- }
146
- else {
147
- candidatesByFile.set(normalizedPath, {
148
- hasWorkflowCandidate: false,
149
- hasStepCandidate: true,
150
- hasSerdeCandidate: false,
151
- });
152
- }
153
- }
154
- if (serdeCandidates) {
155
- for (const filePath of serdeCandidates) {
156
- const normalizedPath = this.normalizeDiscoveredFilePath(filePath);
157
- const existing = candidatesByFile.get(normalizedPath);
158
- if (existing) {
159
- existing.hasSerdeCandidate = true;
160
- }
161
- else {
162
- candidatesByFile.set(normalizedPath, {
163
- hasWorkflowCandidate: false,
164
- hasStepCandidate: false,
165
- hasSerdeCandidate: true,
166
- });
167
- }
168
- }
169
- }
170
- const fileEntries = Array.from(candidatesByFile.entries()).sort(([a], [b]) => a.localeCompare(b));
171
- const validatedEntries = await Promise.all(fileEntries.map(async ([filePath, candidates]) => {
172
- try {
173
- const fileStats = await (0, promises_1.stat)(filePath);
174
- if (!fileStats.isFile()) {
175
- return null;
176
- }
177
- if (!validatePatterns) {
178
- const isSdkFile = isWorkflowSdkFile(filePath);
179
- return {
180
- filePath,
181
- hasUseWorkflow: candidates.hasWorkflowCandidate,
182
- hasUseStep: candidates.hasStepCandidate,
183
- hasSerde: candidates.hasSerdeCandidate && !isSdkFile,
184
- };
185
- }
186
- const source = await (0, promises_1.readFile)(filePath, 'utf-8');
187
- const patterns = detectWorkflowPatterns(source);
188
- const isSdkFile = isWorkflowSdkFile(filePath);
189
- return {
190
- filePath,
191
- hasUseWorkflow: patterns.hasUseWorkflow,
192
- hasUseStep: patterns.hasUseStep,
193
- hasSerde: patterns.hasSerde && !isSdkFile,
194
- };
195
- }
196
- catch {
197
- return null;
198
- }
199
- }));
200
- const workflowFiles = new Set();
201
- const stepFiles = new Set();
202
- const serdeFiles = new Set();
203
- for (const entry of validatedEntries) {
204
- if (!entry) {
205
- continue;
206
- }
207
- if (entry.hasUseWorkflow) {
208
- workflowFiles.add(entry.filePath);
209
- }
210
- if (entry.hasUseStep) {
211
- stepFiles.add(entry.filePath);
212
- }
213
- if (entry.hasSerde) {
214
- serdeFiles.add(entry.filePath);
215
- }
216
- }
217
- return { workflowFiles, stepFiles, serdeFiles };
218
- }
219
- async validateDiscoveredEntryFiles() {
220
- const workflowCandidates = new Set(this.discoveredWorkflowFiles);
221
- const stepCandidates = new Set(this.discoveredStepFiles);
222
- const serdeCandidates = new Set(this.discoveredSerdeFiles);
223
- const { workflowFiles, stepFiles, serdeFiles } = await this.reconcileDiscoveredEntries({
224
- workflowCandidates,
225
- stepCandidates,
226
- serdeCandidates,
227
- validatePatterns: true,
228
- });
229
- // Reconcile validated entries against the snapshot we started with so
230
- // file discoveries that arrive during validation are preserved.
231
- let workflowsChanged = false;
232
- let stepsChanged = false;
233
- let serdeChanged = false;
234
- for (const filePath of workflowCandidates) {
235
- if (!workflowFiles.has(filePath)) {
236
- workflowsChanged =
237
- this.discoveredWorkflowFiles.delete(filePath) || workflowsChanged;
238
- }
239
- }
240
- for (const filePath of workflowFiles) {
241
- if (!this.discoveredWorkflowFiles.has(filePath)) {
242
- this.discoveredWorkflowFiles.add(filePath);
243
- workflowsChanged = true;
244
- }
245
- }
246
- for (const filePath of stepCandidates) {
247
- if (!stepFiles.has(filePath)) {
248
- stepsChanged =
249
- this.discoveredStepFiles.delete(filePath) || stepsChanged;
250
- }
251
- }
252
- for (const filePath of stepFiles) {
253
- if (!this.discoveredStepFiles.has(filePath)) {
254
- this.discoveredStepFiles.add(filePath);
255
- stepsChanged = true;
256
- }
257
- }
258
- for (const filePath of serdeCandidates) {
259
- if (!serdeFiles.has(filePath)) {
260
- serdeChanged =
261
- this.discoveredSerdeFiles.delete(filePath) || serdeChanged;
262
- }
263
- }
264
- for (const filePath of serdeFiles) {
265
- if (!this.discoveredSerdeFiles.has(filePath)) {
266
- this.discoveredSerdeFiles.add(filePath);
267
- serdeChanged = true;
268
- }
269
- }
270
- if (workflowsChanged || stepsChanged) {
271
- this.scheduleWorkflowsCacheWrite();
272
- }
273
- }
274
- async buildDiscoveredFiles(inputFiles, implicitStepFiles) {
275
- const outputDir = await this.findAppDirectory();
276
- const workflowGeneratedDir = (0, node_path_1.join)(outputDir, '.well-known/workflow/v1');
277
- const cacheDir = (0, node_path_1.join)(this.config.workingDir, this.getDistDir(), 'cache');
278
- await (0, promises_1.mkdir)(cacheDir, { recursive: true });
279
- const manifestBuildDir = (0, node_path_1.join)(cacheDir, 'workflow-generated-manifest');
280
- const tempRouteFileName = 'route.js.temp';
281
- const trackedDiscoveredEntries = await this.collectTrackedDiscoveredEntries();
282
- const discoveredStepFileCandidates = Array.from(new Set([
283
- ...this.discoveredStepFiles,
284
- ...trackedDiscoveredEntries.discoveredSteps,
285
- ...implicitStepFiles,
286
- ])).sort();
287
- const discoveredWorkflowFileCandidates = Array.from(new Set([
288
- ...this.discoveredWorkflowFiles,
289
- ...trackedDiscoveredEntries.discoveredWorkflows,
290
- ])).sort();
291
- const discoveredSerdeFileCandidates = Array.from(new Set([
292
- ...this.discoveredSerdeFiles,
293
- ...trackedDiscoveredEntries.discoveredSerdeFiles,
294
- ])).sort();
295
- const discoveredStepFiles = await this.filterExistingFiles(discoveredStepFileCandidates);
296
- const discoveredWorkflowFiles = await this.filterExistingFiles(discoveredWorkflowFileCandidates);
297
- const existingSerdeFileCandidates = await this.filterExistingFiles(discoveredSerdeFileCandidates);
298
- const discoveredSerdeFiles = await this.collectTransitiveSerdeFiles({
299
- entryFiles: [...discoveredStepFiles, ...discoveredWorkflowFiles],
300
- serdeFiles: existingSerdeFileCandidates,
301
- });
302
- const discoveredEntries = {
303
- discoveredSteps: discoveredStepFiles,
304
- discoveredWorkflows: discoveredWorkflowFiles,
305
- discoveredSerdeFiles,
306
- };
307
- const existingInputFiles = await this.filterExistingFiles(inputFiles);
308
- const buildInputFiles = Array.from(new Set([
309
- ...existingInputFiles,
310
- ...discoveredStepFiles,
311
- ...discoveredWorkflowFiles,
312
- ...discoveredSerdeFiles,
313
- ])).sort();
314
- // Ensure output directories exist
315
- await (0, promises_1.mkdir)(workflowGeneratedDir, { recursive: true });
316
- await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, '.gitignore'), '*');
317
- const tsconfigPath = await this.findTsConfigPath();
318
- const options = {
319
- inputFiles: buildInputFiles,
320
- workflowGeneratedDir,
321
- tsconfigPath,
322
- routeFileName: tempRouteFileName,
323
- discoveredEntries,
324
- };
325
- const { manifest: stepsManifest } = await this.buildStepsFunction(options);
326
- const workflowsBundle = await this.buildWorkflowsFunction(options);
327
- await this.buildWebhookRoute({
328
- workflowGeneratedDir,
329
- routeFileName: tempRouteFileName,
330
- });
331
- await this.refreshTrackedDependencyFiles(workflowGeneratedDir, tempRouteFileName);
332
- // Merge manifests from both bundles
333
- const manifest = {
334
- steps: { ...stepsManifest.steps, ...workflowsBundle?.manifest?.steps },
335
- workflows: {
336
- ...stepsManifest.workflows,
337
- ...workflowsBundle?.manifest?.workflows,
338
- },
339
- classes: {
340
- ...stepsManifest.classes,
341
- ...workflowsBundle?.manifest?.classes,
342
- },
343
- };
344
- const manifestFilePath = (0, node_path_1.join)(workflowGeneratedDir, 'manifest.json');
345
- const manifestBuildPath = (0, node_path_1.join)(manifestBuildDir, 'manifest.json');
346
- const workflowBundlePath = (0, node_path_1.join)(workflowGeneratedDir, `flow/${tempRouteFileName}`);
347
- const manifestJson = await this.createManifest({
348
- workflowBundlePath,
349
- manifestDir: manifestBuildDir,
350
- manifest,
351
- });
352
- if (manifestJson) {
353
- await this.rewriteJsonFileWithStableKeyOrder(manifestBuildPath);
354
- await this.copyFileIfChanged(manifestBuildPath, manifestFilePath);
355
- }
356
- else {
357
- await (0, promises_1.rm)(manifestBuildPath, { force: true });
358
- await (0, promises_1.rm)(manifestFilePath, { force: true });
359
- }
360
- await this.writeFunctionsConfig(outputDir);
361
- await this.copyFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, `flow/${tempRouteFileName}`), (0, node_path_1.join)(workflowGeneratedDir, 'flow/route.js'));
362
- await this.copyFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, `step/${tempRouteFileName}`), (0, node_path_1.join)(workflowGeneratedDir, 'step/route.js'));
363
- await this.copyFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, `webhook/[token]/${tempRouteFileName}`), (0, node_path_1.join)(workflowGeneratedDir, 'webhook/[token]/route.js'));
364
- // Expose manifest as a static file when WORKFLOW_PUBLIC_MANIFEST=1.
365
- // Next.js serves files from public/ at the root URL.
366
- if (this.shouldExposePublicManifest && manifestJson) {
367
- const publicManifestDir = (0, node_path_1.join)(this.config.workingDir, 'public/.well-known/workflow/v1');
368
- await (0, promises_1.mkdir)(publicManifestDir, { recursive: true });
369
- if (process.env.VERCEL_DEPLOYMENT_ID === undefined) {
370
- await this.writeFileIfChanged((0, node_path_1.join)(publicManifestDir, '.gitignore'), '*');
371
- }
372
- await this.copyFileIfChanged(manifestFilePath, (0, node_path_1.join)(publicManifestDir, 'manifest.json'));
373
- }
374
- // Notify deferred entry loaders waiting on route.js stubs.
375
- this.socketIO?.emit('build-complete');
376
- }
377
- async cleanupGeneratedArtifactsOnBoot(outputDir) {
378
- const workflowGeneratedDir = (0, node_path_1.join)(outputDir, '.well-known/workflow/v1');
379
- const flowRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'flow');
380
- const stepRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'step');
381
- const webhookRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'webhook/[token]');
382
- const staleArtifactPaths = [
383
- (0, node_path_1.join)(flowRouteDir, 'route.js.temp'),
384
- (0, node_path_1.join)(flowRouteDir, 'route.js.temp.debug.json'),
385
- (0, node_path_1.join)(flowRouteDir, 'route.js.debug.json'),
386
- (0, node_path_1.join)(stepRouteDir, 'route.js.temp'),
387
- (0, node_path_1.join)(stepRouteDir, 'route.js.temp.debug.json'),
388
- (0, node_path_1.join)(stepRouteDir, 'route.js.debug.json'),
389
- (0, node_path_1.join)(stepRouteDir, step_copy_utils_js_1.DEFERRED_STEP_COPY_DIR_NAME),
390
- (0, node_path_1.join)(webhookRouteDir, 'route.js.temp'),
391
- (0, node_path_1.join)(workflowGeneratedDir, 'manifest.json'),
392
- ];
393
- await Promise.all([
394
- ...staleArtifactPaths.map((stalePath) => (0, promises_1.rm)(stalePath, { recursive: true, force: true })),
395
- (0, socket_server_js_1.cleanupStaleSocketInfoFiles)((0, node_path_1.join)(this.config.workingDir, this.getDistDir())),
396
- this.removeStaleDeferredTempFiles(flowRouteDir),
397
- this.removeStaleDeferredTempFiles(stepRouteDir),
398
- this.removeStaleDeferredTempFiles(webhookRouteDir),
399
- ]);
400
- }
401
- async removeStaleDeferredTempFiles(routeDir) {
402
- const routeEntries = await (0, promises_1.readdir)(routeDir, {
403
- withFileTypes: true,
404
- }).catch(() => []);
405
- await Promise.all(routeEntries
406
- .filter((entry) => entry.isFile() &&
407
- entry.name.startsWith('route.js.') &&
408
- entry.name.endsWith('.tmp'))
409
- .map((entry) => (0, promises_1.rm)((0, node_path_1.join)(routeDir, entry.name), {
410
- force: true,
411
- })));
412
- }
413
- async createDiscoverySocketServer() {
414
- if (this.socketIO || process.env.WORKFLOW_SOCKET_PORT) {
415
- return;
416
- }
417
- process.env.WORKFLOW_SOCKET_INFO_PATH = this.getSocketInfoFilePath();
418
- const config = {
419
- isDevServer: Boolean(this.config.watch),
420
- socketInfoFilePath: this.getSocketInfoFilePath(),
421
- onFileDiscovered: (filePath, hasWorkflow, hasStep, hasSerde) => {
422
- const normalizedFilePath = this.normalizeDiscoveredFilePath(filePath);
423
- let hasCacheTrackingChange = false;
424
- const wasTrackedDependency = this.trackedDependencyFiles.has(normalizedFilePath);
425
- if (hasWorkflow) {
426
- if (!this.discoveredWorkflowFiles.has(normalizedFilePath)) {
427
- this.discoveredWorkflowFiles.add(normalizedFilePath);
428
- hasCacheTrackingChange = true;
429
- }
430
- }
431
- else {
432
- const wasDeleted = this.discoveredWorkflowFiles.delete(normalizedFilePath);
433
- hasCacheTrackingChange = wasDeleted || hasCacheTrackingChange;
434
- }
435
- if (hasStep) {
436
- if (!this.discoveredStepFiles.has(normalizedFilePath)) {
437
- this.discoveredStepFiles.add(normalizedFilePath);
438
- hasCacheTrackingChange = true;
439
- }
440
- }
441
- else {
442
- const wasDeleted = this.discoveredStepFiles.delete(normalizedFilePath);
443
- hasCacheTrackingChange = wasDeleted || hasCacheTrackingChange;
444
- }
445
- if (hasSerde) {
446
- if (!this.discoveredSerdeFiles.has(normalizedFilePath)) {
447
- hasCacheTrackingChange = true;
448
- }
449
- this.discoveredSerdeFiles.add(normalizedFilePath);
450
- }
451
- else {
452
- const wasDeleted = this.discoveredSerdeFiles.delete(normalizedFilePath);
453
- hasCacheTrackingChange = wasDeleted || hasCacheTrackingChange;
454
- }
455
- if (hasCacheTrackingChange) {
456
- this.scheduleWorkflowsCacheWrite();
457
- }
458
- if (hasWorkflow ||
459
- hasStep ||
460
- hasSerde ||
461
- hasCacheTrackingChange ||
462
- wasTrackedDependency) {
463
- this.scheduleDeferredRebuild();
464
- }
465
- },
466
- onTriggerBuild: () => {
467
- this.scheduleDeferredRebuild();
468
- },
469
- };
470
- this.socketIO = await (0, socket_server_js_1.createSocketServer)(config);
471
- }
472
- async initializeDiscoveryState() {
473
- if (this.cacheInitialized) {
474
- return;
475
- }
476
- await this.loadWorkflowsCache();
477
- await this.loadDiscoveredEntriesFromInputGraph();
478
- this.cacheInitialized = true;
479
- }
480
- getDistDir() {
481
- return this.config.distDir || '.next';
482
- }
483
- getWorkflowsCacheFilePath() {
484
- return (0, node_path_1.join)(this.config.workingDir, this.getDistDir(), 'cache', 'workflows.json');
485
- }
486
- getSocketInfoFilePath() {
487
- return (0, node_path_1.join)(this.config.workingDir, this.getDistDir(), socket_server_js_1.SOCKET_INFO_FILENAME);
488
- }
489
- normalizeDiscoveredFilePath(filePath) {
490
- return (0, node_path_1.isAbsolute)(filePath)
491
- ? filePath
492
- : (0, node_path_1.resolve)(this.config.workingDir, filePath);
493
- }
494
- async filterExistingFiles(filePaths) {
495
- const normalizedFilePaths = Array.from(new Set(filePaths.map((filePath) => this.normalizeDiscoveredFilePath(filePath)))).sort();
496
- const existingFiles = await Promise.all(normalizedFilePaths.map(async (filePath) => {
497
- try {
498
- const fileStats = await (0, promises_1.stat)(filePath);
499
- return fileStats.isFile() ? filePath : null;
500
- }
501
- catch {
502
- return null;
503
- }
504
- }));
505
- return existingFiles.filter((filePath) => Boolean(filePath));
506
- }
507
- async createDeferredBuildSignature(inputFiles) {
508
- const normalizedFiles = Array.from(new Set([
509
- ...inputFiles.map((filePath) => this.normalizeDiscoveredFilePath(filePath)),
510
- ...this.trackedDependencyFiles,
511
- ])).sort();
512
- const signatureParts = await Promise.all(normalizedFiles.map(async (filePath) => {
513
- try {
514
- const fileStats = await (0, promises_1.stat)(filePath);
515
- return `${filePath}:${fileStats.size}:${Math.trunc(fileStats.mtimeMs)}`;
516
- }
517
- catch {
518
- return `${filePath}:missing`;
519
- }
520
- }));
521
- const signatureHash = (0, node_crypto_1.createHash)('sha256');
522
- for (const signaturePart of signatureParts) {
523
- signatureHash.update(signaturePart);
524
- signatureHash.update('\n');
525
- }
526
- return signatureHash.digest('hex');
527
- }
528
- async collectTrackedDiscoveredEntries() {
529
- if (this.trackedDependencyFiles.size === 0) {
530
- return {
531
- discoveredSteps: [],
532
- discoveredWorkflows: [],
533
- discoveredSerdeFiles: [],
534
- };
535
- }
536
- const { workflowFiles, stepFiles, serdeFiles } = await this.reconcileDiscoveredEntries({
537
- workflowCandidates: this.trackedDependencyFiles,
538
- stepCandidates: this.trackedDependencyFiles,
539
- serdeCandidates: this.trackedDependencyFiles,
540
- validatePatterns: true,
541
- });
542
- return {
543
- discoveredSteps: Array.from(stepFiles).sort(),
544
- discoveredWorkflows: Array.from(workflowFiles).sort(),
545
- discoveredSerdeFiles: Array.from(serdeFiles).sort(),
546
- };
547
- }
548
- async refreshTrackedDependencyFiles(workflowGeneratedDir, routeFileName) {
549
- const bundleFiles = [
550
- (0, node_path_1.join)(workflowGeneratedDir, `step/${routeFileName}`),
551
- (0, node_path_1.join)(workflowGeneratedDir, `flow/${routeFileName}`),
552
- ];
553
- const trackedFiles = new Set();
554
- for (const bundleFile of bundleFiles) {
555
- const bundleSources = await this.extractBundleSourceFiles(bundleFile);
556
- for (const sourceFile of bundleSources) {
557
- trackedFiles.add(sourceFile);
558
- }
559
- }
560
- if (trackedFiles.size > 0) {
561
- this.trackedDependencyFiles = trackedFiles;
562
- }
563
- }
564
- async extractBundleSourceFiles(bundleFilePath) {
565
- let bundleContents;
566
- try {
567
- bundleContents = await (0, promises_1.readFile)(bundleFilePath, 'utf-8');
568
- }
569
- catch {
570
- return [];
571
- }
572
- const baseDirectory = (0, node_path_1.dirname)(bundleFilePath);
573
- const localSourceFiles = new Set();
574
- const sourceMapMatches = bundleContents.matchAll(/\/\/# sourceMappingURL=data:application\/json[^,]*;base64,([A-Za-z0-9+/=]+)/g);
575
- for (const match of sourceMapMatches) {
576
- const base64Value = match[1];
577
- if (!base64Value) {
578
- continue;
579
- }
580
- let sourceMap;
581
- try {
582
- sourceMap = JSON.parse(Buffer.from(base64Value, 'base64').toString('utf-8'));
583
- }
584
- catch {
585
- continue;
586
- }
587
- const sourceRoot = typeof sourceMap.sourceRoot === 'string' ? sourceMap.sourceRoot : '';
588
- const sources = Array.isArray(sourceMap.sources)
589
- ? sourceMap.sources.filter((source) => typeof source === 'string')
590
- : [];
591
- for (const source of sources) {
592
- if (source.startsWith('webpack://') || source.startsWith('<')) {
593
- continue;
594
- }
595
- let resolvedSourcePath;
596
- if (source.startsWith('file://')) {
597
- try {
598
- resolvedSourcePath = decodeURIComponent(new URL(source).pathname);
599
- }
600
- catch {
601
- continue;
602
- }
603
- }
604
- else if ((0, node_path_1.isAbsolute)(source)) {
605
- resolvedSourcePath = source;
606
- }
607
- else {
608
- resolvedSourcePath = (0, node_path_1.resolve)(baseDirectory, sourceRoot, source);
609
- }
610
- const normalizedSourcePath = this.normalizeDiscoveredFilePath(resolvedSourcePath);
611
- const normalizedSourcePathForCheck = normalizedSourcePath.replace(/\\/g, '/');
612
- if (normalizedSourcePathForCheck.includes('/.well-known/workflow/') ||
613
- normalizedSourcePathForCheck.includes('/node_modules/') ||
614
- normalizedSourcePathForCheck.includes('/.pnpm/') ||
615
- normalizedSourcePathForCheck.includes('/.next/') ||
616
- normalizedSourcePathForCheck.endsWith('/virtual-entry.js')) {
617
- continue;
618
- }
619
- localSourceFiles.add(normalizedSourcePath);
620
- }
621
- }
622
- return Array.from(localSourceFiles);
623
- }
624
- scheduleWorkflowsCacheWrite() {
625
- if (this.cacheWriteTimer) {
626
- clearTimeout(this.cacheWriteTimer);
627
- }
628
- this.cacheWriteTimer = setTimeout(() => {
629
- this.cacheWriteTimer = null;
630
- void this.writeWorkflowsCache().catch((error) => {
631
- console.warn('Failed to write workflow discovery cache', error);
632
- });
633
- }, 50);
634
- }
635
- scheduleDeferredRebuild() {
636
- if (!this.config.watch) {
637
- return;
638
- }
639
- if (this.deferredRebuildTimer) {
640
- clearTimeout(this.deferredRebuildTimer);
641
- }
642
- this.deferredRebuildTimer = setTimeout(() => {
643
- this.deferredRebuildTimer = null;
644
- void this.onBeforeDeferredEntries().catch((error) => {
645
- console.warn('[workflow] Deferred rebuild after source update failed.', error);
646
- });
647
- }, 75);
648
- }
649
- async readWorkflowsCache() {
650
- const cacheFilePath = this.getWorkflowsCacheFilePath();
651
- try {
652
- const cacheContents = await (0, promises_1.readFile)(cacheFilePath, 'utf-8');
653
- const parsed = JSON.parse(cacheContents);
654
- const workflowFiles = Array.isArray(parsed.workflowFiles)
655
- ? parsed.workflowFiles.filter((item) => typeof item === 'string')
656
- : [];
657
- const stepFiles = Array.isArray(parsed.stepFiles)
658
- ? parsed.stepFiles.filter((item) => typeof item === 'string')
659
- : [];
660
- return { workflowFiles, stepFiles };
661
- }
662
- catch {
663
- return null;
664
- }
665
- }
666
- async loadWorkflowsCache() {
667
- const cachedData = await this.readWorkflowsCache();
668
- if (!cachedData) {
669
- return;
670
- }
671
- const { workflowFiles, stepFiles, serdeFiles } = await this.reconcileDiscoveredEntries({
672
- workflowCandidates: cachedData.workflowFiles,
673
- stepCandidates: cachedData.stepFiles,
674
- serdeCandidates: this.discoveredSerdeFiles,
675
- validatePatterns: true,
676
- });
677
- this.discoveredWorkflowFiles.clear();
678
- this.discoveredStepFiles.clear();
679
- this.discoveredSerdeFiles.clear();
680
- for (const filePath of workflowFiles) {
681
- this.discoveredWorkflowFiles.add(filePath);
682
- }
683
- for (const filePath of stepFiles) {
684
- this.discoveredStepFiles.add(filePath);
685
- }
686
- for (const filePath of serdeFiles) {
687
- this.discoveredSerdeFiles.add(filePath);
688
- }
689
- }
690
- async loadDiscoveredEntriesFromInputGraph() {
691
- const inputFiles = await this.getInputFiles();
692
- if (inputFiles.length === 0) {
693
- return;
694
- }
695
- const { discoveredWorkflows, discoveredSteps, discoveredSerdeFiles } = await this.discoverEntries(inputFiles, this.config.workingDir);
696
- const { workflowFiles, stepFiles, serdeFiles } = await this.reconcileDiscoveredEntries({
697
- workflowCandidates: discoveredWorkflows,
698
- stepCandidates: discoveredSteps,
699
- serdeCandidates: discoveredSerdeFiles,
700
- validatePatterns: true,
701
- });
702
- let hasChanges = false;
703
- for (const filePath of workflowFiles) {
704
- if (!this.discoveredWorkflowFiles.has(filePath)) {
705
- this.discoveredWorkflowFiles.add(filePath);
706
- hasChanges = true;
707
- }
708
- }
709
- for (const filePath of stepFiles) {
710
- if (!this.discoveredStepFiles.has(filePath)) {
711
- this.discoveredStepFiles.add(filePath);
712
- hasChanges = true;
713
- }
714
- }
715
- for (const filePath of serdeFiles) {
716
- if (!this.discoveredSerdeFiles.has(filePath)) {
717
- this.discoveredSerdeFiles.add(filePath);
718
- hasChanges = true;
719
- }
720
- }
721
- if (hasChanges) {
722
- this.scheduleWorkflowsCacheWrite();
723
- }
724
- }
725
- async writeWorkflowsCache() {
726
- const cacheFilePath = this.getWorkflowsCacheFilePath();
727
- const cacheDir = (0, node_path_1.join)(this.config.workingDir, this.getDistDir(), 'cache');
728
- await (0, promises_1.mkdir)(cacheDir, { recursive: true });
729
- const cacheData = {
730
- workflowFiles: Array.from(this.discoveredWorkflowFiles).sort(),
731
- stepFiles: Array.from(this.discoveredStepFiles).sort(),
732
- };
733
- await (0, promises_1.writeFile)(cacheFilePath, JSON.stringify(cacheData, null, 2));
734
- }
735
- async writeStubFiles(outputDir) {
736
- // Turbopack currently has a worker-concurrency limitation for pending
737
- // virtual entries. Warn if parallelism is too low to reliably discover.
738
- const parallelismCount = node_os_1.default.availableParallelism();
739
- if (process.env.TURBOPACK && parallelismCount < 4) {
740
- console.warn(`Available parallelism of ${parallelismCount} is less than needed 4. This can cause workflows/steps to fail to discover properly in turbopack`);
741
- }
742
- const routeStubContent = [
743
- `// ${ROUTE_STUB_FILE_MARKER}`,
744
- 'export const __workflowRouteStub = true;',
745
- ].join('\n');
746
- const workflowGeneratedDir = (0, node_path_1.join)(outputDir, '.well-known/workflow/v1');
747
- await (0, promises_1.mkdir)((0, node_path_1.join)(workflowGeneratedDir, 'flow'), { recursive: true });
748
- await (0, promises_1.mkdir)((0, node_path_1.join)(workflowGeneratedDir, 'step'), { recursive: true });
749
- await (0, promises_1.mkdir)((0, node_path_1.join)(workflowGeneratedDir, 'webhook/[token]'), {
750
- recursive: true,
751
- });
752
- await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, '.gitignore'), '*');
753
- // route.js stubs are replaced by generated route.js output once discovery
754
- // finishes and a deferred build completes.
755
- await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, 'flow/route.js'), routeStubContent);
756
- await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, 'step/route.js'), routeStubContent);
757
- await this.writeFileIfChanged((0, node_path_1.join)(workflowGeneratedDir, 'webhook/[token]/route.js'), routeStubContent);
758
- }
759
- async getInputFiles() {
760
- const inputFiles = await super.getInputFiles();
761
- return inputFiles.filter((item) => {
762
- // Match App Router entrypoints: route.ts, page.ts, layout.ts in app/ or src/app/ directories
763
- // Matches: /app/page.ts, /app/dashboard/page.ts, /src/app/route.ts, etc.
764
- if (item.match(/(^|.*[/\\])(app|src[/\\]app)([/\\](route|page|layout)\.|[/\\].*[/\\](route|page|layout)\.)/)) {
765
- return true;
766
- }
767
- // Match Pages Router entrypoints: files in pages/ or src/pages/
768
- if (item.match(/[/\\](pages|src[/\\]pages)[/\\]/)) {
769
- return true;
770
- }
771
- return false;
772
- });
773
- }
774
- async writeFunctionsConfig(outputDir) {
775
- // we don't run this in development mode as it's not needed
776
- if (process.env.NODE_ENV === 'development') {
777
- return;
778
- }
779
- const generatedConfig = {
780
- version: '0',
781
- steps: {
782
- maxDuration: 'max',
783
- experimentalTriggers: [STEP_QUEUE_TRIGGER],
784
- },
785
- workflows: {
786
- maxDuration: 'max',
787
- experimentalTriggers: [WORKFLOW_QUEUE_TRIGGER],
788
- },
789
- };
790
- // We write this file to the generated directory for
791
- // the Next.js builder to consume
792
- await this.writeFileIfChanged((0, node_path_1.join)(outputDir, '.well-known/workflow/v1/config.json'), JSON.stringify(generatedConfig, null, 2));
793
- }
794
- async writeFileIfChanged(filePath, contents) {
795
- const nextBuffer = Buffer.isBuffer(contents)
796
- ? contents
797
- : Buffer.from(contents);
798
- try {
799
- const currentBuffer = await (0, promises_1.readFile)(filePath);
800
- if (currentBuffer.equals(nextBuffer)) {
801
- return false;
802
- }
803
- }
804
- catch {
805
- // File does not exist yet or cannot be read; write a fresh copy.
806
- }
807
- await (0, promises_1.mkdir)((0, node_path_1.dirname)(filePath), { recursive: true });
808
- await (0, promises_1.writeFile)(filePath, nextBuffer);
809
- return true;
810
- }
811
- async copyFileIfChanged(sourcePath, destinationPath) {
812
- const sourceContents = await (0, promises_1.readFile)(sourcePath);
813
- return this.writeFileIfChanged(destinationPath, sourceContents);
814
- }
815
- sortJsonValue(value) {
816
- if (Array.isArray(value)) {
817
- return value.map((item) => this.sortJsonValue(item));
818
- }
819
- if (value && typeof value === 'object') {
820
- const sortedEntries = Object.entries(value)
821
- .sort(([a], [b]) => a.localeCompare(b))
822
- .map(([key, entryValue]) => [key, this.sortJsonValue(entryValue)]);
823
- return Object.fromEntries(sortedEntries);
824
- }
825
- return value;
826
- }
827
- async rewriteJsonFileWithStableKeyOrder(filePath) {
828
- try {
829
- const contents = await (0, promises_1.readFile)(filePath, 'utf-8');
830
- const parsed = JSON.parse(contents);
831
- const normalized = this.sortJsonValue(parsed);
832
- await this.writeFileIfChanged(filePath, `${JSON.stringify(normalized, null, 2)}\n`);
833
- }
834
- catch {
835
- // Manifest may not exist (e.g. manifest generation failed); ignore.
836
- }
837
- }
838
- mergeWorkflowManifest(target, source) {
839
- if (source.steps) {
840
- target.steps = Object.assign(target.steps || {}, source.steps);
841
- }
842
- if (source.workflows) {
843
- target.workflows = Object.assign(target.workflows || {}, source.workflows);
844
- }
845
- if (source.classes) {
846
- target.classes = Object.assign(target.classes || {}, source.classes);
847
- }
848
- }
849
- async getRelativeFilenameForSwc(filePath) {
850
- const workingDir = this.config.workingDir;
851
- const normalizedWorkingDir = workingDir
852
- .replace(/\\/g, '/')
853
- .replace(/\/$/, '');
854
- const normalizedFilepath = filePath.replace(/\\/g, '/');
855
- // Windows fix: Use case-insensitive comparison to work around drive letter casing issues.
856
- const lowerWd = normalizedWorkingDir.toLowerCase();
857
- const lowerPath = normalizedFilepath.toLowerCase();
858
- let relativeFilename;
859
- if (lowerPath.startsWith(`${lowerWd}/`)) {
860
- relativeFilename = normalizedFilepath.substring(normalizedWorkingDir.length + 1);
861
- }
862
- else if (lowerPath === lowerWd) {
863
- relativeFilename = '.';
864
- }
865
- else {
866
- relativeFilename = (0, node_path_1.relative)(workingDir, filePath).replace(/\\/g, '/');
867
- if (relativeFilename.startsWith('../')) {
868
- const aliasedRelativePath = await resolveWorkflowAliasRelativePath(filePath, workingDir);
869
- if (aliasedRelativePath) {
870
- relativeFilename = aliasedRelativePath;
871
- }
872
- else {
873
- relativeFilename = relativeFilename
874
- .split('/')
875
- .filter((part) => part !== '..')
876
- .join('/');
877
- }
878
- }
879
- }
880
- if (relativeFilename.includes(':') || relativeFilename.startsWith('/')) {
881
- relativeFilename = (0, node_path_1.basename)(normalizedFilepath);
882
- }
883
- return relativeFilename;
884
- }
885
- getRelativeImportSpecifier(fromFilePath, toFilePath) {
886
- let relativePath = (0, node_path_1.relative)((0, node_path_1.dirname)(fromFilePath), toFilePath).replace(/\\/g, '/');
887
- if (!relativePath.startsWith('.')) {
888
- relativePath = `./${relativePath}`;
889
- }
890
- return relativePath;
891
- }
892
- getStepCopyFileName(filePath) {
893
- const normalizedPath = filePath.replace(/\\/g, '/');
894
- const hash = (0, node_crypto_1.createHash)('sha256').update(normalizedPath).digest('hex');
895
- const extension = (0, node_path_1.extname)(normalizedPath);
896
- return `${hash.slice(0, 16)}${extension || '.js'}`;
897
- }
898
- rewriteCopiedStepImportSpecifier(specifier, sourceFilePath, copiedFilePath, copiedStepFileBySourcePath) {
899
- if (!specifier.startsWith('.')) {
900
- return specifier;
901
- }
902
- const specifierMatch = specifier.match(/^([^?#]+)(.*)$/);
903
- const importPath = specifierMatch?.[1] ?? specifier;
904
- const suffix = specifierMatch?.[2] ?? '';
905
- const absoluteTargetPath = (0, node_path_1.resolve)((0, node_path_1.dirname)(sourceFilePath), importPath);
906
- const resolvedTargetPath = this.resolveCopiedStepImportTargetPath(absoluteTargetPath);
907
- const normalizedTargetPath = resolvedTargetPath.replace(/\\/g, '/');
908
- const copiedTargetPath = copiedStepFileBySourcePath.get(normalizedTargetPath) ||
909
- (() => {
910
- try {
911
- const realTargetPath = (0, node_fs_1.realpathSync)(resolvedTargetPath).replace(/\\/g, '/');
912
- return copiedStepFileBySourcePath.get(realTargetPath);
913
- }
914
- catch {
915
- return undefined;
916
- }
917
- })();
918
- let rewrittenPath = (0, node_path_1.relative)((0, node_path_1.dirname)(copiedFilePath), copiedTargetPath || resolvedTargetPath).replace(/\\/g, '/');
919
- if (!rewrittenPath.startsWith('.')) {
920
- rewrittenPath = `./${rewrittenPath}`;
921
- }
922
- return `${rewrittenPath}${suffix}`;
923
- }
924
- resolveCopiedStepImportTargetPath(targetPath) {
925
- if ((0, node_fs_1.existsSync)(targetPath)) {
926
- return targetPath;
927
- }
928
- const extensionMatch = targetPath.match(/(\.[^./\\]+)$/);
929
- const extension = extensionMatch?.[1]?.toLowerCase();
930
- if (!extension) {
931
- return targetPath;
932
- }
933
- const extensionFallbacks = extension === '.js'
934
- ? ['.ts', '.tsx', '.mts', '.cts']
935
- : extension === '.mjs'
936
- ? ['.mts']
937
- : extension === '.cjs'
938
- ? ['.cts']
939
- : extension === '.jsx'
940
- ? ['.tsx']
941
- : [];
942
- if (extensionFallbacks.length === 0) {
943
- return targetPath;
944
- }
945
- const targetWithoutExtension = targetPath.slice(0, -extension.length);
946
- for (const fallbackExtension of extensionFallbacks) {
947
- const fallbackPath = `${targetWithoutExtension}${fallbackExtension}`;
948
- if ((0, node_fs_1.existsSync)(fallbackPath)) {
949
- return fallbackPath;
950
- }
951
- }
952
- return targetPath;
953
- }
954
- rewriteRelativeImportsForCopiedStep(source, sourceFilePath, copiedFilePath, copiedStepFileBySourcePath) {
955
- const rewriteSpecifier = (specifier) => this.rewriteCopiedStepImportSpecifier(specifier, sourceFilePath, copiedFilePath, copiedStepFileBySourcePath);
956
- const rewritePattern = (currentSource, pattern) => currentSource.replace(pattern, (_match, prefix, specifier, suffix) => `${prefix}${rewriteSpecifier(specifier)}${suffix}`);
957
- let rewrittenSource = source;
958
- rewrittenSource = rewritePattern(rewrittenSource, /(from\s+['"])([^'"]+)(['"])/g);
959
- rewrittenSource = rewritePattern(rewrittenSource, /(import\s+['"])([^'"]+)(['"])/g);
960
- rewrittenSource = rewritePattern(rewrittenSource, /(import\(\s*['"])([^'"]+)(['"]\s*\))/g);
961
- rewrittenSource = rewritePattern(rewrittenSource, /(require\(\s*['"])([^'"]+)(['"]\s*\))/g);
962
- return rewrittenSource;
963
- }
964
- extractRelativeImportSpecifiers(source) {
965
- const relativeSpecifiers = new Set();
966
- const importPatterns = [
967
- /from\s+['"]([^'"]+)['"]/g,
968
- /import\s+['"]([^'"]+)['"]/g,
969
- /import\(\s*['"]([^'"]+)['"]\s*\)/g,
970
- /require\(\s*['"]([^'"]+)['"]\s*\)/g,
971
- ];
972
- for (const importPattern of importPatterns) {
973
- for (const match of source.matchAll(importPattern)) {
974
- const specifier = match[1];
975
- if (specifier?.startsWith('.')) {
976
- relativeSpecifiers.add(specifier);
977
- }
978
- }
979
- }
980
- return Array.from(relativeSpecifiers);
981
- }
982
- shouldSkipTransitiveStepFile(filePath) {
983
- const normalizedPath = filePath.replace(/\\/g, '/');
984
- return (normalizedPath.includes('/.well-known/workflow/') ||
985
- normalizedPath.includes('/.next/') ||
986
- normalizedPath.includes('/node_modules/') ||
987
- normalizedPath.includes('/.pnpm/'));
988
- }
989
- async resolveTransitiveStepImportTargetPath(sourceFilePath, specifier) {
990
- const specifierMatch = specifier.match(/^([^?#]+)(.*)$/);
991
- const importPath = specifierMatch?.[1] ?? specifier;
992
- const absoluteTargetPath = (0, node_path_1.resolve)((0, node_path_1.dirname)(sourceFilePath), importPath);
993
- const candidatePaths = new Set([
994
- this.resolveCopiedStepImportTargetPath(absoluteTargetPath),
995
- ]);
996
- if (!(0, node_path_1.extname)(absoluteTargetPath)) {
997
- const extensionCandidates = [
998
- '.ts',
999
- '.tsx',
1000
- '.mts',
1001
- '.cts',
1002
- '.js',
1003
- '.jsx',
1004
- '.mjs',
1005
- '.cjs',
1006
- ];
1007
- for (const extensionCandidate of extensionCandidates) {
1008
- candidatePaths.add(`${absoluteTargetPath}${extensionCandidate}`);
1009
- candidatePaths.add((0, node_path_1.join)(absoluteTargetPath, `index${extensionCandidate}`));
1010
- }
1011
- }
1012
- for (const candidatePath of candidatePaths) {
1013
- const resolvedPath = this.resolveCopiedStepImportTargetPath(candidatePath);
1014
- const normalizedResolvedPath = this.normalizeDiscoveredFilePath(resolvedPath);
1015
- if (this.shouldSkipTransitiveStepFile(normalizedResolvedPath)) {
1016
- continue;
1017
- }
1018
- try {
1019
- const fileStats = await (0, promises_1.stat)(normalizedResolvedPath);
1020
- if (fileStats.isFile()) {
1021
- return normalizedResolvedPath;
1022
- }
1023
- }
1024
- catch {
1025
- // Try the next candidate path.
1026
- }
1027
- }
1028
- return null;
1029
- }
1030
- async collectTransitiveStepFiles({ stepFiles, seedFiles = [], }) {
1031
- const normalizedSeedFiles = Array.from(new Set([...stepFiles, ...seedFiles].map((stepFile) => this.normalizeDiscoveredFilePath(stepFile)))).sort();
1032
- // Intentionally re-validate step seeds against current file contents
1033
- // instead of blindly trusting callers. This prevents stale/manual seed
1034
- // paths from persisting when files no longer contain "use step".
1035
- const discoveredStepFiles = new Set();
1036
- const queuedFiles = [...normalizedSeedFiles];
1037
- const visitedFiles = new Set();
1038
- const sourceCache = new Map();
1039
- const patternCache = new Map();
1040
- const getSource = async (filePath) => {
1041
- if (sourceCache.has(filePath)) {
1042
- return sourceCache.get(filePath) ?? null;
1043
- }
1044
- try {
1045
- const source = await (0, promises_1.readFile)(filePath, 'utf-8');
1046
- sourceCache.set(filePath, source);
1047
- return source;
1048
- }
1049
- catch {
1050
- sourceCache.set(filePath, null);
1051
- return null;
1052
- }
1053
- };
1054
- const getPatterns = async (filePath) => {
1055
- if (patternCache.has(filePath)) {
1056
- return patternCache.get(filePath) ?? null;
1057
- }
1058
- const source = await getSource(filePath);
1059
- if (source === null) {
1060
- patternCache.set(filePath, null);
1061
- return null;
1062
- }
1063
- const patterns = detectWorkflowPatterns(source);
1064
- patternCache.set(filePath, patterns);
1065
- return patterns;
1066
- };
1067
- while (queuedFiles.length > 0) {
1068
- const currentFile = queuedFiles.pop();
1069
- if (!currentFile || visitedFiles.has(currentFile)) {
1070
- continue;
1071
- }
1072
- visitedFiles.add(currentFile);
1073
- const currentSource = await getSource(currentFile);
1074
- if (currentSource === null) {
1075
- continue;
1076
- }
1077
- const currentPatterns = await getPatterns(currentFile);
1078
- if (currentPatterns?.hasUseStep) {
1079
- discoveredStepFiles.add(currentFile);
1080
- }
1081
- const relativeImportSpecifiers = this.extractRelativeImportSpecifiers(currentSource);
1082
- for (const specifier of relativeImportSpecifiers) {
1083
- const resolvedImportPath = await this.resolveTransitiveStepImportTargetPath(currentFile, specifier);
1084
- if (!resolvedImportPath) {
1085
- continue;
1086
- }
1087
- if (!visitedFiles.has(resolvedImportPath)) {
1088
- queuedFiles.push(resolvedImportPath);
1089
- }
1090
- const importPatterns = await getPatterns(resolvedImportPath);
1091
- if (importPatterns?.hasUseStep) {
1092
- discoveredStepFiles.add(resolvedImportPath);
1093
- }
1094
- }
1095
- }
1096
- return Array.from(discoveredStepFiles).sort();
1097
- }
1098
- async collectTransitiveSerdeFiles({ entryFiles, serdeFiles, }) {
1099
- const normalizedEntryFiles = Array.from(new Set(entryFiles.map((entryFile) => this.normalizeDiscoveredFilePath(entryFile)))).sort();
1100
- const normalizedSerdeSeedFiles = Array.from(new Set(serdeFiles.map((serdeFile) => this.normalizeDiscoveredFilePath(serdeFile)))).sort();
1101
- // Intentionally re-validate serde seeds against source + SDK filtering.
1102
- // This keeps previously discovered/manual seed entries from sticking when
1103
- // files no longer match serde patterns or resolve to SDK internals.
1104
- const discoveredSerdeFiles = new Set();
1105
- const queuedFiles = Array.from(new Set([...normalizedEntryFiles, ...normalizedSerdeSeedFiles]));
1106
- const visitedFiles = new Set();
1107
- const sourceCache = new Map();
1108
- const patternCache = new Map();
1109
- const getSource = async (filePath) => {
1110
- if (sourceCache.has(filePath)) {
1111
- return sourceCache.get(filePath) ?? null;
1112
- }
1113
- try {
1114
- const source = await (0, promises_1.readFile)(filePath, 'utf-8');
1115
- sourceCache.set(filePath, source);
1116
- return source;
1117
- }
1118
- catch {
1119
- sourceCache.set(filePath, null);
1120
- return null;
1121
- }
1122
- };
1123
- const getPatterns = async (filePath) => {
1124
- if (patternCache.has(filePath)) {
1125
- return patternCache.get(filePath) ?? null;
1126
- }
1127
- const source = await getSource(filePath);
1128
- if (source === null) {
1129
- patternCache.set(filePath, null);
1130
- return null;
1131
- }
1132
- const patterns = detectWorkflowPatterns(source);
1133
- patternCache.set(filePath, patterns);
1134
- return patterns;
1135
- };
1136
- for (const serdeSeedFile of normalizedSerdeSeedFiles) {
1137
- const seedPatterns = await getPatterns(serdeSeedFile);
1138
- if (seedPatterns?.hasSerde && !isWorkflowSdkFile(serdeSeedFile)) {
1139
- discoveredSerdeFiles.add(serdeSeedFile);
1140
- }
1141
- }
1142
- while (queuedFiles.length > 0) {
1143
- const currentFile = queuedFiles.pop();
1144
- if (!currentFile || visitedFiles.has(currentFile)) {
1145
- continue;
1146
- }
1147
- visitedFiles.add(currentFile);
1148
- const currentSource = await getSource(currentFile);
1149
- if (currentSource === null) {
1150
- continue;
1151
- }
1152
- const relativeImportSpecifiers = this.extractRelativeImportSpecifiers(currentSource);
1153
- for (const specifier of relativeImportSpecifiers) {
1154
- const resolvedImportPath = await this.resolveTransitiveStepImportTargetPath(currentFile, specifier);
1155
- if (!resolvedImportPath) {
1156
- continue;
1157
- }
1158
- if (!visitedFiles.has(resolvedImportPath)) {
1159
- queuedFiles.push(resolvedImportPath);
1160
- }
1161
- const importPatterns = await getPatterns(resolvedImportPath);
1162
- if (importPatterns?.hasSerde &&
1163
- !isWorkflowSdkFile(resolvedImportPath)) {
1164
- discoveredSerdeFiles.add(resolvedImportPath);
1165
- }
1166
- }
1167
- }
1168
- return Array.from(discoveredSerdeFiles).sort();
1169
- }
1170
- async createResponseBuiltinsStepFile({ stepsRouteDir, }) {
1171
- const copiedStepsDir = (0, node_path_1.join)(stepsRouteDir, step_copy_utils_js_1.DEFERRED_STEP_COPY_DIR_NAME);
1172
- await (0, promises_1.mkdir)(copiedStepsDir, { recursive: true });
1173
- const responseBuiltinsFilePath = (0, node_path_1.join)(copiedStepsDir, 'workflow-response-builtins.ts');
1174
- const source = [
1175
- 'export async function __builtin_response_array_buffer(this: Request | Response) {',
1176
- " 'use step';",
1177
- ' return this.arrayBuffer();',
1178
- '}',
1179
- '',
1180
- 'export async function __builtin_response_json(this: Request | Response) {',
1181
- " 'use step';",
1182
- ' return this.json();',
1183
- '}',
1184
- '',
1185
- 'export async function __builtin_response_text(this: Request | Response) {',
1186
- " 'use step';",
1187
- ' return this.text();',
1188
- '}',
1189
- ].join('\n');
1190
- const sourceMapComment = (0, step_copy_utils_js_1.createDeferredStepCopyInlineSourceMapComment)({
1191
- sourcePath: responseBuiltinsFilePath,
1192
- sourceContent: source,
1193
- });
1194
- await this.writeFileIfChanged(responseBuiltinsFilePath, `${source}\n${sourceMapComment}\n`);
1195
- return responseBuiltinsFilePath;
1196
- }
1197
- async copyDiscoveredStepFiles({ stepFiles, stepsRouteDir, }) {
1198
- const copiedStepsDir = (0, node_path_1.join)(stepsRouteDir, step_copy_utils_js_1.DEFERRED_STEP_COPY_DIR_NAME);
1199
- await (0, promises_1.mkdir)(copiedStepsDir, { recursive: true });
1200
- const normalizedStepFiles = Array.from(new Set(stepFiles.map((stepFile) => this.normalizeDiscoveredFilePath(stepFile)))).sort();
1201
- const copiedStepFileBySourcePath = new Map();
1202
- const expectedFileNames = new Set();
1203
- const copiedStepFiles = [];
1204
- for (const normalizedStepFile of normalizedStepFiles) {
1205
- const copiedFileName = this.getStepCopyFileName(normalizedStepFile);
1206
- const copiedFilePath = (0, node_path_1.join)(copiedStepsDir, copiedFileName);
1207
- const normalizedPathKey = normalizedStepFile.replace(/\\/g, '/');
1208
- copiedStepFileBySourcePath.set(normalizedPathKey, copiedFilePath);
1209
- try {
1210
- const realPathKey = (0, node_fs_1.realpathSync)(normalizedStepFile).replace(/\\/g, '/');
1211
- copiedStepFileBySourcePath.set(realPathKey, copiedFilePath);
1212
- }
1213
- catch {
1214
- // Keep best-effort mapping when source cannot be realpath-resolved.
1215
- }
1216
- expectedFileNames.add(copiedFileName);
1217
- copiedStepFiles.push(copiedFilePath);
1218
- }
1219
- for (const normalizedStepFile of normalizedStepFiles) {
1220
- const source = await (0, promises_1.readFile)(normalizedStepFile, 'utf-8');
1221
- const copiedFilePath = copiedStepFileBySourcePath.get(normalizedStepFile.replace(/\\/g, '/'));
1222
- if (!copiedFilePath) {
1223
- continue;
1224
- }
1225
- const rewrittenSource = this.rewriteRelativeImportsForCopiedStep(source, normalizedStepFile, copiedFilePath, copiedStepFileBySourcePath);
1226
- const metadataComment = (0, step_copy_utils_js_1.createDeferredStepSourceMetadataComment)({
1227
- relativeFilename: await this.getRelativeFilenameForSwc(normalizedStepFile),
1228
- absolutePath: normalizedStepFile.replace(/\\/g, '/'),
1229
- });
1230
- const sourceMapComment = (0, step_copy_utils_js_1.createDeferredStepCopyInlineSourceMapComment)({
1231
- sourcePath: normalizedStepFile,
1232
- sourceContent: source,
1233
- generatedContent: rewrittenSource,
1234
- });
1235
- const copiedSource = `${metadataComment}\n${rewrittenSource}\n${sourceMapComment}`;
1236
- await this.writeFileIfChanged(copiedFilePath, copiedSource);
1237
- }
1238
- const existingEntries = await (0, promises_1.readdir)(copiedStepsDir, {
1239
- withFileTypes: true,
1240
- }).catch(() => []);
1241
- await Promise.all(existingEntries
1242
- .filter((entry) => !expectedFileNames.has(entry.name))
1243
- .map((entry) => (0, promises_1.rm)((0, node_path_1.join)(copiedStepsDir, entry.name), {
1244
- recursive: true,
1245
- force: true,
1246
- })));
1247
- return copiedStepFiles;
1248
- }
1249
- async createDeferredStepsManifest({ stepFiles, workflowFiles, serdeOnlyFiles, }) {
1250
- const workflowManifest = {};
1251
- const filesForStepTransform = Array.from(new Set([...stepFiles, ...serdeOnlyFiles])).sort();
1252
- await Promise.all(filesForStepTransform.map(async (stepFile) => {
1253
- const source = await (0, promises_1.readFile)(stepFile, 'utf-8');
1254
- const relativeFilename = await this.getRelativeFilenameForSwc(stepFile);
1255
- const { workflowManifest: fileManifest } = await applySwcTransform(relativeFilename, source, 'step', stepFile, this.config.projectRoot || this.config.workingDir);
1256
- this.mergeWorkflowManifest(workflowManifest, fileManifest);
1257
- }));
1258
- const stepFileSet = new Set(stepFiles);
1259
- const workflowOnlyFiles = workflowFiles
1260
- .filter((workflowFile) => !stepFileSet.has(workflowFile))
1261
- .sort();
1262
- await Promise.all(workflowOnlyFiles.map(async (workflowFile) => {
1263
- try {
1264
- const source = await (0, promises_1.readFile)(workflowFile, 'utf-8');
1265
- const relativeFilename = await this.getRelativeFilenameForSwc(workflowFile);
1266
- const { workflowManifest: fileManifest } = await applySwcTransform(relativeFilename, source, 'workflow', workflowFile, this.config.projectRoot || this.config.workingDir);
1267
- this.mergeWorkflowManifest(workflowManifest, {
1268
- workflows: fileManifest.workflows,
1269
- classes: fileManifest.classes,
1270
- });
1271
- }
1272
- catch (error) {
1273
- console.log(`Warning: Failed to extract workflow metadata from ${workflowFile}:`, error instanceof Error ? error.message : String(error));
1274
- }
1275
- }));
1276
- return workflowManifest;
1277
- }
1278
- async buildStepsFunction({ workflowGeneratedDir, routeFileName = 'route.js', discoveredEntries, }) {
1279
- const stepsRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'step');
1280
- await (0, promises_1.mkdir)(stepsRouteDir, { recursive: true });
1281
- const discovered = discoveredEntries;
1282
- const workflowFiles = [...discovered.discoveredWorkflows].sort();
1283
- const stepFiles = await this.collectTransitiveStepFiles({
1284
- stepFiles: [...discovered.discoveredSteps].sort(),
1285
- // Workflow transforms can inline step IDs and remove runtime imports,
1286
- // so seed transitive traversal with workflow files too.
1287
- seedFiles: workflowFiles,
1288
- });
1289
- const serdeFiles = [...discovered.discoveredSerdeFiles].sort();
1290
- const stepFileSet = new Set(stepFiles);
1291
- const serdeOnlyFiles = serdeFiles.filter((file) => !stepFileSet.has(file));
1292
- // Copy all discovered step sources so they are transformed in step mode.
1293
- // Importing raw node_modules files directly can bypass loader transforms,
1294
- // which prevents step registrars from being emitted.
1295
- const copiedStepSourceFiles = stepFiles;
1296
- const copiedDiscoveredStepFiles = await this.copyDiscoveredStepFiles({
1297
- stepFiles: copiedStepSourceFiles,
1298
- stepsRouteDir,
1299
- });
1300
- const responseBuiltinsStepFilePath = await this.createResponseBuiltinsStepFile({
1301
- stepsRouteDir,
1302
- });
1303
- const copiedStepFiles = [
1304
- responseBuiltinsStepFilePath,
1305
- ...copiedDiscoveredStepFiles,
1306
- ];
1307
- const manifestStepFiles = Array.from(new Set([...stepFiles, responseBuiltinsStepFilePath])).sort();
1308
- const stepRouteFile = (0, node_path_1.join)(stepsRouteDir, routeFileName);
1309
- const copiedStepImports = copiedStepFiles
1310
- .map((copiedStepFile) => {
1311
- const importSpecifier = this.getRelativeImportSpecifier(stepRouteFile, copiedStepFile);
1312
- return `import '${importSpecifier}';`;
1313
- })
1314
- .join('\n');
1315
- const serdeImports = serdeOnlyFiles
1316
- .map((serdeFile) => {
1317
- const normalizedSerdeFile = this.normalizeDiscoveredFilePath(serdeFile);
1318
- const { importPath, isPackage } = getImportPath(normalizedSerdeFile, this.config.workingDir);
1319
- if (isPackage) {
1320
- return `import '${importPath}';`;
1321
- }
1322
- const importSpecifier = this.getRelativeImportSpecifier(stepRouteFile, normalizedSerdeFile);
1323
- return `import '${importSpecifier}';`;
1324
- })
1325
- .join('\n');
1326
- const routeContents = [
1327
- '// biome-ignore-all lint: generated file',
1328
- '/* eslint-disable */',
1329
- copiedStepImports,
1330
- serdeImports
1331
- ? `// Serde files for cross-context class registration\n${serdeImports}`
1332
- : '',
1333
- "export { stepEntrypoint as HEAD, stepEntrypoint as POST } from 'workflow/runtime';",
1334
- ]
1335
- .filter(Boolean)
1336
- .join('\n');
1337
- await this.writeFileIfChanged(stepRouteFile, routeContents);
1338
- const manifest = await this.createDeferredStepsManifest({
1339
- stepFiles: manifestStepFiles,
1340
- workflowFiles,
1341
- serdeOnlyFiles,
1342
- });
1343
- return {
1344
- context: undefined,
1345
- manifest,
1346
- };
1347
- }
1348
- async buildWorkflowsFunction({ inputFiles, workflowGeneratedDir, tsconfigPath, routeFileName = 'route.js', discoveredEntries, }) {
1349
- const workflowsRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'flow');
1350
- await (0, promises_1.mkdir)(workflowsRouteDir, { recursive: true });
1351
- return await this.createWorkflowsBundle({
1352
- format: 'esm',
1353
- outfile: (0, node_path_1.join)(workflowsRouteDir, routeFileName),
1354
- bundleFinalOutput: false,
1355
- // Deferred builds do not reuse the interim esbuild context. Dispose it
1356
- // after each pass to avoid leaking contexts during watch-mode rebuilds.
1357
- keepInterimBundleContext: false,
1358
- inputFiles,
1359
- tsconfigPath,
1360
- discoveredEntries,
1361
- });
1362
- }
1363
- async buildWebhookRoute({ workflowGeneratedDir, routeFileName = 'route.js', }) {
1364
- const webhookRouteFile = (0, node_path_1.join)(workflowGeneratedDir, `webhook/[token]/${routeFileName}`);
1365
- await this.createWebhookBundle({
1366
- outfile: webhookRouteFile,
1367
- bundle: false, // Next.js doesn't need bundling
1368
- });
1369
- }
1370
- async findAppDirectory() {
1371
- const appDir = (0, node_path_1.resolve)(this.config.workingDir, 'app');
1372
- const srcAppDir = (0, node_path_1.resolve)(this.config.workingDir, 'src/app');
1373
- const pagesDir = (0, node_path_1.resolve)(this.config.workingDir, 'pages');
1374
- const srcPagesDir = (0, node_path_1.resolve)(this.config.workingDir, 'src/pages');
1375
- // Helper to check if a path exists and is a directory
1376
- const isDirectory = async (path) => {
1377
- try {
1378
- await (0, promises_1.access)(path, node_fs_1.constants.F_OK);
1379
- const stats = await (0, promises_1.stat)(path);
1380
- if (!stats.isDirectory()) {
1381
- throw new Error(`Path exists but is not a directory: ${path}`);
1382
- }
1383
- return true;
1384
- }
1385
- catch (e) {
1386
- if (e instanceof Error && e.message.includes('not a directory')) {
1387
- throw e;
1388
- }
1389
- return false;
1390
- }
1391
- };
1392
- // Check if app directory exists
1393
- if (await isDirectory(appDir)) {
1394
- return appDir;
1395
- }
1396
- // Check if src/app directory exists
1397
- if (await isDirectory(srcAppDir)) {
1398
- return srcAppDir;
1399
- }
1400
- // If no app directory exists, check for pages directory and create app next to it
1401
- if (await isDirectory(pagesDir)) {
1402
- // Create app directory next to pages directory
1403
- await (0, promises_1.mkdir)(appDir, { recursive: true });
1404
- return appDir;
1405
- }
1406
- if (await isDirectory(srcPagesDir)) {
1407
- // Create src/app directory next to src/pages directory
1408
- await (0, promises_1.mkdir)(srcAppDir, { recursive: true });
1409
- return srcAppDir;
1410
- }
1411
- throw new Error('Could not find Next.js app or pages directory. Expected one of: "app", "src/app", "pages", or "src/pages" to exist.');
1412
- }
1413
- }
1414
- CachedNextBuilderDeferred = NextDeferredBuilder;
1415
- return NextDeferredBuilder;
1416
- }
1417
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGRlci1kZWZlcnJlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9idWlsZGVyLWRlZmVycmVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBaURBLHdEQXUrREM7QUF4aEVELDZDQUF5QztBQUN6QyxxQ0FBOEQ7QUFDOUQsK0NBUTBCO0FBQzFCLHNEQUF5QjtBQUN6Qix5Q0FRbUI7QUFDbkIseURBTTRCO0FBQzVCLDZEQUk4QjtBQUU5QixNQUFNLHNCQUFzQixHQUFHLDBCQUEwQixDQUFDO0FBVTFELElBQUkseUJBQThCLENBQUM7QUFFbkMsaUZBQWlGO0FBQ2pGLGdGQUFnRjtBQUNoRixvRUFBb0U7QUFDN0QsS0FBSyxVQUFVLHNCQUFzQjtJQUMxQyxJQUFJLHlCQUF5QixFQUFFLENBQUM7UUFDOUIsT0FBTyx5QkFBeUIsQ0FBQztJQUNuQyxDQUFDO0lBRUQsTUFBTSxFQUNKLFdBQVcsRUFBRSxnQkFBZ0IsRUFDN0Isa0JBQWtCLEVBQ2xCLHNCQUFzQixFQUN0QixpQkFBaUIsRUFDakIsc0JBQXNCLEVBQ3RCLGFBQWEsRUFDYixpQkFBaUIsRUFDakIsZ0NBQWdDO0lBQ2hDLDRJQUE0STtNQUM3SSxHQUFHLENBQUMsTUFBTSxJQUFJLENBQ2IsOEJBQThCLENBQy9CLENBQXdDLENBQUM7SUFFMUMsTUFBTSxtQkFBb0IsU0FBUSxnQkFBZ0I7UUFDeEMsUUFBUSxDQUFZO1FBQ1gsdUJBQXVCLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUM1QyxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQ3hDLG9CQUFvQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDbEQsc0JBQXNCLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUMzQyxrQkFBa0IsR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDdkMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLGVBQWUsR0FBMEIsSUFBSSxDQUFDO1FB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QUFLLEVBQUMsU0FBUyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQzVDLE9BQU8sU0FBUyxDQUFDO1lBQ25CLENBQUM7WUFFRCxNQUFNLElBQUksS0FBSyxDQUNiLHFIQUFxSCxDQUN0SCxDQUFDO1FBQ0osQ0FBQztLQUNGO0lBRUQseUJBQXlCLEdBQUcsbUJBQW1CLENBQUM7SUFDaEQsT0FBTyxtQkFBbUIsQ0FBQztBQUM3QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ25vZGU6Y3J5cHRvJztcbmltcG9ydCB7IGNvbnN0YW50cywgZXhpc3RzU3luYywgcmVhbHBhdGhTeW5jIH0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQge1xuICBhY2Nlc3MsXG4gIG1rZGlyLFxuICByZWFkZGlyLFxuICByZWFkRmlsZSxcbiAgcm0sXG4gIHN0YXQsXG4gIHdyaXRlRmlsZSxcbn0gZnJvbSAnbm9kZTpmcy9wcm9taXNlcyc7XG5pbXBvcnQgb3MgZnJvbSAnbm9kZTpvcyc7XG5pbXBvcnQge1xuICBiYXNlbmFtZSxcbiAgZGlybmFtZSxcbiAgZXh0bmFtZSxcbiAgaXNBYnNvbHV0ZSxcbiAgam9pbixcbiAgcmVsYXRpdmUsXG4gIHJlc29sdmUsXG59IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQge1xuICBjbGVhbnVwU3RhbGVTb2NrZXRJbmZvRmlsZXMsXG4gIGNyZWF0ZVNvY2tldFNlcnZlcixcbiAgU09DS0VUX0lORk9fRklMRU5BTUUsXG4gIHR5cGUgU29ja2V0SU8sXG4gIHR5cGUgU29ja2V0U2VydmVyQ29uZmlnLFxufSBmcm9tICcuL3NvY2tldC1zZXJ2ZXIuanMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlRGVmZXJyZWRTdGVwQ29weUlubGluZVNvdXJjZU1hcENvbW1lbnQsXG4gIGNyZWF0ZURlZmVycmVkU3RlcFNvdXJjZU1ldGFkYXRhQ29tbWVudCxcbiAgREVGRVJSRURfU1RFUF9DT1BZX0RJUl9OQU1FLFxufSBmcm9tICcuL3N0ZXAtY29weS11dGlscy5qcyc7XG5cbmNvbnN0IFJPVVRFX1NUVUJfRklMRV9NQVJLRVIgPSAnV09SS0ZMT1dfUk9VVEVfU1RVQl9GSUxFJztcblxudHlwZSBXb3JrZmxvd01hbmlmZXN0ID0gaW1wb3J0KCdAd29ya2Zsb3cvYnVpbGRlcnMnKS5Xb3JrZmxvd01hbmlmZXN0O1xuXG5pbnRlcmZhY2UgRGVmZXJyZWREaXNjb3ZlcmVkRW50cmllcyB7XG4gIGRpc2NvdmVyZWRTdGVwczogc3RyaW5nW107XG4gIGRpc2NvdmVyZWRXb3JrZmxvd3M6IHN0cmluZ1tdO1xuICBkaXNjb3ZlcmVkU2VyZGVGaWxlczogc3RyaW5nW107XG59XG5cbmxldCBDYWNoZWROZXh0QnVpbGRlckRlZmVycmVkOiBhbnk7XG5cbi8vIENyZWF0ZSB0aGUgZGVmZXJyZWQgTmV4dCBidWlsZGVyIGR5bmFtaWNhbGx5IGJ5IGV4dGVuZGluZyB0aGUgRVNNIEJhc2VCdWlsZGVyLlxuLy8gRXhwb3J0ZWQgYXMgZ2V0TmV4dEJ1aWxkZXJEZWZlcnJlZCgpIHRvIGFsbG93IENvbW1vbkpTIG1vZHVsZXMgdG8gaW1wb3J0IGZyb21cbi8vIHRoZSBFU00gQHdvcmtmbG93L2J1aWxkZXJzIHBhY2thZ2UgdmlhIGR5bmFtaWMgaW1wb3J0IGF0IHJ1bnRpbWUuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0TmV4dEJ1aWxkZXJEZWZlcnJlZCgpIHtcbiAgaWYgKENhY2hlZE5leHRCdWlsZGVyRGVmZXJyZWQpIHtcbiAgICByZXR1cm4gQ2FjaGVkTmV4dEJ1aWxkZXJEZWZlcnJlZDtcbiAgfVxuXG4gIGNvbnN0IHtcbiAgICBCYXNlQnVpbGRlcjogQmFzZUJ1aWxkZXJDbGFzcyxcbiAgICBTVEVQX1FVRVVFX1RSSUdHRVIsXG4gICAgV09SS0ZMT1dfUVVFVUVfVFJJR0dFUixcbiAgICBhcHBseVN3Y1RyYW5zZm9ybSxcbiAgICBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zLFxuICAgIGdldEltcG9ydFBhdGgsXG4gICAgaXNXb3JrZmxvd1Nka0ZpbGUsXG4gICAgcmVzb2x2ZVdvcmtmbG93QWxpYXNSZWxhdGl2ZVBhdGgsXG4gICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc2VjdXJpdHkvbm9HbG9iYWxFdmFsOiBOZWVkIHRvIHVzZSBldmFsIGhlcmUgdG8gYXZvaWQgVHlwZVNjcmlwdCBmcm9tIHRyYW5zcGlsaW5nIHRoZSBpbXBvcnQgc3RhdGVtZW50IGludG8gYHJlcXVpcmUoKWBcbiAgfSA9IChhd2FpdCBldmFsKFxuICAgICdpbXBvcnQoXCJAd29ya2Zsb3cvYnVpbGRlcnNcIiknXG4gICkpIGFzIHR5cGVvZiBpbXBvcnQoJ0B3b3JrZmxvdy9idWlsZGVycycpO1xuXG4gIGNsYXNzIE5leHREZWZlcnJlZEJ1aWxkZXIgZXh0ZW5kcyBCYXNlQnVpbGRlckNsYXNzIHtcbiAgICBwcml2YXRlIHNvY2tldElPPzogU29ja2V0SU87XG4gICAgcHJpdmF0ZSByZWFkb25seSBkaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZGlzY292ZXJlZFN0ZXBGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZGlzY292ZXJlZFNlcmRlRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBwcml2YXRlIHRyYWNrZWREZXBlbmRlbmN5RmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBwcml2YXRlIGRlZmVycmVkQnVpbGRRdWV1ZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIHByaXZhdGUgY2FjaGVJbml0aWFsaXplZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgY2FjaGVXcml0ZVRpbWVyOiBOb2RlSlMuVGltZW91dCB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgZGVmZXJyZWRSZWJ1aWxkVGltZXI6IE5vZGVKUy5UaW1lb3V0IHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBsYXN0RGVmZXJyZWRCdWlsZFNpZ25hdHVyZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICBhc3luYyBidWlsZCgpIHtcbiAgICAgIGNvbnN0IG91dHB1dERpciA9IGF3YWl0IHRoaXMuZmluZEFwcERpcmVjdG9yeSgpO1xuXG4gICAgICBhd2FpdCB0aGlzLmluaXRpYWxpemVEaXNjb3ZlcnlTdGF0ZSgpO1xuICAgICAgYXdhaXQgdGhpcy5jbGVhbnVwR2VuZXJhdGVkQXJ0aWZhY3RzT25Cb290KG91dHB1dERpcik7XG5cbiAgICAgIGF3YWl0IHRoaXMud3JpdGVTdHViRmlsZXMob3V0cHV0RGlyKTtcbiAgICAgIGF3YWl0IHRoaXMuY3JlYXRlRGlzY292ZXJ5U29ja2V0U2VydmVyKCk7XG4gICAgfVxuXG4gICAgYXN5bmMgb25CZWZvcmVEZWZlcnJlZEVudHJpZXMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBhd2FpdCB0aGlzLmluaXRpYWxpemVEaXNjb3ZlcnlTdGF0ZSgpO1xuICAgICAgYXdhaXQgdGhpcy52YWxpZGF0ZURpc2NvdmVyZWRFbnRyeUZpbGVzKCk7XG4gICAgICBjb25zdCBpbXBsaWNpdFN0ZXBGaWxlcyA9IGF3YWl0IHRoaXMucmVzb2x2ZUltcGxpY2l0U3RlcEZpbGVzKCk7XG5cbiAgICAgIGNvbnN0IHBlbmRpbmdCdWlsZCA9IHRoaXMuZGVmZXJyZWRCdWlsZFF1ZXVlLnRoZW4oKCkgPT5cbiAgICAgICAgdGhpcy5idWlsZERlZmVycmVkRW50cmllc1VudGlsU3RhYmxlKGltcGxpY2l0U3RlcEZpbGVzKVxuICAgICAgKTtcblxuICAgICAgLy8gS2VlcCB0aGUgcXVldWUgY2hhaW4gYWxpdmUgZXZlbiB3aGVuIHRoZSBjdXJyZW50IGJ1aWxkIGZhaWxzIHNvIGZ1dHVyZVxuICAgICAgLy8gY2FsbGJhY2tzIGNhbiBlbnF1ZXVlIGFub3RoZXIgYXR0ZW1wdCB3aXRob3V0IHRyaWdnZXJpbmcgdW5oYW5kbGVkXG4gICAgICAvLyByZWplY3Rpb24gd2FybmluZ3MuXG4gICAgICB0aGlzLmRlZmVycmVkQnVpbGRRdWV1ZSA9IHBlbmRpbmdCdWlsZC5jYXRjaCgoKSA9PiB7XG4gICAgICAgIC8vIEVycm9yIGlzIHN1cmZhY2VkIHRocm91Z2ggYHBlbmRpbmdCdWlsZGAgYmVsb3cuXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgcGVuZGluZ0J1aWxkO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Q3VycmVudElucHV0RmlsZXMoaW1wbGljaXRTdGVwRmlsZXM6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuICAgICAgcmV0dXJuIEFycmF5LmZyb20oXG4gICAgICAgIG5ldyBTZXQoW1xuICAgICAgICAgIC4uLnRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMsXG4gICAgICAgICAgLi4udGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLFxuICAgICAgICAgIC4uLnRoaXMuZGlzY292ZXJlZFNlcmRlRmlsZXMsXG4gICAgICAgICAgLi4uaW1wbGljaXRTdGVwRmlsZXMsXG4gICAgICAgIF0pXG4gICAgICApLnNvcnQoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGJ1aWxkRGVmZXJyZWRFbnRyaWVzVW50aWxTdGFibGUoXG4gICAgICBpbXBsaWNpdFN0ZXBGaWxlczogc3RyaW5nW11cbiAgICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIC8vIEEgc3VjY2Vzc2Z1bCBidWlsZCBjYW4gZGlzY292ZXIgYWRkaXRpb25hbCB0cmFuc2l0aXZlIGRlcGVuZGVuY3kgZmlsZXNcbiAgICAgIC8vICh2aWEgc291cmNlIG1hcHMpLCB3aGljaCBjaGFuZ2VzIHRoZSBzaWduYXR1cmUgYW5kIG1heSByZXF1aXJlIG9uZSBtb3JlXG4gICAgICAvLyBidWlsZCBwYXNzIHRvIGluY2x1ZGUgbmV3bHkgZGlzY292ZXJlZCBzZXJkZSBmaWxlcy5cbiAgICAgIGNvbnN0IG1heEJ1aWxkUGFzc2VzID0gMztcblxuICAgICAgZm9yIChsZXQgYnVpbGRQYXNzID0gMDsgYnVpbGRQYXNzIDwgbWF4QnVpbGRQYXNzZXM7IGJ1aWxkUGFzcysrKSB7XG4gICAgICAgIGNvbnN0IGlucHV0RmlsZXMgPSB0aGlzLmdldEN1cnJlbnRJbnB1dEZpbGVzKGltcGxpY2l0U3RlcEZpbGVzKTtcbiAgICAgICAgY29uc3QgYnVpbGRTaWduYXR1cmUgPVxuICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlRGVmZXJyZWRCdWlsZFNpZ25hdHVyZShpbnB1dEZpbGVzKTtcbiAgICAgICAgaWYgKGJ1aWxkU2lnbmF0dXJlID09PSB0aGlzLmxhc3REZWZlcnJlZEJ1aWxkU2lnbmF0dXJlKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmJ1aWxkRGlzY292ZXJlZEZpbGVzKGlucHV0RmlsZXMsIGltcGxpY2l0U3RlcEZpbGVzKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBpZiAodGhpcy5jb25maWcud2F0Y2gpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMudmFsaWRhdGVEaXNjb3ZlcmVkRW50cnlGaWxlcygpO1xuICAgICAgICAgICAgY29uc3QgcmVjb3ZlcmVkSW5wdXRGaWxlcyA9XG4gICAgICAgICAgICAgIHRoaXMuZ2V0Q3VycmVudElucHV0RmlsZXMoaW1wbGljaXRTdGVwRmlsZXMpO1xuICAgICAgICAgICAgY29uc3QgcmVjb3ZlcmVkU2lnbmF0dXJlID1cbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy5jcmVhdGVEZWZlcnJlZEJ1aWxkU2lnbmF0dXJlKHJlY292ZXJlZElucHV0RmlsZXMpO1xuICAgICAgICAgICAgaWYgKHJlY292ZXJlZFNpZ25hdHVyZSAhPT0gYnVpbGRTaWduYXR1cmUpIHtcbiAgICAgICAgICAgICAgLy8gQSBmaWxlIHdhcyBhZGRlZC9yZW1vdmVkIHdoaWxlIHRoaXMgYnVpbGQgd2FzIHJ1bm5pbmc7IHJldHJ5XG4gICAgICAgICAgICAgIC8vIGltbWVkaWF0ZWx5IHdpdGggdGhlIHJlZnJlc2hlZCBkaXNjb3ZlcmVkLWVudHJ5IHN0YXRlLlxuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgJ1t3b3JrZmxvd10gRGVmZXJyZWQgZW50cmllcyBidWlsZCBmYWlsZWQuIFdpbGwgcmV0cnkgb25seSBhZnRlciBpbnB1dHMgY2hhbmdlLicsXG4gICAgICAgICAgICAgIGVycm9yXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5sYXN0RGVmZXJyZWRCdWlsZFNpZ25hdHVyZSA9IGJ1aWxkU2lnbmF0dXJlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sYXN0RGVmZXJyZWRCdWlsZFNpZ25hdHVyZSA9IGJ1aWxkU2lnbmF0dXJlO1xuXG4gICAgICAgIGNvbnN0IHBvc3RCdWlsZElucHV0RmlsZXMgPVxuICAgICAgICAgIHRoaXMuZ2V0Q3VycmVudElucHV0RmlsZXMoaW1wbGljaXRTdGVwRmlsZXMpO1xuICAgICAgICBjb25zdCBwb3N0QnVpbGRTaWduYXR1cmUgPVxuICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlRGVmZXJyZWRCdWlsZFNpZ25hdHVyZShwb3N0QnVpbGRJbnB1dEZpbGVzKTtcbiAgICAgICAgaWYgKHBvc3RCdWlsZFNpZ25hdHVyZSA9PT0gYnVpbGRTaWduYXR1cmUpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAnW3dvcmtmbG93XSBEZWZlcnJlZCBlbnRyaWVzIGJ1aWxkIHNpZ25hdHVyZSBkaWQgbm90IHN0YWJpbGl6ZSBhZnRlciAzIHBhc3Nlcy4nXG4gICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcmVzb2x2ZUltcGxpY2l0U3RlcEZpbGVzKCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgIGNvbnN0IHdvcmtmbG93U3RkbGliUGF0aCA9IHRoaXMucmVzb2x2ZVdvcmtmbG93U3RkbGliU3RlcEZpbGVQYXRoKCk7XG4gICAgICByZXR1cm4gd29ya2Zsb3dTdGRsaWJQYXRoID8gW3dvcmtmbG93U3RkbGliUGF0aF0gOiBbXTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlc29sdmVXb3JrZmxvd1N0ZGxpYlN0ZXBGaWxlUGF0aCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgIGxldCB3b3JrZmxvd0Nqc0VudHJ5OiBzdHJpbmc7XG4gICAgICB0cnkge1xuICAgICAgICB3b3JrZmxvd0Nqc0VudHJ5ID0gcmVxdWlyZS5yZXNvbHZlKCd3b3JrZmxvdycsIHtcbiAgICAgICAgICBwYXRoczogW3RoaXMuY29uZmlnLndvcmtpbmdEaXJdLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgd29ya2Zsb3dEaXN0RGlyID0gZGlybmFtZSh3b3JrZmxvd0Nqc0VudHJ5KTtcbiAgICAgIGNvbnN0IHdvcmtmbG93U3RkbGliUGF0aCA9IHRoaXMubm9ybWFsaXplRGlzY292ZXJlZEZpbGVQYXRoKFxuICAgICAgICBqb2luKHdvcmtmbG93RGlzdERpciwgJ3N0ZGxpYi5qcycpXG4gICAgICApO1xuICAgICAgcmV0dXJuIGV4aXN0c1N5bmMod29ya2Zsb3dTdGRsaWJQYXRoKSA/IHdvcmtmbG93U3RkbGliUGF0aCA6IG51bGw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZWNvbmNpbGVEaXNjb3ZlcmVkRW50cmllcyh7XG4gICAgICB3b3JrZmxvd0NhbmRpZGF0ZXMsXG4gICAgICBzdGVwQ2FuZGlkYXRlcyxcbiAgICAgIHNlcmRlQ2FuZGlkYXRlcyxcbiAgICAgIHZhbGlkYXRlUGF0dGVybnMsXG4gICAgfToge1xuICAgICAgd29ya2Zsb3dDYW5kaWRhdGVzOiBJdGVyYWJsZTxzdHJpbmc+O1xuICAgICAgc3RlcENhbmRpZGF0ZXM6IEl0ZXJhYmxlPHN0cmluZz47XG4gICAgICBzZXJkZUNhbmRpZGF0ZXM/OiBJdGVyYWJsZTxzdHJpbmc+O1xuICAgICAgdmFsaWRhdGVQYXR0ZXJuczogYm9vbGVhbjtcbiAgICB9KTogUHJvbWlzZTx7XG4gICAgICB3b3JrZmxvd0ZpbGVzOiBTZXQ8c3RyaW5nPjtcbiAgICAgIHN0ZXBGaWxlczogU2V0PHN0cmluZz47XG4gICAgICBzZXJkZUZpbGVzOiBTZXQ8c3RyaW5nPjtcbiAgICB9PiB7XG4gICAgICBjb25zdCBjYW5kaWRhdGVzQnlGaWxlID0gbmV3IE1hcDxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICB7XG4gICAgICAgICAgaGFzV29ya2Zsb3dDYW5kaWRhdGU6IGJvb2xlYW47XG4gICAgICAgICAgaGFzU3RlcENhbmRpZGF0ZTogYm9vbGVhbjtcbiAgICAgICAgICBoYXNTZXJkZUNhbmRpZGF0ZTogYm9vbGVhbjtcbiAgICAgICAgfVxuICAgICAgPigpO1xuXG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHdvcmtmbG93Q2FuZGlkYXRlcykge1xuICAgICAgICBjb25zdCBub3JtYWxpemVkUGF0aCA9IHRoaXMubm9ybWFsaXplRGlzY292ZXJlZEZpbGVQYXRoKGZpbGVQYXRoKTtcbiAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBjYW5kaWRhdGVzQnlGaWxlLmdldChub3JtYWxpemVkUGF0aCk7XG4gICAgICAgIGlmIChleGlzdGluZykge1xuICAgICAgICAgIGV4aXN0aW5nLmhhc1dvcmtmbG93Q2FuZGlkYXRlID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjYW5kaWRhdGVzQnlGaWxlLnNldChub3JtYWxpemVkUGF0aCwge1xuICAgICAgICAgICAgaGFzV29ya2Zsb3dDYW5kaWRhdGU6IHRydWUsXG4gICAgICAgICAgICBoYXNTdGVwQ2FuZGlkYXRlOiBmYWxzZSxcbiAgICAgICAgICAgIGhhc1NlcmRlQ2FuZGlkYXRlOiBmYWxzZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHN0ZXBDYW5kaWRhdGVzKSB7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoZmlsZVBhdGgpO1xuICAgICAgICBjb25zdCBleGlzdGluZyA9IGNhbmRpZGF0ZXNCeUZpbGUuZ2V0KG5vcm1hbGl6ZWRQYXRoKTtcbiAgICAgICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICAgICAgZXhpc3RpbmcuaGFzU3RlcENhbmRpZGF0ZSA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2FuZGlkYXRlc0J5RmlsZS5zZXQobm9ybWFsaXplZFBhdGgsIHtcbiAgICAgICAgICAgIGhhc1dvcmtmbG93Q2FuZGlkYXRlOiBmYWxzZSxcbiAgICAgICAgICAgIGhhc1N0ZXBDYW5kaWRhdGU6IHRydWUsXG4gICAgICAgICAgICBoYXNTZXJkZUNhbmRpZGF0ZTogZmFsc2UsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHNlcmRlQ2FuZGlkYXRlcykge1xuICAgICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHNlcmRlQ2FuZGlkYXRlcykge1xuICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoZmlsZVBhdGgpO1xuICAgICAgICAgIGNvbnN0IGV4aXN0aW5nID0gY2FuZGlkYXRlc0J5RmlsZS5nZXQobm9ybWFsaXplZFBhdGgpO1xuICAgICAgICAgIGlmIChleGlzdGluZykge1xuICAgICAgICAgICAgZXhpc3RpbmcuaGFzU2VyZGVDYW5kaWRhdGUgPSB0cnVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYW5kaWRhdGVzQnlGaWxlLnNldChub3JtYWxpemVkUGF0aCwge1xuICAgICAgICAgICAgICBoYXNXb3JrZmxvd0NhbmRpZGF0ZTogZmFsc2UsXG4gICAgICAgICAgICAgIGhhc1N0ZXBDYW5kaWRhdGU6IGZhbHNlLFxuICAgICAgICAgICAgICBoYXNTZXJkZUNhbmRpZGF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBmaWxlRW50cmllcyA9IEFycmF5LmZyb20oY2FuZGlkYXRlc0J5RmlsZS5lbnRyaWVzKCkpLnNvcnQoXG4gICAgICAgIChbYV0sIFtiXSkgPT4gYS5sb2NhbGVDb21wYXJlKGIpXG4gICAgICApO1xuICAgICAgY29uc3QgdmFsaWRhdGVkRW50cmllcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBmaWxlRW50cmllcy5tYXAoYXN5bmMgKFtmaWxlUGF0aCwgY2FuZGlkYXRlc10pID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgZmlsZVN0YXRzID0gYXdhaXQgc3RhdChmaWxlUGF0aCk7XG4gICAgICAgICAgICBpZiAoIWZpbGVTdGF0cy5pc0ZpbGUoKSkge1xuICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF2YWxpZGF0ZVBhdHRlcm5zKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGlzU2RrRmlsZSA9IGlzV29ya2Zsb3dTZGtGaWxlKGZpbGVQYXRoKTtcbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBmaWxlUGF0aCxcbiAgICAgICAgICAgICAgICBoYXNVc2VXb3JrZmxvdzogY2FuZGlkYXRlcy5oYXNXb3JrZmxvd0NhbmRpZGF0ZSxcbiAgICAgICAgICAgICAgICBoYXNVc2VTdGVwOiBjYW5kaWRhdGVzLmhhc1N0ZXBDYW5kaWRhdGUsXG4gICAgICAgICAgICAgICAgaGFzU2VyZGU6IGNhbmRpZGF0ZXMuaGFzU2VyZGVDYW5kaWRhdGUgJiYgIWlzU2RrRmlsZSxcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgICAgICAgY29uc3QgcGF0dGVybnMgPSBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zKHNvdXJjZSk7XG4gICAgICAgICAgICBjb25zdCBpc1Nka0ZpbGUgPSBpc1dvcmtmbG93U2RrRmlsZShmaWxlUGF0aCk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBmaWxlUGF0aCxcbiAgICAgICAgICAgICAgaGFzVXNlV29ya2Zsb3c6IHBhdHRlcm5zLmhhc1VzZVdvcmtmbG93LFxuICAgICAgICAgICAgICBoYXNVc2VTdGVwOiBwYXR0ZXJucy5oYXNVc2VTdGVwLFxuICAgICAgICAgICAgICBoYXNTZXJkZTogcGF0dGVybnMuaGFzU2VyZGUgJiYgIWlzU2RrRmlsZSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgICBjb25zdCB3b3JrZmxvd0ZpbGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBjb25zdCBzdGVwRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgIGNvbnN0IHNlcmRlRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgIGZvciAoY29uc3QgZW50cnkgb2YgdmFsaWRhdGVkRW50cmllcykge1xuICAgICAgICBpZiAoIWVudHJ5KSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVudHJ5Lmhhc1VzZVdvcmtmbG93KSB7XG4gICAgICAgICAgd29ya2Zsb3dGaWxlcy5hZGQoZW50cnkuZmlsZVBhdGgpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlbnRyeS5oYXNVc2VTdGVwKSB7XG4gICAgICAgICAgc3RlcEZpbGVzLmFkZChlbnRyeS5maWxlUGF0aCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVudHJ5Lmhhc1NlcmRlKSB7XG4gICAgICAgICAgc2VyZGVGaWxlcy5hZGQoZW50cnkuZmlsZVBhdGgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7IHdvcmtmbG93RmlsZXMsIHN0ZXBGaWxlcywgc2VyZGVGaWxlcyB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgdmFsaWRhdGVEaXNjb3ZlcmVkRW50cnlGaWxlcygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IHdvcmtmbG93Q2FuZGlkYXRlcyA9IG5ldyBTZXQodGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcyk7XG4gICAgICBjb25zdCBzdGVwQ2FuZGlkYXRlcyA9IG5ldyBTZXQodGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzKTtcbiAgICAgIGNvbnN0IHNlcmRlQ2FuZGlkYXRlcyA9IG5ldyBTZXQodGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcyk7XG4gICAgICBjb25zdCB7IHdvcmtmbG93RmlsZXMsIHN0ZXBGaWxlcywgc2VyZGVGaWxlcyB9ID1cbiAgICAgICAgYXdhaXQgdGhpcy5yZWNvbmNpbGVEaXNjb3ZlcmVkRW50cmllcyh7XG4gICAgICAgICAgd29ya2Zsb3dDYW5kaWRhdGVzLFxuICAgICAgICAgIHN0ZXBDYW5kaWRhdGVzLFxuICAgICAgICAgIHNlcmRlQ2FuZGlkYXRlcyxcbiAgICAgICAgICB2YWxpZGF0ZVBhdHRlcm5zOiB0cnVlLFxuICAgICAgICB9KTtcblxuICAgICAgLy8gUmVjb25jaWxlIHZhbGlkYXRlZCBlbnRyaWVzIGFnYWluc3QgdGhlIHNuYXBzaG90IHdlIHN0YXJ0ZWQgd2l0aCBzb1xuICAgICAgLy8gZmlsZSBkaXNjb3ZlcmllcyB0aGF0IGFycml2ZSBkdXJpbmcgdmFsaWRhdGlvbiBhcmUgcHJlc2VydmVkLlxuICAgICAgbGV0IHdvcmtmbG93c0NoYW5nZWQgPSBmYWxzZTtcbiAgICAgIGxldCBzdGVwc0NoYW5nZWQgPSBmYWxzZTtcbiAgICAgIGxldCBzZXJkZUNoYW5nZWQgPSBmYWxzZTtcblxuICAgICAgZm9yIChjb25zdCBmaWxlUGF0aCBvZiB3b3JrZmxvd0NhbmRpZGF0ZXMpIHtcbiAgICAgICAgaWYgKCF3b3JrZmxvd0ZpbGVzLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICB3b3JrZmxvd3NDaGFuZ2VkID1cbiAgICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMuZGVsZXRlKGZpbGVQYXRoKSB8fCB3b3JrZmxvd3NDaGFuZ2VkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHdvcmtmbG93RmlsZXMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzLmFkZChmaWxlUGF0aCk7XG4gICAgICAgICAgd29ya2Zsb3dzQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZm9yIChjb25zdCBmaWxlUGF0aCBvZiBzdGVwQ2FuZGlkYXRlcykge1xuICAgICAgICBpZiAoIXN0ZXBGaWxlcy5oYXMoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgc3RlcHNDaGFuZ2VkID1cbiAgICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFN0ZXBGaWxlcy5kZWxldGUoZmlsZVBhdGgpIHx8IHN0ZXBzQ2hhbmdlZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZm9yIChjb25zdCBmaWxlUGF0aCBvZiBzdGVwRmlsZXMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRpc2NvdmVyZWRTdGVwRmlsZXMuaGFzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFN0ZXBGaWxlcy5hZGQoZmlsZVBhdGgpO1xuICAgICAgICAgIHN0ZXBzQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZm9yIChjb25zdCBmaWxlUGF0aCBvZiBzZXJkZUNhbmRpZGF0ZXMpIHtcbiAgICAgICAgaWYgKCFzZXJkZUZpbGVzLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICBzZXJkZUNoYW5nZWQgPVxuICAgICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcy5kZWxldGUoZmlsZVBhdGgpIHx8IHNlcmRlQ2hhbmdlZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZm9yIChjb25zdCBmaWxlUGF0aCBvZiBzZXJkZUZpbGVzKSB7XG4gICAgICAgIGlmICghdGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcy5oYXMoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcy5hZGQoZmlsZVBhdGgpO1xuICAgICAgICAgIHNlcmRlQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHdvcmtmbG93c0NoYW5nZWQgfHwgc3RlcHNDaGFuZ2VkKSB7XG4gICAgICAgIHRoaXMuc2NoZWR1bGVXb3JrZmxvd3NDYWNoZVdyaXRlKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBidWlsZERpc2NvdmVyZWRGaWxlcyhcbiAgICAgIGlucHV0RmlsZXM6IHN0cmluZ1tdLFxuICAgICAgaW1wbGljaXRTdGVwRmlsZXM6IHN0cmluZ1tdXG4gICAgKSB7XG4gICAgICBjb25zdCBvdXRwdXREaXIgPSBhd2FpdCB0aGlzLmZpbmRBcHBEaXJlY3RvcnkoKTtcbiAgICAgIGNvbnN0IHdvcmtmbG93R2VuZXJhdGVkRGlyID0gam9pbihvdXRwdXREaXIsICcud2VsbC1rbm93bi93b3JrZmxvdy92MScpO1xuICAgICAgY29uc3QgY2FjaGVEaXIgPSBqb2luKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsIHRoaXMuZ2V0RGlzdERpcigpLCAnY2FjaGUnKTtcbiAgICAgIGF3YWl0IG1rZGlyKGNhY2hlRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgIGNvbnN0IG1hbmlmZXN0QnVpbGREaXIgPSBqb2luKGNhY2hlRGlyLCAnd29ya2Zsb3ctZ2VuZXJhdGVkLW1hbmlmZXN0Jyk7XG4gICAgICBjb25zdCB0ZW1wUm91dGVGaWxlTmFtZSA9ICdyb3V0ZS5qcy50ZW1wJztcbiAgICAgIGNvbnN0IHRyYWNrZWREaXNjb3ZlcmVkRW50cmllcyA9XG4gICAgICAgIGF3YWl0IHRoaXMuY29sbGVjdFRyYWNrZWREaXNjb3ZlcmVkRW50cmllcygpO1xuICAgICAgY29uc3QgZGlzY292ZXJlZFN0ZXBGaWxlQ2FuZGlkYXRlcyA9IEFycmF5LmZyb20oXG4gICAgICAgIG5ldyBTZXQoW1xuICAgICAgICAgIC4uLnRoaXMuZGlzY292ZXJlZFN0ZXBGaWxlcyxcbiAgICAgICAgICAuLi50cmFja2VkRGlzY292ZXJlZEVudHJpZXMuZGlzY292ZXJlZFN0ZXBzLFxuICAgICAgICAgIC4uLmltcGxpY2l0U3RlcEZpbGVzLFxuICAgICAgICBdKVxuICAgICAgKS5zb3J0KCk7XG4gICAgICBjb25zdCBkaXNjb3ZlcmVkV29ya2Zsb3dGaWxlQ2FuZGlkYXRlcyA9IEFycmF5LmZyb20oXG4gICAgICAgIG5ldyBTZXQoW1xuICAgICAgICAgIC4uLnRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMsXG4gICAgICAgICAgLi4udHJhY2tlZERpc2NvdmVyZWRFbnRyaWVzLmRpc2NvdmVyZWRXb3JrZmxvd3MsXG4gICAgICAgIF0pXG4gICAgICApLnNvcnQoKTtcbiAgICAgIGNvbnN0IGRpc2NvdmVyZWRTZXJkZUZpbGVDYW5kaWRhdGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbXG4gICAgICAgICAgLi4udGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcyxcbiAgICAgICAgICAuLi50cmFja2VkRGlzY292ZXJlZEVudHJpZXMuZGlzY292ZXJlZFNlcmRlRmlsZXMsXG4gICAgICAgIF0pXG4gICAgICApLnNvcnQoKTtcbiAgICAgIGNvbnN0IGRpc2NvdmVyZWRTdGVwRmlsZXMgPSBhd2FpdCB0aGlzLmZpbHRlckV4aXN0aW5nRmlsZXMoXG4gICAgICAgIGRpc2NvdmVyZWRTdGVwRmlsZUNhbmRpZGF0ZXNcbiAgICAgICk7XG4gICAgICBjb25zdCBkaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcyA9IGF3YWl0IHRoaXMuZmlsdGVyRXhpc3RpbmdGaWxlcyhcbiAgICAgICAgZGlzY292ZXJlZFdvcmtmbG93RmlsZUNhbmRpZGF0ZXNcbiAgICAgICk7XG4gICAgICBjb25zdCBleGlzdGluZ1NlcmRlRmlsZUNhbmRpZGF0ZXMgPSBhd2FpdCB0aGlzLmZpbHRlckV4aXN0aW5nRmlsZXMoXG4gICAgICAgIGRpc2NvdmVyZWRTZXJkZUZpbGVDYW5kaWRhdGVzXG4gICAgICApO1xuICAgICAgY29uc3QgZGlzY292ZXJlZFNlcmRlRmlsZXMgPSBhd2FpdCB0aGlzLmNvbGxlY3RUcmFuc2l0aXZlU2VyZGVGaWxlcyh7XG4gICAgICAgIGVudHJ5RmlsZXM6IFsuLi5kaXNjb3ZlcmVkU3RlcEZpbGVzLCAuLi5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlc10sXG4gICAgICAgIHNlcmRlRmlsZXM6IGV4aXN0aW5nU2VyZGVGaWxlQ2FuZGlkYXRlcyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgZGlzY292ZXJlZEVudHJpZXMgPSB7XG4gICAgICAgIGRpc2NvdmVyZWRTdGVwczogZGlzY292ZXJlZFN0ZXBGaWxlcyxcbiAgICAgICAgZGlzY292ZXJlZFdvcmtmbG93czogZGlzY292ZXJlZFdvcmtmbG93RmlsZXMsXG4gICAgICAgIGRpc2NvdmVyZWRTZXJkZUZpbGVzLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGV4aXN0aW5nSW5wdXRGaWxlcyA9IGF3YWl0IHRoaXMuZmlsdGVyRXhpc3RpbmdGaWxlcyhpbnB1dEZpbGVzKTtcbiAgICAgIGNvbnN0IGJ1aWxkSW5wdXRGaWxlcyA9IEFycmF5LmZyb20oXG4gICAgICAgIG5ldyBTZXQoW1xuICAgICAgICAgIC4uLmV4aXN0aW5nSW5wdXRGaWxlcyxcbiAgICAgICAgICAuLi5kaXNjb3ZlcmVkU3RlcEZpbGVzLFxuICAgICAgICAgIC4uLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzLFxuICAgICAgICAgIC4uLmRpc2NvdmVyZWRTZXJkZUZpbGVzLFxuICAgICAgICBdKVxuICAgICAgKS5zb3J0KCk7XG5cbiAgICAgIC8vIEVuc3VyZSBvdXRwdXQgZGlyZWN0b3JpZXMgZXhpc3RcbiAgICAgIGF3YWl0IG1rZGlyKHdvcmtmbG93R2VuZXJhdGVkRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQoXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICcuZ2l0aWdub3JlJyksXG4gICAgICAgICcqJ1xuICAgICAgKTtcblxuICAgICAgY29uc3QgdHNjb25maWdQYXRoID0gYXdhaXQgdGhpcy5maW5kVHNDb25maWdQYXRoKCk7XG5cbiAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgIGlucHV0RmlsZXM6IGJ1aWxkSW5wdXRGaWxlcyxcbiAgICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXIsXG4gICAgICAgIHRzY29uZmlnUGF0aCxcbiAgICAgICAgcm91dGVGaWxlTmFtZTogdGVtcFJvdXRlRmlsZU5hbWUsXG4gICAgICAgIGRpc2NvdmVyZWRFbnRyaWVzLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgeyBtYW5pZmVzdDogc3RlcHNNYW5pZmVzdCB9ID1cbiAgICAgICAgYXdhaXQgdGhpcy5idWlsZFN0ZXBzRnVuY3Rpb24ob3B0aW9ucyk7XG4gICAgICBjb25zdCB3b3JrZmxvd3NCdW5kbGUgPSBhd2FpdCB0aGlzLmJ1aWxkV29ya2Zsb3dzRnVuY3Rpb24ob3B0aW9ucyk7XG4gICAgICBhd2FpdCB0aGlzLmJ1aWxkV2ViaG9va1JvdXRlKHtcbiAgICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXIsXG4gICAgICAgIHJvdXRlRmlsZU5hbWU6IHRlbXBSb3V0ZUZpbGVOYW1lLFxuICAgICAgfSk7XG4gICAgICBhd2FpdCB0aGlzLnJlZnJlc2hUcmFja2VkRGVwZW5kZW5jeUZpbGVzKFxuICAgICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcixcbiAgICAgICAgdGVtcFJvdXRlRmlsZU5hbWVcbiAgICAgICk7XG5cbiAgICAgIC8vIE1lcmdlIG1hbmlmZXN0cyBmcm9tIGJvdGggYnVuZGxlc1xuICAgICAgY29uc3QgbWFuaWZlc3QgPSB7XG4gICAgICAgIHN0ZXBzOiB7IC4uLnN0ZXBzTWFuaWZlc3Quc3RlcHMsIC4uLndvcmtmbG93c0J1bmRsZT8ubWFuaWZlc3Q/LnN0ZXBzIH0sXG4gICAgICAgIHdvcmtmbG93czoge1xuICAgICAgICAgIC4uLnN0ZXBzTWFuaWZlc3Qud29ya2Zsb3dzLFxuICAgICAgICAgIC4uLndvcmtmbG93c0J1bmRsZT8ubWFuaWZlc3Q/LndvcmtmbG93cyxcbiAgICAgICAgfSxcbiAgICAgICAgY2xhc3Nlczoge1xuICAgICAgICAgIC4uLnN0ZXBzTWFuaWZlc3QuY2xhc3NlcyxcbiAgICAgICAgICAuLi53b3JrZmxvd3NCdW5kbGU/Lm1hbmlmZXN0Py5jbGFzc2VzLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgbWFuaWZlc3RGaWxlUGF0aCA9IGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdtYW5pZmVzdC5qc29uJyk7XG4gICAgICBjb25zdCBtYW5pZmVzdEJ1aWxkUGF0aCA9IGpvaW4obWFuaWZlc3RCdWlsZERpciwgJ21hbmlmZXN0Lmpzb24nKTtcbiAgICAgIGNvbnN0IHdvcmtmbG93QnVuZGxlUGF0aCA9IGpvaW4oXG4gICAgICAgIHdvcmtmbG93R2VuZXJhdGVkRGlyLFxuICAgICAgICBgZmxvdy8ke3RlbXBSb3V0ZUZpbGVOYW1lfWBcbiAgICAgICk7XG4gICAgICBjb25zdCBtYW5pZmVzdEpzb24gPSBhd2FpdCB0aGlzLmNyZWF0ZU1hbmlmZXN0KHtcbiAgICAgICAgd29ya2Zsb3dCdW5kbGVQYXRoLFxuICAgICAgICBtYW5pZmVzdERpcjogbWFuaWZlc3RCdWlsZERpcixcbiAgICAgICAgbWFuaWZlc3QsXG4gICAgICB9KTtcbiAgICAgIGlmIChtYW5pZmVzdEpzb24pIHtcbiAgICAgICAgYXdhaXQgdGhpcy5yZXdyaXRlSnNvbkZpbGVXaXRoU3RhYmxlS2V5T3JkZXIobWFuaWZlc3RCdWlsZFBhdGgpO1xuICAgICAgICBhd2FpdCB0aGlzLmNvcHlGaWxlSWZDaGFuZ2VkKG1hbmlmZXN0QnVpbGRQYXRoLCBtYW5pZmVzdEZpbGVQYXRoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHJtKG1hbmlmZXN0QnVpbGRQYXRoLCB7IGZvcmNlOiB0cnVlIH0pO1xuICAgICAgICBhd2FpdCBybShtYW5pZmVzdEZpbGVQYXRoLCB7IGZvcmNlOiB0cnVlIH0pO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCB0aGlzLndyaXRlRnVuY3Rpb25zQ29uZmlnKG91dHB1dERpcik7XG5cbiAgICAgIGF3YWl0IHRoaXMuY29weUZpbGVJZkNoYW5nZWQoXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsIGBmbG93LyR7dGVtcFJvdXRlRmlsZU5hbWV9YCksXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdmbG93L3JvdXRlLmpzJylcbiAgICAgICk7XG4gICAgICBhd2FpdCB0aGlzLmNvcHlGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCBgc3RlcC8ke3RlbXBSb3V0ZUZpbGVOYW1lfWApLFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnc3RlcC9yb3V0ZS5qcycpXG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy5jb3B5RmlsZUlmQ2hhbmdlZChcbiAgICAgICAgam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgYHdlYmhvb2svW3Rva2VuXS8ke3RlbXBSb3V0ZUZpbGVOYW1lfWApLFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnd2ViaG9vay9bdG9rZW5dL3JvdXRlLmpzJylcbiAgICAgICk7XG5cbiAgICAgIC8vIEV4cG9zZSBtYW5pZmVzdCBhcyBhIHN0YXRpYyBmaWxlIHdoZW4gV09SS0ZMT1dfUFVCTElDX01BTklGRVNUPTEuXG4gICAgICAvLyBOZXh0LmpzIHNlcnZlcyBmaWxlcyBmcm9tIHB1YmxpYy8gYXQgdGhlIHJvb3QgVVJMLlxuICAgICAgaWYgKHRoaXMuc2hvdWxkRXhwb3NlUHVibGljTWFuaWZlc3QgJiYgbWFuaWZlc3RKc29uKSB7XG4gICAgICAgIGNvbnN0IHB1YmxpY01hbmlmZXN0RGlyID0gam9pbihcbiAgICAgICAgICB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgICAgICdwdWJsaWMvLndlbGwta25vd24vd29ya2Zsb3cvdjEnXG4gICAgICAgICk7XG4gICAgICAgIGF3YWl0IG1rZGlyKHB1YmxpY01hbmlmZXN0RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgaWYgKHByb2Nlc3MuZW52LlZFUkNFTF9ERVBMT1lNRU5UX0lEID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLndyaXRlRmlsZUlmQ2hhbmdlZChcbiAgICAgICAgICAgIGpvaW4ocHVibGljTWFuaWZlc3REaXIsICcuZ2l0aWdub3JlJyksXG4gICAgICAgICAgICAnKidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMuY29weUZpbGVJZkNoYW5nZWQoXG4gICAgICAgICAgbWFuaWZlc3RGaWxlUGF0aCxcbiAgICAgICAgICBqb2luKHB1YmxpY01hbmlmZXN0RGlyLCAnbWFuaWZlc3QuanNvbicpXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vIE5vdGlmeSBkZWZlcnJlZCBlbnRyeSBsb2FkZXJzIHdhaXRpbmcgb24gcm91dGUuanMgc3R1YnMuXG4gICAgICB0aGlzLnNvY2tldElPPy5lbWl0KCdidWlsZC1jb21wbGV0ZScpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY2xlYW51cEdlbmVyYXRlZEFydGlmYWN0c09uQm9vdChcbiAgICAgIG91dHB1dERpcjogc3RyaW5nXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBjb25zdCB3b3JrZmxvd0dlbmVyYXRlZERpciA9IGpvaW4ob3V0cHV0RGlyLCAnLndlbGwta25vd24vd29ya2Zsb3cvdjEnKTtcbiAgICAgIGNvbnN0IGZsb3dSb3V0ZURpciA9IGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdmbG93Jyk7XG4gICAgICBjb25zdCBzdGVwUm91dGVEaXIgPSBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnc3RlcCcpO1xuICAgICAgY29uc3Qgd2ViaG9va1JvdXRlRGlyID0gam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgJ3dlYmhvb2svW3Rva2VuXScpO1xuXG4gICAgICBjb25zdCBzdGFsZUFydGlmYWN0UGF0aHMgPSBbXG4gICAgICAgIGpvaW4oZmxvd1JvdXRlRGlyLCAncm91dGUuanMudGVtcCcpLFxuICAgICAgICBqb2luKGZsb3dSb3V0ZURpciwgJ3JvdXRlLmpzLnRlbXAuZGVidWcuanNvbicpLFxuICAgICAgICBqb2luKGZsb3dSb3V0ZURpciwgJ3JvdXRlLmpzLmRlYnVnLmpzb24nKSxcbiAgICAgICAgam9pbihzdGVwUm91dGVEaXIsICdyb3V0ZS5qcy50ZW1wJyksXG4gICAgICAgIGpvaW4oc3RlcFJvdXRlRGlyLCAncm91dGUuanMudGVtcC5kZWJ1Zy5qc29uJyksXG4gICAgICAgIGpvaW4oc3RlcFJvdXRlRGlyLCAncm91dGUuanMuZGVidWcuanNvbicpLFxuICAgICAgICBqb2luKHN0ZXBSb3V0ZURpciwgREVGRVJSRURfU1RFUF9DT1BZX0RJUl9OQU1FKSxcbiAgICAgICAgam9pbih3ZWJob29rUm91dGVEaXIsICdyb3V0ZS5qcy50ZW1wJyksXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdtYW5pZmVzdC5qc29uJyksXG4gICAgICBdO1xuXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgIC4uLnN0YWxlQXJ0aWZhY3RQYXRocy5tYXAoKHN0YWxlUGF0aCkgPT5cbiAgICAgICAgICBybShzdGFsZVBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KVxuICAgICAgICApLFxuICAgICAgICBjbGVhbnVwU3RhbGVTb2NrZXRJbmZvRmlsZXMoXG4gICAgICAgICAgam9pbih0aGlzLmNvbmZpZy53b3JraW5nRGlyLCB0aGlzLmdldERpc3REaXIoKSlcbiAgICAgICAgKSxcbiAgICAgICAgdGhpcy5yZW1vdmVTdGFsZURlZmVycmVkVGVtcEZpbGVzKGZsb3dSb3V0ZURpciksXG4gICAgICAgIHRoaXMucmVtb3ZlU3RhbGVEZWZlcnJlZFRlbXBGaWxlcyhzdGVwUm91dGVEaXIpLFxuICAgICAgICB0aGlzLnJlbW92ZVN0YWxlRGVmZXJyZWRUZW1wRmlsZXMod2ViaG9va1JvdXRlRGlyKSxcbiAgICAgIF0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcmVtb3ZlU3RhbGVEZWZlcnJlZFRlbXBGaWxlcyhcbiAgICAgIHJvdXRlRGlyOiBzdHJpbmdcbiAgICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IHJvdXRlRW50cmllcyA9IGF3YWl0IHJlYWRkaXIocm91dGVEaXIsIHtcbiAgICAgICAgd2l0aEZpbGVUeXBlczogdHJ1ZSxcbiAgICAgIH0pLmNhdGNoKCgpID0+IFtdKTtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICByb3V0ZUVudHJpZXNcbiAgICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgKGVudHJ5KSA9PlxuICAgICAgICAgICAgICBlbnRyeS5pc0ZpbGUoKSAmJlxuICAgICAgICAgICAgICBlbnRyeS5uYW1lLnN0YXJ0c1dpdGgoJ3JvdXRlLmpzLicpICYmXG4gICAgICAgICAgICAgIGVudHJ5Lm5hbWUuZW5kc1dpdGgoJy50bXAnKVxuICAgICAgICAgIClcbiAgICAgICAgICAubWFwKChlbnRyeSkgPT5cbiAgICAgICAgICAgIHJtKGpvaW4ocm91dGVEaXIsIGVudHJ5Lm5hbWUpLCB7XG4gICAgICAgICAgICAgIGZvcmNlOiB0cnVlLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICApXG4gICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY3JlYXRlRGlzY292ZXJ5U29ja2V0U2VydmVyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgaWYgKHRoaXMuc29ja2V0SU8gfHwgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfU09DS0VUX1BPUlQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzLmVudi5XT1JLRkxPV19TT0NLRVRfSU5GT19QQVRIID0gdGhpcy5nZXRTb2NrZXRJbmZvRmlsZVBhdGgoKTtcbiAgICAgIGNvbnN0IGNvbmZpZzogU29ja2V0U2VydmVyQ29uZmlnID0ge1xuICAgICAgICBpc0RldlNlcnZlcjogQm9vbGVhbih0aGlzLmNvbmZpZy53YXRjaCksXG4gICAgICAgIHNvY2tldEluZm9GaWxlUGF0aDogdGhpcy5nZXRTb2NrZXRJbmZvRmlsZVBhdGgoKSxcbiAgICAgICAgb25GaWxlRGlzY292ZXJlZDogKFxuICAgICAgICAgIGZpbGVQYXRoOiBzdHJpbmcsXG4gICAgICAgICAgaGFzV29ya2Zsb3c6IGJvb2xlYW4sXG4gICAgICAgICAgaGFzU3RlcDogYm9vbGVhbixcbiAgICAgICAgICBoYXNTZXJkZTogYm9vbGVhblxuICAgICAgICApID0+IHtcbiAgICAgICAgICBjb25zdCBub3JtYWxpemVkRmlsZVBhdGggPSB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChmaWxlUGF0aCk7XG4gICAgICAgICAgbGV0IGhhc0NhY2hlVHJhY2tpbmdDaGFuZ2UgPSBmYWxzZTtcbiAgICAgICAgICBjb25zdCB3YXNUcmFja2VkRGVwZW5kZW5jeSA9XG4gICAgICAgICAgICB0aGlzLnRyYWNrZWREZXBlbmRlbmN5RmlsZXMuaGFzKG5vcm1hbGl6ZWRGaWxlUGF0aCk7XG5cbiAgICAgICAgICBpZiAoaGFzV29ya2Zsb3cpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcy5oYXMobm9ybWFsaXplZEZpbGVQYXRoKSkge1xuICAgICAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzLmFkZChub3JtYWxpemVkRmlsZVBhdGgpO1xuICAgICAgICAgICAgICBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3Qgd2FzRGVsZXRlZCA9XG4gICAgICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMuZGVsZXRlKG5vcm1hbGl6ZWRGaWxlUGF0aCk7XG4gICAgICAgICAgICBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlID0gd2FzRGVsZXRlZCB8fCBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChoYXNTdGVwKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZGlzY292ZXJlZFN0ZXBGaWxlcy5oYXMobm9ybWFsaXplZEZpbGVQYXRoKSkge1xuICAgICAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRTdGVwRmlsZXMuYWRkKG5vcm1hbGl6ZWRGaWxlUGF0aCk7XG4gICAgICAgICAgICAgIGhhc0NhY2hlVHJhY2tpbmdDaGFuZ2UgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCB3YXNEZWxldGVkID1cbiAgICAgICAgICAgICAgdGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzLmRlbGV0ZShub3JtYWxpemVkRmlsZVBhdGgpO1xuICAgICAgICAgICAgaGFzQ2FjaGVUcmFja2luZ0NoYW5nZSA9IHdhc0RlbGV0ZWQgfHwgaGFzQ2FjaGVUcmFja2luZ0NoYW5nZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaGFzU2VyZGUpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNjb3ZlcmVkU2VyZGVGaWxlcy5oYXMobm9ybWFsaXplZEZpbGVQYXRoKSkge1xuICAgICAgICAgICAgICBoYXNDYWNoZVRyYWNraW5nQ2hhbmdlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFNlcmRlRmlsZXMuYWRkKG5vcm1hbGl6ZWRGaWxlUGF0aCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHdhc0RlbGV0ZWQgPVxuICAgICAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmRlbGV0ZShub3JtYWxpemVkRmlsZVBhdGgpO1xuICAgICAgICAgICAgaGFzQ2FjaGVUcmFja2luZ0NoYW5nZSA9IHdhc0RlbGV0ZWQgfHwgaGFzQ2FjaGVUcmFja2luZ0NoYW5nZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoaGFzQ2FjaGVUcmFja2luZ0NoYW5nZSkge1xuICAgICAgICAgICAgdGhpcy5zY2hlZHVsZVdvcmtmbG93c0NhY2hlV3JpdGUoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBoYXNXb3JrZmxvdyB8fFxuICAgICAgICAgICAgaGFzU3RlcCB8fFxuICAgICAgICAgICAgaGFzU2VyZGUgfHxcbiAgICAgICAgICAgIGhhc0NhY2hlVHJhY2tpbmdDaGFuZ2UgfHxcbiAgICAgICAgICAgIHdhc1RyYWNrZWREZXBlbmRlbmN5XG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLnNjaGVkdWxlRGVmZXJyZWRSZWJ1aWxkKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvblRyaWdnZXJCdWlsZDogKCkgPT4ge1xuICAgICAgICAgIHRoaXMuc2NoZWR1bGVEZWZlcnJlZFJlYnVpbGQoKTtcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuc29ja2V0SU8gPSBhd2FpdCBjcmVhdGVTb2NrZXRTZXJ2ZXIoY29uZmlnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemVEaXNjb3ZlcnlTdGF0ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGlmICh0aGlzLmNhY2hlSW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCB0aGlzLmxvYWRXb3JrZmxvd3NDYWNoZSgpO1xuICAgICAgYXdhaXQgdGhpcy5sb2FkRGlzY292ZXJlZEVudHJpZXNGcm9tSW5wdXRHcmFwaCgpO1xuICAgICAgdGhpcy5jYWNoZUluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldERpc3REaXIoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiAodGhpcy5jb25maWcgYXMgeyBkaXN0RGlyPzogc3RyaW5nIH0pLmRpc3REaXIgfHwgJy5uZXh0JztcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFdvcmtmbG93c0NhY2hlRmlsZVBhdGgoKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiBqb2luKFxuICAgICAgICB0aGlzLmNvbmZpZy53b3JraW5nRGlyLFxuICAgICAgICB0aGlzLmdldERpc3REaXIoKSxcbiAgICAgICAgJ2NhY2hlJyxcbiAgICAgICAgJ3dvcmtmbG93cy5qc29uJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFNvY2tldEluZm9GaWxlUGF0aCgpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIGpvaW4oXG4gICAgICAgIHRoaXMuY29uZmlnLndvcmtpbmdEaXIsXG4gICAgICAgIHRoaXMuZ2V0RGlzdERpcigpLFxuICAgICAgICBTT0NLRVRfSU5GT19GSUxFTkFNRVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChmaWxlUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgIHJldHVybiBpc0Fic29sdXRlKGZpbGVQYXRoKVxuICAgICAgICA/IGZpbGVQYXRoXG4gICAgICAgIDogcmVzb2x2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCBmaWxlUGF0aCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBmaWx0ZXJFeGlzdGluZ0ZpbGVzKGZpbGVQYXRoczogc3RyaW5nW10pOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICBjb25zdCBub3JtYWxpemVkRmlsZVBhdGhzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChcbiAgICAgICAgICBmaWxlUGF0aHMubWFwKChmaWxlUGF0aCkgPT5cbiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplRGlzY292ZXJlZEZpbGVQYXRoKGZpbGVQYXRoKVxuICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICAgKS5zb3J0KCk7XG5cbiAgICAgIGNvbnN0IGV4aXN0aW5nRmlsZXMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgbm9ybWFsaXplZEZpbGVQYXRocy5tYXAoYXN5bmMgKGZpbGVQYXRoKSA9PiB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGZpbGVTdGF0cyA9IGF3YWl0IHN0YXQoZmlsZVBhdGgpO1xuICAgICAgICAgICAgcmV0dXJuIGZpbGVTdGF0cy5pc0ZpbGUoKSA/IGZpbGVQYXRoIDogbnVsbDtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiBleGlzdGluZ0ZpbGVzLmZpbHRlcigoZmlsZVBhdGgpOiBmaWxlUGF0aCBpcyBzdHJpbmcgPT5cbiAgICAgICAgQm9vbGVhbihmaWxlUGF0aClcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjcmVhdGVEZWZlcnJlZEJ1aWxkU2lnbmF0dXJlKFxuICAgICAgaW5wdXRGaWxlczogc3RyaW5nW11cbiAgICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZEZpbGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbXG4gICAgICAgICAgLi4uaW5wdXRGaWxlcy5tYXAoKGZpbGVQYXRoKSA9PlxuICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoZmlsZVBhdGgpXG4gICAgICAgICAgKSxcbiAgICAgICAgICAuLi50aGlzLnRyYWNrZWREZXBlbmRlbmN5RmlsZXMsXG4gICAgICAgIF0pXG4gICAgICApLnNvcnQoKTtcblxuICAgICAgY29uc3Qgc2lnbmF0dXJlUGFydHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgbm9ybWFsaXplZEZpbGVzLm1hcChhc3luYyAoZmlsZVBhdGgpID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgZmlsZVN0YXRzID0gYXdhaXQgc3RhdChmaWxlUGF0aCk7XG4gICAgICAgICAgICByZXR1cm4gYCR7ZmlsZVBhdGh9OiR7ZmlsZVN0YXRzLnNpemV9OiR7TWF0aC50cnVuYyhmaWxlU3RhdHMubXRpbWVNcyl9YDtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIHJldHVybiBgJHtmaWxlUGF0aH06bWlzc2luZ2A7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgKTtcblxuICAgICAgY29uc3Qgc2lnbmF0dXJlSGFzaCA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpO1xuICAgICAgZm9yIChjb25zdCBzaWduYXR1cmVQYXJ0IG9mIHNpZ25hdHVyZVBhcnRzKSB7XG4gICAgICAgIHNpZ25hdHVyZUhhc2gudXBkYXRlKHNpZ25hdHVyZVBhcnQpO1xuICAgICAgICBzaWduYXR1cmVIYXNoLnVwZGF0ZSgnXFxuJyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzaWduYXR1cmVIYXNoLmRpZ2VzdCgnaGV4Jyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjb2xsZWN0VHJhY2tlZERpc2NvdmVyZWRFbnRyaWVzKCk6IFByb21pc2U8e1xuICAgICAgZGlzY292ZXJlZFN0ZXBzOiBzdHJpbmdbXTtcbiAgICAgIGRpc2NvdmVyZWRXb3JrZmxvd3M6IHN0cmluZ1tdO1xuICAgICAgZGlzY292ZXJlZFNlcmRlRmlsZXM6IHN0cmluZ1tdO1xuICAgIH0+IHtcbiAgICAgIGlmICh0aGlzLnRyYWNrZWREZXBlbmRlbmN5RmlsZXMuc2l6ZSA9PT0gMCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGRpc2NvdmVyZWRTdGVwczogW10sXG4gICAgICAgICAgZGlzY292ZXJlZFdvcmtmbG93czogW10sXG4gICAgICAgICAgZGlzY292ZXJlZFNlcmRlRmlsZXM6IFtdLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7IHdvcmtmbG93RmlsZXMsIHN0ZXBGaWxlcywgc2VyZGVGaWxlcyB9ID1cbiAgICAgICAgYXdhaXQgdGhpcy5yZWNvbmNpbGVEaXNjb3ZlcmVkRW50cmllcyh7XG4gICAgICAgICAgd29ya2Zsb3dDYW5kaWRhdGVzOiB0aGlzLnRyYWNrZWREZXBlbmRlbmN5RmlsZXMsXG4gICAgICAgICAgc3RlcENhbmRpZGF0ZXM6IHRoaXMudHJhY2tlZERlcGVuZGVuY3lGaWxlcyxcbiAgICAgICAgICBzZXJkZUNhbmRpZGF0ZXM6IHRoaXMudHJhY2tlZERlcGVuZGVuY3lGaWxlcyxcbiAgICAgICAgICB2YWxpZGF0ZVBhdHRlcm5zOiB0cnVlLFxuICAgICAgICB9KTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZGlzY292ZXJlZFN0ZXBzOiBBcnJheS5mcm9tKHN0ZXBGaWxlcykuc29ydCgpLFxuICAgICAgICBkaXNjb3ZlcmVkV29ya2Zsb3dzOiBBcnJheS5mcm9tKHdvcmtmbG93RmlsZXMpLnNvcnQoKSxcbiAgICAgICAgZGlzY292ZXJlZFNlcmRlRmlsZXM6IEFycmF5LmZyb20oc2VyZGVGaWxlcykuc29ydCgpLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJlZnJlc2hUcmFja2VkRGVwZW5kZW5jeUZpbGVzKFxuICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXI6IHN0cmluZyxcbiAgICAgIHJvdXRlRmlsZU5hbWU6IHN0cmluZ1xuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgY29uc3QgYnVuZGxlRmlsZXMgPSBbXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsIGBzdGVwLyR7cm91dGVGaWxlTmFtZX1gKSxcbiAgICAgICAgam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgYGZsb3cvJHtyb3V0ZUZpbGVOYW1lfWApLFxuICAgICAgXTtcbiAgICAgIGNvbnN0IHRyYWNrZWRGaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgICBmb3IgKGNvbnN0IGJ1bmRsZUZpbGUgb2YgYnVuZGxlRmlsZXMpIHtcbiAgICAgICAgY29uc3QgYnVuZGxlU291cmNlcyA9IGF3YWl0IHRoaXMuZXh0cmFjdEJ1bmRsZVNvdXJjZUZpbGVzKGJ1bmRsZUZpbGUpO1xuICAgICAgICBmb3IgKGNvbnN0IHNvdXJjZUZpbGUgb2YgYnVuZGxlU291cmNlcykge1xuICAgICAgICAgIHRyYWNrZWRGaWxlcy5hZGQoc291cmNlRmlsZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHRyYWNrZWRGaWxlcy5zaXplID4gMCkge1xuICAgICAgICB0aGlzLnRyYWNrZWREZXBlbmRlbmN5RmlsZXMgPSB0cmFja2VkRmlsZXM7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBleHRyYWN0QnVuZGxlU291cmNlRmlsZXMoXG4gICAgICBidW5kbGVGaWxlUGF0aDogc3RyaW5nXG4gICAgKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgICAgbGV0IGJ1bmRsZUNvbnRlbnRzOiBzdHJpbmc7XG4gICAgICB0cnkge1xuICAgICAgICBidW5kbGVDb250ZW50cyA9IGF3YWl0IHJlYWRGaWxlKGJ1bmRsZUZpbGVQYXRoLCAndXRmLTgnKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGJhc2VEaXJlY3RvcnkgPSBkaXJuYW1lKGJ1bmRsZUZpbGVQYXRoKTtcbiAgICAgIGNvbnN0IGxvY2FsU291cmNlRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgIGNvbnN0IHNvdXJjZU1hcE1hdGNoZXMgPSBidW5kbGVDb250ZW50cy5tYXRjaEFsbChcbiAgICAgICAgL1xcL1xcLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uXFwvanNvblteLF0qO2Jhc2U2NCwoW0EtWmEtejAtOSsvPV0rKS9nXG4gICAgICApO1xuXG4gICAgICBmb3IgKGNvbnN0IG1hdGNoIG9mIHNvdXJjZU1hcE1hdGNoZXMpIHtcbiAgICAgICAgY29uc3QgYmFzZTY0VmFsdWUgPSBtYXRjaFsxXTtcbiAgICAgICAgaWYgKCFiYXNlNjRWYWx1ZSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHNvdXJjZU1hcDogeyBzb3VyY2VSb290PzogdW5rbm93bjsgc291cmNlcz86IHVua25vd24gfTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBzb3VyY2VNYXAgPSBKU09OLnBhcnNlKFxuICAgICAgICAgICAgQnVmZmVyLmZyb20oYmFzZTY0VmFsdWUsICdiYXNlNjQnKS50b1N0cmluZygndXRmLTgnKVxuICAgICAgICAgICkgYXMgeyBzb3VyY2VSb290PzogdW5rbm93bjsgc291cmNlcz86IHVua25vd24gfTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzb3VyY2VSb290ID1cbiAgICAgICAgICB0eXBlb2Ygc291cmNlTWFwLnNvdXJjZVJvb3QgPT09ICdzdHJpbmcnID8gc291cmNlTWFwLnNvdXJjZVJvb3QgOiAnJztcbiAgICAgICAgY29uc3Qgc291cmNlcyA9IEFycmF5LmlzQXJyYXkoc291cmNlTWFwLnNvdXJjZXMpXG4gICAgICAgICAgPyBzb3VyY2VNYXAuc291cmNlcy5maWx0ZXIoXG4gICAgICAgICAgICAgIChzb3VyY2UpOiBzb3VyY2UgaXMgc3RyaW5nID0+IHR5cGVvZiBzb3VyY2UgPT09ICdzdHJpbmcnXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiBbXTtcblxuICAgICAgICBmb3IgKGNvbnN0IHNvdXJjZSBvZiBzb3VyY2VzKSB7XG4gICAgICAgICAgaWYgKHNvdXJjZS5zdGFydHNXaXRoKCd3ZWJwYWNrOi8vJykgfHwgc291cmNlLnN0YXJ0c1dpdGgoJzwnKSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbGV0IHJlc29sdmVkU291cmNlUGF0aDogc3RyaW5nO1xuICAgICAgICAgIGlmIChzb3VyY2Uuc3RhcnRzV2l0aCgnZmlsZTovLycpKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICByZXNvbHZlZFNvdXJjZVBhdGggPSBkZWNvZGVVUklDb21wb25lbnQobmV3IFVSTChzb3VyY2UpLnBhdGhuYW1lKTtcbiAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKGlzQWJzb2x1dGUoc291cmNlKSkge1xuICAgICAgICAgICAgcmVzb2x2ZWRTb3VyY2VQYXRoID0gc291cmNlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNvbHZlZFNvdXJjZVBhdGggPSByZXNvbHZlKGJhc2VEaXJlY3RvcnksIHNvdXJjZVJvb3QsIHNvdXJjZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3Qgbm9ybWFsaXplZFNvdXJjZVBhdGggPVxuICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgocmVzb2x2ZWRTb3VyY2VQYXRoKTtcbiAgICAgICAgICBjb25zdCBub3JtYWxpemVkU291cmNlUGF0aEZvckNoZWNrID0gbm9ybWFsaXplZFNvdXJjZVBhdGgucmVwbGFjZShcbiAgICAgICAgICAgIC9cXFxcL2csXG4gICAgICAgICAgICAnLydcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRTb3VyY2VQYXRoRm9yQ2hlY2suaW5jbHVkZXMoJy8ud2VsbC1rbm93bi93b3JrZmxvdy8nKSB8fFxuICAgICAgICAgICAgbm9ybWFsaXplZFNvdXJjZVBhdGhGb3JDaGVjay5pbmNsdWRlcygnL25vZGVfbW9kdWxlcy8nKSB8fFxuICAgICAgICAgICAgbm9ybWFsaXplZFNvdXJjZVBhdGhGb3JDaGVjay5pbmNsdWRlcygnLy5wbnBtLycpIHx8XG4gICAgICAgICAgICBub3JtYWxpemVkU291cmNlUGF0aEZvckNoZWNrLmluY2x1ZGVzKCcvLm5leHQvJykgfHxcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRTb3VyY2VQYXRoRm9yQ2hlY2suZW5kc1dpdGgoJy92aXJ0dWFsLWVudHJ5LmpzJylcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGxvY2FsU291cmNlRmlsZXMuYWRkKG5vcm1hbGl6ZWRTb3VyY2VQYXRoKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gQXJyYXkuZnJvbShsb2NhbFNvdXJjZUZpbGVzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNjaGVkdWxlV29ya2Zsb3dzQ2FjaGVXcml0ZSgpOiB2b2lkIHtcbiAgICAgIGlmICh0aGlzLmNhY2hlV3JpdGVUaW1lcikge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5jYWNoZVdyaXRlVGltZXIpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmNhY2hlV3JpdGVUaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLmNhY2hlV3JpdGVUaW1lciA9IG51bGw7XG4gICAgICAgIHZvaWQgdGhpcy53cml0ZVdvcmtmbG93c0NhY2hlKCkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgY29uc29sZS53YXJuKCdGYWlsZWQgdG8gd3JpdGUgd29ya2Zsb3cgZGlzY292ZXJ5IGNhY2hlJywgZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICAgIH0sIDUwKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNjaGVkdWxlRGVmZXJyZWRSZWJ1aWxkKCk6IHZvaWQge1xuICAgICAgaWYgKCF0aGlzLmNvbmZpZy53YXRjaCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmRlZmVycmVkUmVidWlsZFRpbWVyKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmRlZmVycmVkUmVidWlsZFRpbWVyKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5kZWZlcnJlZFJlYnVpbGRUaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLmRlZmVycmVkUmVidWlsZFRpbWVyID0gbnVsbDtcbiAgICAgICAgdm9pZCB0aGlzLm9uQmVmb3JlRGVmZXJyZWRFbnRyaWVzKCkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgJ1t3b3JrZmxvd10gRGVmZXJyZWQgcmVidWlsZCBhZnRlciBzb3VyY2UgdXBkYXRlIGZhaWxlZC4nLFxuICAgICAgICAgICAgZXJyb3JcbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgIH0sIDc1KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJlYWRXb3JrZmxvd3NDYWNoZSgpOiBQcm9taXNlPHtcbiAgICAgIHdvcmtmbG93RmlsZXM6IHN0cmluZ1tdO1xuICAgICAgc3RlcEZpbGVzOiBzdHJpbmdbXTtcbiAgICB9IHwgbnVsbD4ge1xuICAgICAgY29uc3QgY2FjaGVGaWxlUGF0aCA9IHRoaXMuZ2V0V29ya2Zsb3dzQ2FjaGVGaWxlUGF0aCgpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjYWNoZUNvbnRlbnRzID0gYXdhaXQgcmVhZEZpbGUoY2FjaGVGaWxlUGF0aCwgJ3V0Zi04Jyk7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UoY2FjaGVDb250ZW50cykgYXMge1xuICAgICAgICAgIHdvcmtmbG93RmlsZXM/OiB1bmtub3duO1xuICAgICAgICAgIHN0ZXBGaWxlcz86IHVua25vd247XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3Qgd29ya2Zsb3dGaWxlcyA9IEFycmF5LmlzQXJyYXkocGFyc2VkLndvcmtmbG93RmlsZXMpXG4gICAgICAgICAgPyBwYXJzZWQud29ya2Zsb3dGaWxlcy5maWx0ZXIoXG4gICAgICAgICAgICAgIChpdGVtKTogaXRlbSBpcyBzdHJpbmcgPT4gdHlwZW9mIGl0ZW0gPT09ICdzdHJpbmcnXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiBbXTtcbiAgICAgICAgY29uc3Qgc3RlcEZpbGVzID0gQXJyYXkuaXNBcnJheShwYXJzZWQuc3RlcEZpbGVzKVxuICAgICAgICAgID8gcGFyc2VkLnN0ZXBGaWxlcy5maWx0ZXIoXG4gICAgICAgICAgICAgIChpdGVtKTogaXRlbSBpcyBzdHJpbmcgPT4gdHlwZW9mIGl0ZW0gPT09ICdzdHJpbmcnXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiBbXTtcblxuICAgICAgICByZXR1cm4geyB3b3JrZmxvd0ZpbGVzLCBzdGVwRmlsZXMgfTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGxvYWRXb3JrZmxvd3NDYWNoZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IGNhY2hlZERhdGEgPSBhd2FpdCB0aGlzLnJlYWRXb3JrZmxvd3NDYWNoZSgpO1xuICAgICAgaWYgKCFjYWNoZWREYXRhKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHsgd29ya2Zsb3dGaWxlcywgc3RlcEZpbGVzLCBzZXJkZUZpbGVzIH0gPVxuICAgICAgICBhd2FpdCB0aGlzLnJlY29uY2lsZURpc2NvdmVyZWRFbnRyaWVzKHtcbiAgICAgICAgICB3b3JrZmxvd0NhbmRpZGF0ZXM6IGNhY2hlZERhdGEud29ya2Zsb3dGaWxlcyxcbiAgICAgICAgICBzdGVwQ2FuZGlkYXRlczogY2FjaGVkRGF0YS5zdGVwRmlsZXMsXG4gICAgICAgICAgc2VyZGVDYW5kaWRhdGVzOiB0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLFxuICAgICAgICAgIHZhbGlkYXRlUGF0dGVybnM6IHRydWUsXG4gICAgICAgIH0pO1xuXG4gICAgICB0aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzLmNsZWFyKCk7XG4gICAgICB0aGlzLmRpc2NvdmVyZWRTdGVwRmlsZXMuY2xlYXIoKTtcbiAgICAgIHRoaXMuZGlzY292ZXJlZFNlcmRlRmlsZXMuY2xlYXIoKTtcbiAgICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2Ygd29ya2Zsb3dGaWxlcykge1xuICAgICAgICB0aGlzLmRpc2NvdmVyZWRXb3JrZmxvd0ZpbGVzLmFkZChmaWxlUGF0aCk7XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHN0ZXBGaWxlcykge1xuICAgICAgICB0aGlzLmRpc2NvdmVyZWRTdGVwRmlsZXMuYWRkKGZpbGVQYXRoKTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2Ygc2VyZGVGaWxlcykge1xuICAgICAgICB0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmFkZChmaWxlUGF0aCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBsb2FkRGlzY292ZXJlZEVudHJpZXNGcm9tSW5wdXRHcmFwaCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IGlucHV0RmlsZXMgPSBhd2FpdCB0aGlzLmdldElucHV0RmlsZXMoKTtcbiAgICAgIGlmIChpbnB1dEZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgZGlzY292ZXJlZFdvcmtmbG93cywgZGlzY292ZXJlZFN0ZXBzLCBkaXNjb3ZlcmVkU2VyZGVGaWxlcyB9ID1cbiAgICAgICAgYXdhaXQgdGhpcy5kaXNjb3ZlckVudHJpZXMoaW5wdXRGaWxlcywgdGhpcy5jb25maWcud29ya2luZ0Rpcik7XG4gICAgICBjb25zdCB7IHdvcmtmbG93RmlsZXMsIHN0ZXBGaWxlcywgc2VyZGVGaWxlcyB9ID1cbiAgICAgICAgYXdhaXQgdGhpcy5yZWNvbmNpbGVEaXNjb3ZlcmVkRW50cmllcyh7XG4gICAgICAgICAgd29ya2Zsb3dDYW5kaWRhdGVzOiBkaXNjb3ZlcmVkV29ya2Zsb3dzLFxuICAgICAgICAgIHN0ZXBDYW5kaWRhdGVzOiBkaXNjb3ZlcmVkU3RlcHMsXG4gICAgICAgICAgc2VyZGVDYW5kaWRhdGVzOiBkaXNjb3ZlcmVkU2VyZGVGaWxlcyxcbiAgICAgICAgICB2YWxpZGF0ZVBhdHRlcm5zOiB0cnVlLFxuICAgICAgICB9KTtcblxuICAgICAgbGV0IGhhc0NoYW5nZXMgPSBmYWxzZTtcbiAgICAgIGZvciAoY29uc3QgZmlsZVBhdGggb2Ygd29ya2Zsb3dGaWxlcykge1xuICAgICAgICBpZiAoIXRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMuaGFzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFdvcmtmbG93RmlsZXMuYWRkKGZpbGVQYXRoKTtcbiAgICAgICAgICBoYXNDaGFuZ2VzID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZm9yIChjb25zdCBmaWxlUGF0aCBvZiBzdGVwRmlsZXMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRpc2NvdmVyZWRTdGVwRmlsZXMuaGFzKGZpbGVQYXRoKSkge1xuICAgICAgICAgIHRoaXMuZGlzY292ZXJlZFN0ZXBGaWxlcy5hZGQoZmlsZVBhdGgpO1xuICAgICAgICAgIGhhc0NoYW5nZXMgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHNlcmRlRmlsZXMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICB0aGlzLmRpc2NvdmVyZWRTZXJkZUZpbGVzLmFkZChmaWxlUGF0aCk7XG4gICAgICAgICAgaGFzQ2hhbmdlcyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGhhc0NoYW5nZXMpIHtcbiAgICAgICAgdGhpcy5zY2hlZHVsZVdvcmtmbG93c0NhY2hlV3JpdGUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHdyaXRlV29ya2Zsb3dzQ2FjaGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBjb25zdCBjYWNoZUZpbGVQYXRoID0gdGhpcy5nZXRXb3JrZmxvd3NDYWNoZUZpbGVQYXRoKCk7XG4gICAgICBjb25zdCBjYWNoZURpciA9IGpvaW4odGhpcy5jb25maWcud29ya2luZ0RpciwgdGhpcy5nZXREaXN0RGlyKCksICdjYWNoZScpO1xuICAgICAgYXdhaXQgbWtkaXIoY2FjaGVEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gICAgICBjb25zdCBjYWNoZURhdGEgPSB7XG4gICAgICAgIHdvcmtmbG93RmlsZXM6IEFycmF5LmZyb20odGhpcy5kaXNjb3ZlcmVkV29ya2Zsb3dGaWxlcykuc29ydCgpLFxuICAgICAgICBzdGVwRmlsZXM6IEFycmF5LmZyb20odGhpcy5kaXNjb3ZlcmVkU3RlcEZpbGVzKS5zb3J0KCksXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCB3cml0ZUZpbGUoY2FjaGVGaWxlUGF0aCwgSlNPTi5zdHJpbmdpZnkoY2FjaGVEYXRhLCBudWxsLCAyKSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyB3cml0ZVN0dWJGaWxlcyhvdXRwdXREaXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgLy8gVHVyYm9wYWNrIGN1cnJlbnRseSBoYXMgYSB3b3JrZXItY29uY3VycmVuY3kgbGltaXRhdGlvbiBmb3IgcGVuZGluZ1xuICAgICAgLy8gdmlydHVhbCBlbnRyaWVzLiBXYXJuIGlmIHBhcmFsbGVsaXNtIGlzIHRvbyBsb3cgdG8gcmVsaWFibHkgZGlzY292ZXIuXG4gICAgICBjb25zdCBwYXJhbGxlbGlzbUNvdW50ID0gb3MuYXZhaWxhYmxlUGFyYWxsZWxpc20oKTtcbiAgICAgIGlmIChwcm9jZXNzLmVudi5UVVJCT1BBQ0sgJiYgcGFyYWxsZWxpc21Db3VudCA8IDQpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGBBdmFpbGFibGUgcGFyYWxsZWxpc20gb2YgJHtwYXJhbGxlbGlzbUNvdW50fSBpcyBsZXNzIHRoYW4gbmVlZGVkIDQuIFRoaXMgY2FuIGNhdXNlIHdvcmtmbG93cy9zdGVwcyB0byBmYWlsIHRvIGRpc2NvdmVyIHByb3Blcmx5IGluIHR1cmJvcGFja2BcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgcm91dGVTdHViQ29udGVudCA9IFtcbiAgICAgICAgYC8vICR7Uk9VVEVfU1RVQl9GSUxFX01BUktFUn1gLFxuICAgICAgICAnZXhwb3J0IGNvbnN0IF9fd29ya2Zsb3dSb3V0ZVN0dWIgPSB0cnVlOycsXG4gICAgICBdLmpvaW4oJ1xcbicpO1xuICAgICAgY29uc3Qgd29ya2Zsb3dHZW5lcmF0ZWREaXIgPSBqb2luKG91dHB1dERpciwgJy53ZWxsLWtub3duL3dvcmtmbG93L3YxJyk7XG5cbiAgICAgIGF3YWl0IG1rZGlyKGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdmbG93JyksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgYXdhaXQgbWtkaXIoam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgJ3N0ZXAnKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBhd2FpdCBta2Rpcihqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnd2ViaG9vay9bdG9rZW5dJyksIHtcbiAgICAgICAgcmVjdXJzaXZlOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnLmdpdGlnbm9yZScpLFxuICAgICAgICAnKidcbiAgICAgICk7XG5cbiAgICAgIC8vIHJvdXRlLmpzIHN0dWJzIGFyZSByZXBsYWNlZCBieSBnZW5lcmF0ZWQgcm91dGUuanMgb3V0cHV0IG9uY2UgZGlzY292ZXJ5XG4gICAgICAvLyBmaW5pc2hlcyBhbmQgYSBkZWZlcnJlZCBidWlsZCBjb21wbGV0ZXMuXG4gICAgICBhd2FpdCB0aGlzLndyaXRlRmlsZUlmQ2hhbmdlZChcbiAgICAgICAgam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgJ2Zsb3cvcm91dGUuanMnKSxcbiAgICAgICAgcm91dGVTdHViQ29udGVudFxuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnc3RlcC9yb3V0ZS5qcycpLFxuICAgICAgICByb3V0ZVN0dWJDb250ZW50XG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQoXG4gICAgICAgIGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICd3ZWJob29rL1t0b2tlbl0vcm91dGUuanMnKSxcbiAgICAgICAgcm91dGVTdHViQ29udGVudFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYXN5bmMgZ2V0SW5wdXRGaWxlcygpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICBjb25zdCBpbnB1dEZpbGVzID0gYXdhaXQgc3VwZXIuZ2V0SW5wdXRGaWxlcygpO1xuICAgICAgcmV0dXJuIGlucHV0RmlsZXMuZmlsdGVyKChpdGVtKSA9PiB7XG4gICAgICAgIC8vIE1hdGNoIEFwcCBSb3V0ZXIgZW50cnlwb2ludHM6IHJvdXRlLnRzLCBwYWdlLnRzLCBsYXlvdXQudHMgaW4gYXBwLyBvciBzcmMvYXBwLyBkaXJlY3Rvcmllc1xuICAgICAgICAvLyBNYXRjaGVzOiAvYXBwL3BhZ2UudHMsIC9hcHAvZGFzaGJvYXJkL3BhZ2UudHMsIC9zcmMvYXBwL3JvdXRlLnRzLCBldGMuXG4gICAgICAgIGlmIChcbiAgICAgICAgICBpdGVtLm1hdGNoKFxuICAgICAgICAgICAgLyhefC4qWy9cXFxcXSkoYXBwfHNyY1svXFxcXF1hcHApKFsvXFxcXF0ocm91dGV8cGFnZXxsYXlvdXQpXFwufFsvXFxcXF0uKlsvXFxcXF0ocm91dGV8cGFnZXxsYXlvdXQpXFwuKS9cbiAgICAgICAgICApXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIE1hdGNoIFBhZ2VzIFJvdXRlciBlbnRyeXBvaW50czogZmlsZXMgaW4gcGFnZXMvIG9yIHNyYy9wYWdlcy9cbiAgICAgICAgaWYgKGl0ZW0ubWF0Y2goL1svXFxcXF0ocGFnZXN8c3JjWy9cXFxcXXBhZ2VzKVsvXFxcXF0vKSkge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgd3JpdGVGdW5jdGlvbnNDb25maWcob3V0cHV0RGlyOiBzdHJpbmcpIHtcbiAgICAgIC8vIHdlIGRvbid0IHJ1biB0aGlzIGluIGRldmVsb3BtZW50IG1vZGUgYXMgaXQncyBub3QgbmVlZGVkXG4gICAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdkZXZlbG9wbWVudCcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgZ2VuZXJhdGVkQ29uZmlnID0ge1xuICAgICAgICB2ZXJzaW9uOiAnMCcsXG4gICAgICAgIHN0ZXBzOiB7XG4gICAgICAgICAgbWF4RHVyYXRpb246ICdtYXgnLFxuICAgICAgICAgIGV4cGVyaW1lbnRhbFRyaWdnZXJzOiBbU1RFUF9RVUVVRV9UUklHR0VSXSxcbiAgICAgICAgfSxcbiAgICAgICAgd29ya2Zsb3dzOiB7XG4gICAgICAgICAgbWF4RHVyYXRpb246ICdtYXgnLFxuICAgICAgICAgIGV4cGVyaW1lbnRhbFRyaWdnZXJzOiBbV09SS0ZMT1dfUVVFVUVfVFJJR0dFUl0sXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICAvLyBXZSB3cml0ZSB0aGlzIGZpbGUgdG8gdGhlIGdlbmVyYXRlZCBkaXJlY3RvcnkgZm9yXG4gICAgICAvLyB0aGUgTmV4dC5qcyBidWlsZGVyIHRvIGNvbnN1bWVcbiAgICAgIGF3YWl0IHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKFxuICAgICAgICBqb2luKG91dHB1dERpciwgJy53ZWxsLWtub3duL3dvcmtmbG93L3YxL2NvbmZpZy5qc29uJyksXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KGdlbmVyYXRlZENvbmZpZywgbnVsbCwgMilcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyB3cml0ZUZpbGVJZkNoYW5nZWQoXG4gICAgICBmaWxlUGF0aDogc3RyaW5nLFxuICAgICAgY29udGVudHM6IHN0cmluZyB8IEJ1ZmZlclxuICAgICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgY29uc3QgbmV4dEJ1ZmZlciA9IEJ1ZmZlci5pc0J1ZmZlcihjb250ZW50cylcbiAgICAgICAgPyBjb250ZW50c1xuICAgICAgICA6IEJ1ZmZlci5mcm9tKGNvbnRlbnRzKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY3VycmVudEJ1ZmZlciA9IGF3YWl0IHJlYWRGaWxlKGZpbGVQYXRoKTtcbiAgICAgICAgaWYgKGN1cnJlbnRCdWZmZXIuZXF1YWxzKG5leHRCdWZmZXIpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gRmlsZSBkb2VzIG5vdCBleGlzdCB5ZXQgb3IgY2Fubm90IGJlIHJlYWQ7IHdyaXRlIGEgZnJlc2ggY29weS5cbiAgICAgIH1cblxuICAgICAgYXdhaXQgbWtkaXIoZGlybmFtZShmaWxlUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgYXdhaXQgd3JpdGVGaWxlKGZpbGVQYXRoLCBuZXh0QnVmZmVyKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29weUZpbGVJZkNoYW5nZWQoXG4gICAgICBzb3VyY2VQYXRoOiBzdHJpbmcsXG4gICAgICBkZXN0aW5hdGlvblBhdGg6IHN0cmluZ1xuICAgICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgY29uc3Qgc291cmNlQ29udGVudHMgPSBhd2FpdCByZWFkRmlsZShzb3VyY2VQYXRoKTtcbiAgICAgIHJldHVybiB0aGlzLndyaXRlRmlsZUlmQ2hhbmdlZChkZXN0aW5hdGlvblBhdGgsIHNvdXJjZUNvbnRlbnRzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNvcnRKc29uVmFsdWUodmFsdWU6IHVua25vd24pOiB1bmtub3duIHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gdmFsdWUubWFwKChpdGVtKSA9PiB0aGlzLnNvcnRKc29uVmFsdWUoaXRlbSkpO1xuICAgICAgfVxuICAgICAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgY29uc3Qgc29ydGVkRW50cmllcyA9IE9iamVjdC5lbnRyaWVzKHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVxuICAgICAgICAgIC5zb3J0KChbYV0sIFtiXSkgPT4gYS5sb2NhbGVDb21wYXJlKGIpKVxuICAgICAgICAgIC5tYXAoKFtrZXksIGVudHJ5VmFsdWVdKSA9PiBba2V5LCB0aGlzLnNvcnRKc29uVmFsdWUoZW50cnlWYWx1ZSldKTtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhzb3J0ZWRFbnRyaWVzKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJld3JpdGVKc29uRmlsZVdpdGhTdGFibGVLZXlPcmRlcihcbiAgICAgIGZpbGVQYXRoOiBzdHJpbmdcbiAgICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGNvbnRlbnRzID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGNvbnRlbnRzKSBhcyB1bmtub3duO1xuICAgICAgICBjb25zdCBub3JtYWxpemVkID0gdGhpcy5zb3J0SnNvblZhbHVlKHBhcnNlZCk7XG4gICAgICAgIGF3YWl0IHRoaXMud3JpdGVGaWxlSWZDaGFuZ2VkKFxuICAgICAgICAgIGZpbGVQYXRoLFxuICAgICAgICAgIGAke0pTT04uc3RyaW5naWZ5KG5vcm1hbGl6ZWQsIG51bGwsIDIpfVxcbmBcbiAgICAgICAgKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBNYW5pZmVzdCBtYXkgbm90IGV4aXN0IChlLmcuIG1hbmlmZXN0IGdlbmVyYXRpb24gZmFpbGVkKTsgaWdub3JlLlxuICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgbWVyZ2VXb3JrZmxvd01hbmlmZXN0KFxuICAgICAgdGFyZ2V0OiBXb3JrZmxvd01hbmlmZXN0LFxuICAgICAgc291cmNlOiBXb3JrZmxvd01hbmlmZXN0XG4gICAgKTogdm9pZCB7XG4gICAgICBpZiAoc291cmNlLnN0ZXBzKSB7XG4gICAgICAgIHRhcmdldC5zdGVwcyA9IE9iamVjdC5hc3NpZ24odGFyZ2V0LnN0ZXBzIHx8IHt9LCBzb3VyY2Uuc3RlcHMpO1xuICAgICAgfVxuICAgICAgaWYgKHNvdXJjZS53b3JrZmxvd3MpIHtcbiAgICAgICAgdGFyZ2V0LndvcmtmbG93cyA9IE9iamVjdC5hc3NpZ24oXG4gICAgICAgICAgdGFyZ2V0LndvcmtmbG93cyB8fCB7fSxcbiAgICAgICAgICBzb3VyY2Uud29ya2Zsb3dzXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoc291cmNlLmNsYXNzZXMpIHtcbiAgICAgICAgdGFyZ2V0LmNsYXNzZXMgPSBPYmplY3QuYXNzaWduKHRhcmdldC5jbGFzc2VzIHx8IHt9LCBzb3VyY2UuY2xhc3Nlcyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBnZXRSZWxhdGl2ZUZpbGVuYW1lRm9yU3djKGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgY29uc3Qgd29ya2luZ0RpciA9IHRoaXMuY29uZmlnLndvcmtpbmdEaXI7XG4gICAgICBjb25zdCBub3JtYWxpemVkV29ya2luZ0RpciA9IHdvcmtpbmdEaXJcbiAgICAgICAgLnJlcGxhY2UoL1xcXFwvZywgJy8nKVxuICAgICAgICAucmVwbGFjZSgvXFwvJC8sICcnKTtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRGaWxlcGF0aCA9IGZpbGVQYXRoLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcblxuICAgICAgLy8gV2luZG93cyBmaXg6IFVzZSBjYXNlLWluc2Vuc2l0aXZlIGNvbXBhcmlzb24gdG8gd29yayBhcm91bmQgZHJpdmUgbGV0dGVyIGNhc2luZyBpc3N1ZXMuXG4gICAgICBjb25zdCBsb3dlcldkID0gbm9ybWFsaXplZFdvcmtpbmdEaXIudG9Mb3dlckNhc2UoKTtcbiAgICAgIGNvbnN0IGxvd2VyUGF0aCA9IG5vcm1hbGl6ZWRGaWxlcGF0aC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICBsZXQgcmVsYXRpdmVGaWxlbmFtZTogc3RyaW5nO1xuICAgICAgaWYgKGxvd2VyUGF0aC5zdGFydHNXaXRoKGAke2xvd2VyV2R9L2ApKSB7XG4gICAgICAgIHJlbGF0aXZlRmlsZW5hbWUgPSBub3JtYWxpemVkRmlsZXBhdGguc3Vic3RyaW5nKFxuICAgICAgICAgIG5vcm1hbGl6ZWRXb3JraW5nRGlyLmxlbmd0aCArIDFcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAobG93ZXJQYXRoID09PSBsb3dlcldkKSB7XG4gICAgICAgIHJlbGF0aXZlRmlsZW5hbWUgPSAnLic7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZWxhdGl2ZUZpbGVuYW1lID0gcmVsYXRpdmUod29ya2luZ0RpciwgZmlsZVBhdGgpLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgICAgaWYgKHJlbGF0aXZlRmlsZW5hbWUuc3RhcnRzV2l0aCgnLi4vJykpIHtcbiAgICAgICAgICBjb25zdCBhbGlhc2VkUmVsYXRpdmVQYXRoID0gYXdhaXQgcmVzb2x2ZVdvcmtmbG93QWxpYXNSZWxhdGl2ZVBhdGgoXG4gICAgICAgICAgICBmaWxlUGF0aCxcbiAgICAgICAgICAgIHdvcmtpbmdEaXJcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChhbGlhc2VkUmVsYXRpdmVQYXRoKSB7XG4gICAgICAgICAgICByZWxhdGl2ZUZpbGVuYW1lID0gYWxpYXNlZFJlbGF0aXZlUGF0aDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVsYXRpdmVGaWxlbmFtZSA9IHJlbGF0aXZlRmlsZW5hbWVcbiAgICAgICAgICAgICAgLnNwbGl0KCcvJylcbiAgICAgICAgICAgICAgLmZpbHRlcigocGFydCkgPT4gcGFydCAhPT0gJy4uJylcbiAgICAgICAgICAgICAgLmpvaW4oJy8nKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHJlbGF0aXZlRmlsZW5hbWUuaW5jbHVkZXMoJzonKSB8fCByZWxhdGl2ZUZpbGVuYW1lLnN0YXJ0c1dpdGgoJy8nKSkge1xuICAgICAgICByZWxhdGl2ZUZpbGVuYW1lID0gYmFzZW5hbWUobm9ybWFsaXplZEZpbGVwYXRoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlbGF0aXZlRmlsZW5hbWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZWxhdGl2ZUltcG9ydFNwZWNpZmllcihcbiAgICAgIGZyb21GaWxlUGF0aDogc3RyaW5nLFxuICAgICAgdG9GaWxlUGF0aDogc3RyaW5nXG4gICAgKTogc3RyaW5nIHtcbiAgICAgIGxldCByZWxhdGl2ZVBhdGggPSByZWxhdGl2ZShkaXJuYW1lKGZyb21GaWxlUGF0aCksIHRvRmlsZVBhdGgpLnJlcGxhY2UoXG4gICAgICAgIC9cXFxcL2csXG4gICAgICAgICcvJ1xuICAgICAgKTtcbiAgICAgIGlmICghcmVsYXRpdmVQYXRoLnN0YXJ0c1dpdGgoJy4nKSkge1xuICAgICAgICByZWxhdGl2ZVBhdGggPSBgLi8ke3JlbGF0aXZlUGF0aH1gO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlbGF0aXZlUGF0aDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFN0ZXBDb3B5RmlsZU5hbWUoZmlsZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICBjb25zdCBub3JtYWxpemVkUGF0aCA9IGZpbGVQYXRoLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgIGNvbnN0IGhhc2ggPSBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUobm9ybWFsaXplZFBhdGgpLmRpZ2VzdCgnaGV4Jyk7XG4gICAgICBjb25zdCBleHRlbnNpb24gPSBleHRuYW1lKG5vcm1hbGl6ZWRQYXRoKTtcbiAgICAgIHJldHVybiBgJHtoYXNoLnNsaWNlKDAsIDE2KX0ke2V4dGVuc2lvbiB8fCAnLmpzJ31gO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmV3cml0ZUNvcGllZFN0ZXBJbXBvcnRTcGVjaWZpZXIoXG4gICAgICBzcGVjaWZpZXI6IHN0cmluZyxcbiAgICAgIHNvdXJjZUZpbGVQYXRoOiBzdHJpbmcsXG4gICAgICBjb3BpZWRGaWxlUGF0aDogc3RyaW5nLFxuICAgICAgY29waWVkU3RlcEZpbGVCeVNvdXJjZVBhdGg6IE1hcDxzdHJpbmcsIHN0cmluZz5cbiAgICApOiBzdHJpbmcge1xuICAgICAgaWYgKCFzcGVjaWZpZXIuc3RhcnRzV2l0aCgnLicpKSB7XG4gICAgICAgIHJldHVybiBzcGVjaWZpZXI7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNwZWNpZmllck1hdGNoID0gc3BlY2lmaWVyLm1hdGNoKC9eKFtePyNdKykoLiopJC8pO1xuICAgICAgY29uc3QgaW1wb3J0UGF0aCA9IHNwZWNpZmllck1hdGNoPy5bMV0gPz8gc3BlY2lmaWVyO1xuICAgICAgY29uc3Qgc3VmZml4ID0gc3BlY2lmaWVyTWF0Y2g/LlsyXSA/PyAnJztcbiAgICAgIGNvbnN0IGFic29sdXRlVGFyZ2V0UGF0aCA9IHJlc29sdmUoZGlybmFtZShzb3VyY2VGaWxlUGF0aCksIGltcG9ydFBhdGgpO1xuICAgICAgY29uc3QgcmVzb2x2ZWRUYXJnZXRQYXRoID1cbiAgICAgICAgdGhpcy5yZXNvbHZlQ29waWVkU3RlcEltcG9ydFRhcmdldFBhdGgoYWJzb2x1dGVUYXJnZXRQYXRoKTtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRUYXJnZXRQYXRoID0gcmVzb2x2ZWRUYXJnZXRQYXRoLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgIGNvbnN0IGNvcGllZFRhcmdldFBhdGggPVxuICAgICAgICBjb3BpZWRTdGVwRmlsZUJ5U291cmNlUGF0aC5nZXQobm9ybWFsaXplZFRhcmdldFBhdGgpIHx8XG4gICAgICAgICgoKSA9PiB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlYWxUYXJnZXRQYXRoID0gcmVhbHBhdGhTeW5jKHJlc29sdmVkVGFyZ2V0UGF0aCkucmVwbGFjZShcbiAgICAgICAgICAgICAgL1xcXFwvZyxcbiAgICAgICAgICAgICAgJy8nXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIGNvcGllZFN0ZXBGaWxlQnlTb3VyY2VQYXRoLmdldChyZWFsVGFyZ2V0UGF0aCk7XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKTtcbiAgICAgIGxldCByZXdyaXR0ZW5QYXRoID0gcmVsYXRpdmUoXG4gICAgICAgIGRpcm5hbWUoY29waWVkRmlsZVBhdGgpLFxuICAgICAgICBjb3BpZWRUYXJnZXRQYXRoIHx8IHJlc29sdmVkVGFyZ2V0UGF0aFxuICAgICAgKS5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gICAgICBpZiAoIXJld3JpdHRlblBhdGguc3RhcnRzV2l0aCgnLicpKSB7XG4gICAgICAgIHJld3JpdHRlblBhdGggPSBgLi8ke3Jld3JpdHRlblBhdGh9YDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBgJHtyZXdyaXR0ZW5QYXRofSR7c3VmZml4fWA7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZXNvbHZlQ29waWVkU3RlcEltcG9ydFRhcmdldFBhdGgodGFyZ2V0UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgIGlmIChleGlzdHNTeW5jKHRhcmdldFBhdGgpKSB7XG4gICAgICAgIHJldHVybiB0YXJnZXRQYXRoO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBleHRlbnNpb25NYXRjaCA9IHRhcmdldFBhdGgubWF0Y2goLyhcXC5bXi4vXFxcXF0rKSQvKTtcbiAgICAgIGNvbnN0IGV4dGVuc2lvbiA9IGV4dGVuc2lvbk1hdGNoPy5bMV0/LnRvTG93ZXJDYXNlKCk7XG4gICAgICBpZiAoIWV4dGVuc2lvbikge1xuICAgICAgICByZXR1cm4gdGFyZ2V0UGF0aDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXh0ZW5zaW9uRmFsbGJhY2tzID1cbiAgICAgICAgZXh0ZW5zaW9uID09PSAnLmpzJ1xuICAgICAgICAgID8gWycudHMnLCAnLnRzeCcsICcubXRzJywgJy5jdHMnXVxuICAgICAgICAgIDogZXh0ZW5zaW9uID09PSAnLm1qcydcbiAgICAgICAgICAgID8gWycubXRzJ11cbiAgICAgICAgICAgIDogZXh0ZW5zaW9uID09PSAnLmNqcydcbiAgICAgICAgICAgICAgPyBbJy5jdHMnXVxuICAgICAgICAgICAgICA6IGV4dGVuc2lvbiA9PT0gJy5qc3gnXG4gICAgICAgICAgICAgICAgPyBbJy50c3gnXVxuICAgICAgICAgICAgICAgIDogW107XG5cbiAgICAgIGlmIChleHRlbnNpb25GYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0YXJnZXRQYXRoO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0YXJnZXRXaXRob3V0RXh0ZW5zaW9uID0gdGFyZ2V0UGF0aC5zbGljZSgwLCAtZXh0ZW5zaW9uLmxlbmd0aCk7XG4gICAgICBmb3IgKGNvbnN0IGZhbGxiYWNrRXh0ZW5zaW9uIG9mIGV4dGVuc2lvbkZhbGxiYWNrcykge1xuICAgICAgICBjb25zdCBmYWxsYmFja1BhdGggPSBgJHt0YXJnZXRXaXRob3V0RXh0ZW5zaW9ufSR7ZmFsbGJhY2tFeHRlbnNpb259YDtcbiAgICAgICAgaWYgKGV4aXN0c1N5bmMoZmFsbGJhY2tQYXRoKSkge1xuICAgICAgICAgIHJldHVybiBmYWxsYmFja1BhdGg7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRhcmdldFBhdGg7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZXdyaXRlUmVsYXRpdmVJbXBvcnRzRm9yQ29waWVkU3RlcChcbiAgICAgIHNvdXJjZTogc3RyaW5nLFxuICAgICAgc291cmNlRmlsZVBhdGg6IHN0cmluZyxcbiAgICAgIGNvcGllZEZpbGVQYXRoOiBzdHJpbmcsXG4gICAgICBjb3BpZWRTdGVwRmlsZUJ5U291cmNlUGF0aDogTWFwPHN0cmluZywgc3RyaW5nPlxuICAgICk6IHN0cmluZyB7XG4gICAgICBjb25zdCByZXdyaXRlU3BlY2lmaWVyID0gKHNwZWNpZmllcjogc3RyaW5nKSA9PlxuICAgICAgICB0aGlzLnJld3JpdGVDb3BpZWRTdGVwSW1wb3J0U3BlY2lmaWVyKFxuICAgICAgICAgIHNwZWNpZmllcixcbiAgICAgICAgICBzb3VyY2VGaWxlUGF0aCxcbiAgICAgICAgICBjb3BpZWRGaWxlUGF0aCxcbiAgICAgICAgICBjb3BpZWRTdGVwRmlsZUJ5U291cmNlUGF0aFxuICAgICAgICApO1xuICAgICAgY29uc3QgcmV3cml0ZVBhdHRlcm4gPSAoY3VycmVudFNvdXJjZTogc3RyaW5nLCBwYXR0ZXJuOiBSZWdFeHApOiBzdHJpbmcgPT5cbiAgICAgICAgY3VycmVudFNvdXJjZS5yZXBsYWNlKFxuICAgICAgICAgIHBhdHRlcm4sXG4gICAgICAgICAgKF9tYXRjaCwgcHJlZml4OiBzdHJpbmcsIHNwZWNpZmllcjogc3RyaW5nLCBzdWZmaXg6IHN0cmluZykgPT5cbiAgICAgICAgICAgIGAke3ByZWZpeH0ke3Jld3JpdGVTcGVjaWZpZXIoc3BlY2lmaWVyKX0ke3N1ZmZpeH1gXG4gICAgICAgICk7XG5cbiAgICAgIGxldCByZXdyaXR0ZW5Tb3VyY2UgPSBzb3VyY2U7XG4gICAgICByZXdyaXR0ZW5Tb3VyY2UgPSByZXdyaXRlUGF0dGVybihcbiAgICAgICAgcmV3cml0dGVuU291cmNlLFxuICAgICAgICAvKGZyb21cXHMrWydcIl0pKFteJ1wiXSspKFsnXCJdKS9nXG4gICAgICApO1xuICAgICAgcmV3cml0dGVuU291cmNlID0gcmV3cml0ZVBhdHRlcm4oXG4gICAgICAgIHJld3JpdHRlblNvdXJjZSxcbiAgICAgICAgLyhpbXBvcnRcXHMrWydcIl0pKFteJ1wiXSspKFsnXCJdKS9nXG4gICAgICApO1xuICAgICAgcmV3cml0dGVuU291cmNlID0gcmV3cml0ZVBhdHRlcm4oXG4gICAgICAgIHJld3JpdHRlblNvdXJjZSxcbiAgICAgICAgLyhpbXBvcnRcXChcXHMqWydcIl0pKFteJ1wiXSspKFsnXCJdXFxzKlxcKSkvZ1xuICAgICAgKTtcbiAgICAgIHJld3JpdHRlblNvdXJjZSA9IHJld3JpdGVQYXR0ZXJuKFxuICAgICAgICByZXdyaXR0ZW5Tb3VyY2UsXG4gICAgICAgIC8ocmVxdWlyZVxcKFxccypbJ1wiXSkoW14nXCJdKykoWydcIl1cXHMqXFwpKS9nXG4gICAgICApO1xuICAgICAgcmV0dXJuIHJld3JpdHRlblNvdXJjZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGV4dHJhY3RSZWxhdGl2ZUltcG9ydFNwZWNpZmllcnMoc291cmNlOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgICBjb25zdCByZWxhdGl2ZVNwZWNpZmllcnMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgIGNvbnN0IGltcG9ydFBhdHRlcm5zID0gW1xuICAgICAgICAvZnJvbVxccytbJ1wiXShbXidcIl0rKVsnXCJdL2csXG4gICAgICAgIC9pbXBvcnRcXHMrWydcIl0oW14nXCJdKylbJ1wiXS9nLFxuICAgICAgICAvaW1wb3J0XFwoXFxzKlsnXCJdKFteJ1wiXSspWydcIl1cXHMqXFwpL2csXG4gICAgICAgIC9yZXF1aXJlXFwoXFxzKlsnXCJdKFteJ1wiXSspWydcIl1cXHMqXFwpL2csXG4gICAgICBdO1xuXG4gICAgICBmb3IgKGNvbnN0IGltcG9ydFBhdHRlcm4gb2YgaW1wb3J0UGF0dGVybnMpIHtcbiAgICAgICAgZm9yIChjb25zdCBtYXRjaCBvZiBzb3VyY2UubWF0Y2hBbGwoaW1wb3J0UGF0dGVybikpIHtcbiAgICAgICAgICBjb25zdCBzcGVjaWZpZXIgPSBtYXRjaFsxXTtcbiAgICAgICAgICBpZiAoc3BlY2lmaWVyPy5zdGFydHNXaXRoKCcuJykpIHtcbiAgICAgICAgICAgIHJlbGF0aXZlU3BlY2lmaWVycy5hZGQoc3BlY2lmaWVyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIEFycmF5LmZyb20ocmVsYXRpdmVTcGVjaWZpZXJzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNob3VsZFNraXBUcmFuc2l0aXZlU3RlcEZpbGUoZmlsZVBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFBhdGggPSBmaWxlUGF0aC5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gICAgICByZXR1cm4gKFxuICAgICAgICBub3JtYWxpemVkUGF0aC5pbmNsdWRlcygnLy53ZWxsLWtub3duL3dvcmtmbG93LycpIHx8XG4gICAgICAgIG5vcm1hbGl6ZWRQYXRoLmluY2x1ZGVzKCcvLm5leHQvJykgfHxcbiAgICAgICAgbm9ybWFsaXplZFBhdGguaW5jbHVkZXMoJy9ub2RlX21vZHVsZXMvJykgfHxcbiAgICAgICAgbm9ybWFsaXplZFBhdGguaW5jbHVkZXMoJy8ucG5wbS8nKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJlc29sdmVUcmFuc2l0aXZlU3RlcEltcG9ydFRhcmdldFBhdGgoXG4gICAgICBzb3VyY2VGaWxlUGF0aDogc3RyaW5nLFxuICAgICAgc3BlY2lmaWVyOiBzdHJpbmdcbiAgICApOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgICAgIGNvbnN0IHNwZWNpZmllck1hdGNoID0gc3BlY2lmaWVyLm1hdGNoKC9eKFtePyNdKykoLiopJC8pO1xuICAgICAgY29uc3QgaW1wb3J0UGF0aCA9IHNwZWNpZmllck1hdGNoPy5bMV0gPz8gc3BlY2lmaWVyO1xuICAgICAgY29uc3QgYWJzb2x1dGVUYXJnZXRQYXRoID0gcmVzb2x2ZShkaXJuYW1lKHNvdXJjZUZpbGVQYXRoKSwgaW1wb3J0UGF0aCk7XG5cbiAgICAgIGNvbnN0IGNhbmRpZGF0ZVBhdGhzID0gbmV3IFNldDxzdHJpbmc+KFtcbiAgICAgICAgdGhpcy5yZXNvbHZlQ29waWVkU3RlcEltcG9ydFRhcmdldFBhdGgoYWJzb2x1dGVUYXJnZXRQYXRoKSxcbiAgICAgIF0pO1xuXG4gICAgICBpZiAoIWV4dG5hbWUoYWJzb2x1dGVUYXJnZXRQYXRoKSkge1xuICAgICAgICBjb25zdCBleHRlbnNpb25DYW5kaWRhdGVzID0gW1xuICAgICAgICAgICcudHMnLFxuICAgICAgICAgICcudHN4JyxcbiAgICAgICAgICAnLm10cycsXG4gICAgICAgICAgJy5jdHMnLFxuICAgICAgICAgICcuanMnLFxuICAgICAgICAgICcuanN4JyxcbiAgICAgICAgICAnLm1qcycsXG4gICAgICAgICAgJy5janMnLFxuICAgICAgICBdO1xuICAgICAgICBmb3IgKGNvbnN0IGV4dGVuc2lvbkNhbmRpZGF0ZSBvZiBleHRlbnNpb25DYW5kaWRhdGVzKSB7XG4gICAgICAgICAgY2FuZGlkYXRlUGF0aHMuYWRkKGAke2Fic29sdXRlVGFyZ2V0UGF0aH0ke2V4dGVuc2lvbkNhbmRpZGF0ZX1gKTtcbiAgICAgICAgICBjYW5kaWRhdGVQYXRocy5hZGQoXG4gICAgICAgICAgICBqb2luKGFic29sdXRlVGFyZ2V0UGF0aCwgYGluZGV4JHtleHRlbnNpb25DYW5kaWRhdGV9YClcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgY2FuZGlkYXRlUGF0aCBvZiBjYW5kaWRhdGVQYXRocykge1xuICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPVxuICAgICAgICAgIHRoaXMucmVzb2x2ZUNvcGllZFN0ZXBJbXBvcnRUYXJnZXRQYXRoKGNhbmRpZGF0ZVBhdGgpO1xuICAgICAgICBjb25zdCBub3JtYWxpemVkUmVzb2x2ZWRQYXRoID1cbiAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChyZXNvbHZlZFBhdGgpO1xuXG4gICAgICAgIGlmICh0aGlzLnNob3VsZFNraXBUcmFuc2l0aXZlU3RlcEZpbGUobm9ybWFsaXplZFJlc29sdmVkUGF0aCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZmlsZVN0YXRzID0gYXdhaXQgc3RhdChub3JtYWxpemVkUmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgICBpZiAoZmlsZVN0YXRzLmlzRmlsZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaXplZFJlc29sdmVkUGF0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8vIFRyeSB0aGUgbmV4dCBjYW5kaWRhdGUgcGF0aC5cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGNvbGxlY3RUcmFuc2l0aXZlU3RlcEZpbGVzKHtcbiAgICAgIHN0ZXBGaWxlcyxcbiAgICAgIHNlZWRGaWxlcyA9IFtdLFxuICAgIH06IHtcbiAgICAgIHN0ZXBGaWxlczogc3RyaW5nW107XG4gICAgICBzZWVkRmlsZXM/OiBzdHJpbmdbXTtcbiAgICB9KTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFNlZWRGaWxlcyA9IEFycmF5LmZyb20oXG4gICAgICAgIG5ldyBTZXQoXG4gICAgICAgICAgWy4uLnN0ZXBGaWxlcywgLi4uc2VlZEZpbGVzXS5tYXAoKHN0ZXBGaWxlKSA9PlxuICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoc3RlcEZpbGUpXG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgICApLnNvcnQoKTtcbiAgICAgIC8vIEludGVudGlvbmFsbHkgcmUtdmFsaWRhdGUgc3RlcCBzZWVkcyBhZ2FpbnN0IGN1cnJlbnQgZmlsZSBjb250ZW50c1xuICAgICAgLy8gaW5zdGVhZCBvZiBibGluZGx5IHRydXN0aW5nIGNhbGxlcnMuIFRoaXMgcHJldmVudHMgc3RhbGUvbWFudWFsIHNlZWRcbiAgICAgIC8vIHBhdGhzIGZyb20gcGVyc2lzdGluZyB3aGVuIGZpbGVzIG5vIGxvbmdlciBjb250YWluIFwidXNlIHN0ZXBcIi5cbiAgICAgIGNvbnN0IGRpc2NvdmVyZWRTdGVwRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgIGNvbnN0IHF1ZXVlZEZpbGVzID0gWy4uLm5vcm1hbGl6ZWRTZWVkRmlsZXNdO1xuICAgICAgY29uc3QgdmlzaXRlZEZpbGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBjb25zdCBzb3VyY2VDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmcgfCBudWxsPigpO1xuICAgICAgY29uc3QgcGF0dGVybkNhY2hlID0gbmV3IE1hcDxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICBSZXR1cm5UeXBlPHR5cGVvZiBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zPiB8IG51bGxcbiAgICAgID4oKTtcblxuICAgICAgY29uc3QgZ2V0U291cmNlID0gYXN5bmMgKGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+ID0+IHtcbiAgICAgICAgaWYgKHNvdXJjZUNhY2hlLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICByZXR1cm4gc291cmNlQ2FjaGUuZ2V0KGZpbGVQYXRoKSA/PyBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgICAgIHNvdXJjZUNhY2hlLnNldChmaWxlUGF0aCwgc291cmNlKTtcbiAgICAgICAgICByZXR1cm4gc291cmNlO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICBzb3VyY2VDYWNoZS5zZXQoZmlsZVBhdGgsIG51bGwpO1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBnZXRQYXR0ZXJucyA9IGFzeW5jIChcbiAgICAgICAgZmlsZVBhdGg6IHN0cmluZ1xuICAgICAgKTogUHJvbWlzZTxSZXR1cm5UeXBlPHR5cGVvZiBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zPiB8IG51bGw+ID0+IHtcbiAgICAgICAgaWYgKHBhdHRlcm5DYWNoZS5oYXMoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgcmV0dXJuIHBhdHRlcm5DYWNoZS5nZXQoZmlsZVBhdGgpID8/IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgZ2V0U291cmNlKGZpbGVQYXRoKTtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHBhdHRlcm5DYWNoZS5zZXQoZmlsZVBhdGgsIG51bGwpO1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhdHRlcm5zID0gZGV0ZWN0V29ya2Zsb3dQYXR0ZXJucyhzb3VyY2UpO1xuICAgICAgICBwYXR0ZXJuQ2FjaGUuc2V0KGZpbGVQYXRoLCBwYXR0ZXJucyk7XG4gICAgICAgIHJldHVybiBwYXR0ZXJucztcbiAgICAgIH07XG5cbiAgICAgIHdoaWxlIChxdWV1ZWRGaWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRGaWxlID0gcXVldWVkRmlsZXMucG9wKCk7XG4gICAgICAgIGlmICghY3VycmVudEZpbGUgfHwgdmlzaXRlZEZpbGVzLmhhcyhjdXJyZW50RmlsZSkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB2aXNpdGVkRmlsZXMuYWRkKGN1cnJlbnRGaWxlKTtcblxuICAgICAgICBjb25zdCBjdXJyZW50U291cmNlID0gYXdhaXQgZ2V0U291cmNlKGN1cnJlbnRGaWxlKTtcbiAgICAgICAgaWYgKGN1cnJlbnRTb3VyY2UgPT09IG51bGwpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGN1cnJlbnRQYXR0ZXJucyA9IGF3YWl0IGdldFBhdHRlcm5zKGN1cnJlbnRGaWxlKTtcbiAgICAgICAgaWYgKGN1cnJlbnRQYXR0ZXJucz8uaGFzVXNlU3RlcCkge1xuICAgICAgICAgIGRpc2NvdmVyZWRTdGVwRmlsZXMuYWRkKGN1cnJlbnRGaWxlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlbGF0aXZlSW1wb3J0U3BlY2lmaWVycyA9XG4gICAgICAgICAgdGhpcy5leHRyYWN0UmVsYXRpdmVJbXBvcnRTcGVjaWZpZXJzKGN1cnJlbnRTb3VyY2UpO1xuICAgICAgICBmb3IgKGNvbnN0IHNwZWNpZmllciBvZiByZWxhdGl2ZUltcG9ydFNwZWNpZmllcnMpIHtcbiAgICAgICAgICBjb25zdCByZXNvbHZlZEltcG9ydFBhdGggPVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5yZXNvbHZlVHJhbnNpdGl2ZVN0ZXBJbXBvcnRUYXJnZXRQYXRoKFxuICAgICAgICAgICAgICBjdXJyZW50RmlsZSxcbiAgICAgICAgICAgICAgc3BlY2lmaWVyXG4gICAgICAgICAgICApO1xuICAgICAgICAgIGlmICghcmVzb2x2ZWRJbXBvcnRQYXRoKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIXZpc2l0ZWRGaWxlcy5oYXMocmVzb2x2ZWRJbXBvcnRQYXRoKSkge1xuICAgICAgICAgICAgcXVldWVkRmlsZXMucHVzaChyZXNvbHZlZEltcG9ydFBhdGgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGltcG9ydFBhdHRlcm5zID0gYXdhaXQgZ2V0UGF0dGVybnMocmVzb2x2ZWRJbXBvcnRQYXRoKTtcbiAgICAgICAgICBpZiAoaW1wb3J0UGF0dGVybnM/Lmhhc1VzZVN0ZXApIHtcbiAgICAgICAgICAgIGRpc2NvdmVyZWRTdGVwRmlsZXMuYWRkKHJlc29sdmVkSW1wb3J0UGF0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBBcnJheS5mcm9tKGRpc2NvdmVyZWRTdGVwRmlsZXMpLnNvcnQoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGNvbGxlY3RUcmFuc2l0aXZlU2VyZGVGaWxlcyh7XG4gICAgICBlbnRyeUZpbGVzLFxuICAgICAgc2VyZGVGaWxlcyxcbiAgICB9OiB7XG4gICAgICBlbnRyeUZpbGVzOiBzdHJpbmdbXTtcbiAgICAgIHNlcmRlRmlsZXM6IHN0cmluZ1tdO1xuICAgIH0pOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICBjb25zdCBub3JtYWxpemVkRW50cnlGaWxlcyA9IEFycmF5LmZyb20oXG4gICAgICAgIG5ldyBTZXQoXG4gICAgICAgICAgZW50cnlGaWxlcy5tYXAoKGVudHJ5RmlsZSkgPT5cbiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplRGlzY292ZXJlZEZpbGVQYXRoKGVudHJ5RmlsZSlcbiAgICAgICAgICApXG4gICAgICAgIClcbiAgICAgICkuc29ydCgpO1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFNlcmRlU2VlZEZpbGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChcbiAgICAgICAgICBzZXJkZUZpbGVzLm1hcCgoc2VyZGVGaWxlKSA9PlxuICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVEaXNjb3ZlcmVkRmlsZVBhdGgoc2VyZGVGaWxlKVxuICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICAgKS5zb3J0KCk7XG4gICAgICAvLyBJbnRlbnRpb25hbGx5IHJlLXZhbGlkYXRlIHNlcmRlIHNlZWRzIGFnYWluc3Qgc291cmNlICsgU0RLIGZpbHRlcmluZy5cbiAgICAgIC8vIFRoaXMga2VlcHMgcHJldmlvdXNseSBkaXNjb3ZlcmVkL21hbnVhbCBzZWVkIGVudHJpZXMgZnJvbSBzdGlja2luZyB3aGVuXG4gICAgICAvLyBmaWxlcyBubyBsb25nZXIgbWF0Y2ggc2VyZGUgcGF0dGVybnMgb3IgcmVzb2x2ZSB0byBTREsgaW50ZXJuYWxzLlxuICAgICAgY29uc3QgZGlzY292ZXJlZFNlcmRlRmlsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgIGNvbnN0IHF1ZXVlZEZpbGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbLi4ubm9ybWFsaXplZEVudHJ5RmlsZXMsIC4uLm5vcm1hbGl6ZWRTZXJkZVNlZWRGaWxlc10pXG4gICAgICApO1xuICAgICAgY29uc3QgdmlzaXRlZEZpbGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBjb25zdCBzb3VyY2VDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmcgfCBudWxsPigpO1xuICAgICAgY29uc3QgcGF0dGVybkNhY2hlID0gbmV3IE1hcDxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICBSZXR1cm5UeXBlPHR5cGVvZiBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zPiB8IG51bGxcbiAgICAgID4oKTtcblxuICAgICAgY29uc3QgZ2V0U291cmNlID0gYXN5bmMgKGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+ID0+IHtcbiAgICAgICAgaWYgKHNvdXJjZUNhY2hlLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICByZXR1cm4gc291cmNlQ2FjaGUuZ2V0KGZpbGVQYXRoKSA/PyBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgICAgIHNvdXJjZUNhY2hlLnNldChmaWxlUGF0aCwgc291cmNlKTtcbiAgICAgICAgICByZXR1cm4gc291cmNlO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICBzb3VyY2VDYWNoZS5zZXQoZmlsZVBhdGgsIG51bGwpO1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBnZXRQYXR0ZXJucyA9IGFzeW5jIChcbiAgICAgICAgZmlsZVBhdGg6IHN0cmluZ1xuICAgICAgKTogUHJvbWlzZTxSZXR1cm5UeXBlPHR5cGVvZiBkZXRlY3RXb3JrZmxvd1BhdHRlcm5zPiB8IG51bGw+ID0+IHtcbiAgICAgICAgaWYgKHBhdHRlcm5DYWNoZS5oYXMoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgcmV0dXJuIHBhdHRlcm5DYWNoZS5nZXQoZmlsZVBhdGgpID8/IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgZ2V0U291cmNlKGZpbGVQYXRoKTtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHBhdHRlcm5DYWNoZS5zZXQoZmlsZVBhdGgsIG51bGwpO1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhdHRlcm5zID0gZGV0ZWN0V29ya2Zsb3dQYXR0ZXJucyhzb3VyY2UpO1xuICAgICAgICBwYXR0ZXJuQ2FjaGUuc2V0KGZpbGVQYXRoLCBwYXR0ZXJucyk7XG4gICAgICAgIHJldHVybiBwYXR0ZXJucztcbiAgICAgIH07XG5cbiAgICAgIGZvciAoY29uc3Qgc2VyZGVTZWVkRmlsZSBvZiBub3JtYWxpemVkU2VyZGVTZWVkRmlsZXMpIHtcbiAgICAgICAgY29uc3Qgc2VlZFBhdHRlcm5zID0gYXdhaXQgZ2V0UGF0dGVybnMoc2VyZGVTZWVkRmlsZSk7XG4gICAgICAgIGlmIChzZWVkUGF0dGVybnM/Lmhhc1NlcmRlICYmICFpc1dvcmtmbG93U2RrRmlsZShzZXJkZVNlZWRGaWxlKSkge1xuICAgICAgICAgIGRpc2NvdmVyZWRTZXJkZUZpbGVzLmFkZChzZXJkZVNlZWRGaWxlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB3aGlsZSAocXVldWVkRmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zdCBjdXJyZW50RmlsZSA9IHF1ZXVlZEZpbGVzLnBvcCgpO1xuICAgICAgICBpZiAoIWN1cnJlbnRGaWxlIHx8IHZpc2l0ZWRGaWxlcy5oYXMoY3VycmVudEZpbGUpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdmlzaXRlZEZpbGVzLmFkZChjdXJyZW50RmlsZSk7XG5cbiAgICAgICAgY29uc3QgY3VycmVudFNvdXJjZSA9IGF3YWl0IGdldFNvdXJjZShjdXJyZW50RmlsZSk7XG4gICAgICAgIGlmIChjdXJyZW50U291cmNlID09PSBudWxsKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZWxhdGl2ZUltcG9ydFNwZWNpZmllcnMgPVxuICAgICAgICAgIHRoaXMuZXh0cmFjdFJlbGF0aXZlSW1wb3J0U3BlY2lmaWVycyhjdXJyZW50U291cmNlKTtcbiAgICAgICAgZm9yIChjb25zdCBzcGVjaWZpZXIgb2YgcmVsYXRpdmVJbXBvcnRTcGVjaWZpZXJzKSB7XG4gICAgICAgICAgY29uc3QgcmVzb2x2ZWRJbXBvcnRQYXRoID1cbiAgICAgICAgICAgIGF3YWl0IHRoaXMucmVzb2x2ZVRyYW5zaXRpdmVTdGVwSW1wb3J0VGFyZ2V0UGF0aChcbiAgICAgICAgICAgICAgY3VycmVudEZpbGUsXG4gICAgICAgICAgICAgIHNwZWNpZmllclxuICAgICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoIXJlc29sdmVkSW1wb3J0UGF0aCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCF2aXNpdGVkRmlsZXMuaGFzKHJlc29sdmVkSW1wb3J0UGF0aCkpIHtcbiAgICAgICAgICAgIHF1ZXVlZEZpbGVzLnB1c2gocmVzb2x2ZWRJbXBvcnRQYXRoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBpbXBvcnRQYXR0ZXJucyA9IGF3YWl0IGdldFBhdHRlcm5zKHJlc29sdmVkSW1wb3J0UGF0aCk7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgaW1wb3J0UGF0dGVybnM/Lmhhc1NlcmRlICYmXG4gICAgICAgICAgICAhaXNXb3JrZmxvd1Nka0ZpbGUocmVzb2x2ZWRJbXBvcnRQYXRoKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgZGlzY292ZXJlZFNlcmRlRmlsZXMuYWRkKHJlc29sdmVkSW1wb3J0UGF0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBBcnJheS5mcm9tKGRpc2NvdmVyZWRTZXJkZUZpbGVzKS5zb3J0KCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjcmVhdGVSZXNwb25zZUJ1aWx0aW5zU3RlcEZpbGUoe1xuICAgICAgc3RlcHNSb3V0ZURpcixcbiAgICB9OiB7XG4gICAgICBzdGVwc1JvdXRlRGlyOiBzdHJpbmc7XG4gICAgfSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICBjb25zdCBjb3BpZWRTdGVwc0RpciA9IGpvaW4oc3RlcHNSb3V0ZURpciwgREVGRVJSRURfU1RFUF9DT1BZX0RJUl9OQU1FKTtcbiAgICAgIGF3YWl0IG1rZGlyKGNvcGllZFN0ZXBzRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICAgICAgY29uc3QgcmVzcG9uc2VCdWlsdGluc0ZpbGVQYXRoID0gam9pbihcbiAgICAgICAgY29waWVkU3RlcHNEaXIsXG4gICAgICAgICd3b3JrZmxvdy1yZXNwb25zZS1idWlsdGlucy50cydcbiAgICAgICk7XG4gICAgICBjb25zdCBzb3VyY2UgPSBbXG4gICAgICAgICdleHBvcnQgYXN5bmMgZnVuY3Rpb24gX19idWlsdGluX3Jlc3BvbnNlX2FycmF5X2J1ZmZlcih0aGlzOiBSZXF1ZXN0IHwgUmVzcG9uc2UpIHsnLFxuICAgICAgICBcIiAgJ3VzZSBzdGVwJztcIixcbiAgICAgICAgJyAgcmV0dXJuIHRoaXMuYXJyYXlCdWZmZXIoKTsnLFxuICAgICAgICAnfScsXG4gICAgICAgICcnLFxuICAgICAgICAnZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9fYnVpbHRpbl9yZXNwb25zZV9qc29uKHRoaXM6IFJlcXVlc3QgfCBSZXNwb25zZSkgeycsXG4gICAgICAgIFwiICAndXNlIHN0ZXAnO1wiLFxuICAgICAgICAnICByZXR1cm4gdGhpcy5qc29uKCk7JyxcbiAgICAgICAgJ30nLFxuICAgICAgICAnJyxcbiAgICAgICAgJ2V4cG9ydCBhc3luYyBmdW5jdGlvbiBfX2J1aWx0aW5fcmVzcG9uc2VfdGV4dCh0aGlzOiBSZXF1ZXN0IHwgUmVzcG9uc2UpIHsnLFxuICAgICAgICBcIiAgJ3VzZSBzdGVwJztcIixcbiAgICAgICAgJyAgcmV0dXJuIHRoaXMudGV4dCgpOycsXG4gICAgICAgICd9JyxcbiAgICAgIF0uam9pbignXFxuJyk7XG4gICAgICBjb25zdCBzb3VyY2VNYXBDb21tZW50ID0gY3JlYXRlRGVmZXJyZWRTdGVwQ29weUlubGluZVNvdXJjZU1hcENvbW1lbnQoe1xuICAgICAgICBzb3VyY2VQYXRoOiByZXNwb25zZUJ1aWx0aW5zRmlsZVBhdGgsXG4gICAgICAgIHNvdXJjZUNvbnRlbnQ6IHNvdXJjZSxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQoXG4gICAgICAgIHJlc3BvbnNlQnVpbHRpbnNGaWxlUGF0aCxcbiAgICAgICAgYCR7c291cmNlfVxcbiR7c291cmNlTWFwQ29tbWVudH1cXG5gXG4gICAgICApO1xuXG4gICAgICByZXR1cm4gcmVzcG9uc2VCdWlsdGluc0ZpbGVQYXRoO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY29weURpc2NvdmVyZWRTdGVwRmlsZXMoe1xuICAgICAgc3RlcEZpbGVzLFxuICAgICAgc3RlcHNSb3V0ZURpcixcbiAgICB9OiB7XG4gICAgICBzdGVwRmlsZXM6IHN0cmluZ1tdO1xuICAgICAgc3RlcHNSb3V0ZURpcjogc3RyaW5nO1xuICAgIH0pOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICBjb25zdCBjb3BpZWRTdGVwc0RpciA9IGpvaW4oc3RlcHNSb3V0ZURpciwgREVGRVJSRURfU1RFUF9DT1BZX0RJUl9OQU1FKTtcbiAgICAgIGF3YWl0IG1rZGlyKGNvcGllZFN0ZXBzRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICAgICAgY29uc3Qgbm9ybWFsaXplZFN0ZXBGaWxlcyA9IEFycmF5LmZyb20oXG4gICAgICAgIG5ldyBTZXQoXG4gICAgICAgICAgc3RlcEZpbGVzLm1hcCgoc3RlcEZpbGUpID0+XG4gICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChzdGVwRmlsZSlcbiAgICAgICAgICApXG4gICAgICAgIClcbiAgICAgICkuc29ydCgpO1xuICAgICAgY29uc3QgY29waWVkU3RlcEZpbGVCeVNvdXJjZVBhdGggPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAgICAgY29uc3QgZXhwZWN0ZWRGaWxlTmFtZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgIGNvbnN0IGNvcGllZFN0ZXBGaWxlczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgZm9yIChjb25zdCBub3JtYWxpemVkU3RlcEZpbGUgb2Ygbm9ybWFsaXplZFN0ZXBGaWxlcykge1xuICAgICAgICBjb25zdCBjb3BpZWRGaWxlTmFtZSA9IHRoaXMuZ2V0U3RlcENvcHlGaWxlTmFtZShub3JtYWxpemVkU3RlcEZpbGUpO1xuICAgICAgICBjb25zdCBjb3BpZWRGaWxlUGF0aCA9IGpvaW4oY29waWVkU3RlcHNEaXIsIGNvcGllZEZpbGVOYW1lKTtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFBhdGhLZXkgPSBub3JtYWxpemVkU3RlcEZpbGUucmVwbGFjZSgvXFxcXC9nLCAnLycpO1xuICAgICAgICBjb3BpZWRTdGVwRmlsZUJ5U291cmNlUGF0aC5zZXQobm9ybWFsaXplZFBhdGhLZXksIGNvcGllZEZpbGVQYXRoKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZWFsUGF0aEtleSA9IHJlYWxwYXRoU3luYyhub3JtYWxpemVkU3RlcEZpbGUpLnJlcGxhY2UoXG4gICAgICAgICAgICAvXFxcXC9nLFxuICAgICAgICAgICAgJy8nXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb3BpZWRTdGVwRmlsZUJ5U291cmNlUGF0aC5zZXQocmVhbFBhdGhLZXksIGNvcGllZEZpbGVQYXRoKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgLy8gS2VlcCBiZXN0LWVmZm9ydCBtYXBwaW5nIHdoZW4gc291cmNlIGNhbm5vdCBiZSByZWFscGF0aC1yZXNvbHZlZC5cbiAgICAgICAgfVxuICAgICAgICBleHBlY3RlZEZpbGVOYW1lcy5hZGQoY29waWVkRmlsZU5hbWUpO1xuICAgICAgICBjb3BpZWRTdGVwRmlsZXMucHVzaChjb3BpZWRGaWxlUGF0aCk7XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3Qgbm9ybWFsaXplZFN0ZXBGaWxlIG9mIG5vcm1hbGl6ZWRTdGVwRmlsZXMpIHtcbiAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgcmVhZEZpbGUobm9ybWFsaXplZFN0ZXBGaWxlLCAndXRmLTgnKTtcbiAgICAgICAgY29uc3QgY29waWVkRmlsZVBhdGggPSBjb3BpZWRTdGVwRmlsZUJ5U291cmNlUGF0aC5nZXQoXG4gICAgICAgICAgbm9ybWFsaXplZFN0ZXBGaWxlLnJlcGxhY2UoL1xcXFwvZywgJy8nKVxuICAgICAgICApO1xuICAgICAgICBpZiAoIWNvcGllZEZpbGVQYXRoKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmV3cml0dGVuU291cmNlID0gdGhpcy5yZXdyaXRlUmVsYXRpdmVJbXBvcnRzRm9yQ29waWVkU3RlcChcbiAgICAgICAgICBzb3VyY2UsXG4gICAgICAgICAgbm9ybWFsaXplZFN0ZXBGaWxlLFxuICAgICAgICAgIGNvcGllZEZpbGVQYXRoLFxuICAgICAgICAgIGNvcGllZFN0ZXBGaWxlQnlTb3VyY2VQYXRoXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IG1ldGFkYXRhQ29tbWVudCA9IGNyZWF0ZURlZmVycmVkU3RlcFNvdXJjZU1ldGFkYXRhQ29tbWVudCh7XG4gICAgICAgICAgcmVsYXRpdmVGaWxlbmFtZTpcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZ2V0UmVsYXRpdmVGaWxlbmFtZUZvclN3Yyhub3JtYWxpemVkU3RlcEZpbGUpLFxuICAgICAgICAgIGFic29sdXRlUGF0aDogbm9ybWFsaXplZFN0ZXBGaWxlLnJlcGxhY2UoL1xcXFwvZywgJy8nKSxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHNvdXJjZU1hcENvbW1lbnQgPSBjcmVhdGVEZWZlcnJlZFN0ZXBDb3B5SW5saW5lU291cmNlTWFwQ29tbWVudCh7XG4gICAgICAgICAgc291cmNlUGF0aDogbm9ybWFsaXplZFN0ZXBGaWxlLFxuICAgICAgICAgIHNvdXJjZUNvbnRlbnQ6IHNvdXJjZSxcbiAgICAgICAgICBnZW5lcmF0ZWRDb250ZW50OiByZXdyaXR0ZW5Tb3VyY2UsXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjb3BpZWRTb3VyY2UgPSBgJHttZXRhZGF0YUNvbW1lbnR9XFxuJHtyZXdyaXR0ZW5Tb3VyY2V9XFxuJHtzb3VyY2VNYXBDb21tZW50fWA7XG5cbiAgICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQoY29waWVkRmlsZVBhdGgsIGNvcGllZFNvdXJjZSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGV4aXN0aW5nRW50cmllcyA9IGF3YWl0IHJlYWRkaXIoY29waWVkU3RlcHNEaXIsIHtcbiAgICAgICAgd2l0aEZpbGVUeXBlczogdHJ1ZSxcbiAgICAgIH0pLmNhdGNoKCgpID0+IFtdKTtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBleGlzdGluZ0VudHJpZXNcbiAgICAgICAgICAuZmlsdGVyKChlbnRyeSkgPT4gIWV4cGVjdGVkRmlsZU5hbWVzLmhhcyhlbnRyeS5uYW1lKSlcbiAgICAgICAgICAubWFwKChlbnRyeSkgPT5cbiAgICAgICAgICAgIHJtKGpvaW4oY29waWVkU3RlcHNEaXIsIGVudHJ5Lm5hbWUpLCB7XG4gICAgICAgICAgICAgIHJlY3Vyc2l2ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgZm9yY2U6IHRydWUsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIClcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiBjb3BpZWRTdGVwRmlsZXM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBjcmVhdGVEZWZlcnJlZFN0ZXBzTWFuaWZlc3Qoe1xuICAgICAgc3RlcEZpbGVzLFxuICAgICAgd29ya2Zsb3dGaWxlcyxcbiAgICAgIHNlcmRlT25seUZpbGVzLFxuICAgIH06IHtcbiAgICAgIHN0ZXBGaWxlczogc3RyaW5nW107XG4gICAgICB3b3JrZmxvd0ZpbGVzOiBzdHJpbmdbXTtcbiAgICAgIHNlcmRlT25seUZpbGVzOiBzdHJpbmdbXTtcbiAgICB9KTogUHJvbWlzZTxXb3JrZmxvd01hbmlmZXN0PiB7XG4gICAgICBjb25zdCB3b3JrZmxvd01hbmlmZXN0OiBXb3JrZmxvd01hbmlmZXN0ID0ge307XG4gICAgICBjb25zdCBmaWxlc0ZvclN0ZXBUcmFuc2Zvcm0gPSBBcnJheS5mcm9tKFxuICAgICAgICBuZXcgU2V0KFsuLi5zdGVwRmlsZXMsIC4uLnNlcmRlT25seUZpbGVzXSlcbiAgICAgICkuc29ydCgpO1xuXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgZmlsZXNGb3JTdGVwVHJhbnNmb3JtLm1hcChhc3luYyAoc3RlcEZpbGUpID0+IHtcbiAgICAgICAgICBjb25zdCBzb3VyY2UgPSBhd2FpdCByZWFkRmlsZShzdGVwRmlsZSwgJ3V0Zi04Jyk7XG4gICAgICAgICAgY29uc3QgcmVsYXRpdmVGaWxlbmFtZSA9XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmdldFJlbGF0aXZlRmlsZW5hbWVGb3JTd2Moc3RlcEZpbGUpO1xuICAgICAgICAgIGNvbnN0IHsgd29ya2Zsb3dNYW5pZmVzdDogZmlsZU1hbmlmZXN0IH0gPSBhd2FpdCBhcHBseVN3Y1RyYW5zZm9ybShcbiAgICAgICAgICAgIHJlbGF0aXZlRmlsZW5hbWUsXG4gICAgICAgICAgICBzb3VyY2UsXG4gICAgICAgICAgICAnc3RlcCcsXG4gICAgICAgICAgICBzdGVwRmlsZSxcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnByb2plY3RSb290IHx8IHRoaXMuY29uZmlnLndvcmtpbmdEaXJcbiAgICAgICAgICApO1xuICAgICAgICAgIHRoaXMubWVyZ2VXb3JrZmxvd01hbmlmZXN0KHdvcmtmbG93TWFuaWZlc3QsIGZpbGVNYW5pZmVzdCk7XG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgICBjb25zdCBzdGVwRmlsZVNldCA9IG5ldyBTZXQoc3RlcEZpbGVzKTtcbiAgICAgIGNvbnN0IHdvcmtmbG93T25seUZpbGVzID0gd29ya2Zsb3dGaWxlc1xuICAgICAgICAuZmlsdGVyKCh3b3JrZmxvd0ZpbGUpID0+ICFzdGVwRmlsZVNldC5oYXMod29ya2Zsb3dGaWxlKSlcbiAgICAgICAgLnNvcnQoKTtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICB3b3JrZmxvd09ubHlGaWxlcy5tYXAoYXN5bmMgKHdvcmtmbG93RmlsZSkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBzb3VyY2UgPSBhd2FpdCByZWFkRmlsZSh3b3JrZmxvd0ZpbGUsICd1dGYtOCcpO1xuICAgICAgICAgICAgY29uc3QgcmVsYXRpdmVGaWxlbmFtZSA9XG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMuZ2V0UmVsYXRpdmVGaWxlbmFtZUZvclN3Yyh3b3JrZmxvd0ZpbGUpO1xuICAgICAgICAgICAgY29uc3QgeyB3b3JrZmxvd01hbmlmZXN0OiBmaWxlTWFuaWZlc3QgfSA9IGF3YWl0IGFwcGx5U3djVHJhbnNmb3JtKFxuICAgICAgICAgICAgICByZWxhdGl2ZUZpbGVuYW1lLFxuICAgICAgICAgICAgICBzb3VyY2UsXG4gICAgICAgICAgICAgICd3b3JrZmxvdycsXG4gICAgICAgICAgICAgIHdvcmtmbG93RmlsZSxcbiAgICAgICAgICAgICAgdGhpcy5jb25maWcucHJvamVjdFJvb3QgfHwgdGhpcy5jb25maWcud29ya2luZ0RpclxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMubWVyZ2VXb3JrZmxvd01hbmlmZXN0KHdvcmtmbG93TWFuaWZlc3QsIHtcbiAgICAgICAgICAgICAgd29ya2Zsb3dzOiBmaWxlTWFuaWZlc3Qud29ya2Zsb3dzLFxuICAgICAgICAgICAgICBjbGFzc2VzOiBmaWxlTWFuaWZlc3QuY2xhc3NlcyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgYFdhcm5pbmc6IEZhaWxlZCB0byBleHRyYWN0IHdvcmtmbG93IG1ldGFkYXRhIGZyb20gJHt3b3JrZmxvd0ZpbGV9OmAsXG4gICAgICAgICAgICAgIGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgICByZXR1cm4gd29ya2Zsb3dNYW5pZmVzdDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGJ1aWxkU3RlcHNGdW5jdGlvbih7XG4gICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcixcbiAgICAgIHJvdXRlRmlsZU5hbWUgPSAncm91dGUuanMnLFxuICAgICAgZGlzY292ZXJlZEVudHJpZXMsXG4gICAgfToge1xuICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXI6IHN0cmluZztcbiAgICAgIHJvdXRlRmlsZU5hbWU/OiBzdHJpbmc7XG4gICAgICBkaXNjb3ZlcmVkRW50cmllczogRGVmZXJyZWREaXNjb3ZlcmVkRW50cmllcztcbiAgICB9KSB7XG4gICAgICBjb25zdCBzdGVwc1JvdXRlRGlyID0gam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgJ3N0ZXAnKTtcbiAgICAgIGF3YWl0IG1rZGlyKHN0ZXBzUm91dGVEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgY29uc3QgZGlzY292ZXJlZCA9IGRpc2NvdmVyZWRFbnRyaWVzO1xuICAgICAgY29uc3Qgd29ya2Zsb3dGaWxlcyA9IFsuLi5kaXNjb3ZlcmVkLmRpc2NvdmVyZWRXb3JrZmxvd3NdLnNvcnQoKTtcbiAgICAgIGNvbnN0IHN0ZXBGaWxlcyA9IGF3YWl0IHRoaXMuY29sbGVjdFRyYW5zaXRpdmVTdGVwRmlsZXMoe1xuICAgICAgICBzdGVwRmlsZXM6IFsuLi5kaXNjb3ZlcmVkLmRpc2NvdmVyZWRTdGVwc10uc29ydCgpLFxuICAgICAgICAvLyBXb3JrZmxvdyB0cmFuc2Zvcm1zIGNhbiBpbmxpbmUgc3RlcCBJRHMgYW5kIHJlbW92ZSBydW50aW1lIGltcG9ydHMsXG4gICAgICAgIC8vIHNvIHNlZWQgdHJhbnNpdGl2ZSB0cmF2ZXJzYWwgd2l0aCB3b3JrZmxvdyBmaWxlcyB0b28uXG4gICAgICAgIHNlZWRGaWxlczogd29ya2Zsb3dGaWxlcyxcbiAgICAgIH0pO1xuICAgICAgY29uc3Qgc2VyZGVGaWxlcyA9IFsuLi5kaXNjb3ZlcmVkLmRpc2NvdmVyZWRTZXJkZUZpbGVzXS5zb3J0KCk7XG4gICAgICBjb25zdCBzdGVwRmlsZVNldCA9IG5ldyBTZXQoc3RlcEZpbGVzKTtcbiAgICAgIGNvbnN0IHNlcmRlT25seUZpbGVzID0gc2VyZGVGaWxlcy5maWx0ZXIoXG4gICAgICAgIChmaWxlKSA9PiAhc3RlcEZpbGVTZXQuaGFzKGZpbGUpXG4gICAgICApO1xuICAgICAgLy8gQ29weSBhbGwgZGlzY292ZXJlZCBzdGVwIHNvdXJjZXMgc28gdGhleSBhcmUgdHJhbnNmb3JtZWQgaW4gc3RlcCBtb2RlLlxuICAgICAgLy8gSW1wb3J0aW5nIHJhdyBub2RlX21vZHVsZXMgZmlsZXMgZGlyZWN0bHkgY2FuIGJ5cGFzcyBsb2FkZXIgdHJhbnNmb3JtcyxcbiAgICAgIC8vIHdoaWNoIHByZXZlbnRzIHN0ZXAgcmVnaXN0cmFycyBmcm9tIGJlaW5nIGVtaXR0ZWQuXG4gICAgICBjb25zdCBjb3BpZWRTdGVwU291cmNlRmlsZXMgPSBzdGVwRmlsZXM7XG4gICAgICBjb25zdCBjb3BpZWREaXNjb3ZlcmVkU3RlcEZpbGVzID0gYXdhaXQgdGhpcy5jb3B5RGlzY292ZXJlZFN0ZXBGaWxlcyh7XG4gICAgICAgIHN0ZXBGaWxlczogY29waWVkU3RlcFNvdXJjZUZpbGVzLFxuICAgICAgICBzdGVwc1JvdXRlRGlyLFxuICAgICAgfSk7XG4gICAgICBjb25zdCByZXNwb25zZUJ1aWx0aW5zU3RlcEZpbGVQYXRoID1cbiAgICAgICAgYXdhaXQgdGhpcy5jcmVhdGVSZXNwb25zZUJ1aWx0aW5zU3RlcEZpbGUoe1xuICAgICAgICAgIHN0ZXBzUm91dGVEaXIsXG4gICAgICAgIH0pO1xuICAgICAgY29uc3QgY29waWVkU3RlcEZpbGVzID0gW1xuICAgICAgICByZXNwb25zZUJ1aWx0aW5zU3RlcEZpbGVQYXRoLFxuICAgICAgICAuLi5jb3BpZWREaXNjb3ZlcmVkU3RlcEZpbGVzLFxuICAgICAgXTtcbiAgICAgIGNvbnN0IG1hbmlmZXN0U3RlcEZpbGVzID0gQXJyYXkuZnJvbShcbiAgICAgICAgbmV3IFNldChbLi4uc3RlcEZpbGVzLCByZXNwb25zZUJ1aWx0aW5zU3RlcEZpbGVQYXRoXSlcbiAgICAgICkuc29ydCgpO1xuXG4gICAgICBjb25zdCBzdGVwUm91dGVGaWxlID0gam9pbihzdGVwc1JvdXRlRGlyLCByb3V0ZUZpbGVOYW1lKTtcbiAgICAgIGNvbnN0IGNvcGllZFN0ZXBJbXBvcnRzID0gY29waWVkU3RlcEZpbGVzXG4gICAgICAgIC5tYXAoKGNvcGllZFN0ZXBGaWxlKSA9PiB7XG4gICAgICAgICAgY29uc3QgaW1wb3J0U3BlY2lmaWVyID0gdGhpcy5nZXRSZWxhdGl2ZUltcG9ydFNwZWNpZmllcihcbiAgICAgICAgICAgIHN0ZXBSb3V0ZUZpbGUsXG4gICAgICAgICAgICBjb3BpZWRTdGVwRmlsZVxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIGBpbXBvcnQgJyR7aW1wb3J0U3BlY2lmaWVyfSc7YDtcbiAgICAgICAgfSlcbiAgICAgICAgLmpvaW4oJ1xcbicpO1xuICAgICAgY29uc3Qgc2VyZGVJbXBvcnRzID0gc2VyZGVPbmx5RmlsZXNcbiAgICAgICAgLm1hcCgoc2VyZGVGaWxlKSA9PiB7XG4gICAgICAgICAgY29uc3Qgbm9ybWFsaXplZFNlcmRlRmlsZSA9XG4gICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZURpc2NvdmVyZWRGaWxlUGF0aChzZXJkZUZpbGUpO1xuICAgICAgICAgIGNvbnN0IHsgaW1wb3J0UGF0aCwgaXNQYWNrYWdlIH0gPSBnZXRJbXBvcnRQYXRoKFxuICAgICAgICAgICAgbm9ybWFsaXplZFNlcmRlRmlsZSxcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLndvcmtpbmdEaXJcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChpc1BhY2thZ2UpIHtcbiAgICAgICAgICAgIHJldHVybiBgaW1wb3J0ICcke2ltcG9ydFBhdGh9JztgO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBpbXBvcnRTcGVjaWZpZXIgPSB0aGlzLmdldFJlbGF0aXZlSW1wb3J0U3BlY2lmaWVyKFxuICAgICAgICAgICAgc3RlcFJvdXRlRmlsZSxcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRTZXJkZUZpbGVcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiBgaW1wb3J0ICcke2ltcG9ydFNwZWNpZmllcn0nO2A7XG4gICAgICAgIH0pXG4gICAgICAgIC5qb2luKCdcXG4nKTtcblxuICAgICAgY29uc3Qgcm91dGVDb250ZW50cyA9IFtcbiAgICAgICAgJy8vIGJpb21lLWlnbm9yZS1hbGwgbGludDogZ2VuZXJhdGVkIGZpbGUnLFxuICAgICAgICAnLyogZXNsaW50LWRpc2FibGUgKi8nLFxuICAgICAgICBjb3BpZWRTdGVwSW1wb3J0cyxcbiAgICAgICAgc2VyZGVJbXBvcnRzXG4gICAgICAgICAgPyBgLy8gU2VyZGUgZmlsZXMgZm9yIGNyb3NzLWNvbnRleHQgY2xhc3MgcmVnaXN0cmF0aW9uXFxuJHtzZXJkZUltcG9ydHN9YFxuICAgICAgICAgIDogJycsXG4gICAgICAgIFwiZXhwb3J0IHsgc3RlcEVudHJ5cG9pbnQgYXMgSEVBRCwgc3RlcEVudHJ5cG9pbnQgYXMgUE9TVCB9IGZyb20gJ3dvcmtmbG93L3J1bnRpbWUnO1wiLFxuICAgICAgXVxuICAgICAgICAuZmlsdGVyKEJvb2xlYW4pXG4gICAgICAgIC5qb2luKCdcXG4nKTtcblxuICAgICAgYXdhaXQgdGhpcy53cml0ZUZpbGVJZkNoYW5nZWQoc3RlcFJvdXRlRmlsZSwgcm91dGVDb250ZW50cyk7XG5cbiAgICAgIGNvbnN0IG1hbmlmZXN0ID0gYXdhaXQgdGhpcy5jcmVhdGVEZWZlcnJlZFN0ZXBzTWFuaWZlc3Qoe1xuICAgICAgICBzdGVwRmlsZXM6IG1hbmlmZXN0U3RlcEZpbGVzLFxuICAgICAgICB3b3JrZmxvd0ZpbGVzLFxuICAgICAgICBzZXJkZU9ubHlGaWxlcyxcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZXh0OiB1bmRlZmluZWQsXG4gICAgICAgIG1hbmlmZXN0LFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGJ1aWxkV29ya2Zsb3dzRnVuY3Rpb24oe1xuICAgICAgaW5wdXRGaWxlcyxcbiAgICAgIHdvcmtmbG93R2VuZXJhdGVkRGlyLFxuICAgICAgdHNjb25maWdQYXRoLFxuICAgICAgcm91dGVGaWxlTmFtZSA9ICdyb3V0ZS5qcycsXG4gICAgICBkaXNjb3ZlcmVkRW50cmllcyxcbiAgICB9OiB7XG4gICAgICBpbnB1dEZpbGVzOiBzdHJpbmdbXTtcbiAgICAgIHdvcmtmbG93R2VuZXJhdGVkRGlyOiBzdHJpbmc7XG4gICAgICB0c2NvbmZpZ1BhdGg/OiBzdHJpbmc7XG4gICAgICByb3V0ZUZpbGVOYW1lPzogc3RyaW5nO1xuICAgICAgZGlzY292ZXJlZEVudHJpZXM6IERlZmVycmVkRGlzY292ZXJlZEVudHJpZXM7XG4gICAgfSkge1xuICAgICAgY29uc3Qgd29ya2Zsb3dzUm91dGVEaXIgPSBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnZmxvdycpO1xuICAgICAgYXdhaXQgbWtkaXIod29ya2Zsb3dzUm91dGVEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY3JlYXRlV29ya2Zsb3dzQnVuZGxlKHtcbiAgICAgICAgZm9ybWF0OiAnZXNtJyxcbiAgICAgICAgb3V0ZmlsZTogam9pbih3b3JrZmxvd3NSb3V0ZURpciwgcm91dGVGaWxlTmFtZSksXG4gICAgICAgIGJ1bmRsZUZpbmFsT3V0cHV0OiBmYWxzZSxcbiAgICAgICAgLy8gRGVmZXJyZWQgYnVpbGRzIGRvIG5vdCByZXVzZSB0aGUgaW50ZXJpbSBlc2J1aWxkIGNvbnRleHQuIERpc3Bvc2UgaXRcbiAgICAgICAgLy8gYWZ0ZXIgZWFjaCBwYXNzIHRvIGF2b2lkIGxlYWtpbmcgY29udGV4dHMgZHVyaW5nIHdhdGNoLW1vZGUgcmVidWlsZHMuXG4gICAgICAgIGtlZXBJbnRlcmltQnVuZGxlQ29udGV4dDogZmFsc2UsXG4gICAgICAgIGlucHV0RmlsZXMsXG4gICAgICAgIHRzY29uZmlnUGF0aCxcbiAgICAgICAgZGlzY292ZXJlZEVudHJpZXMsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGJ1aWxkV2ViaG9va1JvdXRlKHtcbiAgICAgIHdvcmtmbG93R2VuZXJhdGVkRGlyLFxuICAgICAgcm91dGVGaWxlTmFtZSA9ICdyb3V0ZS5qcycsXG4gICAgfToge1xuICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXI6IHN0cmluZztcbiAgICAgIHJvdXRlRmlsZU5hbWU/OiBzdHJpbmc7XG4gICAgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgY29uc3Qgd2ViaG9va1JvdXRlRmlsZSA9IGpvaW4oXG4gICAgICAgIHdvcmtmbG93R2VuZXJhdGVkRGlyLFxuICAgICAgICBgd2ViaG9vay9bdG9rZW5dLyR7cm91dGVGaWxlTmFtZX1gXG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy5jcmVhdGVXZWJob29rQnVuZGxlKHtcbiAgICAgICAgb3V0ZmlsZTogd2ViaG9va1JvdXRlRmlsZSxcbiAgICAgICAgYnVuZGxlOiBmYWxzZSwgLy8gTmV4dC5qcyBkb2Vzbid0IG5lZWQgYnVuZGxpbmdcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZmluZEFwcERpcmVjdG9yeSgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgY29uc3QgYXBwRGlyID0gcmVzb2x2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCAnYXBwJyk7XG4gICAgICBjb25zdCBzcmNBcHBEaXIgPSByZXNvbHZlKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsICdzcmMvYXBwJyk7XG4gICAgICBjb25zdCBwYWdlc0RpciA9IHJlc29sdmUodGhpcy5jb25maWcud29ya2luZ0RpciwgJ3BhZ2VzJyk7XG4gICAgICBjb25zdCBzcmNQYWdlc0RpciA9IHJlc29sdmUodGhpcy5jb25maWcud29ya2luZ0RpciwgJ3NyYy9wYWdlcycpO1xuXG4gICAgICAvLyBIZWxwZXIgdG8gY2hlY2sgaWYgYSBwYXRoIGV4aXN0cyBhbmQgaXMgYSBkaXJlY3RvcnlcbiAgICAgIGNvbnN0IGlzRGlyZWN0b3J5ID0gYXN5bmMgKHBhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGFjY2VzcyhwYXRoLCBjb25zdGFudHMuRl9PSyk7XG4gICAgICAgICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBzdGF0KHBhdGgpO1xuICAgICAgICAgIGlmICghc3RhdHMuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQYXRoIGV4aXN0cyBidXQgaXMgbm90IGEgZGlyZWN0b3J5OiAke3BhdGh9YCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBFcnJvciAmJiBlLm1lc3NhZ2UuaW5jbHVkZXMoJ25vdCBhIGRpcmVjdG9yeScpKSB7XG4gICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIC8vIENoZWNrIGlmIGFwcCBkaXJlY3RvcnkgZXhpc3RzXG4gICAgICBpZiAoYXdhaXQgaXNEaXJlY3RvcnkoYXBwRGlyKSkge1xuICAgICAgICByZXR1cm4gYXBwRGlyO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBpZiBzcmMvYXBwIGRpcmVjdG9yeSBleGlzdHNcbiAgICAgIGlmIChhd2FpdCBpc0RpcmVjdG9yeShzcmNBcHBEaXIpKSB7XG4gICAgICAgIHJldHVybiBzcmNBcHBEaXI7XG4gICAgICB9XG5cbiAgICAgIC8vIElmIG5vIGFwcCBkaXJlY3RvcnkgZXhpc3RzLCBjaGVjayBmb3IgcGFnZXMgZGlyZWN0b3J5IGFuZCBjcmVhdGUgYXBwIG5leHQgdG8gaXRcbiAgICAgIGlmIChhd2FpdCBpc0RpcmVjdG9yeShwYWdlc0RpcikpIHtcbiAgICAgICAgLy8gQ3JlYXRlIGFwcCBkaXJlY3RvcnkgbmV4dCB0byBwYWdlcyBkaXJlY3RvcnlcbiAgICAgICAgYXdhaXQgbWtkaXIoYXBwRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgcmV0dXJuIGFwcERpcjtcbiAgICAgIH1cblxuICAgICAgaWYgKGF3YWl0IGlzRGlyZWN0b3J5KHNyY1BhZ2VzRGlyKSkge1xuICAgICAgICAvLyBDcmVhdGUgc3JjL2FwcCBkaXJlY3RvcnkgbmV4dCB0byBzcmMvcGFnZXMgZGlyZWN0b3J5XG4gICAgICAgIGF3YWl0IG1rZGlyKHNyY0FwcERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICAgIHJldHVybiBzcmNBcHBEaXI7XG4gICAgICB9XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ0NvdWxkIG5vdCBmaW5kIE5leHQuanMgYXBwIG9yIHBhZ2VzIGRpcmVjdG9yeS4gRXhwZWN0ZWQgb25lIG9mOiBcImFwcFwiLCBcInNyYy9hcHBcIiwgXCJwYWdlc1wiLCBvciBcInNyYy9wYWdlc1wiIHRvIGV4aXN0LidcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgQ2FjaGVkTmV4dEJ1aWxkZXJEZWZlcnJlZCA9IE5leHREZWZlcnJlZEJ1aWxkZXI7XG4gIHJldHVybiBOZXh0RGVmZXJyZWRCdWlsZGVyO1xufVxuIl19