@workflow/next 4.0.11 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builder-eager.d.ts.map +1 -1
- package/dist/builder-eager.js +62 -63
- package/dist/builder.d.ts +1 -4
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +2 -28
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +127 -62
- package/dist/loader.d.ts +5 -0
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +29 -253
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +2 -2
- package/dist/swc-plugin-cache.d.ts +7 -0
- package/dist/swc-plugin-cache.d.ts.map +1 -0
- package/dist/swc-plugin-cache.js +23 -0
- package/docs/api-reference/with-workflow.mdx +26 -4
- package/package.json +7 -5
- package/dist/builder-deferred.d.ts +0 -2
- package/dist/builder-deferred.d.ts.map +0 -1
- package/dist/builder-deferred.js +0 -1417
- package/dist/socket-server.d.ts +0 -68
- package/dist/socket-server.d.ts.map +0 -1
- package/dist/socket-server.js +0 -181
- package/dist/step-copy-utils.d.ts +0 -19
- package/dist/step-copy-utils.d.ts.map +0 -1
- package/dist/step-copy-utils.js +0 -101
package/dist/builder-deferred.js
DELETED
|
@@ -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
|