@workflow/next 5.0.0-beta.3 → 5.0.0-beta.31
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 +1 -1
- package/dist/builder-eager.d.ts.map +1 -1
- package/dist/builder-eager.js +385 -201
- 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 +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +369 -67
- package/dist/loader.d.ts +7 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +40 -356
- 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/dist/watch-rebuild.d.ts +63 -0
- package/dist/watch-rebuild.d.ts.map +1 -0
- package/dist/watch-rebuild.js +399 -0
- package/docs/api-reference/with-workflow.mdx +56 -2
- package/docs/next.mdx +5 -3
- package/package.json +8 -7
- package/dist/builder-deferred.d.ts +0 -2
- package/dist/builder-deferred.d.ts.map +0 -1
- package/dist/builder-deferred.js +0 -1401
- package/dist/builder-deferred.js.map +0 -1
- package/dist/builder-eager.js.map +0 -1
- package/dist/builder.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/loader.js.map +0 -1
- package/dist/runtime.js.map +0 -1
- package/dist/socket-server.d.ts +0 -48
- package/dist/socket-server.d.ts.map +0 -1
- package/dist/socket-server.js +0 -154
- package/dist/socket-server.js.map +0 -1
package/dist/builder-eager.js
CHANGED
|
@@ -7,25 +7,25 @@ exports.getNextBuilderEager = getNextBuilderEager;
|
|
|
7
7
|
const node_fs_1 = require("node:fs");
|
|
8
8
|
const promises_1 = require("node:fs/promises");
|
|
9
9
|
const node_path_1 = require("node:path");
|
|
10
|
-
const
|
|
10
|
+
const chokidar_1 = __importDefault(require("chokidar"));
|
|
11
|
+
const watch_rebuild_js_1 = require("./watch-rebuild.js");
|
|
11
12
|
let CachedNextBuilderEager;
|
|
13
|
+
const importEsm = new Function('specifier', 'return import(specifier)');
|
|
12
14
|
// Create the eager Next builder dynamically by extending the ESM BaseBuilder.
|
|
13
15
|
// Exported as getNextBuilderEager() to allow CommonJS modules to import from
|
|
14
16
|
// the ESM @workflow/builders package via dynamic import at runtime.
|
|
15
|
-
async function getNextBuilderEager() {
|
|
17
|
+
async function getNextBuilderEager(buildersModule) {
|
|
16
18
|
if (CachedNextBuilderEager) {
|
|
17
19
|
return CachedNextBuilderEager;
|
|
18
20
|
}
|
|
19
|
-
const { BaseBuilder: BaseBuilderClass,
|
|
20
|
-
|
|
21
|
-
} = (await eval('import("@workflow/builders")'));
|
|
21
|
+
const { BaseBuilder: BaseBuilderClass, WORKFLOW_QUEUE_TRIGGER, detectWorkflowPatterns, parentHasChild, } = buildersModule ??
|
|
22
|
+
(await importEsm('@workflow/builders'));
|
|
22
23
|
class NextBuilder extends BaseBuilderClass {
|
|
23
24
|
async build() {
|
|
24
25
|
const outputDir = await this.findAppDirectory();
|
|
25
26
|
const workflowGeneratedDir = (0, node_path_1.join)(outputDir, '.well-known/workflow/v1');
|
|
26
27
|
// Ensure output directories exist
|
|
27
28
|
await (0, promises_1.mkdir)(workflowGeneratedDir, { recursive: true });
|
|
28
|
-
// ignore the generated assets
|
|
29
29
|
await (0, promises_1.writeFile)((0, node_path_1.join)(workflowGeneratedDir, '.gitignore'), '*');
|
|
30
30
|
const inputFiles = await this.getInputFiles();
|
|
31
31
|
const tsconfigPath = await this.findTsConfigPath();
|
|
@@ -34,53 +34,56 @@ async function getNextBuilderEager() {
|
|
|
34
34
|
workflowGeneratedDir,
|
|
35
35
|
tsconfigPath,
|
|
36
36
|
};
|
|
37
|
-
|
|
38
|
-
const
|
|
37
|
+
// V2: Build combined route (replaces separate step + flow routes)
|
|
38
|
+
const combinedResult = await this.buildCombinedFunction(options);
|
|
39
39
|
await this.buildWebhookRoute({ workflowGeneratedDir });
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
...
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
const writeManifest = async (sourceManifest) => {
|
|
41
|
+
const manifest = {
|
|
42
|
+
steps: { ...sourceManifest?.steps },
|
|
43
|
+
workflows: { ...sourceManifest?.workflows },
|
|
44
|
+
classes: { ...sourceManifest?.classes },
|
|
45
|
+
};
|
|
46
|
+
// Write manifest
|
|
47
|
+
const workflowBundlePath = (0, node_path_1.join)(workflowGeneratedDir, 'flow/route.js');
|
|
48
|
+
const manifestJson = await this.createManifest({
|
|
49
|
+
workflowBundlePath,
|
|
50
|
+
manifestDir: workflowGeneratedDir,
|
|
51
|
+
manifest,
|
|
52
|
+
});
|
|
53
|
+
// Expose manifest as a static file when WORKFLOW_PUBLIC_MANIFEST=1.
|
|
54
|
+
if (this.shouldExposePublicManifest && manifestJson) {
|
|
55
|
+
const publicManifestDir = (0, node_path_1.join)(this.config.workingDir, 'public/.well-known/workflow/v1');
|
|
56
|
+
await (0, promises_1.mkdir)(publicManifestDir, { recursive: true });
|
|
57
|
+
if (process.env.VERCEL_DEPLOYMENT_ID === undefined) {
|
|
58
|
+
await (0, promises_1.writeFile)((0, node_path_1.join)(publicManifestDir, '.gitignore'), '*');
|
|
59
|
+
}
|
|
60
|
+
await (0, promises_1.copyFile)((0, node_path_1.join)(workflowGeneratedDir, 'manifest.json'), (0, node_path_1.join)(publicManifestDir, 'manifest.json'));
|
|
61
|
+
}
|
|
51
62
|
};
|
|
52
|
-
|
|
53
|
-
const workflowBundlePath = (0, node_path_1.join)(workflowGeneratedDir, 'flow/route.js');
|
|
54
|
-
const manifestJson = await this.createManifest({
|
|
55
|
-
workflowBundlePath,
|
|
56
|
-
manifestDir: workflowGeneratedDir,
|
|
57
|
-
manifest,
|
|
58
|
-
});
|
|
59
|
-
// Expose manifest as a static file when WORKFLOW_PUBLIC_MANIFEST=1.
|
|
60
|
-
// Next.js serves files from public/ at the root URL.
|
|
61
|
-
if (this.shouldExposePublicManifest && manifestJson) {
|
|
62
|
-
const publicManifestDir = (0, node_path_1.join)(this.config.workingDir, 'public/.well-known/workflow/v1');
|
|
63
|
-
await (0, promises_1.mkdir)(publicManifestDir, { recursive: true });
|
|
64
|
-
await (0, promises_1.copyFile)((0, node_path_1.join)(workflowGeneratedDir, 'manifest.json'), (0, node_path_1.join)(publicManifestDir, 'manifest.json'));
|
|
65
|
-
}
|
|
63
|
+
await writeManifest(combinedResult?.manifest);
|
|
66
64
|
await this.writeFunctionsConfig(outputDir);
|
|
67
65
|
if (this.config.watch) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
!workflowsBundle?.bundleFinal) {
|
|
73
|
-
throw new Error('Invariant: expected workflows bundle in watch mode');
|
|
66
|
+
// TODO: implement watch mode for combined bundle
|
|
67
|
+
// For now, fall back to full rebuild on file changes
|
|
68
|
+
if (!combinedResult?.interimBundleCtx || !combinedResult.bundleFinal) {
|
|
69
|
+
throw new Error('Invariant: expected workflow build context in watch mode');
|
|
74
70
|
}
|
|
75
|
-
|
|
76
|
-
//
|
|
71
|
+
// Step registrations may be emitted as source imports without an
|
|
72
|
+
// esbuild context when externalizeNonSteps is enabled.
|
|
73
|
+
let stepsCtx = combinedResult.stepsContext;
|
|
77
74
|
let workflowsCtx = {
|
|
78
|
-
interimBundleCtx:
|
|
79
|
-
bundleFinal:
|
|
75
|
+
interimBundleCtx: combinedResult.interimBundleCtx,
|
|
76
|
+
bundleFinal: combinedResult.bundleFinal,
|
|
80
77
|
};
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
let
|
|
78
|
+
let workflowInterimBundleText = combinedResult.workflowInterimBundleText;
|
|
79
|
+
let discoveredEntries = combinedResult.discoveredEntries;
|
|
80
|
+
let stepsManifest = combinedResult.stepsManifest;
|
|
81
|
+
let workflowsManifest = combinedResult.workflowsManifest;
|
|
82
|
+
const stepsOutfile = (0, node_path_1.join)(workflowGeneratedDir, 'flow', '__step_registrations.js');
|
|
83
|
+
const normalizePath = (pathname) => ((0, node_path_1.isAbsolute)(pathname)
|
|
84
|
+
? pathname
|
|
85
|
+
: (0, node_path_1.resolve)(this.config.workingDir, pathname)).replace(/\\/g, '/');
|
|
86
|
+
const sourceSnapshots = new Map();
|
|
84
87
|
const watchableExtensions = new Set([
|
|
85
88
|
'.js',
|
|
86
89
|
'.jsx',
|
|
@@ -107,39 +110,20 @@ async function getNextBuilderEager() {
|
|
|
107
110
|
'/.well-known/workflow/',
|
|
108
111
|
];
|
|
109
112
|
const normalizedGeneratedDir = workflowGeneratedDir.replace(/\\/g, '/');
|
|
113
|
+
const normalizedDistDir = normalizePath(this.config.distDir);
|
|
110
114
|
ignoredPathFragments.push(normalizedGeneratedDir);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
ignored: (pathname) => {
|
|
120
|
-
const normalizedPath = pathname.replace(/\\/g, '/');
|
|
121
|
-
const extension = (0, node_path_1.extname)(normalizedPath);
|
|
122
|
-
if (extension && !watchableExtensions.has(extension)) {
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
125
|
-
if (normalizedPath.startsWith(normalizedGeneratedDir)) {
|
|
115
|
+
const hasIgnoredPathFragment = (normalizedPath) => {
|
|
116
|
+
if (normalizedPath.startsWith(normalizedGeneratedDir) ||
|
|
117
|
+
normalizedPath === normalizedDistDir ||
|
|
118
|
+
normalizedPath.startsWith(`${normalizedDistDir}/`)) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
for (const fragment of ignoredPathFragments) {
|
|
122
|
+
if (normalizedPath.includes(fragment)) {
|
|
126
123
|
return true;
|
|
127
124
|
}
|
|
128
|
-
for (const fragment of ignoredPathFragments) {
|
|
129
|
-
if (normalizedPath.includes(fragment)) {
|
|
130
|
-
return true;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return false;
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
|
-
const readTimeInfoEntries = () => {
|
|
137
|
-
const rawEntries = watcher.getTimeInfoEntries();
|
|
138
|
-
const normalizedEntries = new Map();
|
|
139
|
-
for (const [path, info] of rawEntries) {
|
|
140
|
-
normalizedEntries.set(normalizePath(path), info);
|
|
141
125
|
}
|
|
142
|
-
return
|
|
126
|
+
return false;
|
|
143
127
|
};
|
|
144
128
|
let rebuildQueue = Promise.resolve();
|
|
145
129
|
const enqueue = (task) => {
|
|
@@ -148,143 +132,357 @@ async function getNextBuilderEager() {
|
|
|
148
132
|
});
|
|
149
133
|
return rebuildQueue;
|
|
150
134
|
};
|
|
135
|
+
const readSourceSnapshot = (file) => (0, watch_rebuild_js_1.createSourceSnapshot)({ file, detectWorkflowPatterns });
|
|
136
|
+
const refreshSourceSnapshots = () => (0, watch_rebuild_js_1.replaceSourceSnapshots)({
|
|
137
|
+
discoveredEntries,
|
|
138
|
+
inputFiles: options.inputFiles,
|
|
139
|
+
normalizePath,
|
|
140
|
+
readSnapshot: readSourceSnapshot,
|
|
141
|
+
sourceSnapshots,
|
|
142
|
+
});
|
|
143
|
+
const mergeCombinedManifest = (nextStepsManifest) => ({
|
|
144
|
+
...nextStepsManifest,
|
|
145
|
+
workflows: {
|
|
146
|
+
...nextStepsManifest.workflows,
|
|
147
|
+
...workflowsManifest.workflows,
|
|
148
|
+
},
|
|
149
|
+
classes: {
|
|
150
|
+
...nextStepsManifest.classes,
|
|
151
|
+
...workflowsManifest.classes,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
const hotRebuild = async (refreshStepRegistrations) => {
|
|
155
|
+
if (refreshStepRegistrations) {
|
|
156
|
+
if (stepsCtx) {
|
|
157
|
+
await stepsCtx.rebuild();
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
stepsManifest = await this.createStepSourceRegistrationFile({
|
|
161
|
+
inputFiles: options.inputFiles,
|
|
162
|
+
outfile: stepsOutfile,
|
|
163
|
+
tsconfigPath,
|
|
164
|
+
discoveredEntries,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const workflowResult = await workflowsCtx.interimBundleCtx.rebuild();
|
|
169
|
+
const workflowOutput = workflowResult.outputFiles?.[0]?.text;
|
|
170
|
+
if (!workflowOutput) {
|
|
171
|
+
throw new Error('Invariant: expected workflow output from hot rebuild');
|
|
172
|
+
}
|
|
173
|
+
workflowInterimBundleText = workflowOutput;
|
|
174
|
+
await workflowsCtx.bundleFinal(workflowOutput);
|
|
175
|
+
await writeManifest(mergeCombinedManifest(stepsManifest));
|
|
176
|
+
};
|
|
151
177
|
const fullRebuild = async () => {
|
|
178
|
+
this.clearDiscoveredEntriesCache();
|
|
152
179
|
const newInputFiles = await this.getInputFiles();
|
|
153
180
|
options.inputFiles = newInputFiles;
|
|
154
|
-
await stepsCtx
|
|
155
|
-
const { context: newStepsCtx } = await this.buildStepsFunction(options);
|
|
156
|
-
if (!newStepsCtx) {
|
|
157
|
-
throw new Error('Invariant: expected steps build context after rebuild');
|
|
158
|
-
}
|
|
159
|
-
stepsCtx = newStepsCtx;
|
|
181
|
+
await stepsCtx?.dispose();
|
|
160
182
|
await workflowsCtx.interimBundleCtx.dispose();
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
183
|
+
const newCombined = await this.buildCombinedFunction(options);
|
|
184
|
+
stepsCtx = newCombined.stepsContext;
|
|
185
|
+
discoveredEntries = newCombined.discoveredEntries;
|
|
186
|
+
stepsManifest = newCombined.stepsManifest;
|
|
187
|
+
workflowsManifest = newCombined.workflowsManifest;
|
|
188
|
+
workflowInterimBundleText = newCombined.workflowInterimBundleText;
|
|
189
|
+
if (!newCombined?.interimBundleCtx || !newCombined?.bundleFinal) {
|
|
164
190
|
throw new Error('Invariant: expected workflows bundle context after rebuild');
|
|
165
191
|
}
|
|
166
192
|
workflowsCtx = {
|
|
167
|
-
interimBundleCtx:
|
|
168
|
-
bundleFinal:
|
|
193
|
+
interimBundleCtx: newCombined.interimBundleCtx,
|
|
194
|
+
bundleFinal: newCombined.bundleFinal,
|
|
169
195
|
};
|
|
196
|
+
await writeManifest(newCombined.manifest);
|
|
197
|
+
await refreshSourceSnapshots();
|
|
170
198
|
};
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
199
|
+
const isWatchableFile = (path) => watchableExtensions.has((0, node_path_1.extname)(path));
|
|
200
|
+
const readKnownFiles = async () => {
|
|
201
|
+
const files = new Set();
|
|
202
|
+
const aliases = new Map();
|
|
203
|
+
const relevantFiles = (0, watch_rebuild_js_1.getRelevantFiles)({
|
|
204
|
+
discoveredEntries,
|
|
205
|
+
inputFiles: options.inputFiles,
|
|
206
|
+
normalizePath,
|
|
207
|
+
});
|
|
208
|
+
const addKnownFile = async (filePath) => {
|
|
209
|
+
let realFilePath = filePath;
|
|
210
|
+
try {
|
|
211
|
+
realFilePath = normalizePath(await (0, promises_1.realpath)(filePath));
|
|
212
|
+
}
|
|
213
|
+
catch { }
|
|
214
|
+
const canonicalPath = relevantFiles.has(realFilePath)
|
|
215
|
+
? realFilePath
|
|
216
|
+
: filePath;
|
|
217
|
+
files.add(canonicalPath);
|
|
218
|
+
aliases.set(filePath, canonicalPath);
|
|
219
|
+
aliases.set(realFilePath, canonicalPath);
|
|
220
|
+
return canonicalPath;
|
|
221
|
+
};
|
|
222
|
+
const visit = async (directory) => {
|
|
223
|
+
let dirents;
|
|
224
|
+
try {
|
|
225
|
+
dirents = await (0, promises_1.readdir)(directory, { withFileTypes: true });
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
174
228
|
return;
|
|
175
229
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
230
|
+
await Promise.all(dirents.map(async (dirent) => {
|
|
231
|
+
const filePath = normalizePath((0, node_path_1.join)(directory, dirent.name));
|
|
232
|
+
if (hasIgnoredPathFragment(filePath)) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (dirent.isDirectory()) {
|
|
236
|
+
await visit(filePath);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
let stats;
|
|
240
|
+
try {
|
|
241
|
+
stats = await (0, promises_1.stat)(filePath);
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (stats.isDirectory()) {
|
|
247
|
+
await visit(filePath);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (!stats.isFile() || !isWatchableFile(filePath)) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
await addKnownFile(filePath);
|
|
254
|
+
}));
|
|
255
|
+
};
|
|
256
|
+
await visit(this.config.workingDir);
|
|
257
|
+
return { files, aliases, addKnownFile };
|
|
258
|
+
};
|
|
259
|
+
const mergeFileChanges = (left, right) => ({
|
|
260
|
+
addedFiles: unique([...left.addedFiles, ...right.addedFiles]),
|
|
261
|
+
modifiedFiles: unique([
|
|
262
|
+
...left.modifiedFiles,
|
|
263
|
+
...right.modifiedFiles,
|
|
264
|
+
]),
|
|
265
|
+
removedFiles: unique([...left.removedFiles, ...right.removedFiles]),
|
|
266
|
+
});
|
|
267
|
+
const unique = (paths) => [...new Set(paths)];
|
|
268
|
+
const classifyFileChanges = ({ changedFiles, knownFiles, removedFiles, }) => {
|
|
269
|
+
const addedFiles = [];
|
|
270
|
+
const modifiedFiles = [];
|
|
271
|
+
for (const file of unique(changedFiles)) {
|
|
272
|
+
if (knownFiles.has(file)) {
|
|
273
|
+
modifiedFiles.push(file);
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
addedFiles.push(file);
|
|
277
|
+
knownFiles.add(file);
|
|
180
278
|
}
|
|
279
|
+
}
|
|
280
|
+
for (const file of removedFiles) {
|
|
281
|
+
knownFiles.delete(file);
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
addedFiles,
|
|
285
|
+
modifiedFiles,
|
|
286
|
+
removedFiles: unique(removedFiles),
|
|
181
287
|
};
|
|
182
|
-
logByType(result.errors, 'error');
|
|
183
|
-
logByType(result.warnings, 'warn');
|
|
184
288
|
};
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
logBuildMessages(workflowResult, 'workflows bundle');
|
|
193
|
-
if (!workflowResult.outputFiles ||
|
|
194
|
-
workflowResult.outputFiles.length === 0) {
|
|
195
|
-
console.error('No output generated while rebuilding workflows bundle');
|
|
196
|
-
return;
|
|
289
|
+
const hasFileChanges = ({ addedFiles, modifiedFiles, removedFiles, }) => addedFiles.length > 0 ||
|
|
290
|
+
modifiedFiles.length > 0 ||
|
|
291
|
+
removedFiles.length > 0;
|
|
292
|
+
const stepExecutionFilesChanged = (fileChanges) => {
|
|
293
|
+
const stepEntryFiles = [...discoveredEntries.discoveredSteps].map(normalizePath);
|
|
294
|
+
if (stepEntryFiles.length === 0) {
|
|
295
|
+
return false;
|
|
197
296
|
}
|
|
198
|
-
|
|
199
|
-
|
|
297
|
+
const changedFiles = unique([
|
|
298
|
+
...fileChanges.modifiedFiles,
|
|
299
|
+
...fileChanges.addedFiles,
|
|
300
|
+
...fileChanges.removedFiles,
|
|
301
|
+
]).map(normalizePath);
|
|
302
|
+
return changedFiles.some((changedFile) => stepEntryFiles.includes(changedFile) ||
|
|
303
|
+
stepEntryFiles.some((stepFile) => parentHasChild(stepFile, changedFile)));
|
|
200
304
|
};
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const removed = [];
|
|
205
|
-
for (const path of previousEntries.keys()) {
|
|
206
|
-
if (!currentEntries.has(path) && isWatchableFile(path)) {
|
|
207
|
-
removed.push(path);
|
|
208
|
-
}
|
|
305
|
+
const logDevHmr = (...args) => {
|
|
306
|
+
if (process.env.WORKFLOW_DEV_HMR_LOGS === '1') {
|
|
307
|
+
console.log(...args);
|
|
209
308
|
}
|
|
210
|
-
return removed;
|
|
211
309
|
};
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
310
|
+
await refreshSourceSnapshots();
|
|
311
|
+
let { files: knownFiles, aliases: knownFileAliases, addKnownFile: rememberKnownFile, } = await readKnownFiles();
|
|
312
|
+
const refreshKnownFiles = async () => {
|
|
313
|
+
const nextKnown = await readKnownFiles();
|
|
314
|
+
knownFiles = nextKnown.files;
|
|
315
|
+
knownFileAliases = nextKnown.aliases;
|
|
316
|
+
rememberKnownFile = nextKnown.addKnownFile;
|
|
317
|
+
};
|
|
318
|
+
const processFileChanges = async (fileChanges) => {
|
|
319
|
+
if (!hasFileChanges(fileChanges)) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const decision = await (0, watch_rebuild_js_1.classifyRebuild)({
|
|
323
|
+
discoveredEntries,
|
|
324
|
+
fileChanges,
|
|
325
|
+
inputFiles: options.inputFiles,
|
|
326
|
+
normalizePath,
|
|
327
|
+
parentHasChild,
|
|
328
|
+
readSnapshot: readSourceSnapshot,
|
|
329
|
+
sourceSnapshots,
|
|
330
|
+
});
|
|
331
|
+
if (decision.kind === 'none') {
|
|
332
|
+
logDevHmr('workflow dev hmr: skip');
|
|
333
|
+
for (const [file, snapshot] of decision.snapshots || []) {
|
|
334
|
+
sourceSnapshots.set(file, snapshot);
|
|
223
335
|
}
|
|
224
|
-
if (
|
|
225
|
-
|
|
336
|
+
if (!stepsCtx &&
|
|
337
|
+
workflowInterimBundleText &&
|
|
338
|
+
stepExecutionFilesChanged(fileChanges)) {
|
|
339
|
+
// Source step registrations keep stable imports, so Turbopack
|
|
340
|
+
// can leave the generated flow route cached after a
|
|
341
|
+
// step-body-only edit. Refresh the route wrapper without
|
|
342
|
+
// rediscovering entries or rebuilding the workflow VM.
|
|
343
|
+
await workflowsCtx.bundleFinal(workflowInterimBundleText);
|
|
226
344
|
}
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
if (decision.kind === 'full') {
|
|
348
|
+
logDevHmr('workflow dev hmr: full rediscovery');
|
|
349
|
+
await fullRebuild();
|
|
350
|
+
await refreshKnownFiles();
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
logDevHmr(`workflow dev hmr: hot rebuild${decision.refreshStepRegistrations ? ' with step registration refresh' : ''}`);
|
|
354
|
+
await hotRebuild(decision.refreshStepRegistrations);
|
|
355
|
+
for (const [file, snapshot] of decision.snapshots) {
|
|
356
|
+
sourceSnapshots.set(file, snapshot);
|
|
227
357
|
}
|
|
228
|
-
return { added, modified };
|
|
229
358
|
};
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
addedFiles: added,
|
|
235
|
-
modifiedFiles: modified,
|
|
236
|
-
removedFiles,
|
|
237
|
-
};
|
|
359
|
+
let pendingFileChanges = {
|
|
360
|
+
addedFiles: [],
|
|
361
|
+
modifiedFiles: [],
|
|
362
|
+
removedFiles: [],
|
|
238
363
|
};
|
|
239
|
-
let
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
previousTimeInfo = currentEntries;
|
|
244
|
-
if (isInitial) {
|
|
245
|
-
isInitial = false;
|
|
364
|
+
let flushTimer;
|
|
365
|
+
const scheduleFileChanges = (fileChanges) => {
|
|
366
|
+
pendingFileChanges = mergeFileChanges(pendingFileChanges, fileChanges);
|
|
367
|
+
if (flushTimer) {
|
|
246
368
|
return;
|
|
247
369
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
370
|
+
flushTimer = setTimeout(() => {
|
|
371
|
+
const fileChanges = pendingFileChanges;
|
|
372
|
+
pendingFileChanges = {
|
|
373
|
+
addedFiles: [],
|
|
374
|
+
modifiedFiles: [],
|
|
375
|
+
removedFiles: [],
|
|
376
|
+
};
|
|
377
|
+
flushTimer = undefined;
|
|
378
|
+
enqueue(() => processFileChanges(fileChanges));
|
|
379
|
+
}, 10);
|
|
380
|
+
};
|
|
381
|
+
const resolveExistingEventPath = async (pathname) => {
|
|
382
|
+
const normalizedPath = normalizePath(pathname);
|
|
383
|
+
if (!isWatchableFile(normalizedPath)) {
|
|
251
384
|
return;
|
|
252
385
|
}
|
|
253
|
-
|
|
254
|
-
|
|
386
|
+
const knownPath = knownFileAliases.get(normalizedPath);
|
|
387
|
+
if (knownPath) {
|
|
388
|
+
return knownPath;
|
|
255
389
|
}
|
|
256
|
-
|
|
257
|
-
|
|
390
|
+
try {
|
|
391
|
+
const realFilePath = normalizePath(await (0, promises_1.realpath)(normalizedPath));
|
|
392
|
+
return knownFileAliases.get(realFilePath) ?? normalizedPath;
|
|
258
393
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
394
|
+
catch {
|
|
395
|
+
return normalizedPath;
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
const handleFileAdded = async (pathname) => {
|
|
399
|
+
const normalizedPath = normalizePath(pathname);
|
|
400
|
+
if (!isWatchableFile(normalizedPath)) {
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
const existingPath = await resolveExistingEventPath(normalizedPath);
|
|
404
|
+
const wasKnown = existingPath ? knownFiles.has(existingPath) : false;
|
|
405
|
+
const canonicalPath = await rememberKnownFile(normalizedPath);
|
|
406
|
+
knownFiles.add(canonicalPath);
|
|
407
|
+
scheduleFileChanges({
|
|
408
|
+
addedFiles: wasKnown ? [] : [canonicalPath],
|
|
409
|
+
modifiedFiles: wasKnown ? [canonicalPath] : [],
|
|
410
|
+
removedFiles: [],
|
|
411
|
+
});
|
|
412
|
+
};
|
|
413
|
+
const handleFileChanged = async (pathname) => {
|
|
414
|
+
const canonicalPath = await resolveExistingEventPath(pathname);
|
|
415
|
+
if (!canonicalPath) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
const fileChanges = classifyFileChanges({
|
|
419
|
+
changedFiles: [canonicalPath],
|
|
420
|
+
knownFiles,
|
|
421
|
+
removedFiles: [],
|
|
267
422
|
});
|
|
423
|
+
if (!knownFileAliases.has(canonicalPath)) {
|
|
424
|
+
await rememberKnownFile(canonicalPath);
|
|
425
|
+
}
|
|
426
|
+
scheduleFileChanges(fileChanges);
|
|
427
|
+
};
|
|
428
|
+
const handleFileRemoved = (pathname) => {
|
|
429
|
+
const normalizedPath = normalizePath(pathname);
|
|
430
|
+
if (!isWatchableFile(normalizedPath)) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const canonicalPath = knownFileAliases.get(normalizedPath) ?? normalizedPath;
|
|
434
|
+
const fileChanges = classifyFileChanges({
|
|
435
|
+
changedFiles: [],
|
|
436
|
+
knownFiles,
|
|
437
|
+
removedFiles: [canonicalPath],
|
|
438
|
+
});
|
|
439
|
+
knownFileAliases.delete(normalizedPath);
|
|
440
|
+
scheduleFileChanges(fileChanges);
|
|
441
|
+
};
|
|
442
|
+
const watcher = chokidar_1.default.watch(this.config.workingDir, {
|
|
443
|
+
ignoreInitial: true,
|
|
444
|
+
followSymlinks: true,
|
|
445
|
+
ignored: (pathname) => {
|
|
446
|
+
const normalizedPath = normalizePath(String(pathname));
|
|
447
|
+
const extension = (0, node_path_1.extname)(normalizedPath);
|
|
448
|
+
if (extension && !watchableExtensions.has(extension)) {
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
return hasIgnoredPathFragment(normalizedPath);
|
|
452
|
+
},
|
|
268
453
|
});
|
|
269
|
-
watcher.
|
|
270
|
-
|
|
271
|
-
|
|
454
|
+
watcher.on('add', (pathname) => {
|
|
455
|
+
void handleFileAdded(pathname);
|
|
456
|
+
});
|
|
457
|
+
watcher.on('change', (pathname) => {
|
|
458
|
+
void handleFileChanged(pathname);
|
|
459
|
+
});
|
|
460
|
+
watcher.on('unlink', (pathname) => {
|
|
461
|
+
handleFileRemoved(pathname);
|
|
462
|
+
});
|
|
463
|
+
watcher.on('error', (error) => {
|
|
464
|
+
console.error('Workflow dev watcher error', error);
|
|
465
|
+
});
|
|
466
|
+
watcher.on('ready', () => {
|
|
467
|
+
logDevHmr('workflow dev hmr: ready');
|
|
272
468
|
});
|
|
273
469
|
}
|
|
274
470
|
}
|
|
275
471
|
async getInputFiles() {
|
|
276
472
|
const inputFiles = await super.getInputFiles();
|
|
277
|
-
return inputFiles.filter((
|
|
278
|
-
|
|
279
|
-
//
|
|
280
|
-
if (
|
|
473
|
+
return inputFiles.filter((file) => {
|
|
474
|
+
const entry = (0, node_path_1.relative)(this.config.workingDir, file).replaceAll('\\', '/');
|
|
475
|
+
// Match App Router route, page, and layout entrypoints in app/ or src/app/.
|
|
476
|
+
if (/^(?:app|src\/app)\/(?:.*\/)?(?:route|page|layout)\./.test(entry)) {
|
|
281
477
|
return true;
|
|
282
478
|
}
|
|
283
|
-
// Match Pages Router
|
|
284
|
-
if (
|
|
479
|
+
// Match every Pages Router entrypoint in pages/ or src/pages/.
|
|
480
|
+
if (/^(?:pages|src\/pages)\//.test(entry)) {
|
|
285
481
|
return true;
|
|
286
482
|
}
|
|
287
|
-
|
|
483
|
+
// Match Next.js root entrypoints at the project root or under src/.
|
|
484
|
+
return ['instrumentation', 'middleware', 'proxy'].some((name) => this.config.pageExtensions.some((extension) => entry === `${name}.${extension}` ||
|
|
485
|
+
entry === `src/${name}.${extension}`));
|
|
288
486
|
});
|
|
289
487
|
}
|
|
290
488
|
async writeFunctionsConfig(outputDir) {
|
|
@@ -292,46 +490,32 @@ async function getNextBuilderEager() {
|
|
|
292
490
|
if (process.env.NODE_ENV === 'development') {
|
|
293
491
|
return;
|
|
294
492
|
}
|
|
493
|
+
// V2 combined config: single trigger handles both workflow and step execution.
|
|
494
|
+
// The step route no longer needs its own trigger since steps are executed
|
|
495
|
+
// inline by the combined handler or queued back to __wkf_workflow_* with stepId.
|
|
295
496
|
const generatedConfig = {
|
|
296
497
|
version: '0',
|
|
297
|
-
steps: {
|
|
298
|
-
maxDuration: 'max',
|
|
299
|
-
experimentalTriggers: [STEP_QUEUE_TRIGGER],
|
|
300
|
-
},
|
|
301
498
|
workflows: {
|
|
302
499
|
maxDuration: 'max',
|
|
303
500
|
experimentalTriggers: [WORKFLOW_QUEUE_TRIGGER],
|
|
304
501
|
},
|
|
305
502
|
};
|
|
306
|
-
// We write this file to the generated directory for
|
|
307
|
-
// the Next.js builder to consume
|
|
308
503
|
await (0, promises_1.writeFile)((0, node_path_1.join)(outputDir, '.well-known/workflow/v1/config.json'), JSON.stringify(generatedConfig, null, 2));
|
|
309
504
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
// which turbopack/webpack fail to analyze. If we externalize
|
|
318
|
-
// correctly this shouldn't be an issue although we might want
|
|
319
|
-
// to use cjs as alternative to avoid
|
|
505
|
+
/**
|
|
506
|
+
* V2: Build combined route that handles both workflow and step execution.
|
|
507
|
+
*/
|
|
508
|
+
async buildCombinedFunction({ inputFiles, workflowGeneratedDir, tsconfigPath, }) {
|
|
509
|
+
const flowRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'flow');
|
|
510
|
+
await (0, promises_1.mkdir)(flowRouteDir, { recursive: true });
|
|
511
|
+
return await this.createCombinedBundle({
|
|
320
512
|
format: 'esm',
|
|
321
513
|
inputFiles,
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
tsconfigPath,
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
async buildWorkflowsFunction({ inputFiles, workflowGeneratedDir, tsconfigPath, }) {
|
|
328
|
-
const workflowsRouteDir = (0, node_path_1.join)(workflowGeneratedDir, 'flow');
|
|
329
|
-
await (0, promises_1.mkdir)(workflowsRouteDir, { recursive: true });
|
|
330
|
-
return await this.createWorkflowsBundle({
|
|
331
|
-
format: 'esm',
|
|
332
|
-
outfile: (0, node_path_1.join)(workflowsRouteDir, 'route.js'),
|
|
514
|
+
stepsOutfile: (0, node_path_1.join)(flowRouteDir, '__step_registrations.js'),
|
|
515
|
+
flowOutfile: (0, node_path_1.join)(flowRouteDir, 'route.js'),
|
|
333
516
|
bundleFinalOutput: false,
|
|
334
|
-
|
|
517
|
+
externalizeNonSteps: true,
|
|
518
|
+
sourceStepRegistrationImports: true,
|
|
335
519
|
tsconfigPath,
|
|
336
520
|
});
|
|
337
521
|
}
|
|
@@ -389,4 +573,4 @@ async function getNextBuilderEager() {
|
|
|
389
573
|
CachedNextBuilderEager = NextBuilder;
|
|
390
574
|
return NextBuilder;
|
|
391
575
|
}
|
|
392
|
-
//# sourceMappingURL=builder-eager.js.map
|
|
576
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGRlci1lYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9idWlsZGVyLWVhZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBa0NBLGtEQXF1QkM7QUF2d0JELHFDQUFpRDtBQUNqRCwrQ0FRMEI7QUFDMUIseUNBQXlFO0FBS3pFLHdEQUFnQztBQUVoQyx5REFPNEI7QUFFNUIsSUFBSSxzQkFBMkIsQ0FBQztBQUNoQyxNQUFNLFNBQVMsR0FBRyxJQUFJLFFBQVEsQ0FBQyxXQUFXLEVBQUUsMEJBQTBCLENBRXZELENBQUM7QUFFaEIsOEVBQThFO0FBQzlFLDZFQUE2RTtBQUM3RSxvRUFBb0U7QUFDN0QsS0FBSyxVQUFVLG1CQUFtQixDQUN2QyxjQUFvRDtJQUVwRCxJQUFJLHNCQUFzQixFQUFFLENBQUM7UUFDM0IsT0FBTyxzQkFBc0IsQ0FBQztJQUNoQyxDQUFDO0lBRUQsTUFBTSxFQUNKLFdBQVcsRUFBRSxnQkFBZ0IsRUFDN0Isc0JBQXNCLEVBQ3RCLHNCQUFzQixFQUN0QixjQUFjLEdBQ2YsR0FBRyxjQUFjO1FBQ2xCLENBQUMsTUFBTSxTQUFTLENBQXNDLG9CQUFvQixDQUFDLENBQUMsQ0FBQztJQUU3RSxNQUFNLFdBQVksU0FBUSxnQkFBZ0I7UUFNeEMsS0FBSyxDQUFDLEtBQUs7WUFDVCxNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ2hELE1BQU0sb0JBQW9CLEdBQUcsSUFBQSxnQkFBSSxFQUFDLFNBQVMsRUFBRSx5QkFBeUIsQ0FBQyxDQUFDO1lBRXhFLGtDQUFrQztZQUNsQyxNQUFNLElBQUEsZ0JBQUssRUFBQyxvQkFBb0IsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZELE1BQU0sSUFBQSxvQkFBUyxFQUFDLElBQUEsZ0JBQUksRUFBQyxvQkFBb0IsRUFBRSxZQUFZLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUUv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Q0FBQyxFQUFFLENBQUM7b0JBQ1gsSUFBSSxDQUFDLFlBQVksS0FBSyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsQ0FBQzt3QkFDaEUsTUFBTSxDQUFDLENBQUM7b0JBQ1YsQ0FBQztvQkFDRCxPQUFPLEtBQUssQ0FBQztnQkFDZixDQUFDO1lBQ0gsQ0FBQyxDQUFDO1lBRUYsZ0NBQWdDO1lBQ2hDLElBQUksTUFBTSxXQUFXLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztnQkFDOUIsT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQztZQUVELG9DQUFvQztZQUNwQyxJQUFJLE1BQU0sV0FBVyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7Z0JBQ2pDLE9BQU8sU0FBUyxDQUFDO1lBQ25CLENBQUM7WUFFRCxrRkFBa0Y7WUFDbEYsSUFBSSxNQUFNLFdBQVcsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUNoQywrQ0FBK0M7Z0JBQy9DLE1BQU0sSUFBQSxnQkFBSyxFQUFDLE1BQU0sRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUN6QyxPQUFPLE1BQU0sQ0FBQztZQUNoQixDQUFDO1lBRUQsSUFBSSxNQUFNLFdBQVcsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO2dCQUNuQyx1REFBdUQ7Z0JBQ3ZELE1BQU0sSUFBQSxnQkFBSyxFQUFDLFNBQVMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUM1QyxPQUFPLFNBQVMsQ0FBQztZQUNuQixDQUFDO1lBRUQsTUFBTSxJQUFJLEtBQUssQ0FDYixxSEFBcUgsQ0FDdEgsQ0FBQztRQUNKLENBQUM7S0FDRjtJQUVELHNCQUFzQixHQUFHLFdBQVcsQ0FBQztJQUNyQyxPQUFPLFdBQVcsQ0FBQztBQUNyQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY29uc3RhbnRzLCB0eXBlIERpcmVudCB9IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHtcbiAgYWNjZXNzLFxuICBjb3B5RmlsZSxcbiAgbWtkaXIsXG4gIHJlYWRkaXIsXG4gIHJlYWxwYXRoLFxuICBzdGF0LFxuICB3cml0ZUZpbGUsXG59IGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnO1xuaW1wb3J0IHsgZXh0bmFtZSwgaXNBYnNvbHV0ZSwgam9pbiwgcmVsYXRpdmUsIHJlc29sdmUgfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHR5cGUge1xuICBOZXh0Q29uZmlnIGFzIEJ1aWxkZXJOZXh0Q29uZmlnLFxuICBXb3JrZmxvd01hbmlmZXN0LFxufSBmcm9tICdAd29ya2Zsb3cvYnVpbGRlcnMnO1xuaW1wb3J0IGNob2tpZGFyIGZyb20gJ2Nob2tpZGFyJztcbmltcG9ydCB0eXBlIHsgTmV4dENvbmZpZyBhcyBQcm9qZWN0TmV4dENvbmZpZyB9IGZyb20gJ25leHQnO1xuaW1wb3J0IHtcbiAgY2xhc3NpZnlSZWJ1aWxkLFxuICBjcmVhdGVTb3VyY2VTbmFwc2hvdCxcbiAgdHlwZSBGaWxlQ2hhbmdlcyxcbiAgZ2V0UmVsZXZhbnRGaWxlcyxcbiAgcmVwbGFjZVNvdXJjZVNuYXBzaG90cyxcbiAgdHlwZSBTb3VyY2VTbmFwc2hvdCxcbn0gZnJvbSAnLi93YXRjaC1yZWJ1aWxkLmpzJztcblxubGV0IENhY2hlZE5leHRCdWlsZGVyRWFnZXI6IGFueTtcbmNvbnN0IGltcG9ydEVzbSA9IG5ldyBGdW5jdGlvbignc3BlY2lmaWVyJywgJ3JldHVybiBpbXBvcnQoc3BlY2lmaWVyKScpIGFzIDxUPihcbiAgc3BlY2lmaWVyOiBzdHJpbmdcbikgPT4gUHJvbWlzZTxUPjtcblxuLy8gQ3JlYXRlIHRoZSBlYWdlciBOZXh0IGJ1aWxkZXIgZHluYW1pY2FsbHkgYnkgZXh0ZW5kaW5nIHRoZSBFU00gQmFzZUJ1aWxkZXIuXG4vLyBFeHBvcnRlZCBhcyBnZXROZXh0QnVpbGRlckVhZ2VyKCkgdG8gYWxsb3cgQ29tbW9uSlMgbW9kdWxlcyB0byBpbXBvcnQgZnJvbVxuLy8gdGhlIEVTTSBAd29ya2Zsb3cvYnVpbGRlcnMgcGFja2FnZSB2aWEgZHluYW1pYyBpbXBvcnQgYXQgcnVudGltZS5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXROZXh0QnVpbGRlckVhZ2VyKFxuICBidWlsZGVyc01vZHVsZT86IHR5cGVvZiBpbXBvcnQoJ0B3b3JrZmxvdy9idWlsZGVycycpXG4pIHtcbiAgaWYgKENhY2hlZE5leHRCdWlsZGVyRWFnZXIpIHtcbiAgICByZXR1cm4gQ2FjaGVkTmV4dEJ1aWxkZXJFYWdlcjtcbiAgfVxuXG4gIGNvbnN0IHtcbiAgICBCYXNlQnVpbGRlcjogQmFzZUJ1aWxkZXJDbGFzcyxcbiAgICBXT1JLRkxPV19RVUVVRV9UUklHR0VSLFxuICAgIGRldGVjdFdvcmtmbG93UGF0dGVybnMsXG4gICAgcGFyZW50SGFzQ2hpbGQsXG4gIH0gPSBidWlsZGVyc01vZHVsZSA/P1xuICAoYXdhaXQgaW1wb3J0RXNtPHR5cGVvZiBpbXBvcnQoJ0B3b3JrZmxvdy9idWlsZGVycycpPignQHdvcmtmbG93L2J1aWxkZXJzJykpO1xuXG4gIGNsYXNzIE5leHRCdWlsZGVyIGV4dGVuZHMgQmFzZUJ1aWxkZXJDbGFzcyB7XG4gICAgcHJvdGVjdGVkIGRlY2xhcmUgY29uZmlnOiBCdWlsZGVyTmV4dENvbmZpZyAmIHtcbiAgICAgIHBhZ2VFeHRlbnNpb25zOiBOb25OdWxsYWJsZTxQcm9qZWN0TmV4dENvbmZpZ1sncGFnZUV4dGVuc2lvbnMnXT47XG4gICAgICBkaXN0RGlyOiBzdHJpbmc7XG4gICAgfTtcblxuICAgIGFzeW5jIGJ1aWxkKCkge1xuICAgICAgY29uc3Qgb3V0cHV0RGlyID0gYXdhaXQgdGhpcy5maW5kQXBwRGlyZWN0b3J5KCk7XG4gICAgICBjb25zdCB3b3JrZmxvd0dlbmVyYXRlZERpciA9IGpvaW4ob3V0cHV0RGlyLCAnLndlbGwta25vd24vd29ya2Zsb3cvdjEnKTtcblxuICAgICAgLy8gRW5zdXJlIG91dHB1dCBkaXJlY3RvcmllcyBleGlzdFxuICAgICAgYXdhaXQgbWtkaXIod29ya2Zsb3dHZW5lcmF0ZWREaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgYXdhaXQgd3JpdGVGaWxlKGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICcuZ2l0aWdub3JlJyksICcqJyk7XG5cbiAgICAgIGNvbnN0IGlucHV0RmlsZXMgPSBhd2FpdCB0aGlzLmdldElucHV0RmlsZXMoKTtcbiAgICAgIGNvbnN0IHRzY29uZmlnUGF0aCA9IGF3YWl0IHRoaXMuZmluZFRzQ29uZmlnUGF0aCgpO1xuXG4gICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICBpbnB1dEZpbGVzLFxuICAgICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcixcbiAgICAgICAgdHNjb25maWdQYXRoLFxuICAgICAgfTtcblxuICAgICAgLy8gVjI6IEJ1aWxkIGNvbWJpbmVkIHJvdXRlIChyZXBsYWNlcyBzZXBhcmF0ZSBzdGVwICsgZmxvdyByb3V0ZXMpXG4gICAgICBjb25zdCBjb21iaW5lZFJlc3VsdCA9IGF3YWl0IHRoaXMuYnVpbGRDb21iaW5lZEZ1bmN0aW9uKG9wdGlvbnMpO1xuICAgICAgYXdhaXQgdGhpcy5idWlsZFdlYmhvb2tSb3V0ZSh7IHdvcmtmbG93R2VuZXJhdGVkRGlyIH0pO1xuXG4gICAgICBjb25zdCB3cml0ZU1hbmlmZXN0ID0gYXN5bmMgKFxuICAgICAgICBzb3VyY2VNYW5pZmVzdDogV29ya2Zsb3dNYW5pZmVzdCB8IHVuZGVmaW5lZFxuICAgICAgKSA9PiB7XG4gICAgICAgIGNvbnN0IG1hbmlmZXN0ID0ge1xuICAgICAgICAgIHN0ZXBzOiB7IC4uLnNvdXJjZU1hbmlmZXN0Py5zdGVwcyB9LFxuICAgICAgICAgIHdvcmtmbG93czogeyAuLi5zb3VyY2VNYW5pZmVzdD8ud29ya2Zsb3dzIH0sXG4gICAgICAgICAgY2xhc3NlczogeyAuLi5zb3VyY2VNYW5pZmVzdD8uY2xhc3NlcyB9LFxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFdyaXRlIG1hbmlmZXN0XG4gICAgICAgIGNvbnN0IHdvcmtmbG93QnVuZGxlUGF0aCA9IGpvaW4od29ya2Zsb3dHZW5lcmF0ZWREaXIsICdmbG93L3JvdXRlLmpzJyk7XG4gICAgICAgIGNvbnN0IG1hbmlmZXN0SnNvbiA9IGF3YWl0IHRoaXMuY3JlYXRlTWFuaWZlc3Qoe1xuICAgICAgICAgIHdvcmtmbG93QnVuZGxlUGF0aCxcbiAgICAgICAgICBtYW5pZmVzdERpcjogd29ya2Zsb3dHZW5lcmF0ZWREaXIsXG4gICAgICAgICAgbWFuaWZlc3QsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEV4cG9zZSBtYW5pZmVzdCBhcyBhIHN0YXRpYyBmaWxlIHdoZW4gV09SS0ZMT1dfUFVCTElDX01BTklGRVNUPTEuXG4gICAgICAgIGlmICh0aGlzLnNob3VsZEV4cG9zZVB1YmxpY01hbmlmZXN0ICYmIG1hbmlmZXN0SnNvbikge1xuICAgICAgICAgIGNvbnN0IHB1YmxpY01hbmlmZXN0RGlyID0gam9pbihcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLndvcmtpbmdEaXIsXG4gICAgICAgICAgICAncHVibGljLy53ZWxsLWtub3duL3dvcmtmbG93L3YxJ1xuICAgICAgICAgICk7XG4gICAgICAgICAgYXdhaXQgbWtkaXIocHVibGljTWFuaWZlc3REaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgICAgIGlmIChwcm9jZXNzLmVudi5WRVJDRUxfREVQTE9ZTUVOVF9JRCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBhd2FpdCB3cml0ZUZpbGUoam9pbihwdWJsaWNNYW5pZmVzdERpciwgJy5naXRpZ25vcmUnKSwgJyonKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYXdhaXQgY29weUZpbGUoXG4gICAgICAgICAgICBqb2luKHdvcmtmbG93R2VuZXJhdGVkRGlyLCAnbWFuaWZlc3QuanNvbicpLFxuICAgICAgICAgICAgam9pbihwdWJsaWNNYW5pZmVzdERpciwgJ21hbmlmZXN0Lmpzb24nKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IHdyaXRlTWFuaWZlc3QoY29tYmluZWRSZXN1bHQ/Lm1hbmlmZXN0KTtcblxuICAgICAgYXdhaXQgdGhpcy53cml0ZUZ1bmN0aW9uc0NvbmZpZyhvdXRwdXREaXIpO1xuXG4gICAgICBpZiAodGhpcy5jb25maWcud2F0Y2gpIHtcbiAgICAgICAgLy8gVE9ETzogaW1wbGVtZW50IHdhdGNoIG1vZGUgZm9yIGNvbWJpbmVkIGJ1bmRsZVxuICAgICAgICAvLyBGb3Igbm93LCBmYWxsIGJhY2sgdG8gZnVsbCByZWJ1aWxkIG9uIGZpbGUgY2hhbmdlc1xuICAgICAgICBpZiAoIWNvbWJpbmVkUmVzdWx0Py5pbnRlcmltQnVuZGxlQ3R4IHx8ICFjb21iaW5lZFJlc3VsdC5idW5kbGVGaW5hbCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICdJbnZhcmlhbnQ6IGV4cGVjdGVkIHdvcmtmbG93IGJ1aWxkIGNvbnRleHQgaW4gd2F0Y2ggbW9kZSdcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3RlcCByZWdpc3RyYXRpb25zIG1heSBiZSBlbWl0dGVkIGFzIHNvdXJjZSBpbXBvcnRzIHdpdGhvdXQgYW5cbiAgICAgICAgLy8gZXNidWlsZCBjb250ZXh0IHdoZW4gZXh0ZXJuYWxpemVOb25TdGVwcyBpcyBlbmFibGVkLlxuICAgICAgICBsZXQgc3RlcHNDdHggPSBjb21iaW5lZFJlc3VsdC5zdGVwc0NvbnRleHQ7XG4gICAgICAgIGxldCB3b3JrZmxvd3NDdHggPSB7XG4gICAgICAgICAgaW50ZXJpbUJ1bmRsZUN0eDogY29tYmluZWRSZXN1bHQuaW50ZXJpbUJ1bmRsZUN0eCxcbiAgICAgICAgICBidW5kbGVGaW5hbDogY29tYmluZWRSZXN1bHQuYnVuZGxlRmluYWwsXG4gICAgICAgIH07XG4gICAgICAgIGxldCB3b3JrZmxvd0ludGVyaW1CdW5kbGVUZXh0ID1cbiAgICAgICAgICBjb21iaW5lZFJlc3VsdC53b3JrZmxvd0ludGVyaW1CdW5kbGVUZXh0O1xuICAgICAgICBsZXQgZGlzY292ZXJlZEVudHJpZXMgPSBjb21iaW5lZFJlc3VsdC5kaXNjb3ZlcmVkRW50cmllcztcbiAgICAgICAgbGV0IHN0ZXBzTWFuaWZlc3QgPSBjb21iaW5lZFJlc3VsdC5zdGVwc01hbmlmZXN0O1xuICAgICAgICBsZXQgd29ya2Zsb3dzTWFuaWZlc3QgPSBjb21iaW5lZFJlc3VsdC53b3JrZmxvd3NNYW5pZmVzdDtcbiAgICAgICAgY29uc3Qgc3RlcHNPdXRmaWxlID0gam9pbihcbiAgICAgICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcixcbiAgICAgICAgICAnZmxvdycsXG4gICAgICAgICAgJ19fc3RlcF9yZWdpc3RyYXRpb25zLmpzJ1xuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZVBhdGggPSAocGF0aG5hbWU6IHN0cmluZykgPT5cbiAgICAgICAgICAoaXNBYnNvbHV0ZShwYXRobmFtZSlcbiAgICAgICAgICAgID8gcGF0aG5hbWVcbiAgICAgICAgICAgIDogcmVzb2x2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCBwYXRobmFtZSlcbiAgICAgICAgICApLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgICAgY29uc3Qgc291cmNlU25hcHNob3RzID0gbmV3IE1hcDxzdHJpbmcsIFNvdXJjZVNuYXBzaG90PigpO1xuXG4gICAgICAgIGNvbnN0IHdhdGNoYWJsZUV4dGVuc2lvbnMgPSBuZXcgU2V0KFtcbiAgICAgICAgICAnLmpzJyxcbiAgICAgICAgICAnLmpzeCcsXG4gICAgICAgICAgJy50cycsXG4gICAgICAgICAgJy50c3gnLFxuICAgICAgICAgICcubXRzJyxcbiAgICAgICAgICAnLmN0cycsXG4gICAgICAgICAgJy5janMnLFxuICAgICAgICAgICcubWpzJyxcbiAgICAgICAgXSk7XG4gICAgICAgIGNvbnN0IGlnbm9yZWRQYXRoRnJhZ21lbnRzID0gW1xuICAgICAgICAgICcvLmdpdC8nLFxuICAgICAgICAgICcvbm9kZV9tb2R1bGVzLycsXG4gICAgICAgICAgJy8ubmV4dC8nLFxuICAgICAgICAgICcvLnR1cmJvLycsXG4gICAgICAgICAgJy8udmVyY2VsLycsXG4gICAgICAgICAgJy9kaXN0LycsXG4gICAgICAgICAgJy9idWlsZC8nLFxuICAgICAgICAgICcvb3V0LycsXG4gICAgICAgICAgJy8uY2FjaGUvJyxcbiAgICAgICAgICAnLy55YXJuLycsXG4gICAgICAgICAgJy8ucG5wbS1zdG9yZS8nLFxuICAgICAgICAgICcvLnBhcmNlbC1jYWNoZS8nLFxuICAgICAgICAgICcvLndlbGwta25vd24vd29ya2Zsb3cvJyxcbiAgICAgICAgXTtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZEdlbmVyYXRlZERpciA9IHdvcmtmbG93R2VuZXJhdGVkRGlyLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZERpc3REaXIgPSBub3JtYWxpemVQYXRoKHRoaXMuY29uZmlnLmRpc3REaXIpO1xuICAgICAgICBpZ25vcmVkUGF0aEZyYWdtZW50cy5wdXNoKG5vcm1hbGl6ZWRHZW5lcmF0ZWREaXIpO1xuXG4gICAgICAgIGNvbnN0IGhhc0lnbm9yZWRQYXRoRnJhZ21lbnQgPSAobm9ybWFsaXplZFBhdGg6IHN0cmluZykgPT4ge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRQYXRoLnN0YXJ0c1dpdGgobm9ybWFsaXplZEdlbmVyYXRlZERpcikgfHxcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRQYXRoID09PSBub3JtYWxpemVkRGlzdERpciB8fFxuICAgICAgICAgICAgbm9ybWFsaXplZFBhdGguc3RhcnRzV2l0aChgJHtub3JtYWxpemVkRGlzdERpcn0vYClcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmb3IgKGNvbnN0IGZyYWdtZW50IG9mIGlnbm9yZWRQYXRoRnJhZ21lbnRzKSB7XG4gICAgICAgICAgICBpZiAobm9ybWFsaXplZFBhdGguaW5jbHVkZXMoZnJhZ21lbnQpKSB7XG4gICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgbGV0IHJlYnVpbGRRdWV1ZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuXG4gICAgICAgIGNvbnN0IGVucXVldWUgPSAodGFzazogKCkgPT4gUHJvbWlzZTx2b2lkPikgPT4ge1xuICAgICAgICAgIHJlYnVpbGRRdWV1ZSA9IHJlYnVpbGRRdWV1ZS50aGVuKHRhc2spLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIHByb2Nlc3MgZmlsZSBjaGFuZ2UnLCBlcnJvcik7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHJlYnVpbGRRdWV1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCByZWFkU291cmNlU25hcHNob3QgPSAoZmlsZTogc3RyaW5nKSA9PlxuICAgICAgICAgIGNyZWF0ZVNvdXJjZVNuYXBzaG90KHsgZmlsZSwgZGV0ZWN0V29ya2Zsb3dQYXR0ZXJucyB9KTtcblxuICAgICAgICBjb25zdCByZWZyZXNoU291cmNlU25hcHNob3RzID0gKCkgPT5cbiAgICAgICAgICByZXBsYWNlU291cmNlU25hcHNob3RzKHtcbiAgICAgICAgICAgIGRpc2NvdmVyZWRFbnRyaWVzLFxuICAgICAgICAgICAgaW5wdXRGaWxlczogb3B0aW9ucy5pbnB1dEZpbGVzLFxuICAgICAgICAgICAgbm9ybWFsaXplUGF0aCxcbiAgICAgICAgICAgIHJlYWRTbmFwc2hvdDogcmVhZFNvdXJjZVNuYXBzaG90LFxuICAgICAgICAgICAgc291cmNlU25hcHNob3RzLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IG1lcmdlQ29tYmluZWRNYW5pZmVzdCA9IChcbiAgICAgICAgICBuZXh0U3RlcHNNYW5pZmVzdDogV29ya2Zsb3dNYW5pZmVzdFxuICAgICAgICApOiBXb3JrZmxvd01hbmlmZXN0ID0+ICh7XG4gICAgICAgICAgLi4ubmV4dFN0ZXBzTWFuaWZlc3QsXG4gICAgICAgICAgd29ya2Zsb3dzOiB7XG4gICAgICAgICAgICAuLi5uZXh0U3RlcHNNYW5pZmVzdC53b3JrZmxvd3MsXG4gICAgICAgICAgICAuLi53b3JrZmxvd3NNYW5pZmVzdC53b3JrZmxvd3MsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBjbGFzc2VzOiB7XG4gICAgICAgICAgICAuLi5uZXh0U3RlcHNNYW5pZmVzdC5jbGFzc2VzLFxuICAgICAgICAgICAgLi4ud29ya2Zsb3dzTWFuaWZlc3QuY2xhc3NlcyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBob3RSZWJ1aWxkID0gYXN5bmMgKHJlZnJlc2hTdGVwUmVnaXN0cmF0aW9uczogYm9vbGVhbikgPT4ge1xuICAgICAgICAgIGlmIChyZWZyZXNoU3RlcFJlZ2lzdHJhdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChzdGVwc0N0eCkge1xuICAgICAgICAgICAgICBhd2FpdCBzdGVwc0N0eC5yZWJ1aWxkKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzdGVwc01hbmlmZXN0ID0gYXdhaXQgdGhpcy5jcmVhdGVTdGVwU291cmNlUmVnaXN0cmF0aW9uRmlsZSh7XG4gICAgICAgICAgICAgICAgaW5wdXRGaWxlczogb3B0aW9ucy5pbnB1dEZpbGVzLFxuICAgICAgICAgICAgICAgIG91dGZpbGU6IHN0ZXBzT3V0ZmlsZSxcbiAgICAgICAgICAgICAgICB0c2NvbmZpZ1BhdGgsXG4gICAgICAgICAgICAgICAgZGlzY292ZXJlZEVudHJpZXMsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHdvcmtmbG93UmVzdWx0ID0gYXdhaXQgd29ya2Zsb3dzQ3R4LmludGVyaW1CdW5kbGVDdHgucmVidWlsZCgpO1xuICAgICAgICAgIGNvbnN0IHdvcmtmbG93T3V0cHV0ID0gd29ya2Zsb3dSZXN1bHQub3V0cHV0RmlsZXM/LlswXT8udGV4dDtcbiAgICAgICAgICBpZiAoIXdvcmtmbG93T3V0cHV0KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICdJbnZhcmlhbnQ6IGV4cGVjdGVkIHdvcmtmbG93IG91dHB1dCBmcm9tIGhvdCByZWJ1aWxkJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB3b3JrZmxvd0ludGVyaW1CdW5kbGVUZXh0ID0gd29ya2Zsb3dPdXRwdXQ7XG4gICAgICAgICAgYXdhaXQgd29ya2Zsb3dzQ3R4LmJ1bmRsZUZpbmFsKHdvcmtmbG93T3V0cHV0KTtcbiAgICAgICAgICBhd2FpdCB3cml0ZU1hbmlmZXN0KG1lcmdlQ29tYmluZWRNYW5pZmVzdChzdGVwc01hbmlmZXN0KSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZnVsbFJlYnVpbGQgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5jbGVhckRpc2NvdmVyZWRFbnRyaWVzQ2FjaGUoKTtcbiAgICAgICAgICBjb25zdCBuZXdJbnB1dEZpbGVzID0gYXdhaXQgdGhpcy5nZXRJbnB1dEZpbGVzKCk7XG4gICAgICAgICAgb3B0aW9ucy5pbnB1dEZpbGVzID0gbmV3SW5wdXRGaWxlcztcblxuICAgICAgICAgIGF3YWl0IHN0ZXBzQ3R4Py5kaXNwb3NlKCk7XG4gICAgICAgICAgYXdhaXQgd29ya2Zsb3dzQ3R4LmludGVyaW1CdW5kbGVDdHguZGlzcG9zZSgpO1xuXG4gICAgICAgICAgY29uc3QgbmV3Q29tYmluZWQgPSBhd2FpdCB0aGlzLmJ1aWxkQ29tYmluZWRGdW5jdGlvbihvcHRpb25zKTtcbiAgICAgICAgICBzdGVwc0N0eCA9IG5ld0NvbWJpbmVkLnN0ZXBzQ29udGV4dDtcbiAgICAgICAgICBkaXNjb3ZlcmVkRW50cmllcyA9IG5ld0NvbWJpbmVkLmRpc2NvdmVyZWRFbnRyaWVzO1xuICAgICAgICAgIHN0ZXBzTWFuaWZlc3QgPSBuZXdDb21iaW5lZC5zdGVwc01hbmlmZXN0O1xuICAgICAgICAgIHdvcmtmbG93c01hbmlmZXN0ID0gbmV3Q29tYmluZWQud29ya2Zsb3dzTWFuaWZlc3Q7XG4gICAgICAgICAgd29ya2Zsb3dJbnRlcmltQnVuZGxlVGV4dCA9IG5ld0NvbWJpbmVkLndvcmtmbG93SW50ZXJpbUJ1bmRsZVRleHQ7XG5cbiAgICAgICAgICBpZiAoIW5ld0NvbWJpbmVkPy5pbnRlcmltQnVuZGxlQ3R4IHx8ICFuZXdDb21iaW5lZD8uYnVuZGxlRmluYWwpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgJ0ludmFyaWFudDogZXhwZWN0ZWQgd29ya2Zsb3dzIGJ1bmRsZSBjb250ZXh0IGFmdGVyIHJlYnVpbGQnXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB3b3JrZmxvd3NDdHggPSB7XG4gICAgICAgICAgICBpbnRlcmltQnVuZGxlQ3R4OiBuZXdDb21iaW5lZC5pbnRlcmltQnVuZGxlQ3R4LFxuICAgICAgICAgICAgYnVuZGxlRmluYWw6IG5ld0NvbWJpbmVkLmJ1bmRsZUZpbmFsLFxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBhd2FpdCB3cml0ZU1hbmlmZXN0KG5ld0NvbWJpbmVkLm1hbmlmZXN0KTtcbiAgICAgICAgICBhd2FpdCByZWZyZXNoU291cmNlU25hcHNob3RzKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgaXNXYXRjaGFibGVGaWxlID0gKHBhdGg6IHN0cmluZykgPT5cbiAgICAgICAgICB3YXRjaGFibGVFeHRlbnNpb25zLmhhcyhleHRuYW1lKHBhdGgpKTtcblxuICAgICAgICBjb25zdCByZWFkS25vd25GaWxlcyA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCBmaWxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgICAgIGNvbnN0IGFsaWFzZXMgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAgICAgICAgIGNvbnN0IHJlbGV2YW50RmlsZXMgPSBnZXRSZWxldmFudEZpbGVzKHtcbiAgICAgICAgICAgIGRpc2NvdmVyZWRFbnRyaWVzLFxuICAgICAgICAgICAgaW5wdXRGaWxlczogb3B0aW9ucy5pbnB1dEZpbGVzLFxuICAgICAgICAgICAgbm9ybWFsaXplUGF0aCxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGNvbnN0IGFkZEtub3duRmlsZSA9IGFzeW5jIChmaWxlUGF0aDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBsZXQgcmVhbEZpbGVQYXRoID0gZmlsZVBhdGg7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICByZWFsRmlsZVBhdGggPSBub3JtYWxpemVQYXRoKGF3YWl0IHJlYWxwYXRoKGZpbGVQYXRoKSk7XG4gICAgICAgICAgICB9IGNhdGNoIHt9XG5cbiAgICAgICAgICAgIGNvbnN0IGNhbm9uaWNhbFBhdGggPSByZWxldmFudEZpbGVzLmhhcyhyZWFsRmlsZVBhdGgpXG4gICAgICAgICAgICAgID8gcmVhbEZpbGVQYXRoXG4gICAgICAgICAgICAgIDogZmlsZVBhdGg7XG4gICAgICAgICAgICBmaWxlcy5hZGQoY2Fub25pY2FsUGF0aCk7XG4gICAgICAgICAgICBhbGlhc2VzLnNldChmaWxlUGF0aCwgY2Fub25pY2FsUGF0aCk7XG4gICAgICAgICAgICBhbGlhc2VzLnNldChyZWFsRmlsZVBhdGgsIGNhbm9uaWNhbFBhdGgpO1xuICAgICAgICAgICAgcmV0dXJuIGNhbm9uaWNhbFBhdGg7XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGNvbnN0IHZpc2l0ID0gYXN5bmMgKGRpcmVjdG9yeTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgICBsZXQgZGlyZW50czogRGlyZW50PHN0cmluZz5bXTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGRpcmVudHMgPSBhd2FpdCByZWFkZGlyKGRpcmVjdG9yeSwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pO1xuICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICAgIGRpcmVudHMubWFwKGFzeW5jIChkaXJlbnQpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaWxlUGF0aCA9IG5vcm1hbGl6ZVBhdGgoam9pbihkaXJlY3RvcnksIGRpcmVudC5uYW1lKSk7XG4gICAgICAgICAgICAgICAgaWYgKGhhc0lnbm9yZWRQYXRoRnJhZ21lbnQoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGRpcmVudC5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgICAgICAgICAgICBhd2FpdCB2aXNpdChmaWxlUGF0aCk7XG4gICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IHN0YXRzOiBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIHN0YXQ+PjtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgc3RhdHMgPSBhd2FpdCBzdGF0KGZpbGVQYXRoKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoc3RhdHMuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICAgICAgICAgICAgYXdhaXQgdmlzaXQoZmlsZVBhdGgpO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghc3RhdHMuaXNGaWxlKCkgfHwgIWlzV2F0Y2hhYmxlRmlsZShmaWxlUGF0aCkpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBhd2FpdCBhZGRLbm93bkZpbGUoZmlsZVBhdGgpO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgYXdhaXQgdmlzaXQodGhpcy5jb25maWcud29ya2luZ0Rpcik7XG4gICAgICAgICAgcmV0dXJuIHsgZmlsZXMsIGFsaWFzZXMsIGFkZEtub3duRmlsZSB9O1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IG1lcmdlRmlsZUNoYW5nZXMgPSAoXG4gICAgICAgICAgbGVmdDogRmlsZUNoYW5nZXMsXG4gICAgICAgICAgcmlnaHQ6IEZpbGVDaGFuZ2VzXG4gICAgICAgICk6IEZpbGVDaGFuZ2VzID0+ICh7XG4gICAgICAgICAgYWRkZWRGaWxlczogdW5pcXVlKFsuLi5sZWZ0LmFkZGVkRmlsZXMsIC4uLnJpZ2h0LmFkZGVkRmlsZXNdKSxcbiAgICAgICAgICBtb2RpZmllZEZpbGVzOiB1bmlxdWUoW1xuICAgICAgICAgICAgLi4ubGVmdC5tb2RpZmllZEZpbGVzLFxuICAgICAgICAgICAgLi4ucmlnaHQubW9kaWZpZWRGaWxlcyxcbiAgICAgICAgICBdKSxcbiAgICAgICAgICByZW1vdmVkRmlsZXM6IHVuaXF1ZShbLi4ubGVmdC5yZW1vdmVkRmlsZXMsIC4uLnJpZ2h0LnJlbW92ZWRGaWxlc10pLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB1bmlxdWUgPSAocGF0aHM6IHN0cmluZ1tdKSA9PiBbLi4ubmV3IFNldChwYXRocyldO1xuXG4gICAgICAgIGNvbnN0IGNsYXNzaWZ5RmlsZUNoYW5nZXMgPSAoe1xuICAgICAgICAgIGNoYW5nZWRGaWxlcyxcbiAgICAgICAgICBrbm93bkZpbGVzLFxuICAgICAgICAgIHJlbW92ZWRGaWxlcyxcbiAgICAgICAgfToge1xuICAgICAgICAgIGNoYW5nZWRGaWxlczogc3RyaW5nW107XG4gICAgICAgICAga25vd25GaWxlczogU2V0PHN0cmluZz47XG4gICAgICAgICAgcmVtb3ZlZEZpbGVzOiBzdHJpbmdbXTtcbiAgICAgICAgfSk6IEZpbGVDaGFuZ2VzID0+IHtcbiAgICAgICAgICBjb25zdCBhZGRlZEZpbGVzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICAgIGNvbnN0IG1vZGlmaWVkRmlsZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgdW5pcXVlKGNoYW5nZWRGaWxlcykpIHtcbiAgICAgICAgICAgIGlmIChrbm93bkZpbGVzLmhhcyhmaWxlKSkge1xuICAgICAgICAgICAgICBtb2RpZmllZEZpbGVzLnB1c2goZmlsZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBhZGRlZEZpbGVzLnB1c2goZmlsZSk7XG4gICAgICAgICAgICAgIGtub3duRmlsZXMuYWRkKGZpbGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGZvciAoY29uc3QgZmlsZSBvZiByZW1vdmVkRmlsZXMpIHtcbiAgICAgICAgICAgIGtub3duRmlsZXMuZGVsZXRlKGZpbGUpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhZGRlZEZpbGVzLFxuICAgICAgICAgICAgbW9kaWZpZWRGaWxlcyxcbiAgICAgICAgICAgIHJlbW92ZWRGaWxlczogdW5pcXVlKHJlbW92ZWRGaWxlcyksXG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBoYXNGaWxlQ2hhbmdlcyA9ICh7XG4gICAgICAgICAgYWRkZWRGaWxlcyxcbiAgICAgICAgICBtb2RpZmllZEZpbGVzLFxuICAgICAgICAgIHJlbW92ZWRGaWxlcyxcbiAgICAgICAgfTogRmlsZUNoYW5nZXMpID0+XG4gICAgICAgICAgYWRkZWRGaWxlcy5sZW5ndGggPiAwIHx8XG4gICAgICAgICAgbW9kaWZpZWRGaWxlcy5sZW5ndGggPiAwIHx8XG4gICAgICAgICAgcmVtb3ZlZEZpbGVzLmxlbmd0aCA+IDA7XG4gICAgICAgIGNvbnN0IHN0ZXBFeGVjdXRpb25GaWxlc0NoYW5nZWQgPSAoZmlsZUNoYW5nZXM6IEZpbGVDaGFuZ2VzKSA9PiB7XG4gICAgICAgICAgY29uc3Qgc3RlcEVudHJ5RmlsZXMgPSBbLi4uZGlzY292ZXJlZEVudHJpZXMuZGlzY292ZXJlZFN0ZXBzXS5tYXAoXG4gICAgICAgICAgICBub3JtYWxpemVQYXRoXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoc3RlcEVudHJ5RmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGNoYW5nZWRGaWxlcyA9IHVuaXF1ZShbXG4gICAgICAgICAgICAuLi5maWxlQ2hhbmdlcy5tb2RpZmllZEZpbGVzLFxuICAgICAgICAgICAgLi4uZmlsZUNoYW5nZXMuYWRkZWRGaWxlcyxcbiAgICAgICAgICAgIC4uLmZpbGVDaGFuZ2VzLnJlbW92ZWRGaWxlcyxcbiAgICAgICAgICBdKS5tYXAobm9ybWFsaXplUGF0aCk7XG5cbiAgICAgICAgICByZXR1cm4gY2hhbmdlZEZpbGVzLnNvbWUoXG4gICAgICAgICAgICAoY2hhbmdlZEZpbGUpID0+XG4gICAgICAgICAgICAgIHN0ZXBFbnRyeUZpbGVzLmluY2x1ZGVzKGNoYW5nZWRGaWxlKSB8fFxuICAgICAgICAgICAgICBzdGVwRW50cnlGaWxlcy5zb21lKChzdGVwRmlsZSkgPT5cbiAgICAgICAgICAgICAgICBwYXJlbnRIYXNDaGlsZChzdGVwRmlsZSwgY2hhbmdlZEZpbGUpXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBsb2dEZXZIbXIgPSAoLi4uYXJnczogdW5rbm93bltdKSA9PiB7XG4gICAgICAgICAgaWYgKHByb2Nlc3MuZW52LldPUktGTE9XX0RFVl9ITVJfTE9HUyA9PT0gJzEnKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyguLi5hcmdzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgYXdhaXQgcmVmcmVzaFNvdXJjZVNuYXBzaG90cygpO1xuICAgICAgICBsZXQge1xuICAgICAgICAgIGZpbGVzOiBrbm93bkZpbGVzLFxuICAgICAgICAgIGFsaWFzZXM6IGtub3duRmlsZUFsaWFzZXMsXG4gICAgICAgICAgYWRkS25vd25GaWxlOiByZW1lbWJlcktub3duRmlsZSxcbiAgICAgICAgfSA9IGF3YWl0IHJlYWRLbm93bkZpbGVzKCk7XG5cbiAgICAgICAgY29uc3QgcmVmcmVzaEtub3duRmlsZXMgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgbmV4dEtub3duID0gYXdhaXQgcmVhZEtub3duRmlsZXMoKTtcbiAgICAgICAgICBrbm93bkZpbGVzID0gbmV4dEtub3duLmZpbGVzO1xuICAgICAgICAgIGtub3duRmlsZUFsaWFzZXMgPSBuZXh0S25vd24uYWxpYXNlcztcbiAgICAgICAgICByZW1lbWJlcktub3duRmlsZSA9IG5leHRLbm93bi5hZGRLbm93bkZpbGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgcHJvY2Vzc0ZpbGVDaGFuZ2VzID0gYXN5bmMgKGZpbGVDaGFuZ2VzOiBGaWxlQ2hhbmdlcykgPT4ge1xuICAgICAgICAgIGlmICghaGFzRmlsZUNoYW5nZXMoZmlsZUNoYW5nZXMpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZGVjaXNpb24gPSBhd2FpdCBjbGFzc2lmeVJlYnVpbGQoe1xuICAgICAgICAgICAgZGlzY292ZXJlZEVudHJpZXMsXG4gICAgICAgICAgICBmaWxlQ2hhbmdlcyxcbiAgICAgICAgICAgIGlucHV0RmlsZXM6IG9wdGlvbnMuaW5wdXRGaWxlcyxcbiAgICAgICAgICAgIG5vcm1hbGl6ZVBhdGgsXG4gICAgICAgICAgICBwYXJlbnRIYXNDaGlsZCxcbiAgICAgICAgICAgIHJlYWRTbmFwc2hvdDogcmVhZFNvdXJjZVNuYXBzaG90LFxuICAgICAgICAgICAgc291cmNlU25hcHNob3RzLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmIChkZWNpc2lvbi5raW5kID09PSAnbm9uZScpIHtcbiAgICAgICAgICAgIGxvZ0Rldkhtcignd29ya2Zsb3cgZGV2IGhtcjogc2tpcCcpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBbZmlsZSwgc25hcHNob3RdIG9mIGRlY2lzaW9uLnNuYXBzaG90cyB8fCBbXSkge1xuICAgICAgICAgICAgICBzb3VyY2VTbmFwc2hvdHMuc2V0KGZpbGUsIHNuYXBzaG90KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgIXN0ZXBzQ3R4ICYmXG4gICAgICAgICAgICAgIHdvcmtmbG93SW50ZXJpbUJ1bmRsZVRleHQgJiZcbiAgICAgICAgICAgICAgc3RlcEV4ZWN1dGlvbkZpbGVzQ2hhbmdlZChmaWxlQ2hhbmdlcylcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAvLyBTb3VyY2Ugc3RlcCByZWdpc3RyYXRpb25zIGtlZXAgc3RhYmxlIGltcG9ydHMsIHNvIFR1cmJvcGFja1xuICAgICAgICAgICAgICAvLyBjYW4gbGVhdmUgdGhlIGdlbmVyYXRlZCBmbG93IHJvdXRlIGNhY2hlZCBhZnRlciBhXG4gICAgICAgICAgICAgIC8vIHN0ZXAtYm9keS1vbmx5IGVkaXQuIFJlZnJlc2ggdGhlIHJvdXRlIHdyYXBwZXIgd2l0aG91dFxuICAgICAgICAgICAgICAvLyByZWRpc2NvdmVyaW5nIGVudHJpZXMgb3IgcmVidWlsZGluZyB0aGUgd29ya2Zsb3cgVk0uXG4gICAgICAgICAgICAgIGF3YWl0IHdvcmtmbG93c0N0eC5idW5kbGVGaW5hbCh3b3JrZmxvd0ludGVyaW1CdW5kbGVUZXh0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGRlY2lzaW9uLmtpbmQgPT09ICdmdWxsJykge1xuICAgICAgICAgICAgbG9nRGV2SG1yKCd3b3JrZmxvdyBkZXYgaG1yOiBmdWxsIHJlZGlzY292ZXJ5Jyk7XG4gICAgICAgICAgICBhd2FpdCBmdWxsUmVidWlsZCgpO1xuICAgICAgICAgICAgYXdhaXQgcmVmcmVzaEtub3duRmlsZXMoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsb2dEZXZIbXIoXG4gICAgICAgICAgICBgd29ya2Zsb3cgZGV2IGhtcjogaG90IHJlYnVpbGQke2RlY2lzaW9uLnJlZnJlc2hTdGVwUmVnaXN0cmF0aW9ucyA/ICcgd2l0aCBzdGVwIHJlZ2lzdHJhdGlvbiByZWZyZXNoJyA6ICcnfWBcbiAgICAgICAgICApO1xuICAgICAgICAgIGF3YWl0IGhvdFJlYnVpbGQoZGVjaXNpb24ucmVmcmVzaFN0ZXBSZWdpc3RyYXRpb25zKTtcbiAgICAgICAgICBmb3IgKGNvbnN0IFtmaWxlLCBzbmFwc2hvdF0gb2YgZGVjaXNpb24uc25hcHNob3RzKSB7XG4gICAgICAgICAgICBzb3VyY2VTbmFwc2hvdHMuc2V0KGZpbGUsIHNuYXBzaG90KTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgbGV0IHBlbmRpbmdGaWxlQ2hhbmdlczogRmlsZUNoYW5nZXMgPSB7XG4gICAgICAgICAgYWRkZWRGaWxlczogW10sXG4gICAgICAgICAgbW9kaWZpZWRGaWxlczogW10sXG4gICAgICAgICAgcmVtb3ZlZEZpbGVzOiBbXSxcbiAgICAgICAgfTtcbiAgICAgICAgbGV0IGZsdXNoVGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgdW5kZWZpbmVkO1xuXG4gICAgICAgIGNvbnN0IHNjaGVkdWxlRmlsZUNoYW5nZXMgPSAoZmlsZUNoYW5nZXM6IEZpbGVDaGFuZ2VzKSA9PiB7XG4gICAgICAgICAgcGVuZGluZ0ZpbGVDaGFuZ2VzID0gbWVyZ2VGaWxlQ2hhbmdlcyhcbiAgICAgICAgICAgIHBlbmRpbmdGaWxlQ2hhbmdlcyxcbiAgICAgICAgICAgIGZpbGVDaGFuZ2VzXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoZmx1c2hUaW1lcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmbHVzaFRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmaWxlQ2hhbmdlcyA9IHBlbmRpbmdGaWxlQ2hhbmdlcztcbiAgICAgICAgICAgIHBlbmRpbmdGaWxlQ2hhbmdlcyA9IHtcbiAgICAgICAgICAgICAgYWRkZWRGaWxlczogW10sXG4gICAgICAgICAgICAgIG1vZGlmaWVkRmlsZXM6IFtdLFxuICAgICAgICAgICAgICByZW1vdmVkRmlsZXM6IFtdLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZsdXNoVGltZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBlbnF1ZXVlKCgpID0+IHByb2Nlc3NGaWxlQ2hhbmdlcyhmaWxlQ2hhbmdlcykpO1xuICAgICAgICAgIH0sIDEwKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCByZXNvbHZlRXhpc3RpbmdFdmVudFBhdGggPSBhc3luYyAocGF0aG5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gbm9ybWFsaXplUGF0aChwYXRobmFtZSk7XG4gICAgICAgICAgaWYgKCFpc1dhdGNoYWJsZUZpbGUobm9ybWFsaXplZFBhdGgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3Qga25vd25QYXRoID0ga25vd25GaWxlQWxpYXNlcy5nZXQobm9ybWFsaXplZFBhdGgpO1xuICAgICAgICAgIGlmIChrbm93blBhdGgpIHtcbiAgICAgICAgICAgIHJldHVybiBrbm93blBhdGg7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlYWxGaWxlUGF0aCA9IG5vcm1hbGl6ZVBhdGgoYXdhaXQgcmVhbHBhdGgobm9ybWFsaXplZFBhdGgpKTtcbiAgICAgICAgICAgIHJldHVybiBrbm93bkZpbGVBbGlhc2VzLmdldChyZWFsRmlsZVBhdGgpID8/IG5vcm1hbGl6ZWRQYXRoO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRQYXRoO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBoYW5kbGVGaWxlQWRkZWQgPSBhc3luYyAocGF0aG5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gbm9ybWFsaXplUGF0aChwYXRobmFtZSk7XG4gICAgICAgICAgaWYgKCFpc1dhdGNoYWJsZUZpbGUobm9ybWFsaXplZFBhdGgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZXhpc3RpbmdQYXRoID0gYXdhaXQgcmVzb2x2ZUV4aXN0aW5nRXZlbnRQYXRoKG5vcm1hbGl6ZWRQYXRoKTtcbiAgICAgICAgICBjb25zdCB3YXNLbm93biA9IGV4aXN0aW5nUGF0aCA/IGtub3duRmlsZXMuaGFzKGV4aXN0aW5nUGF0aCkgOiBmYWxzZTtcbiAgICAgICAgICBjb25zdCBjYW5vbmljYWxQYXRoID0gYXdhaXQgcmVtZW1iZXJLbm93bkZpbGUobm9ybWFsaXplZFBhdGgpO1xuICAgICAgICAgIGtub3duRmlsZXMuYWRkKGNhbm9uaWNhbFBhdGgpO1xuICAgICAgICAgIHNjaGVkdWxlRmlsZUNoYW5nZXMoe1xuICAgICAgICAgICAgYWRkZWRGaWxlczogd2FzS25vd24gPyBbXSA6IFtjYW5vbmljYWxQYXRoXSxcbiAgICAgICAgICAgIG1vZGlmaWVkRmlsZXM6IHdhc0tub3duID8gW2Nhbm9uaWNhbFBhdGhdIDogW10sXG4gICAgICAgICAgICByZW1vdmVkRmlsZXM6IFtdLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGhhbmRsZUZpbGVDaGFuZ2VkID0gYXN5bmMgKHBhdGhuYW1lOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICBjb25zdCBjYW5vbmljYWxQYXRoID0gYXdhaXQgcmVzb2x2ZUV4aXN0aW5nRXZlbnRQYXRoKHBhdGhuYW1lKTtcbiAgICAgICAgICBpZiAoIWNhbm9uaWNhbFBhdGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBmaWxlQ2hhbmdlcyA9IGNsYXNzaWZ5RmlsZUNoYW5nZXMoe1xuICAgICAgICAgICAgY2hhbmdlZEZpbGVzOiBbY2Fub25pY2FsUGF0aF0sXG4gICAgICAgICAgICBrbm93bkZpbGVzLFxuICAgICAgICAgICAgcmVtb3ZlZEZpbGVzOiBbXSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpZiAoIWtub3duRmlsZUFsaWFzZXMuaGFzKGNhbm9uaWNhbFBhdGgpKSB7XG4gICAgICAgICAgICBhd2FpdCByZW1lbWJlcktub3duRmlsZShjYW5vbmljYWxQYXRoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgc2NoZWR1bGVGaWxlQ2hhbmdlcyhmaWxlQ2hhbmdlcyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgaGFuZGxlRmlsZVJlbW92ZWQgPSAocGF0aG5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gbm9ybWFsaXplUGF0aChwYXRobmFtZSk7XG4gICAgICAgICAgaWYgKCFpc1dhdGNoYWJsZUZpbGUobm9ybWFsaXplZFBhdGgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgY2Fub25pY2FsUGF0aCA9XG4gICAgICAgICAgICBrbm93bkZpbGVBbGlhc2VzLmdldChub3JtYWxpemVkUGF0aCkgPz8gbm9ybWFsaXplZFBhdGg7XG4gICAgICAgICAgY29uc3QgZmlsZUNoYW5nZXMgPSBjbGFzc2lmeUZpbGVDaGFuZ2VzKHtcbiAgICAgICAgICAgIGNoYW5nZWRGaWxlczogW10sXG4gICAgICAgICAgICBrbm93bkZpbGVzLFxuICAgICAgICAgICAgcmVtb3ZlZEZpbGVzOiBbY2Fub25pY2FsUGF0aF0sXG4gICAgICAgICAgfSk7XG4gICAgICAgICAga25vd25GaWxlQWxpYXNlcy5kZWxldGUobm9ybWFsaXplZFBhdGgpO1xuICAgICAgICAgIHNjaGVkdWxlRmlsZUNoYW5nZXMoZmlsZUNoYW5nZXMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHdhdGNoZXIgPSBjaG9raWRhci53YXRjaCh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCB7XG4gICAgICAgICAgaWdub3JlSW5pdGlhbDogdHJ1ZSxcbiAgICAgICAgICBmb2xsb3dTeW1saW5rczogdHJ1ZSxcbiAgICAgICAgICBpZ25vcmVkOiAocGF0aG5hbWUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gbm9ybWFsaXplUGF0aChTdHJpbmcocGF0aG5hbWUpKTtcbiAgICAgICAgICAgIGNvbnN0IGV4dGVuc2lvbiA9IGV4dG5hbWUobm9ybWFsaXplZFBhdGgpO1xuICAgICAgICAgICAgaWYgKGV4dGVuc2lvbiAmJiAhd2F0Y2hhYmxlRXh0ZW5zaW9ucy5oYXMoZXh0ZW5zaW9uKSkge1xuICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBoYXNJZ25vcmVkUGF0aEZyYWdtZW50KG5vcm1hbGl6ZWRQYXRoKTtcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICB3YXRjaGVyLm9uKCdhZGQnLCAocGF0aG5hbWUpID0+IHtcbiAgICAgICAgICB2b2lkIGhhbmRsZUZpbGVBZGRlZChwYXRobmFtZSk7XG4gICAgICAgIH0pO1xuICAgICAgICB3YXRjaGVyLm9uKCdjaGFuZ2UnLCAocGF0aG5hbWUpID0+IHtcbiAgICAgICAgICB2b2lkIGhhbmRsZUZpbGVDaGFuZ2VkKHBhdGhuYW1lKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHdhdGNoZXIub24oJ3VubGluaycsIChwYXRobmFtZSkgPT4ge1xuICAgICAgICAgIGhhbmRsZUZpbGVSZW1vdmVkKHBhdGhuYW1lKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHdhdGNoZXIub24oJ2Vycm9yJywgKGVycm9yKSA9PiB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignV29ya2Zsb3cgZGV2IHdhdGNoZXIgZXJyb3InLCBlcnJvcik7XG4gICAgICAgIH0pO1xuICAgICAgICB3YXRjaGVyLm9uKCdyZWFkeScsICgpID0+IHtcbiAgICAgICAgICBsb2dEZXZIbXIoJ3dvcmtmbG93IGRldiBobXI6IHJlYWR5Jyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBhc3luYyBnZXRJbnB1dEZpbGVzKCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgIGNvbnN0IGlucHV0RmlsZXMgPSBhd2FpdCBzdXBlci5nZXRJbnB1dEZpbGVzKCk7XG4gICAgICByZXR1cm4gaW5wdXRGaWxlcy5maWx0ZXIoKGZpbGUpID0+IHtcbiAgICAgICAgY29uc3QgZW50cnkgPSByZWxhdGl2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCBmaWxlKS5yZXBsYWNlQWxsKFxuICAgICAgICAgICdcXFxcJyxcbiAgICAgICAgICAnLydcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBNYXRjaCBBcHAgUm91dGVyIHJvdXRlLCBwYWdlLCBhbmQgbGF5b3V0IGVudHJ5cG9pbnRzIGluIGFwcC8gb3Igc3JjL2FwcC8uXG4gICAgICAgIGlmICgvXig/OmFwcHxzcmNcXC9hcHApXFwvKD86LipcXC8pPyg/OnJvdXRlfHBhZ2V8bGF5b3V0KVxcLi8udGVzdChlbnRyeSkpIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1hdGNoIGV2ZXJ5IFBhZ2VzIFJvdXRlciBlbnRyeXBvaW50IGluIHBhZ2VzLyBvciBzcmMvcGFnZXMvLlxuICAgICAgICBpZiAoL14oPzpwYWdlc3xzcmNcXC9wYWdlcylcXC8vLnRlc3QoZW50cnkpKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBNYXRjaCBOZXh0LmpzIHJvb3QgZW50cnlwb2ludHMgYXQgdGhlIHByb2plY3Qgcm9vdCBvciB1bmRlciBzcmMvLlxuICAgICAgICByZXR1cm4gWydpbnN0cnVtZW50YXRpb24nLCAnbWlkZGxld2FyZScsICdwcm94eSddLnNvbWUoKG5hbWUpID0+XG4gICAgICAgICAgdGhpcy5jb25maWcucGFnZUV4dGVuc2lvbnMuc29tZShcbiAgICAgICAgICAgIChleHRlbnNpb24pID0+XG4gICAgICAgICAgICAgIGVudHJ5ID09PSBgJHtuYW1lfS4ke2V4dGVuc2lvbn1gIHx8XG4gICAgICAgICAgICAgIGVudHJ5ID09PSBgc3JjLyR7bmFtZX0uJHtleHRlbnNpb259YFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgd3JpdGVGdW5jdGlvbnNDb25maWcob3V0cHV0RGlyOiBzdHJpbmcpIHtcbiAgICAgIC8vIHdlIGRvbid0IHJ1biB0aGlzIGluIGRldmVsb3BtZW50IG1vZGUgYXMgaXQncyBub3QgbmVlZGVkXG4gICAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdkZXZlbG9wbWVudCcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBWMiBjb21iaW5lZCBjb25maWc6IHNpbmdsZSB0cmlnZ2VyIGhhbmRsZXMgYm90aCB3b3JrZmxvdyBhbmQgc3RlcCBleGVjdXRpb24uXG4gICAgICAvLyBUaGUgc3RlcCByb3V0ZSBubyBsb25nZXIgbmVlZHMgaXRzIG93biB0cmlnZ2VyIHNpbmNlIHN0ZXBzIGFyZSBleGVjdXRlZFxuICAgICAgLy8gaW5saW5lIGJ5IHRoZSBjb21iaW5lZCBoYW5kbGVyIG9yIHF1ZXVlZCBiYWNrIHRvIF9fd2tmX3dvcmtmbG93Xyogd2l0aCBzdGVwSWQuXG4gICAgICBjb25zdCBnZW5lcmF0ZWRDb25maWcgPSB7XG4gICAgICAgIHZlcnNpb246ICcwJyxcbiAgICAgICAgd29ya2Zsb3dzOiB7XG4gICAgICAgICAgbWF4RHVyYXRpb246ICdtYXgnLFxuICAgICAgICAgIGV4cGVyaW1lbnRhbFRyaWdnZXJzOiBbV09SS0ZMT1dfUVVFVUVfVFJJR0dFUl0sXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCB3cml0ZUZpbGUoXG4gICAgICAgIGpvaW4ob3V0cHV0RGlyLCAnLndlbGwta25vd24vd29ya2Zsb3cvdjEvY29uZmlnLmpzb24nKSxcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoZ2VuZXJhdGVkQ29uZmlnLCBudWxsLCAyKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBWMjogQnVpbGQgY29tYmluZWQgcm91dGUgdGhhdCBoYW5kbGVzIGJvdGggd29ya2Zsb3cgYW5kIHN0ZXAgZXhlY3V0aW9uLlxuICAgICAqL1xuICAgIHByaXZhdGUgYXN5bmMgYnVpbGRDb21iaW5lZEZ1bmN0aW9uKHtcbiAgICAgIGlucHV0RmlsZXMsXG4gICAgICB3b3JrZmxvd0dlbmVyYXRlZERpcixcbiAgICAgIHRzY29uZmlnUGF0aCxcbiAgICB9OiB7XG4gICAgICBpbnB1dEZpbGVzOiBzdHJpbmdbXTtcbiAgICAgIHdvcmtmbG93R2VuZXJhdGVkRGlyOiBzdHJpbmc7XG4gICAgICB0c2NvbmZpZ1BhdGg/OiBzdHJpbmc7XG4gICAgfSkge1xuICAgICAgY29uc3QgZmxvd1JvdXRlRGlyID0gam9pbih3b3JrZmxvd0dlbmVyYXRlZERpciwgJ2Zsb3cnKTtcbiAgICAgIGF3YWl0IG1rZGlyKGZsb3dSb3V0ZURpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNyZWF0ZUNvbWJpbmVkQnVuZGxlKHtcbiAgICAgICAgZm9ybWF0OiAnZXNtJyxcbiAgICAgICAgaW5wdXRGaWxlcyxcbiAgICAgICAgc3RlcHNPdXRmaWxlOiBqb2luKGZsb3dSb3V0ZURpciwgJ19fc3RlcF9yZWdpc3RyYXRpb25zLmpzJyksXG4gICAgICAgIGZsb3dPdXRmaWxlOiBqb2luKGZsb3dSb3V0ZURpciwgJ3JvdXRlLmpzJyksXG4gICAgICAgIGJ1bmRsZUZpbmFsT3V0cHV0OiBmYWxzZSxcbiAgICAgICAgZXh0ZXJuYWxpemVOb25TdGVwczogdHJ1ZSxcbiAgICAgICAgc291cmNlU3RlcFJlZ2lzdHJhdGlvbkltcG9ydHM6IHRydWUsXG4gICAgICAgIHRzY29uZmlnUGF0aCxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgYnVpbGRXZWJob29rUm91dGUoe1xuICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXIsXG4gICAgfToge1xuICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXI6IHN0cmluZztcbiAgICB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBjb25zdCB3ZWJob29rUm91dGVGaWxlID0gam9pbihcbiAgICAgICAgd29ya2Zsb3dHZW5lcmF0ZWREaXIsXG4gICAgICAgICd3ZWJob29rL1t0b2tlbl0vcm91dGUuanMnXG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy5jcmVhdGVXZWJob29rQnVuZGxlKHtcbiAgICAgICAgb3V0ZmlsZTogd2ViaG9va1JvdXRlRmlsZSxcbiAgICAgICAgYnVuZGxlOiBmYWxzZSwgLy8gTmV4dC5qcyBkb2Vzbid0IG5lZWQgYnVuZGxpbmdcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZmluZEFwcERpcmVjdG9yeSgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgY29uc3QgYXBwRGlyID0gcmVzb2x2ZSh0aGlzLmNvbmZpZy53b3JraW5nRGlyLCAnYXBwJyk7XG4gICAgICBjb25zdCBzcmNBcHBEaXIgPSByZXNvbHZlKHRoaXMuY29uZmlnLndvcmtpbmdEaXIsICdzcmMvYXBwJyk7XG4gICAgICBjb25zdCBwYWdlc0RpciA9IHJlc29sdmUodGhpcy5jb25maWcud29ya2luZ0RpciwgJ3BhZ2VzJyk7XG4gICAgICBjb25zdCBzcmNQYWdlc0RpciA9IHJlc29sdmUodGhpcy5jb25maWcud29ya2luZ0RpciwgJ3NyYy9wYWdlcycpO1xuXG4gICAgICAvLyBIZWxwZXIgdG8gY2hlY2sgaWYgYSBwYXRoIGV4aXN0cyBhbmQgaXMgYSBkaXJlY3RvcnlcbiAgICAgIGNvbnN0IGlzRGlyZWN0b3J5ID0gYXN5bmMgKHBhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGFjY2VzcyhwYXRoLCBjb25zdGFudHMuRl9PSyk7XG4gICAgICAgICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBzdGF0KHBhdGgpO1xuICAgICAgICAgIGlmICghc3RhdHMuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQYXRoIGV4aXN0cyBidXQgaXMgbm90IGEgZGlyZWN0b3J5OiAke3BhdGh9YCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBFcnJvciAmJiBlLm1lc3NhZ2UuaW5jbHVkZXMoJ25vdCBhIGRpcmVjdG9yeScpKSB7XG4gICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIC8vIENoZWNrIGlmIGFwcCBkaXJlY3RvcnkgZXhpc3RzXG4gICAgICBpZiAoYXdhaXQgaXNEaXJlY3RvcnkoYXBwRGlyKSkge1xuICAgICAgICByZXR1cm4gYXBwRGlyO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBpZiBzcmMvYXBwIGRpcmVjdG9yeSBleGlzdHNcbiAgICAgIGlmIChhd2FpdCBpc0RpcmVjdG9yeShzcmNBcHBEaXIpKSB7XG4gICAgICAgIHJldHVybiBzcmNBcHBEaXI7XG4gICAgICB9XG5cbiAgICAgIC8vIElmIG5vIGFwcCBkaXJlY3RvcnkgZXhpc3RzLCBjaGVjayBmb3IgcGFnZXMgZGlyZWN0b3J5IGFuZCBjcmVhdGUgYXBwIG5leHQgdG8gaXRcbiAgICAgIGlmIChhd2FpdCBpc0RpcmVjdG9yeShwYWdlc0RpcikpIHtcbiAgICAgICAgLy8gQ3JlYXRlIGFwcCBkaXJlY3RvcnkgbmV4dCB0byBwYWdlcyBkaXJlY3RvcnlcbiAgICAgICAgYXdhaXQgbWtkaXIoYXBwRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgcmV0dXJuIGFwcERpcjtcbiAgICAgIH1cblxuICAgICAgaWYgKGF3YWl0IGlzRGlyZWN0b3J5KHNyY1BhZ2VzRGlyKSkge1xuICAgICAgICAvLyBDcmVhdGUgc3JjL2FwcCBkaXJlY3RvcnkgbmV4dCB0byBzcmMvcGFnZXMgZGlyZWN0b3J5XG4gICAgICAgIGF3YWl0IG1rZGlyKHNyY0FwcERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICAgIHJldHVybiBzcmNBcHBEaXI7XG4gICAgICB9XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ0NvdWxkIG5vdCBmaW5kIE5leHQuanMgYXBwIG9yIHBhZ2VzIGRpcmVjdG9yeS4gRXhwZWN0ZWQgb25lIG9mOiBcImFwcFwiLCBcInNyYy9hcHBcIiwgXCJwYWdlc1wiLCBvciBcInNyYy9wYWdlc1wiIHRvIGV4aXN0LidcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgQ2FjaGVkTmV4dEJ1aWxkZXJFYWdlciA9IE5leHRCdWlsZGVyO1xuICByZXR1cm4gTmV4dEJ1aWxkZXI7XG59XG4iXX0=
|