xpine 0.0.4 → 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 ADDED
@@ -0,0 +1,659 @@
1
+ // src/runDevServer.ts
2
+ import expressWs from "express-ws";
3
+ import http from "http";
4
+ import express from "express";
5
+ import EventEmitter from "events";
6
+ import chokidar from "chokidar";
7
+
8
+ // src/scripts/build.ts
9
+ import path3 from "path";
10
+ import fs2 from "fs-extra";
11
+ import { build } from "esbuild";
12
+ import builtinModules from "builtin-modules";
13
+ import ts2 from "typescript";
14
+
15
+ // src/build/typescript-builder.ts
16
+ import ts from "typescript";
17
+ import fs from "fs-extra";
18
+ import path from "path";
19
+ function findDataAttributesAndFunctions(node, sourceFile, foundDataAttributes = [], foundFunctions = []) {
20
+ if (node.kind === ts.SyntaxKind.JsxAttribute) {
21
+ const attribute = getAttributeValuePair(node, sourceFile);
22
+ if (attribute?.[0] === "x-data" && attribute?.[1]) {
23
+ foundDataAttributes.push(attribute[1].replace(/[^a-zA-Z0-9]/g, ""));
24
+ }
25
+ }
26
+ if (node.kind === ts.SyntaxKind.SourceFile) {
27
+ node.forEachChild((child) => {
28
+ if ([ts.SyntaxKind.FunctionDeclaration, ts.SyntaxKind.VariableDeclaration].includes(child.kind)) {
29
+ const functions = getFunctionDeclarationValue(child, sourceFile);
30
+ foundFunctions.push(functions);
31
+ }
32
+ });
33
+ }
34
+ node.forEachChild((child) => {
35
+ findDataAttributesAndFunctions(child, sourceFile, foundDataAttributes, foundFunctions);
36
+ });
37
+ return {
38
+ foundDataAttributes,
39
+ foundFunctions
40
+ };
41
+ }
42
+ function getAttributeValuePair(node, sourceFile) {
43
+ const result = [];
44
+ node.forEachChild((child) => {
45
+ result.push(child.getText(sourceFile));
46
+ });
47
+ return result;
48
+ }
49
+ function getFunctionDeclarationValue(node, sourceFile) {
50
+ const result = {
51
+ name: null,
52
+ isDefaultExport: false,
53
+ hasExport: false
54
+ };
55
+ node.forEachChild((child) => {
56
+ if (child.kind === ts.SyntaxKind.ExportKeyword) {
57
+ result.hasExport = true;
58
+ }
59
+ if (child.kind === ts.SyntaxKind.DefaultKeyword) {
60
+ result.isDefaultExport = true;
61
+ }
62
+ if (child.kind === ts.SyntaxKind.Identifier) {
63
+ result.name = child.getText(sourceFile);
64
+ }
65
+ });
66
+ return result;
67
+ }
68
+ function convertEntryPointsToSingleFile(entryPoints, tempWritePath) {
69
+ fs.writeFileSync(
70
+ tempWritePath,
71
+ entryPoints.map((entry) => `import "${entry}"`).join(";\n")
72
+ );
73
+ }
74
+ function removeClientScriptInTSXFile(pathName) {
75
+ const content = fs.readFileSync(pathName, "utf-8");
76
+ const source = ts.createSourceFile(
77
+ pathName,
78
+ content,
79
+ ts.ScriptTarget.Latest
80
+ );
81
+ let toRemoveFrom;
82
+ let clientDataStart;
83
+ const clientImportsToHoist = [];
84
+ const clientImportsToReplace = [];
85
+ source.forEachChild((child) => {
86
+ if (child.kind === ts.SyntaxKind.ExpressionStatement) {
87
+ const text = child.getText(source);
88
+ if (text.startsWith("<script")) {
89
+ toRemoveFrom = child.pos;
90
+ clientDataStart = child.end;
91
+ }
92
+ }
93
+ if (child.kind === ts.SyntaxKind.ImportDeclaration && child.pos >= clientDataStart) {
94
+ const text = child.getText(source);
95
+ child.forEachChild((child2) => {
96
+ if (child2.kind === ts.SyntaxKind.StringLiteral) {
97
+ const text2 = child2.getText(source);
98
+ const importPath = text2.replace(/[\"\']/g, "");
99
+ const isRelativeImport = importPath.startsWith(".") || importPath.startsWith("/");
100
+ if (!isRelativeImport) return;
101
+ clientImportsToReplace.push({
102
+ old: importPath,
103
+ new: path.join(path.dirname(pathName), importPath)
104
+ });
105
+ }
106
+ });
107
+ clientImportsToHoist.push(text);
108
+ }
109
+ });
110
+ let clientContent = !isNaN(clientDataStart) ? content.slice(clientDataStart) : "";
111
+ for (const clientImport of clientImportsToReplace) {
112
+ clientContent = clientContent.replace(clientImport.old, clientImport.new);
113
+ }
114
+ return {
115
+ content: !isNaN(toRemoveFrom) ? clientImportsToHoist.join("\n") + content.slice(0, toRemoveFrom) : content,
116
+ clientContent,
117
+ fullContent: content,
118
+ toRemoveFrom,
119
+ clientDataStart
120
+ };
121
+ }
122
+
123
+ // src/scripts/build.ts
124
+ import { globSync } from "glob";
125
+ import postcss from "postcss";
126
+ import tailwindPostcss from "@tailwindcss/postcss";
127
+
128
+ // src/util/get-config.ts
129
+ import path2 from "path";
130
+
131
+ // src/util/require.ts
132
+ import { createRequire } from "module";
133
+ var require2 = createRequire(import.meta.url);
134
+ var require_default = require2;
135
+
136
+ // src/util/get-config.ts
137
+ var rootDir = process.cwd();
138
+ function fromRoot(pathName) {
139
+ if (!pathName) return rootDir;
140
+ return path2.join(rootDir, pathName);
141
+ }
142
+ var userConfig = require_default(path2.join(process.cwd(), "./xpine.config.mjs")).default;
143
+ var configDefaults = {
144
+ rootDir: fromRoot(),
145
+ srcDir: fromRoot("./src"),
146
+ distDir: fromRoot("./dist"),
147
+ packageJsonPath: fromRoot("package.json"),
148
+ // We need to use getters here in the event someone wants to change folders, such as the dist folder
149
+ get distPublicDir() {
150
+ return path2.join(this.distDir, "./public");
151
+ },
152
+ get distPublicScriptsDir() {
153
+ return path2.join(this.distPublicDir, "./scripts");
154
+ },
155
+ get distTempFolder() {
156
+ return path2.join(this.distDir, "./temp");
157
+ },
158
+ get clientJSBundlePath() {
159
+ return path2.join(this.distPublicScriptsDir, "./app.js");
160
+ },
161
+ get alpineDataPath() {
162
+ return path2.join(this.distTempFolder, "./alpine-data.ts");
163
+ },
164
+ get serverDistDir() {
165
+ return path2.join(this.distDir, "./server");
166
+ },
167
+ get serverDistAppPath() {
168
+ return path2.join(this.serverDistDir, "./app.js");
169
+ },
170
+ // Important dirs/paths
171
+ get pagesDir() {
172
+ return path2.join(this.srcDir, "./pages");
173
+ },
174
+ get publicDir() {
175
+ return path2.join(this.srcDir, "./public");
176
+ },
177
+ get serverDir() {
178
+ return path2.join(this.srcDir, "./server");
179
+ },
180
+ get runDir() {
181
+ return path2.join(this.serverDir, "./run");
182
+ },
183
+ get serverAppPath() {
184
+ return path2.join(this.serverDir, "./app.ts");
185
+ },
186
+ get globalCSSFile() {
187
+ return path2.join(this.publicDir, "./styles/global.css");
188
+ }
189
+ };
190
+ var config = {
191
+ ...configDefaults,
192
+ ...userConfig
193
+ };
194
+
195
+ // src/scripts/build.ts
196
+ var extensions = [".ts", ".tsx"];
197
+ var packageJson = JSON.parse(fs2.readFileSync(config.packageJsonPath, "utf-8"));
198
+ var allPackages = Object.keys(packageJson.devDependencies).concat(Object.keys(packageJson.dependencies));
199
+ var allPackagesIncludingNode = allPackages.concat(builtinModules);
200
+ async function buildApp(isDev = false) {
201
+ try {
202
+ const srcDirFiles = globSync(config.srcDir + "/**/*.{js,ts,tsx,jsx}");
203
+ const { componentData, dataFiles } = await buildAppFiles(srcDirFiles, isDev);
204
+ const alpineDataFile = await buildAlpineDataFile(componentData, dataFiles);
205
+ await buildClientSideFiles([alpineDataFile], isDev);
206
+ fs2.removeSync(config.distTempFolder);
207
+ await buildCSS();
208
+ await buildPublicFolderSymlinks();
209
+ } catch (err) {
210
+ console.error("Build failed");
211
+ console.error(err);
212
+ }
213
+ }
214
+ async function buildAppFiles(files, isDev) {
215
+ const componentData = [];
216
+ const dataFiles = [];
217
+ const backendFiles = files.filter((file) => extensions.find((ext) => file.endsWith(ext))).filter((file) => !file.startsWith(config.publicDir));
218
+ fs2.ensureDirSync(config.distDir);
219
+ await build({
220
+ entryPoints: backendFiles,
221
+ format: "esm",
222
+ platform: "node",
223
+ outdir: config.distDir,
224
+ bundle: true,
225
+ sourcemap: isDev ? "inline" : false,
226
+ external: allPackages,
227
+ jsx: "transform",
228
+ minify: !isDev,
229
+ plugins: [
230
+ {
231
+ name: "add-dot-js",
232
+ setup(build2) {
233
+ build2.onResolve({ filter: /.*/ }, (args) => {
234
+ const hasAtSign = args.path.startsWith("@");
235
+ const isPackage = hasAtSign ? allPackagesIncludingNode.includes(args.path) : allPackagesIncludingNode.includes(args.path.split("/").shift());
236
+ if (args.importer && !isPackage) {
237
+ const calculatedDir = path3.join(args.resolveDir, args.path);
238
+ let existsAsFile = false;
239
+ for (const extension of extensions) {
240
+ const asFile = calculatedDir + extension;
241
+ const exists = fs2.existsSync(asFile);
242
+ if (exists) existsAsFile = true;
243
+ }
244
+ let outputPath = args.path + (existsAsFile ? "" : "/index") + ".js";
245
+ outputPath = args.path.endsWith(".js") || args.path.endsWith(".mjs") ? args.path : outputPath;
246
+ return { path: outputPath, external: true };
247
+ }
248
+ });
249
+ }
250
+ },
251
+ {
252
+ name: "insert-html-banner-and-remove-client-scripts",
253
+ setup(build2) {
254
+ build2.onLoad({ filter: /.tsx/ }, (args) => {
255
+ const cleanedContent = removeClientScriptInTSXFile(args.path);
256
+ const htmlImportStart = "import { html } from 'xpine';\n";
257
+ const newContent = `${htmlImportStart}${cleanedContent.content}`;
258
+ componentData.push({
259
+ ...args,
260
+ contents: `${htmlImportStart}${cleanedContent.fullContent}`,
261
+ clientContent: cleanedContent.clientContent
262
+ });
263
+ return {
264
+ contents: newContent,
265
+ loader: "tsx"
266
+ };
267
+ });
268
+ }
269
+ },
270
+ {
271
+ name: "get-data-files",
272
+ setup(build2) {
273
+ build2.onLoad({ filter: /\.data\.(js|mjs|ts)$/ }, (args) => {
274
+ const contents = fs2.readFileSync(args.path, "utf-8");
275
+ dataFiles.push({
276
+ ...args,
277
+ contents
278
+ });
279
+ return {
280
+ contents,
281
+ loader: "ts"
282
+ };
283
+ });
284
+ }
285
+ }
286
+ ]
287
+ });
288
+ await logSize(config.distDir, "app");
289
+ return {
290
+ componentData,
291
+ dataFiles
292
+ };
293
+ }
294
+ async function buildClientSideFiles(alpineDataFiles = [], isDev) {
295
+ const tempFilePath = path3.join(config.distTempFolder, "./app.ts");
296
+ fs2.ensureFileSync(tempFilePath);
297
+ const pagesScriptsGlob = config.publicDir + "/scripts/pages/**/*.{js,ts}";
298
+ const clientFiles = globSync(
299
+ config.publicDir + "/**/*.{js,ts}",
300
+ {
301
+ ignore: pagesScriptsGlob
302
+ }
303
+ );
304
+ convertEntryPointsToSingleFile(alpineDataFiles.concat(clientFiles), tempFilePath);
305
+ if (isDev) writeDevServerClientSideCode(tempFilePath);
306
+ writeSpaClientSideCode(tempFilePath);
307
+ await build({
308
+ entryPoints: [tempFilePath],
309
+ bundle: true,
310
+ outdir: config.distPublicScriptsDir,
311
+ minify: !isDev,
312
+ sourcemap: isDev ? "inline" : false
313
+ });
314
+ const pagesFiles = globSync(pagesScriptsGlob);
315
+ await build({
316
+ entryPoints: pagesFiles || [],
317
+ bundle: true,
318
+ outdir: config.distPublicScriptsDir + "/pages",
319
+ minify: !isDev,
320
+ sourcemap: isDev ? "inline" : false
321
+ });
322
+ await logSize(config.distPublicDir, "client");
323
+ }
324
+ function writeDevServerClientSideCode(tempFilePath) {
325
+ const devServerPath = path3.join(import.meta.dirname, "../static/dev-server.js");
326
+ const content = fs2.readFileSync(devServerPath, "utf-8");
327
+ fs2.appendFileSync(tempFilePath, `
328
+ ` + content);
329
+ }
330
+ function writeSpaClientSideCode(tempFilePath) {
331
+ const spaPath = path3.join(import.meta.dirname, "../static/spa.js");
332
+ const content = fs2.readFileSync(spaPath, "utf-8");
333
+ fs2.appendFileSync(tempFilePath, `
334
+ ` + content);
335
+ }
336
+ async function buildAlpineDataFile(componentData, dataFiles) {
337
+ const output = {
338
+ imports: [
339
+ "import Alpine from 'alpinejs';"
340
+ ],
341
+ code: [],
342
+ end: [
343
+ "window.Alpine = Alpine;"
344
+ ]
345
+ };
346
+ const dataFunctionResults = {
347
+ foundDataAttributes: [],
348
+ foundFunctions: [],
349
+ foundImports: []
350
+ };
351
+ const componentsAndDataFiles = componentData.concat(dataFiles);
352
+ for (const component of componentsAndDataFiles) {
353
+ const sourceFile = ts2.createSourceFile(
354
+ component.path,
355
+ component.contents,
356
+ ts2.ScriptTarget.Latest
357
+ );
358
+ const dataFunctionResult = findDataAttributesAndFunctions(sourceFile, sourceFile);
359
+ dataFunctionResults.foundDataAttributes.push(...dataFunctionResult.foundDataAttributes);
360
+ const foundFunctionsWithPath = dataFunctionResult.foundFunctions.map((item) => {
361
+ return {
362
+ ...item,
363
+ path: component.path,
364
+ content: component.clientContent
365
+ };
366
+ });
367
+ dataFunctionResults.foundFunctions.push(...foundFunctionsWithPath);
368
+ }
369
+ const validDataFunctions = dataFunctionResults.foundFunctions.filter((item) => {
370
+ return dataFunctionResults.foundDataAttributes.includes(item.name) && item.content;
371
+ });
372
+ for (const dataFunction of validDataFunctions) {
373
+ if (!dataFunction.hasExport) continue;
374
+ output.code.push(dataFunction.content);
375
+ output.code.push(`Alpine.data('${dataFunction.name}', ${dataFunction.name});`);
376
+ }
377
+ const result = output.imports.join("\n") + "\n" + output.code.join("\n") + "\n" + output.end.join("\n");
378
+ fs2.ensureFileSync(config.alpineDataPath);
379
+ fs2.writeFileSync(config.alpineDataPath, result);
380
+ return config.alpineDataPath;
381
+ }
382
+ async function buildCSS() {
383
+ const cssFiles = globSync(config.srcDir + "/**/*.css");
384
+ for (const file of cssFiles) {
385
+ const fileContents = fs2.readFileSync(file, "utf-8");
386
+ const result = await postcss([tailwindPostcss()]).process(fileContents, { from: file });
387
+ const newPath = file.replace(config.srcDir, config.distDir);
388
+ fs2.ensureFileSync(newPath);
389
+ fs2.writeFileSync(newPath, result.css);
390
+ }
391
+ logSize(config.distPublicDir, "css");
392
+ }
393
+ async function buildPublicFolderSymlinks() {
394
+ const files = globSync(config.publicDir + "/**/*.*", {
395
+ ignore: "/**/*.{css,js,ts,tsx,jsx}"
396
+ });
397
+ for (const file of files) {
398
+ try {
399
+ const newPath = file.replace(config.srcDir, config.distDir);
400
+ const splitNewPath = newPath.split("/");
401
+ splitNewPath.pop();
402
+ const newDir = splitNewPath.join("/");
403
+ fs2.ensureDirSync(newDir);
404
+ fs2.symlinkSync(file, newPath);
405
+ } catch {
406
+ }
407
+ }
408
+ }
409
+ async function logSize(pathName, type, validExtensions = [".js", ".css"]) {
410
+ const files = globSync(pathName + "/**/*" + (type === "css" ? ".css" : ""));
411
+ const fileSizes = files.map((file) => {
412
+ if (!validExtensions.find((ext) => file.endsWith(ext))) return false;
413
+ return {
414
+ file,
415
+ size: fs2.statSync(file).size / (1024 * 1e3)
416
+ };
417
+ }).filter(Boolean);
418
+ const totalSize = fileSizes.reduce((total, current) => {
419
+ return current.size + total;
420
+ }, 0);
421
+ console.info(`[${totalSize.toFixed(3)} MB] Built ${type}`);
422
+ }
423
+
424
+ // src/runDevServer.ts
425
+ import path5 from "path";
426
+
427
+ // src/util/env.ts
428
+ import dotenv from "dotenv";
429
+ import path4 from "path";
430
+ function setupEnv() {
431
+ dotenv.config({ path: path4.join(config.rootDir, `./.env.${process.env.STAGE || "dev"}`) });
432
+ }
433
+
434
+ // src/runDevServer.ts
435
+ setupEnv();
436
+ async function runDevServer() {
437
+ process.env.NODE_ENV = "development";
438
+ const startServer = await import(config.serverDistAppPath + `?cache=${Date.now()}`);
439
+ await buildApp(true);
440
+ let appServer = await startServer.default();
441
+ const watcher = chokidar.watch(config.srcDir, {
442
+ ignoreInitial: true,
443
+ // Ignore map and prisma files
444
+ ignored: (pathName) => pathName.endsWith(".map") || pathName.startsWith(path5.join(config.serverDir, "./prisma"))
445
+ });
446
+ watcher.on("all", async (event, path6) => {
447
+ const shouldReloadServer = path6.startsWith(config.serverDir) && !path6.startsWith(config.runDir) || ["add", "unlink"].includes(event) && path6.startsWith(config.pagesDir);
448
+ if (shouldReloadServer) {
449
+ appServer.server.close();
450
+ await buildApp(true);
451
+ const startServer2 = await import(config.serverDistAppPath + `?cache=${Date.now()}`);
452
+ appServer = await startServer2.default();
453
+ return;
454
+ }
455
+ await buildApp(true);
456
+ refreshEmitter.emit("refresh");
457
+ });
458
+ const wsApp = express();
459
+ const wsServer = http.createServer(wsApp);
460
+ expressWs(wsApp, wsServer);
461
+ class RefreshEmitter extends EventEmitter {
462
+ }
463
+ ;
464
+ const refreshEmitter = new RefreshEmitter();
465
+ wsApp.ws("/dev-server", function(ws) {
466
+ refreshEmitter.removeAllListeners();
467
+ refreshEmitter.on("refresh", () => {
468
+ ws.send("refresh:client");
469
+ });
470
+ });
471
+ const wsPort = 3001;
472
+ wsServer.listen(wsPort);
473
+ wsServer.on("listening", () => {
474
+ console.info(`Dev server listening on port ${wsPort}`);
475
+ });
476
+ }
477
+
478
+ // src/express.ts
479
+ import express2 from "express";
480
+ import { globSync as globSync2 } from "glob";
481
+
482
+ // src/auth.ts
483
+ import jsonwebtoken from "jsonwebtoken";
484
+ var { verify, sign } = jsonwebtoken;
485
+ async function signUser(email, username) {
486
+ return new Promise((resolve, reject) => {
487
+ sign(
488
+ {
489
+ user: {
490
+ email,
491
+ username
492
+ }
493
+ },
494
+ // @ts-ignore
495
+ process.env.JWT_PRIVATE_KEY,
496
+ { expiresIn: "30d" },
497
+ (err, token) => {
498
+ if (err) reject(err);
499
+ resolve(token);
500
+ }
501
+ );
502
+ });
503
+ }
504
+ async function verifyUser(token) {
505
+ return new Promise((resolve, reject) => {
506
+ verify(token, process.env.JWT_PRIVATE_KEY, (err, authorizedData) => {
507
+ if (err) reject(err);
508
+ resolve(authorizedData);
509
+ });
510
+ });
511
+ }
512
+ function getTokenFromRequest(req) {
513
+ const { authorization } = req.headers;
514
+ if (!authorization) return null;
515
+ const token = authorization.split(" ").pop() || "";
516
+ return token || null;
517
+ }
518
+
519
+ // src/express.ts
520
+ import requestIP from "request-ip";
521
+ var doctypeHTML = "<!DOCTYPE html>";
522
+ async function createRouter() {
523
+ const methods = ["get", "post", "put", "patch", "delete"];
524
+ const router = express2.Router();
525
+ const routes = globSync2(config.pagesDir + "/**/*.{tsx,ts}");
526
+ const routeMap = routes.map((route) => {
527
+ return {
528
+ route: route.split(config.pagesDir).pop().replace(".tsx", "").replace(".js", "").replace(".ts", "").replace("/index", "/"),
529
+ path: route.replace(config.srcDir, config.distDir).replace(".tsx", ".js").replace(".ts", ".js"),
530
+ originalRoute: route
531
+ };
532
+ });
533
+ const routeResults = [];
534
+ for (const route of routeMap) {
535
+ const isJSX = route.originalRoute.endsWith(".tsx") || route.originalRoute.endsWith(".jsx");
536
+ const routeItem = process.env.NODE_ENV === "development" ? null : (await import(route.path)).default;
537
+ const slugRoute = route.route.toLowerCase().replace(/[ ]/g, "");
538
+ const foundMethod = methods.find((method) => slugRoute.endsWith(`.${method}`));
539
+ const isDynamicRoute = slugRoute.match(/\[(.*)\]/g);
540
+ let formattedRouteItem = slugRoute;
541
+ if (foundMethod) formattedRouteItem = formattedRouteItem.split(".").shift();
542
+ if (isDynamicRoute) {
543
+ const result = [...formattedRouteItem.matchAll(/(\[)(.*?)(\])/g)];
544
+ for (const match of result) {
545
+ formattedRouteItem = formattedRouteItem.replace(match[0], ":" + match[2]);
546
+ }
547
+ }
548
+ routeResults.push({
549
+ formattedRouteItem,
550
+ foundMethod,
551
+ route
552
+ });
553
+ router[foundMethod || "get"](formattedRouteItem, async (req, res) => {
554
+ try {
555
+ if (routeItem) {
556
+ if (isJSX) {
557
+ res.send(doctypeHTML + await routeItem(req, res));
558
+ } else {
559
+ await routeItem(req, res);
560
+ }
561
+ return;
562
+ }
563
+ const defaultRouteImport = (await import(route.path + `?cache=${Date.now()}`)).default;
564
+ if (isJSX) {
565
+ res.send(doctypeHTML + await defaultRouteImport(req, res));
566
+ } else {
567
+ await defaultRouteImport(req, res);
568
+ }
569
+ } catch (err) {
570
+ console.error(err);
571
+ res.status(err?.status || 500).send(err?.message || "Error");
572
+ }
573
+ });
574
+ }
575
+ return {
576
+ router,
577
+ routeResults
578
+ };
579
+ }
580
+ async function verifyUserMiddleware(req, _res, next) {
581
+ const { usertoken } = req.cookies;
582
+ if (!usertoken) {
583
+ req.user = null;
584
+ }
585
+ try {
586
+ const { user } = await verifyUser(usertoken);
587
+ req.user = user;
588
+ } catch (err) {
589
+ req.user = null;
590
+ }
591
+ next();
592
+ }
593
+ async function createXPineRouter(app, beforeErrorRoute) {
594
+ app.use(express2.static(config.distPublicDir));
595
+ app.use(verifyUserMiddleware);
596
+ app.use(requestIP.mw());
597
+ const { router, routeResults } = await createRouter();
598
+ app.use(function replaceableRouter(req, res, next) {
599
+ router(req, res, next);
600
+ });
601
+ const found404 = routeResults?.find((item) => item?.formattedRouteItem === "/404");
602
+ const import404 = process.env.NODE_ENV === "development" ? null : (await import(found404.route.path)).default;
603
+ if (beforeErrorRoute) beforeErrorRoute(app);
604
+ app.use(async function(req, res) {
605
+ res.status(404);
606
+ if (import404) {
607
+ res.send(doctypeHTML + await import404(req, res));
608
+ } else if (found404 && process.env.NODE_ENV === "development") {
609
+ const import404Item = (await import(found404.route.path + `?cache=${Date.now()}`)).default;
610
+ res.send(doctypeHTML + await import404Item(req, res));
611
+ } else {
612
+ res.send("Error");
613
+ }
614
+ });
615
+ }
616
+
617
+ // src/util/html.ts
618
+ var html = class {
619
+ static attributeObjectToString(props) {
620
+ if (!props) return "";
621
+ return Object.entries(props).filter(([, value]) => value !== null && value !== void 0).map(([key, value], index) => {
622
+ const start = index === 0 ? " " : "";
623
+ return `${start}${key}="${value}"`;
624
+ }).join(" ");
625
+ }
626
+ static async fragment(props) {
627
+ const childrenResult = await Promise.all(props.children.flat());
628
+ return childrenResult.filter(Boolean).join("");
629
+ }
630
+ static async createElement(type, props, ...children) {
631
+ const childrenResult = await Promise.all(children.flat());
632
+ if (typeof type === "function") {
633
+ const result = await type({ ...props, children: childrenResult });
634
+ return result;
635
+ }
636
+ return `<${type}${this.attributeObjectToString(props)}>${childrenResult.filter(Boolean).join("")}</${type}>`;
637
+ }
638
+ };
639
+ function JSXRuntime() {
640
+ return true;
641
+ }
642
+ export {
643
+ JSXRuntime,
644
+ buildApp,
645
+ buildCSS,
646
+ buildPublicFolderSymlinks,
647
+ config,
648
+ createRouter,
649
+ createXPineRouter,
650
+ fromRoot,
651
+ getTokenFromRequest,
652
+ html,
653
+ logSize,
654
+ runDevServer,
655
+ setupEnv,
656
+ signUser,
657
+ verifyUser
658
+ };
659
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3J1bkRldlNlcnZlci50cyIsICIuLi9zcmMvc2NyaXB0cy9idWlsZC50cyIsICIuLi9zcmMvYnVpbGQvdHlwZXNjcmlwdC1idWlsZGVyLnRzIiwgIi4uL3NyYy91dGlsL2dldC1jb25maWcudHMiLCAiLi4vc3JjL3V0aWwvcmVxdWlyZS50cyIsICIuLi9zcmMvdXRpbC9lbnYudHMiLCAiLi4vc3JjL2V4cHJlc3MudHMiLCAiLi4vc3JjL2F1dGgudHMiLCAiLi4vc3JjL3V0aWwvaHRtbC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IGV4cHJlc3NXcyBmcm9tICdleHByZXNzLXdzJztcbmltcG9ydCBodHRwIGZyb20gJ2h0dHAnO1xuaW1wb3J0IGV4cHJlc3MgZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgRXZlbnRFbWl0dGVyIGZyb20gJ2V2ZW50cyc7XG5pbXBvcnQgY2hva2lkYXIgZnJvbSAnY2hva2lkYXInO1xuaW1wb3J0IHsgYnVpbGRBcHAgfSBmcm9tICcuL3NjcmlwdHMvYnVpbGQnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBjb25maWcgfSBmcm9tICcuL3V0aWwvZ2V0LWNvbmZpZyc7XG5pbXBvcnQgeyBzZXR1cEVudiB9IGZyb20gJy4vdXRpbC9lbnYnO1xuXG5zZXR1cEVudigpO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuRGV2U2VydmVyKCkge1xuICBwcm9jZXNzLmVudi5OT0RFX0VOViA9ICdkZXZlbG9wbWVudCc7XG4gIGNvbnN0IHN0YXJ0U2VydmVyID0gYXdhaXQgaW1wb3J0KGNvbmZpZy5zZXJ2ZXJEaXN0QXBwUGF0aCArIGA/Y2FjaGU9JHtEYXRlLm5vdygpfWApO1xuXG4gIC8vIEluaXRpYWwgc2VydmVyIHNldCB1cFxuICBhd2FpdCBidWlsZEFwcCh0cnVlKTtcbiAgbGV0IGFwcFNlcnZlciA9IGF3YWl0IHN0YXJ0U2VydmVyLmRlZmF1bHQoKTtcblxuICAvLyBXYXRjaCBmaWxlc1xuICBjb25zdCB3YXRjaGVyID0gY2hva2lkYXIud2F0Y2goY29uZmlnLnNyY0Rpciwge1xuICAgIGlnbm9yZUluaXRpYWw6IHRydWUsXG4gICAgLy8gSWdub3JlIG1hcCBhbmQgcHJpc21hIGZpbGVzXG4gICAgaWdub3JlZDogKHBhdGhOYW1lKSA9PiBwYXRoTmFtZS5lbmRzV2l0aCgnLm1hcCcpIHx8IHBhdGhOYW1lLnN0YXJ0c1dpdGgocGF0aC5qb2luKGNvbmZpZy5zZXJ2ZXJEaXIsICcuL3ByaXNtYScpKSxcbiAgfSk7XG4gIHdhdGNoZXIub24oJ2FsbCcsIGFzeW5jIChldmVudCwgcGF0aCkgPT4ge1xuICAgIGNvbnN0IHNob3VsZFJlbG9hZFNlcnZlciA9IChwYXRoLnN0YXJ0c1dpdGgoY29uZmlnLnNlcnZlckRpcikgJiYgIXBhdGguc3RhcnRzV2l0aChjb25maWcucnVuRGlyKSkgfHxcbiAgICAgIFsnYWRkJywgJ3VubGluayddLmluY2x1ZGVzKGV2ZW50KSAmJiBwYXRoLnN0YXJ0c1dpdGgoY29uZmlnLnBhZ2VzRGlyKTtcbiAgICBpZiAoc2hvdWxkUmVsb2FkU2VydmVyKSB7XG4gICAgICAvLyBXZSBtb2RpZmllZCBmaWxlcyBpbiB0aGUgc2VydmVyLCByZXN0YXJ0IHRoZSBzZXJ2ZXJcbiAgICAgIGFwcFNlcnZlci5zZXJ2ZXIuY2xvc2UoKTtcbiAgICAgIGF3YWl0IGJ1aWxkQXBwKHRydWUpO1xuICAgICAgY29uc3Qgc3RhcnRTZXJ2ZXIgPSBhd2FpdCBpbXBvcnQoY29uZmlnLnNlcnZlckRpc3RBcHBQYXRoICsgYD9jYWNoZT0ke0RhdGUubm93KCl9YCk7XG4gICAgICBhcHBTZXJ2ZXIgPSBhd2FpdCBzdGFydFNlcnZlci5kZWZhdWx0KCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGF3YWl0IGJ1aWxkQXBwKHRydWUpO1xuICAgIHJlZnJlc2hFbWl0dGVyLmVtaXQoJ3JlZnJlc2gnKTtcbiAgfSk7XG5cbiAgLy8gQ3JlYXRlIHdlYiBzb2NrZXQgc2V2ZXJcbiAgY29uc3Qgd3NBcHAgPSBleHByZXNzKCk7XG4gIGNvbnN0IHdzU2VydmVyID0gaHR0cC5jcmVhdGVTZXJ2ZXIod3NBcHApO1xuICBleHByZXNzV3Mod3NBcHAsIHdzU2VydmVyKTtcbiAgY2xhc3MgUmVmcmVzaEVtaXR0ZXIgZXh0ZW5kcyBFdmVudEVtaXR0ZXIgeyB9O1xuICBjb25zdCByZWZyZXNoRW1pdHRlciA9IG5ldyBSZWZyZXNoRW1pdHRlcigpO1xuXG4gIC8vIEB0cy1pZ25vcmVcbiAgd3NBcHAud3MoJy9kZXYtc2VydmVyJywgZnVuY3Rpb24gKHdzKSB7XG4gICAgcmVmcmVzaEVtaXR0ZXIucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgcmVmcmVzaEVtaXR0ZXIub24oJ3JlZnJlc2gnLCAoKSA9PiB7XG4gICAgICB3cy5zZW5kKCdyZWZyZXNoOmNsaWVudCcpO1xuICAgIH0pO1xuICB9KTtcblxuICBjb25zdCB3c1BvcnQgPSAzMDAxO1xuICB3c1NlcnZlci5saXN0ZW4od3NQb3J0KTtcbiAgd3NTZXJ2ZXIub24oJ2xpc3RlbmluZycsICgpID0+IHtcbiAgICBjb25zb2xlLmluZm8oYERldiBzZXJ2ZXIgbGlzdGVuaW5nIG9uIHBvcnQgJHt3c1BvcnR9YCk7XG4gIH0pO1xufVxuXG5cbiIsICJpbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgeyBidWlsZCB9IGZyb20gJ2VzYnVpbGQnO1xuaW1wb3J0IGJ1aWx0aW5Nb2R1bGVzIGZyb20gJ2J1aWx0aW4tbW9kdWxlcyc7XG5pbXBvcnQgdHMgZnJvbSAndHlwZXNjcmlwdCc7XG5pbXBvcnQge1xuICBjb252ZXJ0RW50cnlQb2ludHNUb1NpbmdsZUZpbGUsXG4gIGZpbmREYXRhQXR0cmlidXRlc0FuZEZ1bmN0aW9ucyxcbiAgcmVtb3ZlQ2xpZW50U2NyaXB0SW5UU1hGaWxlXG59IGZyb20gJy4uL2J1aWxkL3R5cGVzY3JpcHQtYnVpbGRlcic7XG5pbXBvcnQgeyBnbG9iU3luYyB9IGZyb20gJ2dsb2InO1xuaW1wb3J0IHBvc3Rjc3MgZnJvbSAncG9zdGNzcyc7XG4vLyBAdHMtaWdub3JlXG5pbXBvcnQgdGFpbHdpbmRQb3N0Y3NzIGZyb20gJ0B0YWlsd2luZGNzcy9wb3N0Y3NzJztcbmltcG9ydCB7IGNvbmZpZyB9IGZyb20gJy4uL3V0aWwvZ2V0LWNvbmZpZyc7XG5cbi8vIEV4dGVuc2lvbnMgdG8gbG9vayBmb3IgaW4gdGhlIGJ1bmRsZVxuY29uc3QgZXh0ZW5zaW9ucyA9IFsnLnRzJywgJy50c3gnXTtcbmNvbnN0IHBhY2thZ2VKc29uID0gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMoY29uZmlnLnBhY2thZ2VKc29uUGF0aCwgJ3V0Zi04JykpO1xuY29uc3QgYWxsUGFja2FnZXMgPSBPYmplY3Qua2V5cyhwYWNrYWdlSnNvbi5kZXZEZXBlbmRlbmNpZXMpLmNvbmNhdChPYmplY3Qua2V5cyhwYWNrYWdlSnNvbi5kZXBlbmRlbmNpZXMpKTtcbmNvbnN0IGFsbFBhY2thZ2VzSW5jbHVkaW5nTm9kZSA9IGFsbFBhY2thZ2VzLmNvbmNhdChidWlsdGluTW9kdWxlcyk7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWlsZEFwcChpc0RldiA9IGZhbHNlKSB7XG4gIHRyeSB7XG4gICAgY29uc3Qgc3JjRGlyRmlsZXMgPSBnbG9iU3luYyhjb25maWcuc3JjRGlyICsgJy8qKi8qLntqcyx0cyx0c3gsanN4fScpO1xuICAgIGNvbnN0IHsgY29tcG9uZW50RGF0YSwgZGF0YUZpbGVzLCB9ID0gYXdhaXQgYnVpbGRBcHBGaWxlcyhzcmNEaXJGaWxlcywgaXNEZXYpO1xuICAgIGNvbnN0IGFscGluZURhdGFGaWxlID0gYXdhaXQgYnVpbGRBbHBpbmVEYXRhRmlsZShjb21wb25lbnREYXRhLCBkYXRhRmlsZXMpO1xuICAgIGF3YWl0IGJ1aWxkQ2xpZW50U2lkZUZpbGVzKFthbHBpbmVEYXRhRmlsZV0sIGlzRGV2KTtcbiAgICBmcy5yZW1vdmVTeW5jKGNvbmZpZy5kaXN0VGVtcEZvbGRlcik7XG4gICAgYXdhaXQgYnVpbGRDU1MoKTtcbiAgICBhd2FpdCBidWlsZFB1YmxpY0ZvbGRlclN5bWxpbmtzKCk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGNvbnNvbGUuZXJyb3IoJ0J1aWxkIGZhaWxlZCcpO1xuICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBidWlsZEFwcEZpbGVzKGZpbGVzOiBzdHJpbmdbXSwgaXNEZXY/OiBib29sZWFuKSB7XG4gIGNvbnN0IGNvbXBvbmVudERhdGEgPSBbXTtcbiAgY29uc3QgZGF0YUZpbGVzID0gW107XG4gIC8vIEZpbHRlciBvdXQgY2xpZW50IHNpZGUgZmlsZXMgYW5kIGZpbGVzIHRoYXQgYXJlbid0IG9mIHRoZSBhbGxvd2VkIGV4dGVuc2lvbnNcbiAgY29uc3QgYmFja2VuZEZpbGVzID0gZmlsZXNcbiAgICAuZmlsdGVyKChmaWxlKSA9PiBleHRlbnNpb25zLmZpbmQoZXh0ID0+IGZpbGUuZW5kc1dpdGgoZXh0KSkpXG4gICAgLmZpbHRlcigoZmlsZSkgPT4gIWZpbGUuc3RhcnRzV2l0aChjb25maWcucHVibGljRGlyKSk7XG4gIGZzLmVuc3VyZURpclN5bmMoY29uZmlnLmRpc3REaXIpO1xuICAvLyBCdWlsZCBiYWNrZW5kL1NTUiBUU1ggbW9kdWxlc1xuICBhd2FpdCBidWlsZCh7XG4gICAgZW50cnlQb2ludHM6IGJhY2tlbmRGaWxlcyxcbiAgICBmb3JtYXQ6ICdlc20nLFxuICAgIHBsYXRmb3JtOiAnbm9kZScsXG4gICAgb3V0ZGlyOiBjb25maWcuZGlzdERpcixcbiAgICBidW5kbGU6IHRydWUsXG4gICAgc291cmNlbWFwOiBpc0RldiA/ICdpbmxpbmUnIDogZmFsc2UsXG4gICAgZXh0ZXJuYWw6IGFsbFBhY2thZ2VzLFxuICAgIGpzeDogJ3RyYW5zZm9ybScsXG4gICAgbWluaWZ5OiAhaXNEZXYsXG4gICAgcGx1Z2luczogW1xuICAgICAge1xuICAgICAgICBuYW1lOiAnYWRkLWRvdC1qcycsXG4gICAgICAgIHNldHVwKGJ1aWxkKSB7XG4gICAgICAgICAgYnVpbGQub25SZXNvbHZlKHsgZmlsdGVyOiAvLiovLCB9LCBhcmdzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGhhc0F0U2lnbiA9IGFyZ3MucGF0aC5zdGFydHNXaXRoKCdAJyk7XG4gICAgICAgICAgICBjb25zdCBpc1BhY2thZ2UgPSBoYXNBdFNpZ24gP1xuICAgICAgICAgICAgICBhbGxQYWNrYWdlc0luY2x1ZGluZ05vZGUuaW5jbHVkZXMoYXJncy5wYXRoKSA6XG4gICAgICAgICAgICAgIGFsbFBhY2thZ2VzSW5jbHVkaW5nTm9kZS5pbmNsdWRlcyhhcmdzLnBhdGguc3BsaXQoJy8nKS5zaGlmdCgpKTtcbiAgICAgICAgICAgIGlmIChhcmdzLmltcG9ydGVyICYmICFpc1BhY2thZ2UpIHtcbiAgICAgICAgICAgICAgLy8gSWYgd2UncmUgZG9pbmcgYW4gaW5kZXggaW1wb3J0IHdlIG5lZWQgL2luZGV4LmpzXG4gICAgICAgICAgICAgIGNvbnN0IGNhbGN1bGF0ZWREaXIgPSBwYXRoLmpvaW4oYXJncy5yZXNvbHZlRGlyLCBhcmdzLnBhdGgpO1xuICAgICAgICAgICAgICBsZXQgZXhpc3RzQXNGaWxlID0gZmFsc2U7XG4gICAgICAgICAgICAgIGZvciAoY29uc3QgZXh0ZW5zaW9uIG9mIGV4dGVuc2lvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhc0ZpbGUgPSBjYWxjdWxhdGVkRGlyICsgZXh0ZW5zaW9uO1xuICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0cyA9IGZzLmV4aXN0c1N5bmMoYXNGaWxlKTtcbiAgICAgICAgICAgICAgICBpZiAoZXhpc3RzKSBleGlzdHNBc0ZpbGUgPSB0cnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGxldCBvdXRwdXRQYXRoID0gYXJncy5wYXRoICsgKGV4aXN0c0FzRmlsZSA/ICcnIDogJy9pbmRleCcpICsgJy5qcyc7XG4gICAgICAgICAgICAgIG91dHB1dFBhdGggPSBhcmdzLnBhdGguZW5kc1dpdGgoJy5qcycpIHx8IGFyZ3MucGF0aC5lbmRzV2l0aCgnLm1qcycpID8gYXJncy5wYXRoIDogb3V0cHV0UGF0aDtcbiAgICAgICAgICAgICAgcmV0dXJuIHsgcGF0aDogb3V0cHV0UGF0aCwgZXh0ZXJuYWw6IHRydWUsIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBuYW1lOiAnaW5zZXJ0LWh0bWwtYmFubmVyLWFuZC1yZW1vdmUtY2xpZW50LXNjcmlwdHMnLFxuICAgICAgICBzZXR1cChidWlsZCkge1xuICAgICAgICAgIGJ1aWxkLm9uTG9hZCh7IGZpbHRlcjogLy50c3gvLCB9LCBhcmdzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNsZWFuZWRDb250ZW50ID0gcmVtb3ZlQ2xpZW50U2NyaXB0SW5UU1hGaWxlKGFyZ3MucGF0aCk7XG4gICAgICAgICAgICBjb25zdCBodG1sSW1wb3J0U3RhcnQgPSAnaW1wb3J0IHsgaHRtbCB9IGZyb20gXFwneHBpbmVcXCc7XFxuJztcbiAgICAgICAgICAgIGNvbnN0IG5ld0NvbnRlbnQgPSBgJHtodG1sSW1wb3J0U3RhcnR9JHtjbGVhbmVkQ29udGVudC5jb250ZW50fWA7XG4gICAgICAgICAgICBjb21wb25lbnREYXRhLnB1c2goe1xuICAgICAgICAgICAgICAuLi5hcmdzLFxuICAgICAgICAgICAgICBjb250ZW50czogYCR7aHRtbEltcG9ydFN0YXJ0fSR7Y2xlYW5lZENvbnRlbnQuZnVsbENvbnRlbnR9YCxcbiAgICAgICAgICAgICAgY2xpZW50Q29udGVudDogY2xlYW5lZENvbnRlbnQuY2xpZW50Q29udGVudCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgY29udGVudHM6IG5ld0NvbnRlbnQsXG4gICAgICAgICAgICAgIGxvYWRlcjogJ3RzeCcsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ2dldC1kYXRhLWZpbGVzJyxcbiAgICAgICAgc2V0dXAoYnVpbGQpIHtcbiAgICAgICAgICBidWlsZC5vbkxvYWQoeyBmaWx0ZXI6IC9cXC5kYXRhXFwuKGpzfG1qc3x0cykkLywgfSwgYXJncyA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb250ZW50cyA9IGZzLnJlYWRGaWxlU3luYyhhcmdzLnBhdGgsICd1dGYtOCcpO1xuICAgICAgICAgICAgZGF0YUZpbGVzLnB1c2goe1xuICAgICAgICAgICAgICAuLi5hcmdzLFxuICAgICAgICAgICAgICBjb250ZW50cyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgY29udGVudHMsXG4gICAgICAgICAgICAgIGxvYWRlcjogJ3RzJyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgXSxcbiAgfSk7XG4gIGF3YWl0IGxvZ1NpemUoY29uZmlnLmRpc3REaXIsICdhcHAnKTtcbiAgcmV0dXJuIHtcbiAgICBjb21wb25lbnREYXRhLFxuICAgIGRhdGFGaWxlcyxcbiAgfTtcbn1cblxuLy8gQnVpbGQgY2xpZW50IHNpZGUgZmlsZXNcbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkQ2xpZW50U2lkZUZpbGVzKGFscGluZURhdGFGaWxlczogc3RyaW5nW10gPSBbXSwgaXNEZXY/OiBib29sZWFuKSB7XG4gIC8vIFdyaXRlIHRoZSB0ZW1wIGZpbGUgdG8gdXNlXG4gIGNvbnN0IHRlbXBGaWxlUGF0aCA9IHBhdGguam9pbihjb25maWcuZGlzdFRlbXBGb2xkZXIsICcuL2FwcC50cycpO1xuICBmcy5lbnN1cmVGaWxlU3luYyh0ZW1wRmlsZVBhdGgpO1xuICAvLyBHZXQgYWxsIHRzL2pzIGZpbGVzIGluIHB1YmxpYyBmb2xkZXIgYnV0IGlnbm9yZSB0aGUgcGFnZXMgc2NyaXB0c1xuICBjb25zdCBwYWdlc1NjcmlwdHNHbG9iID0gY29uZmlnLnB1YmxpY0RpciArICcvc2NyaXB0cy9wYWdlcy8qKi8qLntqcyx0c30nO1xuICBjb25zdCBjbGllbnRGaWxlcyA9IGdsb2JTeW5jKFxuICAgIGNvbmZpZy5wdWJsaWNEaXIgKyAnLyoqLyoue2pzLHRzfScsXG4gICAge1xuICAgICAgaWdub3JlOiBwYWdlc1NjcmlwdHNHbG9iLFxuICAgIH1cbiAgKTtcbiAgLy8gRmlsdGVyIG91dCBhbGwgcHVibGljL3BhZ2VzIGZpbGVzXG4gIGNvbnZlcnRFbnRyeVBvaW50c1RvU2luZ2xlRmlsZShhbHBpbmVEYXRhRmlsZXMuY29uY2F0KGNsaWVudEZpbGVzKSwgdGVtcEZpbGVQYXRoKTtcbiAgLy8gV3JpdGUgZGV2IHNlcnZlciBjb2RlIHRvIHRoZSB0ZW1wIGZpbGUgcGF0aFxuICBpZiAoaXNEZXYpIHdyaXRlRGV2U2VydmVyQ2xpZW50U2lkZUNvZGUodGVtcEZpbGVQYXRoKTtcbiAgLy8gV3JpdGUgc3BhIGZ1bmN0aW9uYWxpdHkgdG8gdGhlIHRlbXAgZmlsZSBwYXRoXG4gIHdyaXRlU3BhQ2xpZW50U2lkZUNvZGUodGVtcEZpbGVQYXRoKTtcbiAgYXdhaXQgYnVpbGQoe1xuICAgIGVudHJ5UG9pbnRzOiBbdGVtcEZpbGVQYXRoXSxcbiAgICBidW5kbGU6IHRydWUsXG4gICAgb3V0ZGlyOiBjb25maWcuZGlzdFB1YmxpY1NjcmlwdHNEaXIsXG4gICAgbWluaWZ5OiAhaXNEZXYsXG4gICAgc291cmNlbWFwOiBpc0RldiA/ICdpbmxpbmUnIDogZmFsc2UsXG4gIH0pO1xuICAvLyBCdWlsZCBwYWdlcyBmaWxlcyBzY3JpcHRzXG4gIGNvbnN0IHBhZ2VzRmlsZXMgPSBnbG9iU3luYyhwYWdlc1NjcmlwdHNHbG9iKTtcbiAgYXdhaXQgYnVpbGQoe1xuICAgIGVudHJ5UG9pbnRzOiBwYWdlc0ZpbGVzIHx8IFtdLFxuICAgIGJ1bmRsZTogdHJ1ZSxcbiAgICBvdXRkaXI6IGNvbmZpZy5kaXN0UHVibGljU2NyaXB0c0RpciArICcvcGFnZXMnLFxuICAgIG1pbmlmeTogIWlzRGV2LFxuICAgIHNvdXJjZW1hcDogaXNEZXYgPyAnaW5saW5lJyA6IGZhbHNlLFxuICB9KTtcbiAgYXdhaXQgbG9nU2l6ZShjb25maWcuZGlzdFB1YmxpY0RpciwgJ2NsaWVudCcpO1xufVxuXG5mdW5jdGlvbiB3cml0ZURldlNlcnZlckNsaWVudFNpZGVDb2RlKHRlbXBGaWxlUGF0aDogc3RyaW5nKSB7XG4gIGNvbnN0IGRldlNlcnZlclBhdGggPSBwYXRoLmpvaW4oaW1wb3J0Lm1ldGEuZGlybmFtZSwgJy4uL3N0YXRpYy9kZXYtc2VydmVyLmpzJyk7XG4gIGNvbnN0IGNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmMoZGV2U2VydmVyUGF0aCwgJ3V0Zi04Jyk7XG4gIGZzLmFwcGVuZEZpbGVTeW5jKHRlbXBGaWxlUGF0aCwgYFxcbmAgKyBjb250ZW50KTtcbn1cblxuZnVuY3Rpb24gd3JpdGVTcGFDbGllbnRTaWRlQ29kZSh0ZW1wRmlsZVBhdGg6IHN0cmluZykge1xuICBjb25zdCBzcGFQYXRoID0gcGF0aC5qb2luKGltcG9ydC5tZXRhLmRpcm5hbWUsICcuLi9zdGF0aWMvc3BhLmpzJyk7XG4gIGNvbnN0IGNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmMoc3BhUGF0aCwgJ3V0Zi04Jyk7XG4gIGZzLmFwcGVuZEZpbGVTeW5jKHRlbXBGaWxlUGF0aCwgYFxcbmAgKyBjb250ZW50KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gYnVpbGRBbHBpbmVEYXRhRmlsZShjb21wb25lbnREYXRhOiBhbnlbXSwgZGF0YUZpbGVzOiBhbnlbXSkge1xuICBjb25zdCBvdXRwdXQgPSB7XG4gICAgaW1wb3J0czogW1xuICAgICAgJ2ltcG9ydCBBbHBpbmUgZnJvbSBcXCdhbHBpbmVqc1xcJzsnXG4gICAgXSxcbiAgICBjb2RlOiBbXSxcbiAgICBlbmQ6IFtcbiAgICAgICd3aW5kb3cuQWxwaW5lID0gQWxwaW5lOydcbiAgICBdLFxuICB9O1xuICBjb25zdCBkYXRhRnVuY3Rpb25SZXN1bHRzID0ge1xuICAgIGZvdW5kRGF0YUF0dHJpYnV0ZXM6IFtdLFxuICAgIGZvdW5kRnVuY3Rpb25zOiBbXSxcbiAgICBmb3VuZEltcG9ydHM6IFtdLFxuICB9O1xuICBjb25zdCBjb21wb25lbnRzQW5kRGF0YUZpbGVzID0gY29tcG9uZW50RGF0YS5jb25jYXQoZGF0YUZpbGVzKTtcbiAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgY29tcG9uZW50c0FuZERhdGFGaWxlcykge1xuICAgIC8vIFNpbmdsZSBzb3VyY2UgZmlsZVxuICAgIGNvbnN0IHNvdXJjZUZpbGUgPSB0cy5jcmVhdGVTb3VyY2VGaWxlKFxuICAgICAgY29tcG9uZW50LnBhdGgsXG4gICAgICBjb21wb25lbnQuY29udGVudHMsXG4gICAgICB0cy5TY3JpcHRUYXJnZXQuTGF0ZXN0XG4gICAgKTtcbiAgICBjb25zdCBkYXRhRnVuY3Rpb25SZXN1bHQgPSBmaW5kRGF0YUF0dHJpYnV0ZXNBbmRGdW5jdGlvbnMoc291cmNlRmlsZSwgc291cmNlRmlsZSk7XG4gICAgZGF0YUZ1bmN0aW9uUmVzdWx0cy5mb3VuZERhdGFBdHRyaWJ1dGVzLnB1c2goLi4uZGF0YUZ1bmN0aW9uUmVzdWx0LmZvdW5kRGF0YUF0dHJpYnV0ZXMpO1xuICAgIGNvbnN0IGZvdW5kRnVuY3Rpb25zV2l0aFBhdGggPSBkYXRhRnVuY3Rpb25SZXN1bHQuZm91bmRGdW5jdGlvbnMubWFwKGl0ZW0gPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uaXRlbSxcbiAgICAgICAgcGF0aDogY29tcG9uZW50LnBhdGgsXG4gICAgICAgIGNvbnRlbnQ6IGNvbXBvbmVudC5jbGllbnRDb250ZW50LFxuICAgICAgfTtcbiAgICB9KTtcbiAgICBkYXRhRnVuY3Rpb25SZXN1bHRzLmZvdW5kRnVuY3Rpb25zLnB1c2goLi4uZm91bmRGdW5jdGlvbnNXaXRoUGF0aCk7XG4gIH1cbiAgY29uc3QgdmFsaWREYXRhRnVuY3Rpb25zID0gZGF0YUZ1bmN0aW9uUmVzdWx0cy5mb3VuZEZ1bmN0aW9ucy5maWx0ZXIoaXRlbSA9PiB7XG4gICAgcmV0dXJuIGRhdGFGdW5jdGlvblJlc3VsdHMuZm91bmREYXRhQXR0cmlidXRlcy5pbmNsdWRlcyhpdGVtLm5hbWUpICYmIGl0ZW0uY29udGVudDtcbiAgfSk7XG4gIGZvciAoY29uc3QgZGF0YUZ1bmN0aW9uIG9mIHZhbGlkRGF0YUZ1bmN0aW9ucykge1xuICAgIGlmICghZGF0YUZ1bmN0aW9uLmhhc0V4cG9ydCkgY29udGludWU7XG4gICAgb3V0cHV0LmNvZGUucHVzaChkYXRhRnVuY3Rpb24uY29udGVudCk7XG4gICAgb3V0cHV0LmNvZGUucHVzaChgQWxwaW5lLmRhdGEoJyR7ZGF0YUZ1bmN0aW9uLm5hbWV9JywgJHtkYXRhRnVuY3Rpb24ubmFtZX0pO2ApO1xuICB9XG4gIGNvbnN0IHJlc3VsdCA9IG91dHB1dC5pbXBvcnRzLmpvaW4oJ1xcbicpICsgJ1xcbicgKyBvdXRwdXQuY29kZS5qb2luKCdcXG4nKSArICdcXG4nICsgb3V0cHV0LmVuZC5qb2luKCdcXG4nKTtcbiAgZnMuZW5zdXJlRmlsZVN5bmMoY29uZmlnLmFscGluZURhdGFQYXRoKTtcbiAgZnMud3JpdGVGaWxlU3luYyhjb25maWcuYWxwaW5lRGF0YVBhdGgsIHJlc3VsdCk7XG4gIHJldHVybiBjb25maWcuYWxwaW5lRGF0YVBhdGg7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWlsZENTUygpIHtcbiAgY29uc3QgY3NzRmlsZXMgPSBnbG9iU3luYyhjb25maWcuc3JjRGlyICsgJy8qKi8qLmNzcycpO1xuICBmb3IgKGNvbnN0IGZpbGUgb2YgY3NzRmlsZXMpIHtcbiAgICBjb25zdCBmaWxlQ29udGVudHMgPSBmcy5yZWFkRmlsZVN5bmMoZmlsZSwgJ3V0Zi04Jyk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcG9zdGNzcyhbdGFpbHdpbmRQb3N0Y3NzKCldKS5wcm9jZXNzKGZpbGVDb250ZW50cywgeyBmcm9tOiBmaWxlLCB9KTtcbiAgICAvLyBXcml0ZSB0byBkaXN0IGZvbGRlclxuICAgIGNvbnN0IG5ld1BhdGggPSBmaWxlLnJlcGxhY2UoY29uZmlnLnNyY0RpciwgY29uZmlnLmRpc3REaXIpO1xuICAgIGZzLmVuc3VyZUZpbGVTeW5jKG5ld1BhdGgpO1xuICAgIGZzLndyaXRlRmlsZVN5bmMobmV3UGF0aCwgcmVzdWx0LmNzcyk7XG4gIH1cbiAgbG9nU2l6ZShjb25maWcuZGlzdFB1YmxpY0RpciwgJ2NzcycpO1xufVxuXG4vLyBXZSBuZWVkIHRvIHN5bWxpbmsgdGhlIG5vbiBDU1Mgb3IgSlMgZmlsZXMgZnJvbSB0aGUgc3JjL3B1YmxpYyBmb2xkZXIgaW50byB0aGUgZGlzdCBmb2xkZXJcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWlsZFB1YmxpY0ZvbGRlclN5bWxpbmtzKCkge1xuICBjb25zdCBmaWxlcyA9IGdsb2JTeW5jKGNvbmZpZy5wdWJsaWNEaXIgKyAnLyoqLyouKicsIHtcbiAgICBpZ25vcmU6ICcvKiovKi57Y3NzLGpzLHRzLHRzeCxqc3h9JyxcbiAgfSk7XG5cbiAgLy8gQ3JlYXRlIHN5bWxpbmtzIGluIGRpc3QgZGlyZWN0b3J5XG4gIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBuZXdQYXRoID0gZmlsZS5yZXBsYWNlKGNvbmZpZy5zcmNEaXIsIGNvbmZpZy5kaXN0RGlyKTtcbiAgICAgIGNvbnN0IHNwbGl0TmV3UGF0aCA9IG5ld1BhdGguc3BsaXQoJy8nKTtcbiAgICAgIHNwbGl0TmV3UGF0aC5wb3AoKTtcbiAgICAgIGNvbnN0IG5ld0RpciA9IHNwbGl0TmV3UGF0aC5qb2luKCcvJyk7XG4gICAgICBmcy5lbnN1cmVEaXJTeW5jKG5ld0Rpcik7XG4gICAgICBmcy5zeW1saW5rU3luYyhmaWxlLCBuZXdQYXRoKTtcbiAgICB9IGNhdGNoIHsgfVxuICB9XG59XG5cbnR5cGUgRmlsZUl0ZW0gPSB7XG4gIGZpbGU6IHN0cmluZztcbiAgc2l6ZTogbnVtYmVyO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbG9nU2l6ZShwYXRoTmFtZTogc3RyaW5nLCB0eXBlOiAnYXBwJyB8ICdjbGllbnQnIHwgJ2NzcycsIHZhbGlkRXh0ZW5zaW9ucyA9IFsnLmpzJywgJy5jc3MnXSkge1xuICBjb25zdCBmaWxlcyA9IGdsb2JTeW5jKHBhdGhOYW1lICsgJy8qKi8qJyArICh0eXBlID09PSAnY3NzJyA/ICcuY3NzJyA6ICcnKSk7XG4gIGNvbnN0IGZpbGVTaXplcyA9IGZpbGVzLm1hcCgoZmlsZSkgPT4ge1xuICAgIGlmICghdmFsaWRFeHRlbnNpb25zLmZpbmQoZXh0ID0+IGZpbGUuZW5kc1dpdGgoZXh0KSkpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4ge1xuICAgICAgZmlsZSxcbiAgICAgIHNpemU6IChmcy5zdGF0U3luYyhmaWxlKS5zaXplKSAvICgxMDI0ICogMTAwMCksXG4gICAgfTtcbiAgfSkuZmlsdGVyKEJvb2xlYW4pO1xuICBjb25zdCB0b3RhbFNpemUgPSBmaWxlU2l6ZXMucmVkdWNlKCh0b3RhbCwgY3VycmVudDogRmlsZUl0ZW0pID0+IHtcbiAgICByZXR1cm4gY3VycmVudC5zaXplICsgdG90YWw7XG4gIH0sIDApO1xuICBjb25zb2xlLmluZm8oYFske3RvdGFsU2l6ZS50b0ZpeGVkKDMpfSBNQl0gQnVpbHQgJHt0eXBlfWApO1xufVxuIiwgImltcG9ydCB0cyBmcm9tICd0eXBlc2NyaXB0JztcbmltcG9ydCBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcblxudHlwZSBJbXBvcnREZWNsYXJhdGlvbiA9IHtcbiAgbm9kZTogdHMuTm9kZTtcbiAgaW1wb3J0UGF0aDogc3RyaW5nO1xufVxuXG4vLyBub2RlIGFyZyBzaG91bGQgaW5pdGlhbGx5IGJlIHRoZSBzb3VyY2Ugbm9kZVxuZXhwb3J0IGZ1bmN0aW9uIGdldEltcG9ydERlY2xhcmF0aW9uTm9kZXMobm9kZTogdHMuTm9kZSwgc291cmNlRmlsZTogdHMuU291cmNlRmlsZSwgaW1wb3J0RGVjbGFyYXRpb25zOiBJbXBvcnREZWNsYXJhdGlvbltdID0gW10pIHtcbiAgaWYgKG5vZGUua2luZCA9PT0gdHMuU3ludGF4S2luZC5JbXBvcnREZWNsYXJhdGlvbikge1xuICAgIGxldCBpbXBvcnRQYXRoID0gbnVsbDtcbiAgICBub2RlLmZvckVhY2hDaGlsZChjaGlsZCA9PiB7XG4gICAgICBpZiAoY2hpbGQua2luZCA9PT0gdHMuU3ludGF4S2luZC5TdHJpbmdMaXRlcmFsKSB7XG4gICAgICAgIGltcG9ydFBhdGggPSBjaGlsZC5nZXRUZXh0KHNvdXJjZUZpbGUpLnJlcGxhY2UoL1tcXFwiXFwnXS9nLCAnJyk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaW1wb3J0RGVjbGFyYXRpb25zLnB1c2goe1xuICAgICAgbm9kZSxcbiAgICAgIGltcG9ydFBhdGgsXG4gICAgfSk7XG4gIH1cbiAgbm9kZS5mb3JFYWNoQ2hpbGQoY2hpbGQgPT4ge1xuICAgIGdldEltcG9ydERlY2xhcmF0aW9uTm9kZXMoY2hpbGQsIHNvdXJjZUZpbGUsIGltcG9ydERlY2xhcmF0aW9ucyk7XG4gIH0pO1xuICByZXR1cm4gaW1wb3J0RGVjbGFyYXRpb25zO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RyaXBJbXBvcnRzTm9kZXNGcm9tRmlsZShpbXBvcnRzVG9TdHJpcDogc3RyaW5nW10sIGNvbnRlbnQ6IHN0cmluZywgaW1wb3J0RGVjbGFyYXRpb25zOiBJbXBvcnREZWNsYXJhdGlvbltdKSB7XG4gIGxldCBvdXRwdXRDb250ZW50ID0gY29udGVudDtcbiAgY29uc3QgZmlsdGVyZWRJbXBvcnRzID0gaW1wb3J0RGVjbGFyYXRpb25zLmZpbHRlcihpdGVtID0+IGltcG9ydHNUb1N0cmlwLmluY2x1ZGVzKGl0ZW0uaW1wb3J0UGF0aCkpO1xuICBmb3IgKGNvbnN0IGltcG9ydEl0ZW0gb2YgZmlsdGVyZWRJbXBvcnRzKSB7XG4gICAgb3V0cHV0Q29udGVudCA9IG91dHB1dENvbnRlbnQuc2xpY2UoMCwgaW1wb3J0SXRlbS5ub2RlLnBvcykgKyBvdXRwdXRDb250ZW50LnNsaWNlKGltcG9ydEl0ZW0ubm9kZS5lbmQpO1xuICB9XG4gIHJldHVybiBvdXRwdXRDb250ZW50O1xufVxuXG50eXBlIEZvdW5kQWxwaW5lRnVuY3Rpb24gPSB7XG4gIG5hbWU6IHN0cmluZztcbiAgaXNEZWZhdWx0RXhwb3J0OiBib29sZWFuO1xuICBoYXNFeHBvcnQ6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kRGF0YUF0dHJpYnV0ZXNBbmRGdW5jdGlvbnMoXG4gIG5vZGU6IHRzLk5vZGUsXG4gIHNvdXJjZUZpbGU6IHRzLlNvdXJjZUZpbGUsXG4gIGZvdW5kRGF0YUF0dHJpYnV0ZXM6IHN0cmluZ1tdID0gW10sXG4gIGZvdW5kRnVuY3Rpb25zOiBGb3VuZEFscGluZUZ1bmN0aW9uW10gPSBbXVxuKSB7XG4gIGlmIChub2RlLmtpbmQgPT09IHRzLlN5bnRheEtpbmQuSnN4QXR0cmlidXRlKSB7XG4gICAgY29uc3QgYXR0cmlidXRlID0gZ2V0QXR0cmlidXRlVmFsdWVQYWlyKG5vZGUsIHNvdXJjZUZpbGUpO1xuICAgIGlmIChhdHRyaWJ1dGU/LlswXSA9PT0gJ3gtZGF0YScgJiYgYXR0cmlidXRlPy5bMV0pIHtcbiAgICAgIC8vIFdlIGZvdW5kIGEgZGF0YSBhdHRyaWJ1dGUsIFxuICAgICAgLy8gc28gbm93IHdlIGhhdmUgdG8gc2VhcmNoIHRocm91Z2hvdXQgdGhlIGZpbGUgZm9yIGEgZnVuY3Rpb24gZGVjbGFyYXRpb24gb2YgdGhlIHNhbWUgbmFtZVxuICAgICAgZm91bmREYXRhQXR0cmlidXRlcy5wdXNoKGF0dHJpYnV0ZVsxXS5yZXBsYWNlKC9bXmEtekEtWjAtOV0vZywgJycpKTtcbiAgICB9XG4gIH1cbiAgaWYgKG5vZGUua2luZCA9PT0gdHMuU3ludGF4S2luZC5Tb3VyY2VGaWxlKSB7XG4gICAgbm9kZS5mb3JFYWNoQ2hpbGQoY2hpbGQgPT4ge1xuICAgICAgaWYgKFt0cy5TeW50YXhLaW5kLkZ1bmN0aW9uRGVjbGFyYXRpb24sIHRzLlN5bnRheEtpbmQuVmFyaWFibGVEZWNsYXJhdGlvbl0uaW5jbHVkZXMoY2hpbGQua2luZCkpIHtcbiAgICAgICAgY29uc3QgZnVuY3Rpb25zID0gZ2V0RnVuY3Rpb25EZWNsYXJhdGlvblZhbHVlKGNoaWxkLCBzb3VyY2VGaWxlKTtcbiAgICAgICAgZm91bmRGdW5jdGlvbnMucHVzaChmdW5jdGlvbnMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgbm9kZS5mb3JFYWNoQ2hpbGQoY2hpbGQgPT4ge1xuICAgIGZpbmREYXRhQXR0cmlidXRlc0FuZEZ1bmN0aW9ucyhjaGlsZCwgc291cmNlRmlsZSwgZm91bmREYXRhQXR0cmlidXRlcywgZm91bmRGdW5jdGlvbnMpO1xuICB9KTtcbiAgcmV0dXJuIHtcbiAgICBmb3VuZERhdGFBdHRyaWJ1dGVzLFxuICAgIGZvdW5kRnVuY3Rpb25zLFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QXR0cmlidXRlVmFsdWVQYWlyKG5vZGU6IHRzLk5vZGUsIHNvdXJjZUZpbGU6IHRzLlNvdXJjZUZpbGUpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHJlc3VsdCA9IFtdO1xuICBub2RlLmZvckVhY2hDaGlsZChjaGlsZCA9PiB7XG4gICAgcmVzdWx0LnB1c2goY2hpbGQuZ2V0VGV4dChzb3VyY2VGaWxlKSk7XG4gIH0pO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RnVuY3Rpb25EZWNsYXJhdGlvblZhbHVlKG5vZGU6IHRzLk5vZGUsIHNvdXJjZUZpbGU6IHRzLlNvdXJjZUZpbGUpOiBGb3VuZEFscGluZUZ1bmN0aW9uIHtcbiAgY29uc3QgcmVzdWx0ID0ge1xuICAgIG5hbWU6IG51bGwsXG4gICAgaXNEZWZhdWx0RXhwb3J0OiBmYWxzZSxcbiAgICBoYXNFeHBvcnQ6IGZhbHNlLFxuICB9O1xuICBub2RlLmZvckVhY2hDaGlsZChjaGlsZCA9PiB7XG4gICAgaWYgKGNoaWxkLmtpbmQgPT09IHRzLlN5bnRheEtpbmQuRXhwb3J0S2V5d29yZCkge1xuICAgICAgcmVzdWx0Lmhhc0V4cG9ydCA9IHRydWU7XG4gICAgfVxuICAgIGlmIChjaGlsZC5raW5kID09PSB0cy5TeW50YXhLaW5kLkRlZmF1bHRLZXl3b3JkKSB7XG4gICAgICByZXN1bHQuaXNEZWZhdWx0RXhwb3J0ID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKGNoaWxkLmtpbmQgPT09IHRzLlN5bnRheEtpbmQuSWRlbnRpZmllcikge1xuICAgICAgcmVzdWx0Lm5hbWUgPSBjaGlsZC5nZXRUZXh0KHNvdXJjZUZpbGUpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8vIENvbnZlcnQgZW50cnkgcG9pbnQgZmlsZXMgaW50byBvbmUgYmlnIGJ1bmRsZSBmaWxlXG5leHBvcnQgZnVuY3Rpb24gY29udmVydEVudHJ5UG9pbnRzVG9TaW5nbGVGaWxlKGVudHJ5UG9pbnRzOiBzdHJpbmdbXSwgdGVtcFdyaXRlUGF0aDogc3RyaW5nKSB7XG4gIGZzLndyaXRlRmlsZVN5bmMoXG4gICAgdGVtcFdyaXRlUGF0aCxcbiAgICBlbnRyeVBvaW50c1xuICAgICAgLm1hcChlbnRyeSA9PiBgaW1wb3J0IFwiJHtlbnRyeX1cImApXG4gICAgICAuam9pbignO1xcbicpXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmVDbGllbnRTY3JpcHRJblRTWEZpbGUocGF0aE5hbWU6IHN0cmluZykge1xuICBjb25zdCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKHBhdGhOYW1lLCAndXRmLTgnKTtcbiAgY29uc3Qgc291cmNlID0gdHMuY3JlYXRlU291cmNlRmlsZShcbiAgICBwYXRoTmFtZSxcbiAgICBjb250ZW50LFxuICAgIHRzLlNjcmlwdFRhcmdldC5MYXRlc3RcbiAgKTtcbiAgbGV0IHRvUmVtb3ZlRnJvbTogbnVtYmVyO1xuICBsZXQgY2xpZW50RGF0YVN0YXJ0OiBudW1iZXI7XG4gIGNvbnN0IGNsaWVudEltcG9ydHNUb0hvaXN0ID0gW107XG4gIGNvbnN0IGNsaWVudEltcG9ydHNUb1JlcGxhY2UgPSBbXTtcbiAgc291cmNlLmZvckVhY2hDaGlsZCgoY2hpbGQpID0+IHtcbiAgICBpZiAoY2hpbGQua2luZCA9PT0gdHMuU3ludGF4S2luZC5FeHByZXNzaW9uU3RhdGVtZW50KSB7XG4gICAgICBjb25zdCB0ZXh0ID0gY2hpbGQuZ2V0VGV4dChzb3VyY2UpO1xuICAgICAgLy8gUmVtb3ZlIGZyb20gaGVyZVxuICAgICAgaWYgKHRleHQuc3RhcnRzV2l0aCgnPHNjcmlwdCcpKSB7XG4gICAgICAgIHRvUmVtb3ZlRnJvbSA9IGNoaWxkLnBvcztcbiAgICAgICAgY2xpZW50RGF0YVN0YXJ0ID0gY2hpbGQuZW5kO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBIb2lzdCB0aGUgY2xpZW50IGltcG9ydHMgdG8gYWJvdmUgdGhlIDxzY3JpcHQgLz4gdGFnXG4gICAgaWYgKGNoaWxkLmtpbmQgPT09IHRzLlN5bnRheEtpbmQuSW1wb3J0RGVjbGFyYXRpb24gJiYgY2hpbGQucG9zID49IGNsaWVudERhdGFTdGFydCkge1xuICAgICAgY29uc3QgdGV4dCA9IGNoaWxkLmdldFRleHQoc291cmNlKTtcbiAgICAgIGNoaWxkLmZvckVhY2hDaGlsZChjaGlsZCA9PiB7XG4gICAgICAgIGlmIChjaGlsZC5raW5kID09PSB0cy5TeW50YXhLaW5kLlN0cmluZ0xpdGVyYWwpIHtcbiAgICAgICAgICAvLyBLZWVwIHRyYWNrIG9mIGNsaWVudCBpbXBvcnRzIG5lZWRlZCBmb3IgcGF0aCByZXBsYWNlbWVudCB0byBiZSBhYnNvbHV0ZVxuICAgICAgICAgIGNvbnN0IHRleHQgPSBjaGlsZC5nZXRUZXh0KHNvdXJjZSk7XG4gICAgICAgICAgY29uc3QgaW1wb3J0UGF0aCA9IHRleHQucmVwbGFjZSgvW1xcXCJcXCddL2csICcnKTtcbiAgICAgICAgICBjb25zdCBpc1JlbGF0aXZlSW1wb3J0ID0gaW1wb3J0UGF0aC5zdGFydHNXaXRoKCcuJykgfHwgaW1wb3J0UGF0aC5zdGFydHNXaXRoKCcvJyk7XG4gICAgICAgICAgaWYgKCFpc1JlbGF0aXZlSW1wb3J0KSByZXR1cm47XG4gICAgICAgICAgY2xpZW50SW1wb3J0c1RvUmVwbGFjZS5wdXNoKHtcbiAgICAgICAgICAgIG9sZDogaW1wb3J0UGF0aCxcbiAgICAgICAgICAgIG5ldzogcGF0aC5qb2luKHBhdGguZGlybmFtZShwYXRoTmFtZSksIGltcG9ydFBhdGgpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGNsaWVudEltcG9ydHNUb0hvaXN0LnB1c2godGV4dCk7XG4gICAgfVxuICB9KTtcbiAgbGV0IGNsaWVudENvbnRlbnQgPSAhaXNOYU4oY2xpZW50RGF0YVN0YXJ0KSA/IGNvbnRlbnQuc2xpY2UoY2xpZW50RGF0YVN0YXJ0KSA6ICcnO1xuICBmb3IgKGNvbnN0IGNsaWVudEltcG9ydCBvZiBjbGllbnRJbXBvcnRzVG9SZXBsYWNlKSB7XG4gICAgY2xpZW50Q29udGVudCA9IGNsaWVudENvbnRlbnQucmVwbGFjZShjbGllbnRJbXBvcnQub2xkLCBjbGllbnRJbXBvcnQubmV3KTtcbiAgfVxuICByZXR1cm4ge1xuICAgIGNvbnRlbnQ6ICFpc05hTih0b1JlbW92ZUZyb20pID9cbiAgICAgIGNsaWVudEltcG9ydHNUb0hvaXN0LmpvaW4oJ1xcbicpICsgY29udGVudC5zbGljZSgwLCB0b1JlbW92ZUZyb20pIDpcbiAgICAgIGNvbnRlbnQsXG4gICAgY2xpZW50Q29udGVudCxcbiAgICBmdWxsQ29udGVudDogY29udGVudCxcbiAgICB0b1JlbW92ZUZyb20sXG4gICAgY2xpZW50RGF0YVN0YXJ0LFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJpbnRSZWN1cnNpdmVGcm9tKFxuICBub2RlOiB0cy5Ob2RlLCBpbmRlbnRMZXZlbDogbnVtYmVyLCBzb3VyY2VGaWxlOiB0cy5Tb3VyY2VGaWxlXG4pIHtcbiAgY29uc3QgaW5kZW50YXRpb24gPSAnLScucmVwZWF0KGluZGVudExldmVsKTtcbiAgY29uc3Qgc3ludGF4S2luZCA9IHRzLlN5bnRheEtpbmRbbm9kZS5raW5kXTtcbiAgY29uc3Qgbm9kZVRleHQgPSBub2RlLmdldFRleHQoc291cmNlRmlsZSk7XG4gIGNvbnNvbGUubG9nKGAke2luZGVudGF0aW9ufSR7c3ludGF4S2luZH06ICR7bm9kZVRleHR9YCk7XG5cbiAgbm9kZS5mb3JFYWNoQ2hpbGQoY2hpbGQgPT5cbiAgICBwcmludFJlY3Vyc2l2ZUZyb20oY2hpbGQsIGluZGVudExldmVsICsgMSwgc291cmNlRmlsZSlcbiAgKTtcbn1cbiIsICJpbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCByZXF1aXJlIGZyb20gJy4vcmVxdWlyZSc7XG5pbXBvcnQgeyBYUGluZUNvbmZpZyB9IGZyb20gJy4uLy4uL3R5cGVzJztcblxuY29uc3Qgcm9vdERpciA9IHByb2Nlc3MuY3dkKCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tUm9vdChwYXRoTmFtZT86IHN0cmluZykge1xuICBpZiAoIXBhdGhOYW1lKSByZXR1cm4gcm9vdERpcjtcbiAgcmV0dXJuIHBhdGguam9pbihyb290RGlyLCBwYXRoTmFtZSk7XG59XG5cbmNvbnN0IHVzZXJDb25maWcgPSByZXF1aXJlKHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCAnLi94cGluZS5jb25maWcubWpzJykpLmRlZmF1bHQ7XG5cbmNvbnN0IGNvbmZpZ0RlZmF1bHRzID0ge1xuICByb290RGlyOiBmcm9tUm9vdCgpLFxuICBzcmNEaXI6IGZyb21Sb290KCcuL3NyYycpLFxuICBkaXN0RGlyOiBmcm9tUm9vdCgnLi9kaXN0JyksXG4gIHBhY2thZ2VKc29uUGF0aDogZnJvbVJvb3QoJ3BhY2thZ2UuanNvbicpLFxuICAvLyBXZSBuZWVkIHRvIHVzZSBnZXR0ZXJzIGhlcmUgaW4gdGhlIGV2ZW50IHNvbWVvbmUgd2FudHMgdG8gY2hhbmdlIGZvbGRlcnMsIHN1Y2ggYXMgdGhlIGRpc3QgZm9sZGVyXG4gIGdldCBkaXN0UHVibGljRGlyKCkge1xuICAgIHJldHVybiBwYXRoLmpvaW4odGhpcy5kaXN0RGlyLCAnLi9wdWJsaWMnKTtcbiAgfSxcbiAgZ2V0IGRpc3RQdWJsaWNTY3JpcHRzRGlyKCkge1xuICAgIHJldHVybiBwYXRoLmpvaW4odGhpcy5kaXN0UHVibGljRGlyLCAnLi9zY3JpcHRzJyk7XG4gIH0sXG4gIGdldCBkaXN0VGVtcEZvbGRlcigpIHtcbiAgICByZXR1cm4gcGF0aC5qb2luKHRoaXMuZGlzdERpciwgJy4vdGVtcCcpO1xuICB9LFxuICBnZXQgY2xpZW50SlNCdW5kbGVQYXRoKCkge1xuICAgIHJldHVybiBwYXRoLmpvaW4odGhpcy5kaXN0UHVibGljU2NyaXB0c0RpciwgJy4vYXBwLmpzJyk7XG4gIH0sXG4gIGdldCBhbHBpbmVEYXRhUGF0aCgpIHtcbiAgICByZXR1cm4gcGF0aC5qb2luKHRoaXMuZGlzdFRlbXBGb2xkZXIsICcuL2FscGluZS1kYXRhLnRzJyk7XG4gIH0sXG4gIGdldCBzZXJ2ZXJEaXN0RGlyKCkge1xuICAgIHJldHVybiBwYXRoLmpvaW4odGhpcy5kaXN0RGlyLCAnLi9zZXJ2ZXInKTtcbiAgfSxcbiAgZ2V0IHNlcnZlckRpc3RBcHBQYXRoKCkge1xuICAgIHJldHVybiBwYXRoLmpvaW4odGhpcy5zZXJ2ZXJEaXN0RGlyLCAnLi9hcHAuanMnKTtcbiAgfSxcbiAgLy8gSW1wb3J0YW50IGRpcnMvcGF0aHNcbiAgZ2V0IHBhZ2VzRGlyKCkge1xuICAgIHJldHVybiBwYXRoLmpvaW4odGhpcy5zcmNEaXIsICcuL3BhZ2VzJyk7XG4gIH0sXG4gIGdldCBwdWJsaWNEaXIoKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLnNyY0RpciwgJy4vcHVibGljJyk7XG4gIH0sXG4gIGdldCBzZXJ2ZXJEaXIoKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLnNyY0RpciwgJy4vc2VydmVyJyk7XG4gIH0sXG4gIGdldCBydW5EaXIoKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLnNlcnZlckRpciwgJy4vcnVuJyk7XG4gIH0sXG4gIGdldCBzZXJ2ZXJBcHBQYXRoKCkge1xuICAgIHJldHVybiBwYXRoLmpvaW4odGhpcy5zZXJ2ZXJEaXIsICcuL2FwcC50cycpO1xuICB9LFxuICBnZXQgZ2xvYmFsQ1NTRmlsZSgpIHtcbiAgICByZXR1cm4gcGF0aC5qb2luKHRoaXMucHVibGljRGlyLCAnLi9zdHlsZXMvZ2xvYmFsLmNzcycpO1xuICB9LFxufTtcblxuZXhwb3J0IGNvbnN0IGNvbmZpZzogWFBpbmVDb25maWcgPSB7XG4gIC4uLmNvbmZpZ0RlZmF1bHRzLFxuICAuLi51c2VyQ29uZmlnLFxufTsiLCAiaW1wb3J0IHsgY3JlYXRlUmVxdWlyZSB9IGZyb20gJ21vZHVsZSc7XG5cbmNvbnN0IHJlcXVpcmUgPSBjcmVhdGVSZXF1aXJlKGltcG9ydC5tZXRhLnVybCk7XG5cbmV4cG9ydCBkZWZhdWx0IHJlcXVpcmU7IiwgImltcG9ydCBkb3RlbnYgZnJvbSAnZG90ZW52JztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgY29uZmlnIH0gZnJvbSAnLi9nZXQtY29uZmlnJztcblxuZXhwb3J0IGZ1bmN0aW9uIHNldHVwRW52KCkge1xuICBkb3RlbnYuY29uZmlnKHsgcGF0aDogcGF0aC5qb2luKGNvbmZpZy5yb290RGlyLCBgLi8uZW52LiR7cHJvY2Vzcy5lbnYuU1RBR0UgfHwgJ2Rldid9YCksfSk7XG59XG4iLCAiaW1wb3J0IGV4cHJlc3MsIHsgTmV4dEZ1bmN0aW9uLCBFeHByZXNzLCBSZXF1ZXN0LCBSZXNwb25zZSB9IGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHsgZ2xvYlN5bmMgfSBmcm9tICdnbG9iJztcbmltcG9ydCB7IGNvbmZpZyB9IGZyb20gJy4vdXRpbC9nZXQtY29uZmlnJztcbmltcG9ydCB7IHZlcmlmeVVzZXIgfSBmcm9tICcuL2F1dGgnO1xuaW1wb3J0IHJlcXVlc3RJUCBmcm9tICdyZXF1ZXN0LWlwJztcbmltcG9ydCB7IFNlcnZlclJlcXVlc3QgfSBmcm9tICcuLi90eXBlcyc7XG5cbmNvbnN0IGRvY3R5cGVIVE1MID0gJzwhRE9DVFlQRSBodG1sPic7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVSb3V0ZXIoKSB7XG4gIGNvbnN0IG1ldGhvZHMgPSBbJ2dldCcsICdwb3N0JywgJ3B1dCcsICdwYXRjaCcsICdkZWxldGUnXTtcbiAgY29uc3Qgcm91dGVyID0gZXhwcmVzcy5Sb3V0ZXIoKTtcbiAgY29uc3Qgcm91dGVzID0gZ2xvYlN5bmMoY29uZmlnLnBhZ2VzRGlyICsgJy8qKi8qLnt0c3gsdHN9Jyk7XG4gIGNvbnN0IHJvdXRlTWFwID0gcm91dGVzLm1hcChyb3V0ZSA9PiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJvdXRlOiByb3V0ZS5zcGxpdChjb25maWcucGFnZXNEaXIpLnBvcCgpLnJlcGxhY2UoJy50c3gnLCAnJykucmVwbGFjZSgnLmpzJywgJycpLnJlcGxhY2UoJy50cycsICcnKS5yZXBsYWNlKCcvaW5kZXgnLCAnLycpLFxuICAgICAgcGF0aDogcm91dGUucmVwbGFjZShjb25maWcuc3JjRGlyLCBjb25maWcuZGlzdERpcikucmVwbGFjZSgnLnRzeCcsICcuanMnKS5yZXBsYWNlKCcudHMnLCAnLmpzJyksXG4gICAgICBvcmlnaW5hbFJvdXRlOiByb3V0ZSxcbiAgICB9O1xuICB9KTtcbiAgY29uc3Qgcm91dGVSZXN1bHRzID0gW107XG5cbiAgZm9yIChjb25zdCByb3V0ZSBvZiByb3V0ZU1hcCkge1xuICAgIGNvbnN0IGlzSlNYID0gcm91dGUub3JpZ2luYWxSb3V0ZS5lbmRzV2l0aCgnLnRzeCcpIHx8IHJvdXRlLm9yaWdpbmFsUm91dGUuZW5kc1dpdGgoJy5qc3gnKTtcbiAgICAvLyBJbXBvcnQgcm91dGVcbiAgICBjb25zdCByb3V0ZUl0ZW0gPSBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50JyA/IG51bGwgOiAoYXdhaXQgaW1wb3J0KHJvdXRlLnBhdGgpKS5kZWZhdWx0O1xuICAgIC8vIENvbmZpZ3VyZSByZXN1bHQsbWV0aG9kcyBmb3IgdGhlIHJvdXRlXG4gICAgY29uc3Qgc2x1Z1JvdXRlID0gcm91dGUucm91dGUudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9bIF0vZywgJycpO1xuICAgIGNvbnN0IGZvdW5kTWV0aG9kID0gbWV0aG9kcy5maW5kKG1ldGhvZCA9PiBzbHVnUm91dGUuZW5kc1dpdGgoYC4ke21ldGhvZH1gKSk7XG4gICAgY29uc3QgaXNEeW5hbWljUm91dGUgPSBzbHVnUm91dGUubWF0Y2goL1xcWyguKilcXF0vZyk7XG4gICAgbGV0IGZvcm1hdHRlZFJvdXRlSXRlbSA9IHNsdWdSb3V0ZTtcbiAgICBpZiAoZm91bmRNZXRob2QpIGZvcm1hdHRlZFJvdXRlSXRlbSA9IGZvcm1hdHRlZFJvdXRlSXRlbS5zcGxpdCgnLicpLnNoaWZ0KCk7XG4gICAgLy8gSGFuZGxlIGR5bmFtaWMgcm91dGluZ1xuICAgIGlmIChpc0R5bmFtaWNSb3V0ZSkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gWy4uLmZvcm1hdHRlZFJvdXRlSXRlbS5tYXRjaEFsbCgvKFxcWykoLio/KShcXF0pL2cpXTtcbiAgICAgIGZvciAoY29uc3QgbWF0Y2ggb2YgcmVzdWx0KSB7XG4gICAgICAgIGZvcm1hdHRlZFJvdXRlSXRlbSA9IGZvcm1hdHRlZFJvdXRlSXRlbS5yZXBsYWNlKG1hdGNoWzBdLCAnOicgKyBtYXRjaFsyXSk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFB1c2ggdG8gdGhlIHJvdXRlIHJlc3VsdHMgYXJyYXlcbiAgICByb3V0ZVJlc3VsdHMucHVzaCh7XG4gICAgICBmb3JtYXR0ZWRSb3V0ZUl0ZW0sXG4gICAgICBmb3VuZE1ldGhvZCxcbiAgICAgIHJvdXRlLFxuICAgIH0pO1xuICAgIHJvdXRlcltmb3VuZE1ldGhvZCB8fCAnZ2V0J10oZm9ybWF0dGVkUm91dGVJdGVtLCBhc3luYyAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBDaGVjayBpZiBpdCdzIGEgc3RyaW5nIHJlc3BvbnNlIGZyb20gdGhlIHJvdXRlSXRlbSBvciBpcyBhIGRpZmZlcmVudCByZXNwb25zZVxuICAgICAgICBpZiAocm91dGVJdGVtKSB7XG4gICAgICAgICAgaWYgKGlzSlNYKSB7XG4gICAgICAgICAgICByZXMuc2VuZChkb2N0eXBlSFRNTCArIChhd2FpdCByb3V0ZUl0ZW0ocmVxLCByZXMpKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGF3YWl0IHJvdXRlSXRlbShyZXEsIHJlcyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkZWZhdWx0Um91dGVJbXBvcnQgPSAoYXdhaXQgaW1wb3J0KHJvdXRlLnBhdGggKyBgP2NhY2hlPSR7RGF0ZS5ub3coKX1gKSkuZGVmYXVsdDtcbiAgICAgICAgLy8gUmVxdWlyZSBldmVyeSB0aW1lIG9ubHkgaWYgaW4gZGV2ZWxvcG1lbnQgbW9kZVxuICAgICAgICBpZiAoaXNKU1gpIHtcbiAgICAgICAgICByZXMuc2VuZChkb2N0eXBlSFRNTCArIChhd2FpdCBkZWZhdWx0Um91dGVJbXBvcnQocmVxLCByZXMpKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYXdhaXQgZGVmYXVsdFJvdXRlSW1wb3J0KHJlcSwgcmVzKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcbiAgICAgICAgcmVzLnN0YXR1cyhlcnI/LnN0YXR1cyB8fCA1MDApLnNlbmQoZXJyPy5tZXNzYWdlIHx8ICdFcnJvcicpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIHJldHVybiB7XG4gICAgcm91dGVyLFxuICAgIHJvdXRlUmVzdWx0cyxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gdmVyaWZ5VXNlck1pZGRsZXdhcmUocmVxOiBTZXJ2ZXJSZXF1ZXN0LCBfcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKSB7XG4gIC8vIEB0cy1pZ25vcmVcbiAgY29uc3QgeyB1c2VydG9rZW4sIH0gPSByZXEuY29va2llcztcbiAgaWYgKCF1c2VydG9rZW4pIHtcbiAgICByZXEudXNlciA9IG51bGw7XG4gIH1cbiAgdHJ5IHtcbiAgICBjb25zdCB7IHVzZXIsIH0gPSBhd2FpdCB2ZXJpZnlVc2VyKHVzZXJ0b2tlbik7XG4gICAgcmVxLnVzZXIgPSB1c2VyO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICByZXEudXNlciA9IG51bGw7XG4gIH1cbiAgbmV4dCgpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlWFBpbmVSb3V0ZXIoYXBwOiBhbnksIGJlZm9yZUVycm9yUm91dGU/OiAoYXBwOiBFeHByZXNzKSA9PiB2b2lkKSB7XG4gIGFwcC51c2UoZXhwcmVzcy5zdGF0aWMoY29uZmlnLmRpc3RQdWJsaWNEaXIpKTtcbiAgYXBwLnVzZSh2ZXJpZnlVc2VyTWlkZGxld2FyZSk7XG4gIGFwcC51c2UocmVxdWVzdElQLm13KCkpO1xuXG4gIGNvbnN0IHsgcm91dGVyLCByb3V0ZVJlc3VsdHMsIH0gPSBhd2FpdCBjcmVhdGVSb3V0ZXIoKTtcbiAgYXBwLnVzZShmdW5jdGlvbiByZXBsYWNlYWJsZVJvdXRlcihyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbikge1xuICAgIHJvdXRlcihyZXEsIHJlcywgbmV4dCk7XG4gIH0pO1xuXG4gIGNvbnN0IGZvdW5kNDA0ID0gcm91dGVSZXN1bHRzPy5maW5kKGl0ZW0gPT4gaXRlbT8uZm9ybWF0dGVkUm91dGVJdGVtID09PSAnLzQwNCcpO1xuICBjb25zdCBpbXBvcnQ0MDQgPSBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50JyA/IG51bGwgOiAoYXdhaXQgaW1wb3J0KGZvdW5kNDA0LnJvdXRlLnBhdGgpKS5kZWZhdWx0O1xuXG4gIGlmIChiZWZvcmVFcnJvclJvdXRlKSBiZWZvcmVFcnJvclJvdXRlKGFwcCk7XG5cbiAgLy8gZXJyb3IgaGFuZGxlclxuICBhcHAudXNlKGFzeW5jIGZ1bmN0aW9uIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpIHtcbiAgICAvLyByZW5kZXIgdGhlIGVycm9yIHBhZ2VcbiAgICByZXMuc3RhdHVzKDQwNCk7XG5cbiAgICBpZiAoaW1wb3J0NDA0KSB7XG4gICAgICByZXMuc2VuZChkb2N0eXBlSFRNTCArIChhd2FpdCBpbXBvcnQ0MDQocmVxLCByZXMpKSk7XG4gICAgfSBlbHNlIGlmIChmb3VuZDQwNCAmJiBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50Jykge1xuICAgICAgY29uc3QgaW1wb3J0NDA0SXRlbSA9IChhd2FpdCBpbXBvcnQoZm91bmQ0MDQucm91dGUucGF0aCArIGA/Y2FjaGU9JHtEYXRlLm5vdygpfWApKS5kZWZhdWx0XG4gICAgICByZXMuc2VuZChkb2N0eXBlSFRNTCArIChhd2FpdCBpbXBvcnQ0MDRJdGVtKHJlcSwgcmVzKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXMuc2VuZCgnRXJyb3InKTtcbiAgICB9XG4gIH0pO1xufSIsICJpbXBvcnQganNvbndlYnRva2VuIGZyb20gJ2pzb253ZWJ0b2tlbic7XG5pbXBvcnQgeyBTZXJ2ZXJSZXF1ZXN0IH0gZnJvbSAnLi4vdHlwZXMnO1xuY29uc3QgeyB2ZXJpZnksIHNpZ24sIH0gPSBqc29ud2VidG9rZW47XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzaWduVXNlcihlbWFpbDogc3RyaW5nLCB1c2VybmFtZTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgc2lnbihcbiAgICAgIHtcbiAgICAgICAgdXNlcjoge1xuICAgICAgICAgIGVtYWlsLFxuICAgICAgICAgIHVzZXJuYW1lLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIHByb2Nlc3MuZW52LkpXVF9QUklWQVRFX0tFWSxcbiAgICAgIHsgZXhwaXJlc0luOiAnMzBkJywgfSxcbiAgICAgIChlcnIsIHRva2VuKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHJlamVjdChlcnIpO1xuICAgICAgICByZXNvbHZlKHRva2VuKTtcbiAgICAgIH0pO1xuICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHZlcmlmeVVzZXIodG9rZW46IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIHZlcmlmeSh0b2tlbiwgcHJvY2Vzcy5lbnYuSldUX1BSSVZBVEVfS0VZLCAoZXJyLCBhdXRob3JpemVkRGF0YSkgPT4ge1xuICAgICAgaWYgKGVycikgcmVqZWN0KGVycik7XG4gICAgICByZXNvbHZlKGF1dGhvcml6ZWREYXRhKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUb2tlbkZyb21SZXF1ZXN0KHJlcTogU2VydmVyUmVxdWVzdCkge1xuICAvLyBAdHMtaWdub3JlXG4gIGNvbnN0IHsgYXV0aG9yaXphdGlvbiwgfSA9IHJlcS5oZWFkZXJzO1xuICBpZiAoIWF1dGhvcml6YXRpb24pIHJldHVybiBudWxsO1xuICBjb25zdCB0b2tlbiA9IGF1dGhvcml6YXRpb24uc3BsaXQoJyAnKS5wb3AoKSB8fCAnJztcbiAgcmV0dXJuIHRva2VuIHx8IG51bGw7XG59IiwgImV4cG9ydCBjbGFzcyBodG1sIHtcblxuICBzdGF0aWMgYXR0cmlidXRlT2JqZWN0VG9TdHJpbmcocHJvcHMpIHtcbiAgICBpZiAoIXByb3BzKSByZXR1cm4gJyc7XG4gICAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKHByb3BzKVxuICAgICAgLmZpbHRlcigoWywgdmFsdWVdKSA9PiB2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZSAhPT0gdW5kZWZpbmVkKVxuICAgICAgLm1hcCgoW2tleSwgdmFsdWVdLCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBzdGFydCA9IGluZGV4ID09PSAwID8gJyAnIDogJyc7XG4gICAgICAgIHJldHVybiBgJHtzdGFydH0ke2tleX09XCIke3ZhbHVlfVwiYDtcbiAgICAgIH0pXG4gICAgICAuam9pbignICcpO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGZyYWdtZW50KHByb3BzKSB7XG4gICAgY29uc3QgY2hpbGRyZW5SZXN1bHQgPSBhd2FpdCBQcm9taXNlLmFsbChwcm9wcy5jaGlsZHJlbi5mbGF0KCkpO1xuICAgIHJldHVybiBjaGlsZHJlblJlc3VsdC5maWx0ZXIoQm9vbGVhbikuam9pbignJyk7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgY3JlYXRlRWxlbWVudCh0eXBlLCBwcm9wcywgLi4uY2hpbGRyZW4pIHtcbiAgICBjb25zdCBjaGlsZHJlblJlc3VsdCA9IGF3YWl0IFByb21pc2UuYWxsKGNoaWxkcmVuLmZsYXQoKSk7XG4gICAgLy8gSGFuZGxlIHBhc3NpbmcgaW4gYW5vdGhlciBlbGVtZW50XG4gICAgaWYgKHR5cGVvZiB0eXBlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0eXBlKHsgLi4ucHJvcHMsIGNoaWxkcmVuOiBjaGlsZHJlblJlc3VsdCwgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICByZXR1cm4gYDwke3R5cGV9JHt0aGlzLmF0dHJpYnV0ZU9iamVjdFRvU3RyaW5nKHByb3BzKX0+JHtjaGlsZHJlblJlc3VsdC5maWx0ZXIoQm9vbGVhbikuam9pbignJyl9PC8ke3R5cGV9PmA7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIEpTWFJ1bnRpbWUoKSB7XG4gIHJldHVybiB0cnVlO1xufSJdLAogICJtYXBwaW5ncyI6ICI7QUFBQSxPQUFPLGVBQWU7QUFDdEIsT0FBTyxVQUFVO0FBQ2pCLE9BQU8sYUFBYTtBQUNwQixPQUFPLGtCQUFrQjtBQUN6QixPQUFP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LEtBQUssQ0FBQztBQUM5RCxXQUFPLGVBQWUsT0FBTyxPQUFPLEVBQUUsS0FBSyxFQUFFO0FBQUEsRUFDL0M7QUFBQSxFQUVBLGFBQWEsY0FBYyxNQUFNLFVBQVUsVUFBVTtBQUNuRCxVQUFNLGlCQUFpQixNQUFNLFFBQVEsSUFBSSxTQUFTLEtBQUssQ0FBQztBQUV4RCxRQUFJLE9BQU8sU0FBUyxZQUFZO0FBQzlCLFlBQU0sU0FBUyxNQUFNLEtBQUssRUFBRSxHQUFHLE9BQU8sVUFBVSxlQUFnQixDQUFDO0FBQ2pFLGFBQU87QUFBQSxJQUNUO0FBQ0EsV0FBTyxJQUFJLElBQUksR0FBRyxLQUFLLHdCQUF3QixLQUFLLENBQUMsSUFBSSxlQUFlLE9BQU8sT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDLEtBQUssSUFBSTtBQUFBLEVBQzNHO0FBQ0Y7QUFFTyxTQUFTLGFBQWE7QUFDM0IsU0FBTztBQUNUOyIsCiAgIm5hbWVzIjogWyJwYXRoIiwgImZzIiwgInRzIiwgImNoaWxkIiwgInRleHQiLCAicGF0aCIsICJyZXF1aXJlIiwgInBhdGgiLCAiZnMiLCAiYnVpbGQiLCAicGF0aCIsICJ0cyIsICJwYXRoIiwgInBhdGgiLCAicGF0aCIsICJwYXRoIiwgInN0YXJ0U2VydmVyIiwgImV4cHJlc3MiLCAiZ2xvYlN5bmMiLCAiZXhwcmVzcyIsICJnbG9iU3luYyJdCn0K