xpine 0.0.3 → 0.0.5
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/index.js +659 -0
- package/dist/src/scripts/xpine-build.js +421 -0
- package/dist/src/scripts/xpine-dev.js +482 -0
- package/dist/src/static/dev-server.js +10 -0
- package/dist/src/static/spa.js +152 -0
- package/index.ts +5 -5
- package/package.json +3 -2
- package/src/runDevServer.ts +2 -2
- package/src/scripts/build-module.ts +1 -1
- package/src/scripts/build.ts +1 -1
- package/src/scripts/xpine-build.ts +1 -1
- package/src/scripts/xpine-dev.ts +1 -1
- package/src/util/get-config.ts +1 -1
- package/src/util/require.ts +1 -1
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/scripts/build.ts
|
|
4
|
+
import path3 from "path";
|
|
5
|
+
import fs2 from "fs-extra";
|
|
6
|
+
import { build } from "esbuild";
|
|
7
|
+
import builtinModules from "builtin-modules";
|
|
8
|
+
import ts2 from "typescript";
|
|
9
|
+
|
|
10
|
+
// src/build/typescript-builder.ts
|
|
11
|
+
import ts from "typescript";
|
|
12
|
+
import fs from "fs-extra";
|
|
13
|
+
import path from "path";
|
|
14
|
+
function findDataAttributesAndFunctions(node, sourceFile, foundDataAttributes = [], foundFunctions = []) {
|
|
15
|
+
if (node.kind === ts.SyntaxKind.JsxAttribute) {
|
|
16
|
+
const attribute = getAttributeValuePair(node, sourceFile);
|
|
17
|
+
if (attribute?.[0] === "x-data" && attribute?.[1]) {
|
|
18
|
+
foundDataAttributes.push(attribute[1].replace(/[^a-zA-Z0-9]/g, ""));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (node.kind === ts.SyntaxKind.SourceFile) {
|
|
22
|
+
node.forEachChild((child) => {
|
|
23
|
+
if ([ts.SyntaxKind.FunctionDeclaration, ts.SyntaxKind.VariableDeclaration].includes(child.kind)) {
|
|
24
|
+
const functions = getFunctionDeclarationValue(child, sourceFile);
|
|
25
|
+
foundFunctions.push(functions);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
node.forEachChild((child) => {
|
|
30
|
+
findDataAttributesAndFunctions(child, sourceFile, foundDataAttributes, foundFunctions);
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
foundDataAttributes,
|
|
34
|
+
foundFunctions
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function getAttributeValuePair(node, sourceFile) {
|
|
38
|
+
const result = [];
|
|
39
|
+
node.forEachChild((child) => {
|
|
40
|
+
result.push(child.getText(sourceFile));
|
|
41
|
+
});
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
function getFunctionDeclarationValue(node, sourceFile) {
|
|
45
|
+
const result = {
|
|
46
|
+
name: null,
|
|
47
|
+
isDefaultExport: false,
|
|
48
|
+
hasExport: false
|
|
49
|
+
};
|
|
50
|
+
node.forEachChild((child) => {
|
|
51
|
+
if (child.kind === ts.SyntaxKind.ExportKeyword) {
|
|
52
|
+
result.hasExport = true;
|
|
53
|
+
}
|
|
54
|
+
if (child.kind === ts.SyntaxKind.DefaultKeyword) {
|
|
55
|
+
result.isDefaultExport = true;
|
|
56
|
+
}
|
|
57
|
+
if (child.kind === ts.SyntaxKind.Identifier) {
|
|
58
|
+
result.name = child.getText(sourceFile);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
function convertEntryPointsToSingleFile(entryPoints, tempWritePath) {
|
|
64
|
+
fs.writeFileSync(
|
|
65
|
+
tempWritePath,
|
|
66
|
+
entryPoints.map((entry) => `import "${entry}"`).join(";\n")
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
function removeClientScriptInTSXFile(pathName) {
|
|
70
|
+
const content = fs.readFileSync(pathName, "utf-8");
|
|
71
|
+
const source = ts.createSourceFile(
|
|
72
|
+
pathName,
|
|
73
|
+
content,
|
|
74
|
+
ts.ScriptTarget.Latest
|
|
75
|
+
);
|
|
76
|
+
let toRemoveFrom;
|
|
77
|
+
let clientDataStart;
|
|
78
|
+
const clientImportsToHoist = [];
|
|
79
|
+
const clientImportsToReplace = [];
|
|
80
|
+
source.forEachChild((child) => {
|
|
81
|
+
if (child.kind === ts.SyntaxKind.ExpressionStatement) {
|
|
82
|
+
const text = child.getText(source);
|
|
83
|
+
if (text.startsWith("<script")) {
|
|
84
|
+
toRemoveFrom = child.pos;
|
|
85
|
+
clientDataStart = child.end;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (child.kind === ts.SyntaxKind.ImportDeclaration && child.pos >= clientDataStart) {
|
|
89
|
+
const text = child.getText(source);
|
|
90
|
+
child.forEachChild((child2) => {
|
|
91
|
+
if (child2.kind === ts.SyntaxKind.StringLiteral) {
|
|
92
|
+
const text2 = child2.getText(source);
|
|
93
|
+
const importPath = text2.replace(/[\"\']/g, "");
|
|
94
|
+
const isRelativeImport = importPath.startsWith(".") || importPath.startsWith("/");
|
|
95
|
+
if (!isRelativeImport) return;
|
|
96
|
+
clientImportsToReplace.push({
|
|
97
|
+
old: importPath,
|
|
98
|
+
new: path.join(path.dirname(pathName), importPath)
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
clientImportsToHoist.push(text);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
let clientContent = !isNaN(clientDataStart) ? content.slice(clientDataStart) : "";
|
|
106
|
+
for (const clientImport of clientImportsToReplace) {
|
|
107
|
+
clientContent = clientContent.replace(clientImport.old, clientImport.new);
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
content: !isNaN(toRemoveFrom) ? clientImportsToHoist.join("\n") + content.slice(0, toRemoveFrom) : content,
|
|
111
|
+
clientContent,
|
|
112
|
+
fullContent: content,
|
|
113
|
+
toRemoveFrom,
|
|
114
|
+
clientDataStart
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/scripts/build.ts
|
|
119
|
+
import { globSync } from "glob";
|
|
120
|
+
import postcss from "postcss";
|
|
121
|
+
import tailwindPostcss from "@tailwindcss/postcss";
|
|
122
|
+
|
|
123
|
+
// src/util/get-config.ts
|
|
124
|
+
import path2 from "path";
|
|
125
|
+
|
|
126
|
+
// src/util/require.ts
|
|
127
|
+
import { createRequire } from "module";
|
|
128
|
+
var require2 = createRequire(import.meta.url);
|
|
129
|
+
var require_default = require2;
|
|
130
|
+
|
|
131
|
+
// src/util/get-config.ts
|
|
132
|
+
var rootDir = process.cwd();
|
|
133
|
+
function fromRoot(pathName) {
|
|
134
|
+
if (!pathName) return rootDir;
|
|
135
|
+
return path2.join(rootDir, pathName);
|
|
136
|
+
}
|
|
137
|
+
var userConfig = require_default(path2.join(process.cwd(), "./xpine.config.mjs")).default;
|
|
138
|
+
var configDefaults = {
|
|
139
|
+
rootDir: fromRoot(),
|
|
140
|
+
srcDir: fromRoot("./src"),
|
|
141
|
+
distDir: fromRoot("./dist"),
|
|
142
|
+
packageJsonPath: fromRoot("package.json"),
|
|
143
|
+
// We need to use getters here in the event someone wants to change folders, such as the dist folder
|
|
144
|
+
get distPublicDir() {
|
|
145
|
+
return path2.join(this.distDir, "./public");
|
|
146
|
+
},
|
|
147
|
+
get distPublicScriptsDir() {
|
|
148
|
+
return path2.join(this.distPublicDir, "./scripts");
|
|
149
|
+
},
|
|
150
|
+
get distTempFolder() {
|
|
151
|
+
return path2.join(this.distDir, "./temp");
|
|
152
|
+
},
|
|
153
|
+
get clientJSBundlePath() {
|
|
154
|
+
return path2.join(this.distPublicScriptsDir, "./app.js");
|
|
155
|
+
},
|
|
156
|
+
get alpineDataPath() {
|
|
157
|
+
return path2.join(this.distTempFolder, "./alpine-data.ts");
|
|
158
|
+
},
|
|
159
|
+
get serverDistDir() {
|
|
160
|
+
return path2.join(this.distDir, "./server");
|
|
161
|
+
},
|
|
162
|
+
get serverDistAppPath() {
|
|
163
|
+
return path2.join(this.serverDistDir, "./app.js");
|
|
164
|
+
},
|
|
165
|
+
// Important dirs/paths
|
|
166
|
+
get pagesDir() {
|
|
167
|
+
return path2.join(this.srcDir, "./pages");
|
|
168
|
+
},
|
|
169
|
+
get publicDir() {
|
|
170
|
+
return path2.join(this.srcDir, "./public");
|
|
171
|
+
},
|
|
172
|
+
get serverDir() {
|
|
173
|
+
return path2.join(this.srcDir, "./server");
|
|
174
|
+
},
|
|
175
|
+
get runDir() {
|
|
176
|
+
return path2.join(this.serverDir, "./run");
|
|
177
|
+
},
|
|
178
|
+
get serverAppPath() {
|
|
179
|
+
return path2.join(this.serverDir, "./app.ts");
|
|
180
|
+
},
|
|
181
|
+
get globalCSSFile() {
|
|
182
|
+
return path2.join(this.publicDir, "./styles/global.css");
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
var config = {
|
|
186
|
+
...configDefaults,
|
|
187
|
+
...userConfig
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// src/scripts/build.ts
|
|
191
|
+
var extensions = [".ts", ".tsx"];
|
|
192
|
+
var packageJson = JSON.parse(fs2.readFileSync(config.packageJsonPath, "utf-8"));
|
|
193
|
+
var allPackages = Object.keys(packageJson.devDependencies).concat(Object.keys(packageJson.dependencies));
|
|
194
|
+
var allPackagesIncludingNode = allPackages.concat(builtinModules);
|
|
195
|
+
async function buildApp(isDev = false) {
|
|
196
|
+
try {
|
|
197
|
+
const srcDirFiles = globSync(config.srcDir + "/**/*.{js,ts,tsx,jsx}");
|
|
198
|
+
const { componentData, dataFiles } = await buildAppFiles(srcDirFiles, isDev);
|
|
199
|
+
const alpineDataFile = await buildAlpineDataFile(componentData, dataFiles);
|
|
200
|
+
await buildClientSideFiles([alpineDataFile], isDev);
|
|
201
|
+
fs2.removeSync(config.distTempFolder);
|
|
202
|
+
await buildCSS();
|
|
203
|
+
await buildPublicFolderSymlinks();
|
|
204
|
+
} catch (err) {
|
|
205
|
+
console.error("Build failed");
|
|
206
|
+
console.error(err);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async function buildAppFiles(files, isDev) {
|
|
210
|
+
const componentData = [];
|
|
211
|
+
const dataFiles = [];
|
|
212
|
+
const backendFiles = files.filter((file) => extensions.find((ext) => file.endsWith(ext))).filter((file) => !file.startsWith(config.publicDir));
|
|
213
|
+
fs2.ensureDirSync(config.distDir);
|
|
214
|
+
await build({
|
|
215
|
+
entryPoints: backendFiles,
|
|
216
|
+
format: "esm",
|
|
217
|
+
platform: "node",
|
|
218
|
+
outdir: config.distDir,
|
|
219
|
+
bundle: true,
|
|
220
|
+
sourcemap: isDev ? "inline" : false,
|
|
221
|
+
external: allPackages,
|
|
222
|
+
jsx: "transform",
|
|
223
|
+
minify: !isDev,
|
|
224
|
+
plugins: [
|
|
225
|
+
{
|
|
226
|
+
name: "add-dot-js",
|
|
227
|
+
setup(build2) {
|
|
228
|
+
build2.onResolve({ filter: /.*/ }, (args) => {
|
|
229
|
+
const hasAtSign = args.path.startsWith("@");
|
|
230
|
+
const isPackage = hasAtSign ? allPackagesIncludingNode.includes(args.path) : allPackagesIncludingNode.includes(args.path.split("/").shift());
|
|
231
|
+
if (args.importer && !isPackage) {
|
|
232
|
+
const calculatedDir = path3.join(args.resolveDir, args.path);
|
|
233
|
+
let existsAsFile = false;
|
|
234
|
+
for (const extension of extensions) {
|
|
235
|
+
const asFile = calculatedDir + extension;
|
|
236
|
+
const exists = fs2.existsSync(asFile);
|
|
237
|
+
if (exists) existsAsFile = true;
|
|
238
|
+
}
|
|
239
|
+
let outputPath = args.path + (existsAsFile ? "" : "/index") + ".js";
|
|
240
|
+
outputPath = args.path.endsWith(".js") || args.path.endsWith(".mjs") ? args.path : outputPath;
|
|
241
|
+
return { path: outputPath, external: true };
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: "insert-html-banner-and-remove-client-scripts",
|
|
248
|
+
setup(build2) {
|
|
249
|
+
build2.onLoad({ filter: /.tsx/ }, (args) => {
|
|
250
|
+
const cleanedContent = removeClientScriptInTSXFile(args.path);
|
|
251
|
+
const htmlImportStart = "import { html } from 'xpine';\n";
|
|
252
|
+
const newContent = `${htmlImportStart}${cleanedContent.content}`;
|
|
253
|
+
componentData.push({
|
|
254
|
+
...args,
|
|
255
|
+
contents: `${htmlImportStart}${cleanedContent.fullContent}`,
|
|
256
|
+
clientContent: cleanedContent.clientContent
|
|
257
|
+
});
|
|
258
|
+
return {
|
|
259
|
+
contents: newContent,
|
|
260
|
+
loader: "tsx"
|
|
261
|
+
};
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
name: "get-data-files",
|
|
267
|
+
setup(build2) {
|
|
268
|
+
build2.onLoad({ filter: /\.data\.(js|mjs|ts)$/ }, (args) => {
|
|
269
|
+
const contents = fs2.readFileSync(args.path, "utf-8");
|
|
270
|
+
dataFiles.push({
|
|
271
|
+
...args,
|
|
272
|
+
contents
|
|
273
|
+
});
|
|
274
|
+
return {
|
|
275
|
+
contents,
|
|
276
|
+
loader: "ts"
|
|
277
|
+
};
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
]
|
|
282
|
+
});
|
|
283
|
+
await logSize(config.distDir, "app");
|
|
284
|
+
return {
|
|
285
|
+
componentData,
|
|
286
|
+
dataFiles
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
async function buildClientSideFiles(alpineDataFiles = [], isDev) {
|
|
290
|
+
const tempFilePath = path3.join(config.distTempFolder, "./app.ts");
|
|
291
|
+
fs2.ensureFileSync(tempFilePath);
|
|
292
|
+
const pagesScriptsGlob = config.publicDir + "/scripts/pages/**/*.{js,ts}";
|
|
293
|
+
const clientFiles = globSync(
|
|
294
|
+
config.publicDir + "/**/*.{js,ts}",
|
|
295
|
+
{
|
|
296
|
+
ignore: pagesScriptsGlob
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
convertEntryPointsToSingleFile(alpineDataFiles.concat(clientFiles), tempFilePath);
|
|
300
|
+
if (isDev) writeDevServerClientSideCode(tempFilePath);
|
|
301
|
+
writeSpaClientSideCode(tempFilePath);
|
|
302
|
+
await build({
|
|
303
|
+
entryPoints: [tempFilePath],
|
|
304
|
+
bundle: true,
|
|
305
|
+
outdir: config.distPublicScriptsDir,
|
|
306
|
+
minify: !isDev,
|
|
307
|
+
sourcemap: isDev ? "inline" : false
|
|
308
|
+
});
|
|
309
|
+
const pagesFiles = globSync(pagesScriptsGlob);
|
|
310
|
+
await build({
|
|
311
|
+
entryPoints: pagesFiles || [],
|
|
312
|
+
bundle: true,
|
|
313
|
+
outdir: config.distPublicScriptsDir + "/pages",
|
|
314
|
+
minify: !isDev,
|
|
315
|
+
sourcemap: isDev ? "inline" : false
|
|
316
|
+
});
|
|
317
|
+
await logSize(config.distPublicDir, "client");
|
|
318
|
+
}
|
|
319
|
+
function writeDevServerClientSideCode(tempFilePath) {
|
|
320
|
+
const devServerPath = path3.join(import.meta.dirname, "../static/dev-server.js");
|
|
321
|
+
const content = fs2.readFileSync(devServerPath, "utf-8");
|
|
322
|
+
fs2.appendFileSync(tempFilePath, `
|
|
323
|
+
` + content);
|
|
324
|
+
}
|
|
325
|
+
function writeSpaClientSideCode(tempFilePath) {
|
|
326
|
+
const spaPath = path3.join(import.meta.dirname, "../static/spa.js");
|
|
327
|
+
const content = fs2.readFileSync(spaPath, "utf-8");
|
|
328
|
+
fs2.appendFileSync(tempFilePath, `
|
|
329
|
+
` + content);
|
|
330
|
+
}
|
|
331
|
+
async function buildAlpineDataFile(componentData, dataFiles) {
|
|
332
|
+
const output = {
|
|
333
|
+
imports: [
|
|
334
|
+
"import Alpine from 'alpinejs';"
|
|
335
|
+
],
|
|
336
|
+
code: [],
|
|
337
|
+
end: [
|
|
338
|
+
"window.Alpine = Alpine;"
|
|
339
|
+
]
|
|
340
|
+
};
|
|
341
|
+
const dataFunctionResults = {
|
|
342
|
+
foundDataAttributes: [],
|
|
343
|
+
foundFunctions: [],
|
|
344
|
+
foundImports: []
|
|
345
|
+
};
|
|
346
|
+
const componentsAndDataFiles = componentData.concat(dataFiles);
|
|
347
|
+
for (const component of componentsAndDataFiles) {
|
|
348
|
+
const sourceFile = ts2.createSourceFile(
|
|
349
|
+
component.path,
|
|
350
|
+
component.contents,
|
|
351
|
+
ts2.ScriptTarget.Latest
|
|
352
|
+
);
|
|
353
|
+
const dataFunctionResult = findDataAttributesAndFunctions(sourceFile, sourceFile);
|
|
354
|
+
dataFunctionResults.foundDataAttributes.push(...dataFunctionResult.foundDataAttributes);
|
|
355
|
+
const foundFunctionsWithPath = dataFunctionResult.foundFunctions.map((item) => {
|
|
356
|
+
return {
|
|
357
|
+
...item,
|
|
358
|
+
path: component.path,
|
|
359
|
+
content: component.clientContent
|
|
360
|
+
};
|
|
361
|
+
});
|
|
362
|
+
dataFunctionResults.foundFunctions.push(...foundFunctionsWithPath);
|
|
363
|
+
}
|
|
364
|
+
const validDataFunctions = dataFunctionResults.foundFunctions.filter((item) => {
|
|
365
|
+
return dataFunctionResults.foundDataAttributes.includes(item.name) && item.content;
|
|
366
|
+
});
|
|
367
|
+
for (const dataFunction of validDataFunctions) {
|
|
368
|
+
if (!dataFunction.hasExport) continue;
|
|
369
|
+
output.code.push(dataFunction.content);
|
|
370
|
+
output.code.push(`Alpine.data('${dataFunction.name}', ${dataFunction.name});`);
|
|
371
|
+
}
|
|
372
|
+
const result = output.imports.join("\n") + "\n" + output.code.join("\n") + "\n" + output.end.join("\n");
|
|
373
|
+
fs2.ensureFileSync(config.alpineDataPath);
|
|
374
|
+
fs2.writeFileSync(config.alpineDataPath, result);
|
|
375
|
+
return config.alpineDataPath;
|
|
376
|
+
}
|
|
377
|
+
async function buildCSS() {
|
|
378
|
+
const cssFiles = globSync(config.srcDir + "/**/*.css");
|
|
379
|
+
for (const file of cssFiles) {
|
|
380
|
+
const fileContents = fs2.readFileSync(file, "utf-8");
|
|
381
|
+
const result = await postcss([tailwindPostcss()]).process(fileContents, { from: file });
|
|
382
|
+
const newPath = file.replace(config.srcDir, config.distDir);
|
|
383
|
+
fs2.ensureFileSync(newPath);
|
|
384
|
+
fs2.writeFileSync(newPath, result.css);
|
|
385
|
+
}
|
|
386
|
+
logSize(config.distPublicDir, "css");
|
|
387
|
+
}
|
|
388
|
+
async function buildPublicFolderSymlinks() {
|
|
389
|
+
const files = globSync(config.publicDir + "/**/*.*", {
|
|
390
|
+
ignore: "/**/*.{css,js,ts,tsx,jsx}"
|
|
391
|
+
});
|
|
392
|
+
for (const file of files) {
|
|
393
|
+
try {
|
|
394
|
+
const newPath = file.replace(config.srcDir, config.distDir);
|
|
395
|
+
const splitNewPath = newPath.split("/");
|
|
396
|
+
splitNewPath.pop();
|
|
397
|
+
const newDir = splitNewPath.join("/");
|
|
398
|
+
fs2.ensureDirSync(newDir);
|
|
399
|
+
fs2.symlinkSync(file, newPath);
|
|
400
|
+
} catch {
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
async function logSize(pathName, type, validExtensions = [".js", ".css"]) {
|
|
405
|
+
const files = globSync(pathName + "/**/*" + (type === "css" ? ".css" : ""));
|
|
406
|
+
const fileSizes = files.map((file) => {
|
|
407
|
+
if (!validExtensions.find((ext) => file.endsWith(ext))) return false;
|
|
408
|
+
return {
|
|
409
|
+
file,
|
|
410
|
+
size: fs2.statSync(file).size / (1024 * 1e3)
|
|
411
|
+
};
|
|
412
|
+
}).filter(Boolean);
|
|
413
|
+
const totalSize = fileSizes.reduce((total, current) => {
|
|
414
|
+
return current.size + total;
|
|
415
|
+
}, 0);
|
|
416
|
+
console.info(`[${totalSize.toFixed(3)} MB] Built ${type}`);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// src/scripts/xpine-build.ts
|
|
420
|
+
buildApp();
|
|
421
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3NjcmlwdHMvYnVpbGQudHMiLCAiLi4vLi4vLi4vc3JjL2J1aWxkL3R5cGVzY3JpcHQtYnVpbGRlci50cyIsICIuLi8uLi8uLi9zcmMvdXRpbC9nZXQtY29uZmlnLnRzIiwgIi4uLy4uLy4uL3NyYy91dGlsL3JlcXVpcmUudHMiLCAiLi4vLi4vLi4vc3JjL3NjcmlwdHMveHBpbmUtYnVpbGQudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCB7IGJ1aWxkIH0gZnJvbSAnZXNidWlsZCc7XG5pbXBvcnQgYnVpbHRpbk1vZHVsZXMgZnJvbSAnYnVpbHRpbi1tb2R1bGVzJztcbmltcG9ydCB0cyBmcm9tICd0eXBlc2NyaXB0JztcbmltcG9ydCB7XG4gIGNvbnZlcnRFbnRyeVBvaW50c1RvU2luZ2xlRmlsZSxcbiAgZmluZERhdGFBdHRyaWJ1dGVzQW5kRnVuY3Rpb25zLFxuICByZW1vdmVDbGllbnRTY3JpcHRJblRTWEZpbGVcbn0gZnJvbSAnLi4vYnVpbGQvdHlwZXNjcmlwdC1idWlsZGVyJztcbmltcG9ydCB7IGdsb2JTeW5jIH0gZnJvbSAnZ2xvYic7XG5pbXBvcnQgcG9zdGNzcyBmcm9tICdwb3N0Y3NzJztcbi8vIEB0cy1pZ25vcmVcbmltcG9ydCB0YWlsd2luZFBvc3Rjc3MgZnJvbSAnQHRhaWx3aW5kY3NzL3Bvc3Rjc3MnO1xuaW1wb3J0IHsgY29uZmlnIH0gZnJvbSAnLi4vdXRpbC9nZXQtY29uZmlnJztcblxuLy8gRXh0ZW5zaW9ucyB0byBsb29rIGZvciBpbiB0aGUgYnVuZGxlXG5jb25zdCBleHRlbnNpb25zID0gWycudHMnLCAnLnRzeCddO1xuY29uc3QgcGFja2FnZUpzb24gPSBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhjb25maWcucGFja2FnZUpzb25QYXRoLCAndXRmLTgnKSk7XG5jb25zdCBhbGxQYWNrYWdlcyA9IE9iamVjdC5rZXlzKHBhY2thZ2VKc29uLmRldkRlcGVuZGVuY2llcykuY29uY2F0KE9iamVjdC5rZXlzKHBhY2thZ2VKc29uLmRlcGVuZGVuY2llcykpO1xuY29uc3QgYWxsUGFja2FnZXNJbmNsdWRpbmdOb2RlID0gYWxsUGFja2FnZXMuY29uY2F0KGJ1aWx0aW5Nb2R1bGVzKTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1aWxkQXBwKGlzRGV2ID0gZmFsc2UpIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBzcmNEaXJGaWxlcyA9IGdsb2JTeW5jKGNvbmZpZy5zcmNEaXIgKyAnLyoqLyoue2pzLHRzLHRzeCxqc3h9Jyk7XG4gICAgY29uc3QgeyBjb21wb25lbnREYXRhLCBkYXRhRmlsZXMsIH0gPSBhd2FpdCBidWlsZEFwcEZpbGVzKHNyY0RpckZpbGVzLCBpc0Rldik7XG4gICAgY29uc3QgYWxwaW5lRGF0YUZpbGUgPSBhd2FpdCBidWlsZEFscGluZURhdGFGaWxlKGNvbXBvbmVudERhdGEsIGRhdGFGaWxlcyk7XG4gICAgYXdhaXQgYnVpbGRDbGllbnRTaWRlRmlsZXMoW2FscGluZURhdGFGaWxlXSwgaXNEZXYpO1xuICAgIGZzLnJlbW92ZVN5bmMoY29uZmlnLmRpc3RUZW1wRm9sZGVyKTtcbiAgICBhd2FpdCBidWlsZENTUygpO1xuICAgIGF3YWl0IGJ1aWxkUHVibGljRm9sZGVyU3ltbGlua3MoKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgY29uc29sZS5lcnJvcignQnVpbGQgZmFpbGVkJyk7XG4gICAgY29uc29sZS5lcnJvcihlcnIpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkQXBwRmlsZXMoZmlsZXM6IHN0cmluZ1tdLCBpc0Rldj86IGJvb2xlYW4pIHtcbiAgY29uc3QgY29tcG9uZW50RGF0YSA9IFtdO1xuICBjb25zdCBkYXRhRmlsZXMgPSBbXTtcbiAgLy8gRmlsdGVyIG91dCBjbGllbnQgc2lkZSBmaWxlcyBhbmQgZmlsZXMgdGhhdCBhcmVuJ3Qgb2YgdGhlIGFsbG93ZWQgZXh0ZW5zaW9uc1xuICBjb25zdCBiYWNrZW5kRmlsZXMgPSBmaWxlc1xuICAgIC5maWx0ZXIoKGZpbGUpID0+IGV4dGVuc2lvbnMuZmluZChleHQgPT4gZmlsZS5lbmRzV2l0aChleHQpKSlcbiAgICAuZmlsdGVyKChmaWxlKSA9PiAhZmlsZS5zdGFydHNXaXRoKGNvbmZpZy5wdWJsaWNEaXIpKTtcbiAgZnMuZW5zdXJlRGlyU3luYyhjb25maWcuZGlzdERpcik7XG4gIC8vIEJ1aWxkIGJhY2tlbmQvU1NSIFRTWCBtb2R1bGVzXG4gIGF3YWl0IGJ1aWxkKHtcbiAgICBlbnRyeVBvaW50czogYmFja2VuZEZpbGVzLFxuICAgIGZvcm1hdDogJ2VzbScsXG4gICAgcGxhdGZvcm06ICdub2RlJyxcbiAgICBvdXRkaXI6IGNvbmZpZy5kaXN0RGlyLFxuICAgIGJ1bmRsZTogdHJ1ZSxcbiAgICBzb3VyY2VtYXA6IGlzRGV2ID8gJ2lubGluZScgOiBmYWxzZSxcbiAgICBleHRlcm5hbDogYWxsUGFja2FnZXMsXG4gICAganN4OiAndHJhbnNmb3JtJyxcbiAgICBtaW5pZnk6ICFpc0RldixcbiAgICBwbHVnaW5zOiBbXG4gICAgICB7XG4gICAgICAgIG5hbWU6ICdhZGQtZG90LWpzJyxcbiAgICAgICAgc2V0dXAoYnVpbGQpIHtcbiAgICAgICAgICBidWlsZC5vblJlc29sdmUoeyBmaWx0ZXI6IC8uKi8sIH0sIGFyZ3MgPT4ge1xuICAgICAgICAgICAgY29uc3QgaGFzQXRTaWduID0gYXJncy5wYXRoLnN0YXJ0c1dpdGgoJ0AnKTtcbiAgICAgICAgICAgIGNvbnN0IGlzUGFja2FnZSA9IGhhc0F0U2lnbiA/XG4gICAgICAgICAgICAgIGFsbFBhY2thZ2VzSW5jbHVkaW5nTm9kZS5pbmNsdWRlcyhhcmdzLnBhdGgpIDpcbiAgICAgICAgICAgICAgYWxsUGFja2FnZXNJbmNsdWRpbmdOb2RlLmluY2x1ZGVzKGFyZ3MucGF0aC5zcGxpdCgnLycpLnNoaWZ0KCkpO1xuICAgICAgICAgICAgaWYgKGFyZ3MuaW1wb3J0ZXIgJiYgIWlzUGFja2FnZSkge1xuICAgICAgICAgICAgICAvLyBJZiB3ZSdyZSBkb2luZyBhbiBpbmRleCBpbXBvcnQgd2UgbmVlZCAvaW5kZXguanNcbiAgICAgICAgICAgICAgY29uc3QgY2FsY3VsYXRlZERpciA9IHBhdGguam9pbihhcmdzLnJlc29sdmVEaXIsIGFyZ3MucGF0aCk7XG4gICAgICAgICAgICAgIGxldCBleGlzdHNBc0ZpbGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgZm9yIChjb25zdCBleHRlbnNpb24gb2YgZXh0ZW5zaW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFzRmlsZSA9IGNhbGN1bGF0ZWREaXIgKyBleHRlbnNpb247XG4gICAgICAgICAgICAgICAgY29uc3QgZXhpc3RzID0gZnMuZXhpc3RzU3luYyhhc0ZpbGUpO1xuICAgICAgICAgICAgICAgIGlmIChleGlzdHMpIGV4aXN0c0FzRmlsZSA9IHRydWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgbGV0IG91dHB1dFBhdGggPSBhcmdzLnBhdGggKyAoZXhpc3RzQXNGaWxlID8gJycgOiAnL2luZGV4JykgKyAnLmpzJztcbiAgICAgICAgICAgICAgb3V0cHV0UGF0aCA9IGFyZ3MucGF0aC5lbmRzV2l0aCgnLmpzJykgfHwgYXJncy5wYXRoLmVuZHNXaXRoKCcubWpzJykgPyBhcmdzLnBhdGggOiBvdXRwdXRQYXRoO1xuICAgICAgICAgICAgICByZXR1cm4geyBwYXRoOiBvdXRwdXRQYXRoLCBleHRlcm5hbDogdHJ1ZSwgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIG5hbWU6ICdpbnNlcnQtaHRtbC1iYW5uZXItYW5kLXJlbW92ZS1jbGllbnQtc2NyaXB0cycsXG4gICAgICAgIHNldHVwKGJ1aWxkKSB7XG4gICAgICAgICAgYnVpbGQub25Mb2FkKHsgZmlsdGVyOiAvLnRzeC8sIH0sIGFyZ3MgPT4ge1xuICAgICAgICAgICAgY29uc3QgY2xlYW5lZENvbnRlbnQgPSByZW1vdmVDbGllbnRTY3JpcHRJblRTWEZpbGUoYXJncy5wYXRoKTtcbiAgICAgICAgICAgIGNvbnN0IGh0bWxJbXBvcnRTdGFydCA9ICdpbXBvcnQgeyBodG1sIH0gZnJvbSBcXCd4cGluZVxcJztcXG4nO1xuICAgICAgICAgICAgY29uc3QgbmV3Q29udGVudCA9IGAke2h0bWxJbXBvcnRTdGFydH0ke2NsZWFuZWRDb250ZW50LmNvbnRlbnR9YDtcbiAgICAgICAgICAgIGNvbXBvbmVudERhdGEucHVzaCh7XG4gICAgICAgICAgICAgIC4uLmFyZ3MsXG4gICAgICAgICAgICAgIGNvbnRlbnRzOiBgJHtodG1sSW1wb3J0U3RhcnR9JHtjbGVhbmVkQ29udGVudC5mdWxsQ29udGVudH1gLFxuICAgICAgICAgICAgICBjbGllbnRDb250ZW50OiBjbGVhbmVkQ29udGVudC5jbGllbnRDb250ZW50LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBjb250ZW50czogbmV3Q29udGVudCxcbiAgICAgICAgICAgICAgbG9hZGVyOiAndHN4JyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBuYW1lOiAnZ2V0LWRhdGEtZmlsZXMnLFxuICAgICAgICBzZXR1cChidWlsZCkge1xuICAgICAgICAgIGJ1aWxkLm9uTG9hZCh7IGZpbHRlcjogL1xcLmRhdGFcXC4oanN8bWpzfHRzKSQvLCB9LCBhcmdzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbnRlbnRzID0gZnMucmVhZEZpbGVTeW5jKGFyZ3MucGF0aCwgJ3V0Zi04Jyk7XG4gICAgICAgICAgICBkYXRhRmlsZXMucHVzaCh7XG4gICAgICAgICAgICAgIC4uLmFyZ3MsXG4gICAgICAgICAgICAgIGNvbnRlbnRzLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBjb250ZW50cyxcbiAgICAgICAgICAgICAgbG9hZGVyOiAndHMnLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgIH1cbiAgICBdLFxuICB9KTtcbiAgYXdhaXQgbG9nU2l6ZShjb25maWcuZGlzdERpciwgJ2FwcCcpO1xuICByZXR1cm4ge1xuICAgIGNvbXBvbmVudERhdGEsXG4gICAgZGF0YUZpbGVzLFxuICB9O1xufVxuXG4vLyBCdWlsZCBjbGllbnQgc2lkZSBmaWxlc1xuYXN5bmMgZnVuY3Rpb24gYnVpbGRDbGllbnRTaWRlRmlsZXMoYWxwaW5lRGF0YUZpbGVzOiBzdHJpbmdbXSA9IFtdLCBpc0Rldj86IGJvb2xlYW4pIHtcbiAgLy8gV3JpdGUgdGhlIHRlbXAgZmlsZSB0byB1c2VcbiAgY29uc3QgdGVtcEZpbGVQYXRoID0gcGF0aC5qb2luKGNvbmZpZy5kaXN0VGVtcEZvbGRlciwgJy4vYXBwLnRzJyk7XG4gIGZzLmVuc3VyZUZpbGVTeW5jKHRlbXBGaWxlUGF0aCk7XG4gIC8vIEdldCBhbGwgdHMvanMgZmlsZXMgaW4gcHVibGljIGZvbGRlciBidXQgaWdub3JlIHRoZSBwYWdlcyBzY3JpcHRzXG4gIGNvbnN0IHBhZ2VzU2NyaXB0c0dsb2IgPSBjb25maWcucHVibGljRGlyICsgJy9zY3JpcHRzL3BhZ2VzLyoqLyoue2pzLHRzfSc7XG4gIGNvbnN0IGNsaWVudEZpbGVzID0gZ2xvYlN5bmMoXG4gICAgY29uZmlnLnB1YmxpY0RpciArICcvKiovKi57anMsdHN9JyxcbiAgICB7XG4gICAgICBpZ25vcmU6IHBhZ2VzU2NyaXB0c0dsb2IsXG4gICAgfVxuICApO1xuICAvLyBGaWx0ZXIgb3V0IGFsbCBwdWJsaWMvcGFnZXMgZmlsZXNcbiAgY29udmVydEVudHJ5UG9pbnRzVG9TaW5nbGVGaWxlKGFscGluZURhdGFGaWxlcy5jb25jYXQoY2xpZW50RmlsZXMpLCB0ZW1wRmlsZVBhdGgpO1xuICAvLyBXcml0ZSBkZXYgc2VydmVyIGNvZGUgdG8gdGhlIHRlbXAgZmlsZSBwYXRoXG4gIGlmIChpc0Rldikgd3JpdGVEZXZTZXJ2ZXJDbGllbnRTaWRlQ29kZSh0ZW1wRmlsZVBhdGgpO1xuICAvLyBXcml0ZSBzcGEgZnVuY3Rpb25hbGl0eSB0byB0aGUgdGVtcCBmaWxlIHBhdGhcbiAgd3JpdGVTcGFDbGllbnRTaWRlQ29kZSh0ZW1wRmlsZVBhdGgpO1xuICBhd2FpdCBidWlsZCh7XG4gICAgZW50cnlQb2ludHM6IFt0ZW1wRmlsZVBhdGhdLFxuICAgIGJ1bmRsZTogdHJ1ZSxcbiAgICBvdXRkaXI6IGNvbmZpZy5kaXN0UHVibGljU2NyaXB0c0RpcixcbiAgICBtaW5pZnk6ICFpc0RldixcbiAgICBzb3VyY2VtYXA6IGlzRGV2ID8gJ2lubGluZScgOiBmYWxzZSxcbiAgfSk7XG4gIC8vIEJ1aWxkIHBhZ2VzIGZpbGVzIHNjcmlwdHNcbiAgY29uc3QgcGFnZXNGaWxlcyA9IGdsb2JTeW5jKHBhZ2VzU2NyaXB0c0dsb2IpO1xuICBhd2FpdCBidWlsZCh7XG4gICAgZW50cnlQb2ludHM6IHBhZ2VzRmlsZXMgfHwgW10sXG4gICAgYnVuZGxlOiB0cnVlLFxuICAgIG91dGRpcjogY29uZmlnLmRpc3RQdWJsaWNTY3JpcHRzRGlyICsgJy9wYWdlcycsXG4gICAgbWluaWZ5OiAhaXNEZXYsXG4gICAgc291cmNlbWFwOiBpc0RldiA/ICdpbmxpbmUnIDogZmFsc2UsXG4gIH0pO1xuICBhd2FpdCBsb2dTaXplKGNvbmZpZy5kaXN0UHVibGljRGlyLCAnY2xpZW50Jyk7XG59XG5cbmZ1bmN0aW9uIHdyaXRlRGV2U2VydmVyQ2xpZW50U2lkZUNvZGUodGVtcEZpbGVQYXRoOiBzdHJpbmcpIHtcbiAgY29uc3QgZGV2U2VydmVyUGF0aCA9IHBhdGguam9pbihpbXBvcnQubWV0YS5kaXJuYW1lLCAnLi4vc3RhdGljL2Rldi1zZXJ2ZXIuanMnKTtcbiAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhkZXZTZXJ2ZXJQYXRoLCAndXRmLTgnKTtcbiAgZnMuYXBwZW5kRmlsZVN5bmModGVtcEZpbGVQYXRoLCBgXFxuYCArIGNvbnRlbnQpO1xufVxuXG5mdW5jdGlvbiB3cml0ZVNwYUNsaWVudFNpZGVDb2RlKHRlbXBGaWxlUGF0aDogc3RyaW5nKSB7XG4gIGNvbnN0IHNwYVBhdGggPSBwYXRoLmpvaW4oaW1wb3J0Lm1ldGEuZGlybmFtZSwgJy4uL3N0YXRpYy9zcGEuanMnKTtcbiAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhzcGFQYXRoLCAndXRmLTgnKTtcbiAgZnMuYXBwZW5kRmlsZVN5bmModGVtcEZpbGVQYXRoLCBgXFxuYCArIGNvbnRlbnQpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBidWlsZEFscGluZURhdGFGaWxlKGNvbXBvbmVudERhdGE6IGFueVtdLCBkYXRhRmlsZXM6IGFueVtdKSB7XG4gIGNvbnN0IG91dHB1dCA9IHtcbiAgICBpbXBvcnRzOiBbXG4gICAgICAnaW1wb3J0IEFscGluZSBmcm9tIFxcJ2FscGluZWpzXFwnOydcbiAgICBdLFxuICAgIGNvZGU6IFtdLFxuICAgIGVuZDogW1xuICAgICAgJ3dpbmRvdy5BbHBpbmUgPSBBbHBpbmU7J1xuICAgIF0sXG4gIH07XG4gIGNvbnN0IGRhdGFGdW5jdGlvblJlc3VsdHMgPSB7XG4gICAgZm91bmREYXRhQXR0cmlidXRlczogW10sXG4gICAgZm91bmRGdW5jdGlvbnM6IFtdLFxuICAgIGZvdW5kSW1wb3J0czogW10sXG4gIH07XG4gIGNvbnN0IGNvbXBvbmVudHNBbmREYXRhRmlsZXMgPSBjb21wb25lbnREYXRhLmNvbmNhdChkYXRhRmlsZXMpO1xuICBmb3IgKGNvbnN0IGNvbXBvbmVudCBvZiBjb21wb25lbnRzQW5kRGF0YUZpbGVzKSB7XG4gICAgLy8gU2luZ2xlIHNvdXJjZSBmaWxlXG4gICAgY29uc3Qgc291cmNlRmlsZSA9IHRzLmNyZWF0ZVNvdXJjZUZpbGUoXG4gICAgICBjb21wb25lbnQucGF0aCxcbiAgICAgIGNvbXBvbmVudC5jb250ZW50cyxcbiAgICAgIHRzLlNjcmlwdFRhcmdldC5MYXRlc3RcbiAgICApO1xuICAgIGNvbnN0IGRhdGFGdW5jdGlvblJlc3VsdCA9IGZpbmREYXRhQXR0cmlidXRlc0FuZEZ1bmN0aW9ucyhzb3VyY2VGaWxlLCBzb3VyY2VGaWxlKTtcbiAgICBkYXRhRnVuY3Rpb25SZXN1bHRzLmZvdW5kRGF0YUF0dHJpYnV0ZXMucHVzaCguLi5kYXRhRnVuY3Rpb25SZXN1bHQuZm91bmREYXRhQXR0cmlidXRlcyk7XG4gICAgY29uc3QgZm91bmRGdW5jdGlvbnNXaXRoUGF0aCA9IGRhdGFGdW5jdGlvblJlc3VsdC5mb3VuZEZ1bmN0aW9ucy5tYXAoaXRlbSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5pdGVtLFxuICAgICAgICBwYXRoOiBjb21wb25lbnQucGF0aCxcbiAgICAgICAgY29udGVudDogY29tcG9uZW50LmNsaWVudENvbnRlbnQsXG4gICAgICB9O1xuICAgIH0pO1xuICAgIGRhdGFGdW5jdGlvblJlc3VsdHMuZm91bmRGdW5jdGlvbnMucHVzaCguLi5mb3VuZEZ1bmN0aW9uc1dpdGhQYXRoKTtcbiAgfVxuICBjb25zdCB2YWxpZERhdGFGdW5jdGlvbnMgPSBkYXRhRnVuY3Rpb25SZXN1bHRzLmZvdW5kRnVuY3Rpb25zLmZpbHRlcihpdGVtID0+IHtcbiAgICByZXR1cm4gZGF0YUZ1bmN0aW9uUmVzdWx0cy5mb3VuZERhdGFBdHRyaWJ1dGVzLmluY2x1ZGVzKGl0ZW0ubmFtZSkgJiYgaXRlbS5jb250ZW50O1xuICB9KTtcbiAgZm9yIChjb25zdCBkYXRhRnVuY3Rpb24gb2YgdmFsaWREYXRhRnVuY3Rpb25zKSB7XG4gICAgaWYgKCFkYXRhRnVuY3Rpb24uaGFzRXhwb3J0KSBjb250aW51ZTtcbiAgICBvdXRwdXQuY29kZS5wdXNoKGRhdGFGdW5jdGlvbi5jb250ZW50KTtcbiAgICBvdXRwdXQuY29kZS5wdXNoKGBBbHBpbmUuZGF0YSgnJHtkYXRhRnVuY3Rpb24ubmFtZX0nLCAke2RhdGFGdW5jdGlvbi5uYW1lfSk7YCk7XG4gIH1cbiAgY29uc3QgcmVzdWx0ID0gb3V0cHV0LmltcG9ydHMuam9pbignXFxuJykgKyAnXFxuJyArIG91dHB1dC5jb2RlLmpvaW4oJ1xcbicpICsgJ1xcbicgKyBvdXRwdXQuZW5kLmpvaW4oJ1xcbicpO1xuICBmcy5lbnN1cmVGaWxlU3luYyhjb25maWcuYWxwaW5lRGF0YVBhdGgpO1xuICBmcy53cml0ZUZpbGVTeW5jKGNvbmZpZy5hbHBpbmVEYXRhUGF0aCwgcmVzdWx0KTtcbiAgcmV0dXJuIGNvbmZpZy5hbHBpbmVEYXRhUGF0aDtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1aWxkQ1NTKCkge1xuICBjb25zdCBjc3NGaWxlcyA9IGdsb2JTeW5jKGNvbmZpZy5zcmNEaXIgKyAnLyoqLyouY3NzJyk7XG4gIGZvciAoY29uc3QgZmlsZSBvZiBjc3NGaWxlcykge1xuICAgIGNvbnN0IGZpbGVDb250ZW50cyA9IGZzLnJlYWRGaWxlU3luYyhmaWxlLCAndXRmLTgnKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwb3N0Y3NzKFt0YWlsd2luZFBvc3Rjc3MoKV0pLnByb2Nlc3MoZmlsZUNvbnRlbnRzLCB7IGZyb206IGZpbGUsIH0pO1xuICAgIC8vIFdyaXRlIHRvIGRpc3QgZm9sZGVyXG4gICAgY29uc3QgbmV3UGF0aCA9IGZpbGUucmVwbGFjZShjb25maWcuc3JjRGlyLCBjb25maWcuZGlzdERpcik7XG4gICAgZnMuZW5zdXJlRmlsZVN5bmMobmV3UGF0aCk7XG4gICAgZnMud3JpdGVGaWxlU3luYyhuZXdQYXRoLCByZXN1bHQuY3NzKTtcbiAgfVxuICBsb2dTaXplKGNvbmZpZy5kaXN0UHVibGljRGlyLCAnY3NzJyk7XG59XG5cbi8vIFdlIG5lZWQgdG8gc3ltbGluayB0aGUgbm9uIENTUyBvciBKUyBmaWxlcyBmcm9tIHRoZSBzcmMvcHVibGljIGZvbGRlciBpbnRvIHRoZSBkaXN0IGZvbGRlclxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1aWxkUHVibGljRm9sZGVyU3ltbGlua3MoKSB7XG4gIGNvbnN0IGZpbGVzID0gZ2xvYlN5bmMoY29uZmlnLnB1YmxpY0RpciArICcvKiovKi4qJywge1xuICAgIGlnbm9yZTogJy8qKi8qLntjc3MsanMsdHMsdHN4LGpzeH0nLFxuICB9KTtcblxuICAvLyBDcmVhdGUgc3ltbGlua3MgaW4gZGlzdCBkaXJlY3RvcnlcbiAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG5ld1BhdGggPSBmaWxlLnJlcGxhY2UoY29uZmlnLnNyY0RpciwgY29uZmlnLmRpc3REaXIpO1xuICAgICAgY29uc3Qgc3BsaXROZXdQYXRoID0gbmV3UGF0aC5zcGxpdCgnLycpO1xuICAgICAgc3BsaXROZXdQYXRoLnBvcCgpO1xuICAgICAgY29uc3QgbmV3RGlyID0gc3BsaXROZXdQYXRoLmpvaW4oJy8nKTtcbiAgICAgIGZzLmVuc3VyZURpclN5bmMobmV3RGlyKTtcbiAgICAgIGZzLnN5bWxpbmtTeW5jKGZpbGUsIG5ld1BhdGgpO1xuICAgIH0gY2F0Y2ggeyB9XG4gIH1cbn1cblxudHlwZSBGaWxlSXRlbSA9IHtcbiAgZmlsZTogc3RyaW5nO1xuICBzaXplOiBudW1iZXI7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsb2dTaXplKHBhdGhOYW1lOiBzdHJpbmcsIHR5cGU6ICdhcHAnIHwgJ2NsaWVudCcgfCAnY3NzJywgdmFsaWRFeHRlbnNpb25zID0gWycuanMnLCAnLmNzcyddKSB7XG4gIGNvbnN0IGZpbGVzID0gZ2xvYlN5bmMocGF0aE5hbWUgKyAnLyoqLyonICsgKHR5cGUgPT09ICdjc3MnID8gJy5jc3MnIDogJycpKTtcbiAgY29uc3QgZmlsZVNpemVzID0gZmlsZXMubWFwKChmaWxlKSA9PiB7XG4gICAgaWYgKCF2YWxpZEV4dGVuc2lvbnMuZmluZChleHQgPT4gZmlsZS5lbmRzV2l0aChleHQpKSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB7XG4gICAgICBmaWxlLFxuICAgICAgc2l6ZTogKGZzLnN0YXRTeW5jKGZpbGUpLnNpemUpIC8gKDEwMjQgKiAxMDAwKSxcbiAgICB9O1xuICB9KS5maWx0ZXIoQm9vbGVhbik7XG4gIGNvbnN0IHRvdGFsU2l6ZSA9IGZpbGVTaXplcy5yZWR1Y2UoKHRvdGFsLCBjdXJyZW50OiBGaWxlSXRlbSkgPT4ge1xuICAgIHJldHVybiBjdXJyZW50LnNpemUgKyB0b3RhbDtcbiAgfSwgMCk7XG4gIGNvbnNvbGUuaW5mbyhgWyR7dG90YWxTaXplLnRvRml4ZWQoMyl9IE1CXSBCdWlsdCAke3R5cGV9YCk7XG59XG4iLCAiaW1wb3J0IHRzIGZyb20gJ3R5cGVzY3JpcHQnO1xuaW1wb3J0IGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuXG50eXBlIEltcG9ydERlY2xhcmF0aW9uID0ge1xuICBub2RlOiB0cy5Ob2RlO1xuICBpbXBvcnRQYXRoOiBzdHJpbmc7XG59XG5cbi8vIG5vZGUgYXJnIHNob3VsZCBpbml0aWFsbHkgYmUgdGhlIHNvdXJjZSBub2RlXG5leHBvcnQgZnVuY3Rpb24gZ2V0SW1wb3J0RGVjbGFyYXRpb25Ob2Rlcyhub2RlOiB0cy5Ob2RlLCBzb3VyY2VGaWxlOiB0cy5Tb3VyY2VGaWxlLCBpbXBvcnREZWNsYXJhdGlvbnM6IEltcG9ydERlY2xhcmF0aW9uW10gPSBbXSkge1xuICBpZiAobm9kZS5raW5kID09PSB0cy5TeW50YXhLaW5kLkltcG9ydERlY2xhcmF0aW9uKSB7XG4gICAgbGV0IGltcG9ydFBhdGggPSBudWxsO1xuICAgIG5vZGUuZm9yRWFjaENoaWxkKGNoaWxkID0+IHtcbiAgICAgIGlmIChjaGlsZC5raW5kID09PSB0cy5TeW50YXhLaW5kLlN0cmluZ0xpdGVyYWwpIHtcbiAgICAgICAgaW1wb3J0UGF0aCA9IGNoaWxkLmdldFRleHQoc291cmNlRmlsZSkucmVwbGFjZSgvW1xcXCJcXCddL2csICcnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpbXBvcnREZWNsYXJhdGlvbnMucHVzaCh7XG4gICAgICBub2RlLFxuICAgICAgaW1wb3J0UGF0aCxcbiAgICB9KTtcbiAgfVxuICBub2RlLmZvckVhY2hDaGlsZChjaGlsZCA9PiB7XG4gICAgZ2V0SW1wb3J0RGVjbGFyYXRpb25Ob2RlcyhjaGlsZCwgc291cmNlRmlsZSwgaW1wb3J0RGVjbGFyYXRpb25zKTtcbiAgfSk7XG4gIHJldHVybiBpbXBvcnREZWNsYXJhdGlvbnM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdHJpcEltcG9ydHNOb2Rlc0Zyb21GaWxlKGltcG9ydHNUb1N0cmlwOiBzdHJpbmdbXSwgY29udGVudDogc3RyaW5nLCBpbXBvcnREZWNsYXJhdGlvbnM6IEltcG9ydERlY2xhcmF0aW9uW10pIHtcbiAgbGV0IG91dHB1dENvbnRlbnQgPSBjb250ZW50O1xuICBjb25zdCBmaWx0ZXJlZEltcG9ydHMgPSBpbXBvcnREZWNsYXJhdGlvbnMuZmlsdGVyKGl0ZW0gPT4gaW1wb3J0c1RvU3RyaXAuaW5jbHVkZXMoaXRlbS5pbXBvcnRQYXRoKSk7XG4gIGZvciAoY29uc3QgaW1wb3J0SXRlbSBvZiBmaWx0ZXJlZEltcG9ydHMpIHtcbiAgICBvdXRwdXRDb250ZW50ID0gb3V0cHV0Q29udGVudC5zbGljZSgwLCBpbXBvcnRJdGVtLm5vZGUucG9zKSArIG91dHB1dENvbnRlbnQuc2xpY2UoaW1wb3J0SXRlbS5ub2RlLmVuZCk7XG4gIH1cbiAgcmV0dXJuIG91dHB1dENvbnRlbnQ7XG59XG5cbnR5cGUgRm91bmRBbHBpbmVGdW5jdGlvbiA9IHtcbiAgbmFtZTogc3RyaW5nO1xuICBpc0RlZmF1bHRFeHBvcnQ6IGJvb2xlYW47XG4gIGhhc0V4cG9ydDogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmREYXRhQXR0cmlidXRlc0FuZEZ1bmN0aW9ucyhcbiAgbm9kZTogdHMuTm9kZSxcbiAgc291cmNlRmlsZTogdHMuU291cmNlRmlsZSxcbiAgZm91bmREYXRhQXR0cmlidXRlczogc3RyaW5nW10gPSBbXSxcbiAgZm91bmRGdW5jdGlvbnM6IEZvdW5kQWxwaW5lRnVuY3Rpb25bXSA9IFtdXG4pIHtcbiAgaWYgKG5vZGUua2luZCA9PT0gdHMuU3ludGF4S2luZC5Kc3hBdHRyaWJ1dGUpIHtcbiAgICBjb25zdCBhdHRyaWJ1dGUgPSBnZXRBdHRyaWJ1dGVWYWx1ZVBhaXIobm9kZSwgc291cmNlRmlsZSk7XG4gICAgaWYgKGF0dHJpYnV0ZT8uWzBdID09PSAneC1kYXRhJyAmJiBhdHRyaWJ1dGU/LlsxXSkge1xuICAgICAgLy8gV2UgZm91bmQgYSBkYXRhIGF0dHJpYnV0ZSwgXG4gICAgICAvLyBzbyBub3cgd2UgaGF2ZSB0byBzZWFyY2ggdGhyb3VnaG91dCB0aGUgZmlsZSBmb3IgYSBmdW5jdGlvbiBkZWNsYXJhdGlvbiBvZiB0aGUgc2FtZSBuYW1lXG4gICAgICBmb3VuZERhdGFBdHRyaWJ1dGVzLnB1c2goYXR0cmlidXRlWzFdLnJlcGxhY2UoL1teYS16QS1aMC05XS9nLCAnJykpO1xuICAgIH1cbiAgfVxuICBpZiAobm9kZS5raW5kID09PSB0cy5TeW50YXhLaW5kLlNvdXJjZUZpbGUpIHtcbiAgICBub2RlLmZvckVhY2hDaGlsZChjaGlsZCA9PiB7XG4gICAgICBpZiAoW3RzLlN5bnRheEtpbmQuRnVuY3Rpb25EZWNsYXJhdGlvbiwgdHMuU3ludGF4S2luZC5WYXJpYWJsZURlY2xhcmF0aW9uXS5pbmNsdWRlcyhjaGlsZC5raW5kKSkge1xuICAgICAgICBjb25zdCBmdW5jdGlvbnMgPSBnZXRGdW5jdGlvbkRlY2xhcmF0aW9uVmFsdWUoY2hpbGQsIHNvdXJjZUZpbGUpO1xuICAgICAgICBmb3VuZEZ1bmN0aW9ucy5wdXNoKGZ1bmN0aW9ucyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBub2RlLmZvckVhY2hDaGlsZChjaGlsZCA9PiB7XG4gICAgZmluZERhdGFBdHRyaWJ1dGVzQW5kRnVuY3Rpb25zKGNoaWxkLCBzb3VyY2VGaWxlLCBmb3VuZERhdGFBdHRyaWJ1dGVzLCBmb3VuZEZ1bmN0aW9ucyk7XG4gIH0pO1xuICByZXR1cm4ge1xuICAgIGZvdW5kRGF0YUF0dHJpYnV0ZXMsXG4gICAgZm91bmRGdW5jdGlvbnMsXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRBdHRyaWJ1dGVWYWx1ZVBhaXIobm9kZTogdHMuTm9kZSwgc291cmNlRmlsZTogdHMuU291cmNlRmlsZSk6IHN0cmluZ1tdIHtcbiAgY29uc3QgcmVzdWx0ID0gW107XG4gIG5vZGUuZm9yRWFjaENoaWxkKGNoaWxkID0+IHtcbiAgICByZXN1bHQucHVzaChjaGlsZC5nZXRUZXh0KHNvdXJjZUZpbGUpKTtcbiAgfSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGdW5jdGlvbkRlY2xhcmF0aW9uVmFsdWUobm9kZTogdHMuTm9kZSwgc291cmNlRmlsZTogdHMuU291cmNlRmlsZSk6IEZvdW5kQWxwaW5lRnVuY3Rpb24ge1xuICBjb25zdCByZXN1bHQgPSB7XG4gICAgbmFtZTogbnVsbCxcbiAgICBpc0RlZmF1bHRFeHBvcnQ6IGZhbHNlLFxuICAgIGhhc0V4cG9ydDogZmFsc2UsXG4gIH07XG4gIG5vZGUuZm9yRWFjaENoaWxkKGNoaWxkID0+IHtcbiAgICBpZiAoY2hpbGQua2luZCA9PT0gdHMuU3ludGF4S2luZC5FeHBvcnRLZXl3b3JkKSB7XG4gICAgICByZXN1bHQuaGFzRXhwb3J0ID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKGNoaWxkLmtpbmQgPT09IHRzLlN5bnRheEtpbmQuRGVmYXVsdEtleXdvcmQpIHtcbiAgICAgIHJlc3VsdC5pc0RlZmF1bHRFeHBvcnQgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAoY2hpbGQua2luZCA9PT0gdHMuU3ludGF4S2luZC5JZGVudGlmaWVyKSB7XG4gICAgICByZXN1bHQubmFtZSA9IGNoaWxkLmdldFRleHQoc291cmNlRmlsZSk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLy8gQ29udmVydCBlbnRyeSBwb2ludCBmaWxlcyBpbnRvIG9uZSBiaWcgYnVuZGxlIGZpbGVcbmV4cG9ydCBmdW5jdGlvbiBjb252ZXJ0RW50cnlQb2ludHNUb1NpbmdsZUZpbGUoZW50cnlQb2ludHM6IHN0cmluZ1tdLCB0ZW1wV3JpdGVQYXRoOiBzdHJpbmcpIHtcbiAgZnMud3JpdGVGaWxlU3luYyhcbiAgICB0ZW1wV3JpdGVQYXRoLFxuICAgIGVudHJ5UG9pbnRzXG4gICAgICAubWFwKGVudHJ5ID0+IGBpbXBvcnQgXCIke2VudHJ5fVwiYClcbiAgICAgIC5qb2luKCc7XFxuJylcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUNsaWVudFNjcmlwdEluVFNYRmlsZShwYXRoTmFtZTogc3RyaW5nKSB7XG4gIGNvbnN0IGNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmMocGF0aE5hbWUsICd1dGYtOCcpO1xuICBjb25zdCBzb3VyY2UgPSB0cy5jcmVhdGVTb3VyY2VGaWxlKFxuICAgIHBhdGhOYW1lLFxuICAgIGNvbnRlbnQsXG4gICAgdHMuU2NyaXB0VGFyZ2V0LkxhdGVzdFxuICApO1xuICBsZXQgdG9SZW1vdmVGcm9tOiBudW1iZXI7XG4gIGxldCBjbGllbnREYXRhU3RhcnQ6IG51bWJlcjtcbiAgY29uc3QgY2xpZW50SW1wb3J0c1RvSG9pc3QgPSBbXTtcbiAgY29uc3QgY2xpZW50SW1wb3J0c1RvUmVwbGFjZSA9IFtdO1xuICBzb3VyY2UuZm9yRWFjaENoaWxkKChjaGlsZCkgPT4ge1xuICAgIGlmIChjaGlsZC5raW5kID09PSB0cy5TeW50YXhLaW5kLkV4cHJlc3Npb25TdGF0ZW1lbnQpIHtcbiAgICAgIGNvbnN0IHRleHQgPSBjaGlsZC5nZXRUZXh0KHNvdXJjZSk7XG4gICAgICAvLyBSZW1vdmUgZnJvbSBoZXJlXG4gICAgICBpZiAodGV4dC5zdGFydHNXaXRoKCc8c2NyaXB0JykpIHtcbiAgICAgICAgdG9SZW1vdmVGcm9tID0gY2hpbGQucG9zO1xuICAgICAgICBjbGllbnREYXRhU3RhcnQgPSBjaGlsZC5lbmQ7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEhvaXN0IHRoZSBjbGllbnQgaW1wb3J0cyB0byBhYm92ZSB0aGUgPHNjcmlwdCAvPiB0YWdcbiAgICBpZiAoY2hpbGQua2luZCA9PT0gdHMuU3ludGF4S2luZC5JbXBvcnREZWNsYXJhdGlvbiAmJiBjaGlsZC5wb3MgPj0gY2xpZW50RGF0YVN0YXJ0KSB7XG4gICAgICBjb25zdCB0ZXh0ID0gY2hpbGQuZ2V0VGV4dChzb3VyY2UpO1xuICAgICAgY2hpbGQuZm9yRWFjaENoaWxkKGNoaWxkID0+IHtcbiAgICAgICAgaWYgKGNoaWxkLmtpbmQgPT09IHRzLlN5bnRheEtpbmQuU3RyaW5nTGl0ZXJhbCkge1xuICAgICAgICAgIC8vIEtlZXAgdHJhY2sgb2YgY2xpZW50IGltcG9ydHMgbmVlZGVkIGZvciBwYXRoIHJlcGxhY2VtZW50IHRvIGJlIGFic29sdXRlXG4gICAgICAgICAgY29uc3QgdGV4dCA9IGNoaWxkLmdldFRleHQoc291cmNlKTtcbiAgICAgICAgICBjb25zdCBpbXBvcnRQYXRoID0gdGV4dC5yZXBsYWNlKC9bXFxcIlxcJ10vZywgJycpO1xuICAgICAgICAgIGNvbnN0IGlzUmVsYXRpdmVJbXBvcnQgPSBpbXBvcnRQYXRoLnN0YXJ0c1dpdGgoJy4nKSB8fCBpbXBvcnRQYXRoLnN0YXJ0c1dpdGgoJy8nKTtcbiAgICAgICAgICBpZiAoIWlzUmVsYXRpdmVJbXBvcnQpIHJldHVybjtcbiAgICAgICAgICBjbGllbnRJbXBvcnRzVG9SZXBsYWNlLnB1c2goe1xuICAgICAgICAgICAgb2xkOiBpbXBvcnRQYXRoLFxuICAgICAgICAgICAgbmV3OiBwYXRoLmpvaW4ocGF0aC5kaXJuYW1lKHBhdGhOYW1lKSwgaW1wb3J0UGF0aCksXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgY2xpZW50SW1wb3J0c1RvSG9pc3QucHVzaCh0ZXh0KTtcbiAgICB9XG4gIH0pO1xuICBsZXQgY2xpZW50Q29udGVudCA9ICFpc05hTihjbGllbnREYXRhU3RhcnQpID8gY29udGVudC5zbGljZShjbGllbnREYXRhU3RhcnQpIDogJyc7XG4gIGZvciAoY29uc3QgY2xpZW50SW1wb3J0IG9mIGNsaWVudEltcG9ydHNUb1JlcGxhY2UpIHtcbiAgICBjbGllbnRDb250ZW50ID0gY2xpZW50Q29udGVudC5yZXBsYWNlKGNsaWVudEltcG9ydC5vbGQsIGNsaWVudEltcG9ydC5uZXcpO1xuICB9XG4gIHJldHVybiB7XG4gICAgY29udGVudDogIWlzTmFOKHRvUmVtb3ZlRnJvbSkgP1xuICAgICAgY2xpZW50SW1wb3J0c1RvSG9pc3Quam9pbignXFxuJykgKyBjb250ZW50LnNsaWNlKDAsIHRvUmVtb3ZlRnJvbSkgOlxuICAgICAgY29udGVudCxcbiAgICBjbGllbnRDb250ZW50LFxuICAgIGZ1bGxDb250ZW50OiBjb250ZW50LFxuICAgIHRvUmVtb3ZlRnJvbSxcbiAgICBjbGllbnREYXRhU3RhcnQsXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmludFJlY3Vyc2l2ZUZyb20oXG4gIG5vZGU6IHRzLk5vZGUsIGluZGVudExldmVsOiBudW1iZXIsIHNvdXJjZUZpbGU6IHRzLlNvdXJjZUZpbGVcbikge1xuICBjb25zdCBpbmRlbnRhdGlvbiA9ICctJy5yZXBlYXQoaW5kZW50TGV2ZWwpO1xuICBjb25zdCBzeW50YXhLaW5kID0gdHMuU3ludGF4S2luZFtub2RlLmtpbmRdO1xuICBjb25zdCBub2RlVGV4dCA9IG5vZGUuZ2V0VGV4dChzb3VyY2VGaWxlKTtcbiAgY29uc29sZS5sb2coYCR7aW5kZW50YXRpb259JHtzeW50YXhLaW5kfTogJHtub2RlVGV4dH1gKTtcblxuICBub2RlLmZvckVhY2hDaGlsZChjaGlsZCA9PlxuICAgIHByaW50UmVjdXJzaXZlRnJvbShjaGlsZCwgaW5kZW50TGV2ZWwgKyAxLCBzb3VyY2VGaWxlKVxuICApO1xufVxuIiwgImltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHJlcXVpcmUgZnJvbSAnLi9yZXF1aXJlJztcbmltcG9ydCB7IFhQaW5lQ29uZmlnIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuXG5jb25zdCByb290RGlyID0gcHJvY2Vzcy5jd2QoKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21Sb290KHBhdGhOYW1lPzogc3RyaW5nKSB7XG4gIGlmICghcGF0aE5hbWUpIHJldHVybiByb290RGlyO1xuICByZXR1cm4gcGF0aC5qb2luKHJvb3REaXIsIHBhdGhOYW1lKTtcbn1cblxuY29uc3QgdXNlckNvbmZpZyA9IHJlcXVpcmUocGF0aC5qb2luKHByb2Nlc3MuY3dkKCksICcuL3hwaW5lLmNvbmZpZy5tanMnKSkuZGVmYXVsdDtcblxuY29uc3QgY29uZmlnRGVmYXVsdHMgPSB7XG4gIHJvb3REaXI6IGZyb21Sb290KCksXG4gIHNyY0RpcjogZnJvbVJvb3QoJy4vc3JjJyksXG4gIGRpc3REaXI6IGZyb21Sb290KCcuL2Rpc3QnKSxcbiAgcGFja2FnZUpzb25QYXRoOiBmcm9tUm9vdCgncGFja2FnZS5qc29uJyksXG4gIC8vIFdlIG5lZWQgdG8gdXNlIGdldHRlcnMgaGVyZSBpbiB0aGUgZXZlbnQgc29tZW9uZSB3YW50cyB0byBjaGFuZ2UgZm9sZGVycywgc3VjaCBhcyB0aGUgZGlzdCBmb2xkZXJcbiAgZ2V0IGRpc3RQdWJsaWNEaXIoKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLmRpc3REaXIsICcuL3B1YmxpYycpO1xuICB9LFxuICBnZXQgZGlzdFB1YmxpY1NjcmlwdHNEaXIoKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLmRpc3RQdWJsaWNEaXIsICcuL3NjcmlwdHMnKTtcbiAgfSxcbiAgZ2V0IGRpc3RUZW1wRm9sZGVyKCkge1xuICAgIHJldHVybiBwYXRoLmpvaW4odGhpcy5kaXN0RGlyLCAnLi90ZW1wJyk7XG4gIH0sXG4gIGdldCBjbGllbnRKU0J1bmRsZVBhdGgoKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLmRpc3RQdWJsaWNTY3JpcHRzRGlyLCAnLi9hcHAuanMnKTtcbiAgfSxcbiAgZ2V0IGFscGluZURhdGFQYXRoKCkge1xuICAgIHJldHVybiBwYXRoLmpvaW4odGhpcy5kaXN0VGVtcEZvbGRlciwgJy4vYWxwaW5lLWRhdGEudHMnKTtcbiAgfSxcbiAgZ2V0IHNlcnZlckRpc3REaXIoKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLmRpc3REaXIsICcuL3NlcnZlcicpO1xuICB9LFxuICBnZXQgc2VydmVyRGlzdEFwcFBhdGgoKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLnNlcnZlckRpc3REaXIsICcuL2FwcC5qcycpO1xuICB9LFxuICAvLyBJbXBvcnRhbnQgZGlycy9wYXRoc1xuICBnZXQgcGFnZXNEaXIoKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLnNyY0RpciwgJy4vcGFnZXMnKTtcbiAgfSxcbiAgZ2V0IHB1YmxpY0RpcigpIHtcbiAgICByZXR1cm4gcGF0aC5qb2luKHRoaXMuc3JjRGlyLCAnLi9wdWJsaWMnKTtcbiAgfSxcbiAgZ2V0IHNlcnZlckRpcigpIHtcbiAgICByZXR1cm4gcGF0aC5qb2luKHRoaXMuc3JjRGlyLCAnLi9zZXJ2ZXInKTtcbiAgfSxcbiAgZ2V0IHJ1bkRpcigpIHtcbiAgICByZXR1cm4gcGF0aC5qb2luKHRoaXMuc2VydmVyRGlyLCAnLi9ydW4nKTtcbiAgfSxcbiAgZ2V0IHNlcnZlckFwcFBhdGgoKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLnNlcnZlckRpciwgJy4vYXBwLnRzJyk7XG4gIH0sXG4gIGdldCBnbG9iYWxDU1NGaWxlKCkge1xuICAgIHJldHVybiBwYXRoLmpvaW4odGhpcy5wdWJsaWNEaXIsICcuL3N0eWxlcy9nbG9iYWwuY3NzJyk7XG4gIH0sXG59O1xuXG5leHBvcnQgY29uc3QgY29uZmlnOiBYUGluZUNvbmZpZyA9IHtcbiAgLi4uY29uZmlnRGVmYXVsdHMsXG4gIC4uLnVzZXJDb25maWcsXG59OyIsICJpbXBvcnQgeyBjcmVhdGVSZXF1aXJlIH0gZnJvbSAnbW9kdWxlJztcblxuY29uc3QgcmVxdWlyZSA9IGNyZWF0ZVJlcXVpcmUoaW1wb3J0Lm1ldGEudXJsKTtcblxuZXhwb3J0IGRlZmF1bHQgcmVxdWlyZTsiLCAiIyEvdXNyL2Jpbi9lbnYgbm9kZVxuXG5pbXBvcnQgeyBidWlsZEFwcCB9IGZyb20gJy4vYnVpbGQnO1xuXG5idWlsZEFwcCgpOyJdLAogICJtYXBwaW5ncyI6ICI7OztBQUFBLE9BQU9BLFdBQVU7QUFDakIsT0FBT0MsU0FBUTtBQUNmLFNBQVMsYUFBYTtBQUN0QixPQUFPLG9CQUFvQjtBQUMzQixPQUFPQyxTQUFROzs7QUNKZixPQUFPLFFBQVE7QUFDZixPQUFPLFFBQVE7QUFDZixPQUFPLFVBQVU7QUEwQ1YsU0FBUywrQkFDZCxNQUNBLFlBQ0Esc0JBQWdDLENBQUMsR0FDakMsaUJBQXdDLENBQUMsR0FDekM7QUFDQSxNQUFJLEtBQUssU0FBUyxHQUFHLFdBQVcsY0FBYztBQUM1QyxVQUFNLFlBQVksc0JBQXNCLE1BQU0sVUFBVTtBQUN4RCxRQUFJLFlBQVksQ0FBQyxNQUFNLFlBQVksWUFBWSxDQUFDLEdBQUc7QUFHakQsMEJBQW9CLEtBQUssVUFBVSxDQUFDLEVBQUUsUUFBUSxpQkFBaUIsRUFBRSxDQUFDO0FBQUEsSUFDcEU7QUFBQSxFQUNGO0FBQ0EsTUFBSSxLQUFLLFNBQVMsR0FBRyxXQUFXLFlBQVk7QUFDMUMsU0FBSyxhQUFhLFdBQVM7QUFDekIsVUFBSSxDQUFDLEdBQUcsV0FBVyxxQkFBcUIsR0FBRyxXQUFXLG1CQUFtQixFQUFFLFNBQVMsTUFBTSxJQUFJLEdBQUc7QUFDL0YsY0FBTSxZQUFZLDRCQUE0QixPQUFPLFVBQVU7QUFDL0QsdUJBQWUsS0FBSyxTQUFTO0FBQUEsTUFDL0I7QUFBQSxJQUNGLENBQUM7QUFBQSxFQUNIO0FBRUEsT0FBSyxhQUFhLFdBQVM7QUFDekIsbUNBQStCLE9BQU8sWUFBWSxxQkFBcUIsY0FBYztBQUFBLEVBQ3ZGLENBQUM7QUFDRCxTQUFPO0FBQUEsSUFDTDtBQUFBLElBQ0E7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ZSxRQUFRLE1BQU0sR0FBRztBQUN0QyxtQkFBYSxJQUFJO0FBQ2pCLFlBQU0sU0FBUyxhQUFhLEtBQUssR0FBRztBQUNwQyxNQUFBQSxJQUFHLGNBQWMsTUFBTTtBQUN2QixNQUFBQSxJQUFHLFlBQVksTUFBTSxPQUFPO0FBQUEsSUFDOUIsUUFBUTtBQUFBLElBQUU7QUFBQSxFQUNaO0FBQ0Y7QUFPQSxlQUFzQixRQUFRLFVBQWtCLE1BQWdDLGtCQUFrQixDQUFDLE9BQU8sTUFBTSxHQUFHO0FBQ2pILFFBQU0sUUFBUSxTQUFTLFdBQVcsV0FBVyxTQUFTLFFBQVEsU0FBUyxHQUFHO0FBQzFFLFFBQU0sWUFBWSxNQUFNLElBQUksQ0FBQyxTQUFTO0FBQ3BDLFFBQUksQ0FBQyxnQkFBZ0IsS0FBSyxTQUFPLEtBQUssU0FBUyxHQUFHLENBQUMsRUFBRyxRQUFPO0FBQzdELFdBQU87QUFBQSxNQUNMO0FBQUEsTUFDQSxNQUFPQSxJQUFHLFNBQVMsSUFBSSxFQUFFLFFBQVMsT0FBTztBQUFBLElBQzNDO0FBQUEsRUFDRixDQUFDLEVBQUUsT0FBTyxPQUFPO0FBQ2pCLFFBQU0sWUFBWSxVQUFVLE9BQU8sQ0FBQyxPQUFPLFlBQXNCO0FBQy9ELFdBQU8sUUFBUSxPQUFPO0FBQUEsRUFDeEIsR0FBRyxDQUFDO0FBQ0osVUFBUSxLQUFLLElBQUksVUFBVSxRQUFRLENBQUMsQ0FBQyxjQUFjLElBQUksRUFBRTtBQUMzRDs7O0FJN1FBLFNBQVM7IiwKICAibmFtZXMiOiBbInBhdGgiLCAiZnMiLCAidHMiLCAiY2hpbGQiLCAidGV4dCIsICJwYXRoIiwgInJlcXVpcmUiLCAicGF0aCIsICJmcyIsICJidWlsZCIsICJwYXRoIiwgInRzIl0KfQo=
|