@napi-rs/cli 3.0.0-alpha.9 → 3.0.0-alpha.91
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/cli.mjs +1 -1
- package/dist/api/__tests__/new.spec.d.ts +1 -0
- package/dist/api/build.d.ts +1 -1
- package/dist/api/templates/ci-template.d.ts +3 -1
- package/dist/api/templates/ci.yml.d.ts +3 -1
- package/dist/api/templates/js-binding.d.ts +1 -0
- package/dist/api/templates/load-wasi-template.d.ts +2 -0
- package/dist/api/templates/package.json.d.ts +9 -2
- package/dist/api/templates/wasi-worker-template.d.ts +2 -0
- package/dist/cli.js +3867 -15
- package/dist/def/artifacts.d.ts +21 -1
- package/dist/def/build.d.ts +149 -4
- package/dist/def/create-npm-dirs.d.ts +10 -0
- package/dist/def/new.d.ts +25 -7
- package/dist/def/pre-publish.d.ts +12 -2
- package/dist/def/rename.d.ts +16 -6
- package/dist/def/universalize.d.ts +10 -0
- package/dist/def/version.d.ts +10 -0
- package/dist/index.cjs +9946 -15669
- package/dist/index.js +3618 -32
- package/dist/utils/__tests__/config.spec.d.ts +1 -0
- package/dist/utils/config.d.ts +48 -4
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/metadata.d.ts +13 -1
- package/dist/utils/misc.d.ts +3 -3
- package/dist/utils/read-config.d.ts +7 -0
- package/dist/utils/target.d.ts +7 -5
- package/dist/utils/typegen.d.ts +1 -1
- package/dist/utils/version.d.ts +2 -1
- package/package.json +38 -34
- package/src/api/__tests__/new.spec.ts +429 -0
- package/src/api/artifacts.ts +81 -9
- package/src/api/build.ts +498 -149
- package/src/api/create-npm-dirs.ts +57 -9
- package/src/api/new.ts +389 -122
- package/src/api/pre-publish.ts +13 -7
- package/src/api/rename.ts +103 -17
- package/src/api/templates/cargo.toml.ts +1 -0
- package/src/api/templates/ci-template.ts +150 -125
- package/src/api/templates/ci.yml.ts +27 -6
- package/src/api/templates/js-binding.ts +148 -220
- package/src/api/templates/load-wasi-template.ts +182 -0
- package/src/api/templates/package.json.ts +47 -5
- package/src/api/templates/wasi-worker-template.ts +122 -0
- package/src/api/universalize.ts +13 -8
- package/src/api/version.ts +5 -2
- package/src/commands/artifacts.ts +2 -2
- package/src/commands/build.ts +1 -1
- package/src/commands/new.ts +46 -45
- package/src/def/artifacts.ts +22 -3
- package/src/def/build.ts +55 -8
- package/src/def/create-npm-dirs.ts +9 -0
- package/src/def/new.ts +28 -3
- package/src/def/pre-publish.ts +12 -3
- package/src/def/rename.ts +11 -2
- package/src/def/universalize.ts +9 -0
- package/src/def/version.ts +9 -0
- package/src/utils/__tests__/__fixtures__/napi_type_def +130 -130
- package/src/utils/__tests__/__snapshots__/config.spec.ts.md +97 -0
- package/src/utils/__tests__/__snapshots__/config.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/target.spec.ts.md +28 -0
- package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +316 -332
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/version.spec.ts.md +8 -7
- package/src/utils/__tests__/__snapshots__/version.spec.ts.snap +0 -0
- package/src/utils/__tests__/config.spec.ts +81 -0
- package/src/utils/cargo.ts +2 -2
- package/src/utils/config.ts +110 -9
- package/src/utils/index.ts +1 -1
- package/src/utils/log.ts +1 -1
- package/src/utils/metadata.ts +52 -14
- package/src/utils/misc.ts +21 -12
- package/src/utils/read-config.ts +20 -0
- package/src/utils/target.ts +22 -4
- package/src/utils/typegen.ts +87 -52
- package/src/utils/version.ts +10 -8
- package/dist/api/artifacts.js +0 -53
- package/dist/api/artifacts.js.map +0 -1
- package/dist/api/build.js +0 -498
- package/dist/api/build.js.map +0 -1
- package/dist/api/create-npm-dirs.js +0 -64
- package/dist/api/create-npm-dirs.js.map +0 -1
- package/dist/api/load-wasi-template.d.ts +0 -1
- package/dist/api/load-wasi-template.js +0 -64
- package/dist/api/load-wasi-template.js.map +0 -1
- package/dist/api/new.js +0 -155
- package/dist/api/new.js.map +0 -1
- package/dist/api/pre-publish.js +0 -158
- package/dist/api/pre-publish.js.map +0 -1
- package/dist/api/rename.js +0 -29
- package/dist/api/rename.js.map +0 -1
- package/dist/api/templates/.gitignore.js +0 -200
- package/dist/api/templates/.gitignore.js.map +0 -1
- package/dist/api/templates/.npmignore.js +0 -15
- package/dist/api/templates/.npmignore.js.map +0 -1
- package/dist/api/templates/build.rs.js +0 -5
- package/dist/api/templates/build.rs.js.map +0 -1
- package/dist/api/templates/cargo.toml.js +0 -26
- package/dist/api/templates/cargo.toml.js.map +0 -1
- package/dist/api/templates/ci-template.js +0 -578
- package/dist/api/templates/ci-template.js.map +0 -1
- package/dist/api/templates/ci.yml.js +0 -99
- package/dist/api/templates/ci.yml.js.map +0 -1
- package/dist/api/templates/index.js +0 -9
- package/dist/api/templates/index.js.map +0 -1
- package/dist/api/templates/js-binding.js +0 -293
- package/dist/api/templates/js-binding.js.map +0 -1
- package/dist/api/templates/lib.rs.js +0 -8
- package/dist/api/templates/lib.rs.js.map +0 -1
- package/dist/api/templates/package.json.js +0 -32
- package/dist/api/templates/package.json.js.map +0 -1
- package/dist/api/universalize.js +0 -39
- package/dist/api/universalize.js.map +0 -1
- package/dist/api/version.js +0 -17
- package/dist/api/version.js.map +0 -1
- package/dist/api/wasi-worker-template.d.ts +0 -1
- package/dist/api/wasi-worker-template.js +0 -53
- package/dist/api/wasi-worker-template.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/artifacts.js +0 -20
- package/dist/commands/artifacts.js.map +0 -1
- package/dist/commands/build.js +0 -35
- package/dist/commands/build.js.map +0 -1
- package/dist/commands/create-npm-dirs.js +0 -8
- package/dist/commands/create-npm-dirs.js.map +0 -1
- package/dist/commands/help.js +0 -13
- package/dist/commands/help.js.map +0 -1
- package/dist/commands/new.js +0 -110
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/pre-publish.js +0 -9
- package/dist/commands/pre-publish.js.map +0 -1
- package/dist/commands/rename.js +0 -8
- package/dist/commands/rename.js.map +0 -1
- package/dist/commands/universalize.js +0 -8
- package/dist/commands/universalize.js.map +0 -1
- package/dist/commands/version.js +0 -8
- package/dist/commands/version.js.map +0 -1
- package/dist/def/artifacts.js +0 -39
- package/dist/def/artifacts.js.map +0 -1
- package/dist/def/build.js +0 -118
- package/dist/def/build.js.map +0 -1
- package/dist/def/create-npm-dirs.js +0 -39
- package/dist/def/create-npm-dirs.js.map +0 -1
- package/dist/def/new.js +0 -67
- package/dist/def/new.js.map +0 -1
- package/dist/def/pre-publish.js +0 -57
- package/dist/def/pre-publish.js.map +0 -1
- package/dist/def/rename.js +0 -59
- package/dist/def/rename.js.map +0 -1
- package/dist/def/universalize.js +0 -34
- package/dist/def/universalize.js.map +0 -1
- package/dist/def/version.js +0 -34
- package/dist/def/version.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/utils/__tests__/target.spec.js +0 -11
- package/dist/utils/__tests__/target.spec.js.map +0 -1
- package/dist/utils/__tests__/typegen.spec.js +0 -42
- package/dist/utils/__tests__/typegen.spec.js.map +0 -1
- package/dist/utils/__tests__/version.spec.js +0 -6
- package/dist/utils/__tests__/version.spec.js.map +0 -1
- package/dist/utils/cargo.js +0 -34
- package/dist/utils/cargo.js.map +0 -1
- package/dist/utils/ci.d.ts +0 -11
- package/dist/utils/ci.js +0 -96
- package/dist/utils/ci.js.map +0 -1
- package/dist/utils/config.js +0 -43
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/index.js +0 -10
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/log.js +0 -15
- package/dist/utils/log.js.map +0 -1
- package/dist/utils/metadata.js +0 -20
- package/dist/utils/metadata.js.map +0 -1
- package/dist/utils/misc.js +0 -41
- package/dist/utils/misc.js.map +0 -1
- package/dist/utils/target.js +0 -121
- package/dist/utils/target.js.map +0 -1
- package/dist/utils/typegen.js +0 -179
- package/dist/utils/typegen.js.map +0 -1
- package/dist/utils/version.js +0 -60
- package/dist/utils/version.js.map +0 -1
- package/src/api/load-wasi-template.ts +0 -66
- package/src/api/wasi-worker-template.ts +0 -52
- package/src/utils/ci.ts +0 -111
package/dist/index.js
CHANGED
|
@@ -1,32 +1,3618 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import path, { join, parse, resolve } from "node:path";
|
|
3
|
+
import * as colors$2 from "colorette";
|
|
4
|
+
import * as colors$1 from "colorette";
|
|
5
|
+
import * as colors from "colorette";
|
|
6
|
+
import { underline, yellow } from "colorette";
|
|
7
|
+
import { Command, Option } from "clipanion";
|
|
8
|
+
import rawDebug from "debug";
|
|
9
|
+
import fs, { copyFile, existsSync, mkdir, mkdirSync, promises, readFile, readdir, rmSync, stat, statSync, unlink, writeFile } from "node:fs";
|
|
10
|
+
import { promisify } from "node:util";
|
|
11
|
+
import { exec, execSync, spawn, spawnSync } from "node:child_process";
|
|
12
|
+
import { isNil, merge, omit, omitBy, pick, sortBy } from "lodash-es";
|
|
13
|
+
import { createHash } from "node:crypto";
|
|
14
|
+
import { homedir } from "node:os";
|
|
15
|
+
import { include, lib } from "wasm-sjlj";
|
|
16
|
+
import { dump, load } from "js-yaml";
|
|
17
|
+
import { parse as parse$1 } from "semver";
|
|
18
|
+
import * as typanion from "typanion";
|
|
19
|
+
import { rename } from "node:fs/promises";
|
|
20
|
+
import { findUp } from "find-up";
|
|
21
|
+
import { Octokit } from "@octokit/rest";
|
|
22
|
+
|
|
23
|
+
//#region rolldown:runtime
|
|
24
|
+
var __create = Object.create;
|
|
25
|
+
var __defProp = Object.defineProperty;
|
|
26
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
27
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
28
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
29
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
30
|
+
var __commonJS = (cb, mod) => function() {
|
|
31
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
32
|
+
};
|
|
33
|
+
var __copyProps = (to, from, except, desc) => {
|
|
34
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
35
|
+
key = keys[i];
|
|
36
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
37
|
+
get: ((k) => from[k]).bind(null, key),
|
|
38
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return to;
|
|
42
|
+
};
|
|
43
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
44
|
+
value: mod,
|
|
45
|
+
enumerable: true
|
|
46
|
+
}) : target, mod));
|
|
47
|
+
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region ../node_modules/@oxc-project/runtime/src/helpers/typeof.js
|
|
50
|
+
var require_typeof = __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/typeof.js"(exports, module) {
|
|
51
|
+
function _typeof$2(o) {
|
|
52
|
+
"@babel/helpers - typeof";
|
|
53
|
+
return module.exports = _typeof$2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
|
|
54
|
+
return typeof o$1;
|
|
55
|
+
} : function(o$1) {
|
|
56
|
+
return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
|
|
57
|
+
}, module.exports.__esModule = true, module.exports["default"] = module.exports, _typeof$2(o);
|
|
58
|
+
}
|
|
59
|
+
module.exports = _typeof$2, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
60
|
+
} });
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region ../node_modules/@oxc-project/runtime/src/helpers/toPrimitive.js
|
|
64
|
+
var require_toPrimitive = __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/toPrimitive.js"(exports, module) {
|
|
65
|
+
var _typeof$1 = require_typeof()["default"];
|
|
66
|
+
function toPrimitive$1(t, r) {
|
|
67
|
+
if ("object" != _typeof$1(t) || !t) return t;
|
|
68
|
+
var e = t[Symbol.toPrimitive];
|
|
69
|
+
if (void 0 !== e) {
|
|
70
|
+
var i = e.call(t, r || "default");
|
|
71
|
+
if ("object" != _typeof$1(i)) return i;
|
|
72
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
73
|
+
}
|
|
74
|
+
return ("string" === r ? String : Number)(t);
|
|
75
|
+
}
|
|
76
|
+
module.exports = toPrimitive$1, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
77
|
+
} });
|
|
78
|
+
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region ../node_modules/@oxc-project/runtime/src/helpers/toPropertyKey.js
|
|
81
|
+
var require_toPropertyKey = __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/toPropertyKey.js"(exports, module) {
|
|
82
|
+
var _typeof = require_typeof()["default"];
|
|
83
|
+
var toPrimitive = require_toPrimitive();
|
|
84
|
+
function toPropertyKey$1(t) {
|
|
85
|
+
var i = toPrimitive(t, "string");
|
|
86
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
87
|
+
}
|
|
88
|
+
module.exports = toPropertyKey$1, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
89
|
+
} });
|
|
90
|
+
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region ../node_modules/@oxc-project/runtime/src/helpers/defineProperty.js
|
|
93
|
+
var require_defineProperty = __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/defineProperty.js"(exports, module) {
|
|
94
|
+
var toPropertyKey = require_toPropertyKey();
|
|
95
|
+
function _defineProperty$10(e, r, t) {
|
|
96
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
97
|
+
value: t,
|
|
98
|
+
enumerable: !0,
|
|
99
|
+
configurable: !0,
|
|
100
|
+
writable: !0
|
|
101
|
+
}) : e[r] = t, e;
|
|
102
|
+
}
|
|
103
|
+
module.exports = _defineProperty$10, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
104
|
+
} });
|
|
105
|
+
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/def/artifacts.ts
|
|
108
|
+
var import_defineProperty$9 = __toESM(require_defineProperty(), 1);
|
|
109
|
+
var BaseArtifactsCommand = class extends Command {
|
|
110
|
+
constructor(..._args) {
|
|
111
|
+
super(..._args);
|
|
112
|
+
(0, import_defineProperty$9.default)(this, "cwd", Option.String("--cwd", process.cwd(), { description: "The working directory of where napi command will be executed in, all other paths options are relative to this path" }));
|
|
113
|
+
(0, import_defineProperty$9.default)(this, "configPath", Option.String("--config-path,-c", { description: "Path to `napi` config json file" }));
|
|
114
|
+
(0, import_defineProperty$9.default)(this, "packageJsonPath", Option.String("--package-json-path", "package.json", { description: "Path to `package.json`" }));
|
|
115
|
+
(0, import_defineProperty$9.default)(this, "outputDir", Option.String("--output-dir,-o,-d", "./artifacts", { description: "Path to the folder where all built `.node` files put, same as `--output-dir` of build command" }));
|
|
116
|
+
(0, import_defineProperty$9.default)(this, "npmDir", Option.String("--npm-dir", "npm", { description: "Path to the folder where the npm packages put" }));
|
|
117
|
+
(0, import_defineProperty$9.default)(this, "buildOutputDir", Option.String("--build-output-dir", { description: "Path to the build output dir, only needed when targets contains `wasm32-wasi-*`" }));
|
|
118
|
+
}
|
|
119
|
+
getOptions() {
|
|
120
|
+
return {
|
|
121
|
+
cwd: this.cwd,
|
|
122
|
+
configPath: this.configPath,
|
|
123
|
+
packageJsonPath: this.packageJsonPath,
|
|
124
|
+
outputDir: this.outputDir,
|
|
125
|
+
npmDir: this.npmDir,
|
|
126
|
+
buildOutputDir: this.buildOutputDir
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
(0, import_defineProperty$9.default)(BaseArtifactsCommand, "paths", [["artifacts"]]);
|
|
131
|
+
(0, import_defineProperty$9.default)(BaseArtifactsCommand, "usage", Command.Usage({ description: "Copy artifacts from Github Actions into npm packages and ready to publish" }));
|
|
132
|
+
function applyDefaultArtifactsOptions(options) {
|
|
133
|
+
return {
|
|
134
|
+
cwd: process.cwd(),
|
|
135
|
+
packageJsonPath: "package.json",
|
|
136
|
+
outputDir: "./artifacts",
|
|
137
|
+
npmDir: "npm",
|
|
138
|
+
...options
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region src/utils/log.ts
|
|
144
|
+
rawDebug.formatters.i = (v) => {
|
|
145
|
+
return colors$2.green(v);
|
|
146
|
+
};
|
|
147
|
+
const debugFactory = (namespace) => {
|
|
148
|
+
const debug$8 = rawDebug(`napi:${namespace}`);
|
|
149
|
+
debug$8.info = (...args) => console.error(colors$2.black(colors$2.bgGreen(" INFO ")), ...args);
|
|
150
|
+
debug$8.warn = (...args) => console.error(colors$2.black(colors$2.bgYellow(" WARNING ")), ...args);
|
|
151
|
+
debug$8.error = (...args) => console.error(colors$2.white(colors$2.bgRed(" ERROR ")), ...args.map((arg) => arg instanceof Error ? arg.stack ?? arg.message : arg));
|
|
152
|
+
return debug$8;
|
|
153
|
+
};
|
|
154
|
+
const debug$7 = debugFactory("utils");
|
|
155
|
+
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region package.json
|
|
158
|
+
var name = "@napi-rs/cli";
|
|
159
|
+
var version$1 = "3.0.0-alpha.91";
|
|
160
|
+
var description = "Cli tools for napi-rs";
|
|
161
|
+
var author = "LongYinan <lynweklm@gmail.com>";
|
|
162
|
+
var homepage = "https://github.com/napi-rs/napi-rs";
|
|
163
|
+
var license = "MIT";
|
|
164
|
+
var type = "module";
|
|
165
|
+
var engines = { "node": ">= 16" };
|
|
166
|
+
var bin = {
|
|
167
|
+
"napi": "./dist/cli.js",
|
|
168
|
+
"napi-raw": "./cli.mjs"
|
|
169
|
+
};
|
|
170
|
+
var main = "./dist/index.cjs";
|
|
171
|
+
var module$1 = "./dist/index.js";
|
|
172
|
+
var exports = {
|
|
173
|
+
".": {
|
|
174
|
+
"import": {
|
|
175
|
+
"types": "./dist/index.d.ts",
|
|
176
|
+
"default": "./dist/index.js"
|
|
177
|
+
},
|
|
178
|
+
"require": {
|
|
179
|
+
"types": "./dist/index.d.ts",
|
|
180
|
+
"default": "./dist/index.cjs"
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
"./package.json": {
|
|
184
|
+
"import": "./package.json",
|
|
185
|
+
"require": "./package.json"
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
var files = ["dist", "src"];
|
|
189
|
+
var keywords = [
|
|
190
|
+
"cli",
|
|
191
|
+
"rust",
|
|
192
|
+
"napi",
|
|
193
|
+
"n-api",
|
|
194
|
+
"node-api",
|
|
195
|
+
"node-addon",
|
|
196
|
+
"neon"
|
|
197
|
+
];
|
|
198
|
+
var maintainers = [{
|
|
199
|
+
"name": "LongYinan",
|
|
200
|
+
"email": "lynweklm@gmail.com",
|
|
201
|
+
"homepage": "https://github.com/Brooooooklyn"
|
|
202
|
+
}, {
|
|
203
|
+
"name": "forehalo",
|
|
204
|
+
"homepage": "https://github.com/forehalo"
|
|
205
|
+
}];
|
|
206
|
+
var repository = {
|
|
207
|
+
"type": "git",
|
|
208
|
+
"url": "git+https://github.com/napi-rs/napi-rs.git"
|
|
209
|
+
};
|
|
210
|
+
var publishConfig = {
|
|
211
|
+
"registry": "https://registry.npmjs.org/",
|
|
212
|
+
"access": "public"
|
|
213
|
+
};
|
|
214
|
+
var bugs = { "url": "https://github.com/napi-rs/napi-rs/issues" };
|
|
215
|
+
var dependencies = {
|
|
216
|
+
"@inquirer/prompts": "^7.4.0",
|
|
217
|
+
"@napi-rs/cross-toolchain": "^0.0.19",
|
|
218
|
+
"@napi-rs/wasm-tools": "^0.0.3",
|
|
219
|
+
"@octokit/rest": "^22.0.0",
|
|
220
|
+
"clipanion": "^4.0.0-rc.4",
|
|
221
|
+
"colorette": "^2.0.20",
|
|
222
|
+
"debug": "^4.4.0",
|
|
223
|
+
"emnapi": "^1.4.0",
|
|
224
|
+
"find-up": "^7.0.0",
|
|
225
|
+
"js-yaml": "^4.1.0",
|
|
226
|
+
"lodash-es": "^4.17.21",
|
|
227
|
+
"semver": "^7.7.1",
|
|
228
|
+
"typanion": "^3.14.0",
|
|
229
|
+
"wasm-sjlj": "^1.0.6"
|
|
230
|
+
};
|
|
231
|
+
var devDependencies = {
|
|
232
|
+
"@emnapi/core": "^1.4.0",
|
|
233
|
+
"@emnapi/runtime": "^1.4.0",
|
|
234
|
+
"@oxc-node/core": "^0.0.29",
|
|
235
|
+
"@std/toml": "npm:@jsr/std__toml@^1.0.8",
|
|
236
|
+
"@types/debug": "^4.1.12",
|
|
237
|
+
"@types/inquirer": "^9.0.7",
|
|
238
|
+
"@types/js-yaml": "^4.0.9",
|
|
239
|
+
"@types/lodash-es": "^4.17.12",
|
|
240
|
+
"@types/node": "^22.13.16",
|
|
241
|
+
"@types/semver": "^7.7.0",
|
|
242
|
+
"ava": "^6.2.0",
|
|
243
|
+
"env-paths": "^3.0.0",
|
|
244
|
+
"prettier": "^3.5.3",
|
|
245
|
+
"rolldown": "^1.0.0-beta.19",
|
|
246
|
+
"tslib": "^2.8.1",
|
|
247
|
+
"typescript": "^5.8.2"
|
|
248
|
+
};
|
|
249
|
+
var peerDependencies = {
|
|
250
|
+
"@emnapi/runtime": "^1.1.0",
|
|
251
|
+
"emnapi": "^1.1.0"
|
|
252
|
+
};
|
|
253
|
+
var peerDependenciesMeta = {
|
|
254
|
+
"@emnapi/runtime": { "optional": true },
|
|
255
|
+
"emnapi": { "optional": true }
|
|
256
|
+
};
|
|
257
|
+
var funding = {
|
|
258
|
+
"type": "github",
|
|
259
|
+
"url": "https://github.com/sponsors/Brooooooklyn"
|
|
260
|
+
};
|
|
261
|
+
var scripts = {
|
|
262
|
+
"clean": "node --import @oxc-node/core/register ./clean.ts",
|
|
263
|
+
"codegen": "node --import @oxc-node/core/register ./codegen/index.ts",
|
|
264
|
+
"build": "tsc && yarn clean && rolldown -c rolldown.config.js",
|
|
265
|
+
"test": "node --import @oxc-node/core/register ../node_modules/ava/entrypoints/cli.mjs"
|
|
266
|
+
};
|
|
267
|
+
var ava = {
|
|
268
|
+
"extensions": { "ts": "module" },
|
|
269
|
+
"timeout": "1m",
|
|
270
|
+
"files": ["**/__tests__/**/*.spec.ts", "e2e/**/*.spec.ts"]
|
|
271
|
+
};
|
|
272
|
+
var gitHead = "71da5b6dc17064e478e5beb0ffa71f73d6238f7d";
|
|
273
|
+
var package_default = {
|
|
274
|
+
name,
|
|
275
|
+
version: version$1,
|
|
276
|
+
description,
|
|
277
|
+
author,
|
|
278
|
+
homepage,
|
|
279
|
+
license,
|
|
280
|
+
type,
|
|
281
|
+
engines,
|
|
282
|
+
bin,
|
|
283
|
+
main,
|
|
284
|
+
module: module$1,
|
|
285
|
+
exports,
|
|
286
|
+
files,
|
|
287
|
+
keywords,
|
|
288
|
+
maintainers,
|
|
289
|
+
repository,
|
|
290
|
+
publishConfig,
|
|
291
|
+
bugs,
|
|
292
|
+
dependencies,
|
|
293
|
+
devDependencies,
|
|
294
|
+
peerDependencies,
|
|
295
|
+
peerDependenciesMeta,
|
|
296
|
+
funding,
|
|
297
|
+
scripts,
|
|
298
|
+
ava,
|
|
299
|
+
gitHead
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
//#endregion
|
|
303
|
+
//#region src/utils/misc.ts
|
|
304
|
+
const readFileAsync = promisify(readFile);
|
|
305
|
+
const writeFileAsync = promisify(writeFile);
|
|
306
|
+
const unlinkAsync = promisify(unlink);
|
|
307
|
+
const copyFileAsync = promisify(copyFile);
|
|
308
|
+
const mkdirAsync = promisify(mkdir);
|
|
309
|
+
const statAsync = promisify(stat);
|
|
310
|
+
const readdirAsync = promisify(readdir);
|
|
311
|
+
async function fileExists(path$1) {
|
|
312
|
+
const exists = await statAsync(path$1).then(() => true).catch(() => false);
|
|
313
|
+
return exists;
|
|
314
|
+
}
|
|
315
|
+
async function dirExistsAsync(path$1) {
|
|
316
|
+
try {
|
|
317
|
+
const stats = await statAsync(path$1);
|
|
318
|
+
return stats.isDirectory();
|
|
319
|
+
} catch {
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
function pick$1(o, ...keys) {
|
|
324
|
+
return keys.reduce((acc, key) => {
|
|
325
|
+
acc[key] = o[key];
|
|
326
|
+
return acc;
|
|
327
|
+
}, {});
|
|
328
|
+
}
|
|
329
|
+
async function updatePackageJson(path$1, partial) {
|
|
330
|
+
const exists = await fileExists(path$1);
|
|
331
|
+
if (!exists) {
|
|
332
|
+
debug$7(`File not exists ${path$1}`);
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const old = JSON.parse(await readFileAsync(path$1, "utf8"));
|
|
336
|
+
await writeFileAsync(path$1, JSON.stringify({
|
|
337
|
+
...old,
|
|
338
|
+
...partial
|
|
339
|
+
}, null, 2));
|
|
340
|
+
}
|
|
341
|
+
const CLI_VERSION = package_default.version;
|
|
342
|
+
|
|
343
|
+
//#endregion
|
|
344
|
+
//#region src/utils/target.ts
|
|
345
|
+
const AVAILABLE_TARGETS = [
|
|
346
|
+
"aarch64-apple-darwin",
|
|
347
|
+
"aarch64-linux-android",
|
|
348
|
+
"aarch64-unknown-linux-gnu",
|
|
349
|
+
"aarch64-unknown-linux-musl",
|
|
350
|
+
"aarch64-pc-windows-msvc",
|
|
351
|
+
"x86_64-apple-darwin",
|
|
352
|
+
"x86_64-pc-windows-msvc",
|
|
353
|
+
"x86_64-unknown-linux-gnu",
|
|
354
|
+
"x86_64-unknown-linux-musl",
|
|
355
|
+
"x86_64-unknown-freebsd",
|
|
356
|
+
"i686-pc-windows-msvc",
|
|
357
|
+
"armv7-unknown-linux-gnueabihf",
|
|
358
|
+
"armv7-unknown-linux-musleabihf",
|
|
359
|
+
"armv7-linux-androideabi",
|
|
360
|
+
"universal-apple-darwin",
|
|
361
|
+
"riscv64gc-unknown-linux-gnu",
|
|
362
|
+
"powerpc64le-unknown-linux-gnu",
|
|
363
|
+
"s390x-unknown-linux-gnu",
|
|
364
|
+
"wasm32-wasi-preview1-threads"
|
|
365
|
+
];
|
|
366
|
+
const DEFAULT_TARGETS = [
|
|
367
|
+
"x86_64-apple-darwin",
|
|
368
|
+
"aarch64-apple-darwin",
|
|
369
|
+
"x86_64-pc-windows-msvc",
|
|
370
|
+
"x86_64-unknown-linux-gnu"
|
|
371
|
+
];
|
|
372
|
+
const TARGET_LINKER = {
|
|
373
|
+
"aarch64-unknown-linux-musl": "aarch64-linux-musl-gcc",
|
|
374
|
+
"riscv64gc-unknown-linux-gnu": "riscv64-linux-gnu-gcc",
|
|
375
|
+
"powerpc64le-unknown-linux-gnu": "powerpc64le-linux-gnu-gcc",
|
|
376
|
+
"s390x-unknown-linux-gnu": "s390x-linux-gnu-gcc"
|
|
377
|
+
};
|
|
378
|
+
const CpuToNodeArch = {
|
|
379
|
+
x86_64: "x64",
|
|
380
|
+
aarch64: "arm64",
|
|
381
|
+
i686: "ia32",
|
|
382
|
+
armv7: "arm",
|
|
383
|
+
riscv64gc: "riscv64",
|
|
384
|
+
powerpc64le: "ppc64"
|
|
385
|
+
};
|
|
386
|
+
const SysToNodePlatform = {
|
|
387
|
+
linux: "linux",
|
|
388
|
+
freebsd: "freebsd",
|
|
389
|
+
darwin: "darwin",
|
|
390
|
+
windows: "win32"
|
|
391
|
+
};
|
|
392
|
+
const UniArchsByPlatform = { darwin: ["x64", "arm64"] };
|
|
393
|
+
/**
|
|
394
|
+
* A triple is a specific format for specifying a target architecture.
|
|
395
|
+
* Triples may be referred to as a target triple which is the architecture for the artifact produced, and the host triple which is the architecture that the compiler is running on.
|
|
396
|
+
* The general format of the triple is `<arch><sub>-<vendor>-<sys>-<abi>` where:
|
|
397
|
+
* - `arch` = The base CPU architecture, for example `x86_64`, `i686`, `arm`, `thumb`, `mips`, etc.
|
|
398
|
+
* - `sub` = The CPU sub-architecture, for example `arm` has `v7`, `v7s`, `v5te`, etc.
|
|
399
|
+
* - `vendor` = The vendor, for example `unknown`, `apple`, `pc`, `nvidia`, etc.
|
|
400
|
+
* - `sys` = The system name, for example `linux`, `windows`, `darwin`, etc. none is typically used for bare-metal without an OS.
|
|
401
|
+
* - `abi` = The ABI, for example `gnu`, `android`, `eabi`, etc.
|
|
402
|
+
*/
|
|
403
|
+
function parseTriple(rawTriple) {
|
|
404
|
+
if (rawTriple === "wasm32-wasi" || rawTriple === "wasm32-wasi-preview1-threads" || rawTriple.startsWith("wasm32-wasip")) return {
|
|
405
|
+
triple: rawTriple,
|
|
406
|
+
platformArchABI: "wasm32-wasi",
|
|
407
|
+
platform: "wasi",
|
|
408
|
+
arch: "wasm32",
|
|
409
|
+
abi: "wasi"
|
|
410
|
+
};
|
|
411
|
+
const triple = rawTriple.endsWith("eabi") ? `${rawTriple.slice(0, -4)}-eabi` : rawTriple;
|
|
412
|
+
const triples = triple.split("-");
|
|
413
|
+
let cpu;
|
|
414
|
+
let sys;
|
|
415
|
+
let abi = null;
|
|
416
|
+
if (triples.length === 2) [cpu, sys] = triples;
|
|
417
|
+
else [cpu, , sys, abi = null] = triples;
|
|
418
|
+
const platform = SysToNodePlatform[sys] ?? sys;
|
|
419
|
+
const arch = CpuToNodeArch[cpu] ?? cpu;
|
|
420
|
+
return {
|
|
421
|
+
triple: rawTriple,
|
|
422
|
+
platformArchABI: abi ? `${platform}-${arch}-${abi}` : `${platform}-${arch}`,
|
|
423
|
+
platform,
|
|
424
|
+
arch,
|
|
425
|
+
abi
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
function getSystemDefaultTarget() {
|
|
429
|
+
const host = execSync(`rustc -vV`, { env: process.env }).toString("utf8").split("\n").find((line) => line.startsWith("host: "));
|
|
430
|
+
const triple = host?.slice(6);
|
|
431
|
+
if (!triple) throw new TypeError(`Can not parse target triple from host`);
|
|
432
|
+
return parseTriple(triple);
|
|
433
|
+
}
|
|
434
|
+
function getTargetLinker(target) {
|
|
435
|
+
return TARGET_LINKER[target];
|
|
436
|
+
}
|
|
437
|
+
function targetToEnvVar(target) {
|
|
438
|
+
return target.replace(/-/g, "_").toUpperCase();
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
//#endregion
|
|
442
|
+
//#region src/utils/version.ts
|
|
443
|
+
let NapiVersion = /* @__PURE__ */ function(NapiVersion$1) {
|
|
444
|
+
NapiVersion$1[NapiVersion$1["Napi1"] = 1] = "Napi1";
|
|
445
|
+
NapiVersion$1[NapiVersion$1["Napi2"] = 2] = "Napi2";
|
|
446
|
+
NapiVersion$1[NapiVersion$1["Napi3"] = 3] = "Napi3";
|
|
447
|
+
NapiVersion$1[NapiVersion$1["Napi4"] = 4] = "Napi4";
|
|
448
|
+
NapiVersion$1[NapiVersion$1["Napi5"] = 5] = "Napi5";
|
|
449
|
+
NapiVersion$1[NapiVersion$1["Napi6"] = 6] = "Napi6";
|
|
450
|
+
NapiVersion$1[NapiVersion$1["Napi7"] = 7] = "Napi7";
|
|
451
|
+
NapiVersion$1[NapiVersion$1["Napi8"] = 8] = "Napi8";
|
|
452
|
+
NapiVersion$1[NapiVersion$1["Napi9"] = 9] = "Napi9";
|
|
453
|
+
return NapiVersion$1;
|
|
454
|
+
}({});
|
|
455
|
+
const NAPI_VERSION_MATRIX = new Map([
|
|
456
|
+
[NapiVersion.Napi1, "8.6.0 | 9.0.0 | 10.0.0"],
|
|
457
|
+
[NapiVersion.Napi2, "8.10.0 | 9.3.0 | 10.0.0"],
|
|
458
|
+
[NapiVersion.Napi3, "6.14.2 | 8.11.2 | 9.11.0 | 10.0.0"],
|
|
459
|
+
[NapiVersion.Napi4, "10.16.0 | 11.8.0 | 12.0.0"],
|
|
460
|
+
[NapiVersion.Napi5, "10.17.0 | 12.11.0 | 13.0.0"],
|
|
461
|
+
[NapiVersion.Napi6, "10.20.0 | 12.17.0 | 14.0.0"],
|
|
462
|
+
[NapiVersion.Napi7, "10.23.0 | 12.19.0 | 14.12.0 | 15.0.0"],
|
|
463
|
+
[NapiVersion.Napi8, "12.22.0 | 14.17.0 | 15.12.0 | 16.0.0"],
|
|
464
|
+
[NapiVersion.Napi9, "18.17.0 | 20.3.0 | 21.1.0"]
|
|
465
|
+
]);
|
|
466
|
+
function parseNodeVersion(v) {
|
|
467
|
+
const matches = v.match(/v?([0-9]+)\.([0-9]+)\.([0-9]+)/i);
|
|
468
|
+
if (!matches) throw new Error("Unknown node version number: " + v);
|
|
469
|
+
const [, major, minor, patch] = matches;
|
|
470
|
+
return {
|
|
471
|
+
major: parseInt(major),
|
|
472
|
+
minor: parseInt(minor),
|
|
473
|
+
patch: parseInt(patch)
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
function requiredNodeVersions(napiVersion) {
|
|
477
|
+
const requirement = NAPI_VERSION_MATRIX.get(napiVersion);
|
|
478
|
+
if (!requirement) return [parseNodeVersion("10.0.0")];
|
|
479
|
+
return requirement.split("|").map(parseNodeVersion);
|
|
480
|
+
}
|
|
481
|
+
function toEngineRequirement(versions) {
|
|
482
|
+
const requirements = [];
|
|
483
|
+
versions.forEach((v, i) => {
|
|
484
|
+
let req = "";
|
|
485
|
+
if (i !== 0) {
|
|
486
|
+
const lastVersion = versions[i - 1];
|
|
487
|
+
req += `< ${lastVersion.major + 1}`;
|
|
488
|
+
}
|
|
489
|
+
req += `${i === 0 ? "" : " || "}>= ${v.major}.${v.minor}.${v.patch}`;
|
|
490
|
+
requirements.push(req);
|
|
491
|
+
});
|
|
492
|
+
return requirements.join(" ");
|
|
493
|
+
}
|
|
494
|
+
function napiEngineRequirement(napiVersion) {
|
|
495
|
+
return toEngineRequirement(requiredNodeVersions(napiVersion));
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
//#endregion
|
|
499
|
+
//#region src/utils/metadata.ts
|
|
500
|
+
async function parseMetadata(manifestPath) {
|
|
501
|
+
if (!fs.existsSync(manifestPath)) throw new Error(`No crate found in manifest: ${manifestPath}`);
|
|
502
|
+
const childProcess = spawn("cargo", [
|
|
503
|
+
"metadata",
|
|
504
|
+
"--manifest-path",
|
|
505
|
+
manifestPath,
|
|
506
|
+
"--format-version",
|
|
507
|
+
"1"
|
|
508
|
+
], { stdio: "pipe" });
|
|
509
|
+
let stdout = "";
|
|
510
|
+
let stderr = "";
|
|
511
|
+
let status = 0;
|
|
512
|
+
let error = null;
|
|
513
|
+
childProcess.stdout.on("data", (data) => {
|
|
514
|
+
stdout += data;
|
|
515
|
+
});
|
|
516
|
+
childProcess.stderr.on("data", (data) => {
|
|
517
|
+
stderr += data;
|
|
518
|
+
});
|
|
519
|
+
await new Promise((resolve$1) => {
|
|
520
|
+
childProcess.on("close", (code) => {
|
|
521
|
+
status = code ?? 0;
|
|
522
|
+
resolve$1();
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
if (error) throw new Error("cargo metadata failed to run", { cause: error });
|
|
526
|
+
if (status !== 0) {
|
|
527
|
+
const simpleMessage = `cargo metadata exited with code ${status}`;
|
|
528
|
+
throw new Error(`${simpleMessage} and error message:\n\n${stderr}`, { cause: new Error(simpleMessage) });
|
|
529
|
+
}
|
|
530
|
+
try {
|
|
531
|
+
return JSON.parse(stdout);
|
|
532
|
+
} catch (e) {
|
|
533
|
+
throw new Error("Failed to parse cargo metadata JSON", { cause: e });
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
//#endregion
|
|
538
|
+
//#region src/utils/config.ts
|
|
539
|
+
async function readNapiConfig(path$1, configPath) {
|
|
540
|
+
if (configPath && !await fileExists(configPath)) throw new Error(`NAPI-RS config not found at ${configPath}`);
|
|
541
|
+
if (!await fileExists(path$1)) throw new Error(`package.json not found at ${path$1}`);
|
|
542
|
+
const content = await readFileAsync(path$1, "utf8");
|
|
543
|
+
let pkgJson;
|
|
544
|
+
try {
|
|
545
|
+
pkgJson = JSON.parse(content);
|
|
546
|
+
} catch (e) {
|
|
547
|
+
throw new Error(`Failed to parse package.json at ${path$1}`, { cause: e });
|
|
548
|
+
}
|
|
549
|
+
let separatedConfig;
|
|
550
|
+
if (configPath) {
|
|
551
|
+
const configContent = await readFileAsync(configPath, "utf8");
|
|
552
|
+
try {
|
|
553
|
+
separatedConfig = JSON.parse(configContent);
|
|
554
|
+
} catch (e) {
|
|
555
|
+
throw new Error(`Failed to parse NAPI-RS config at ${configPath}`, { cause: e });
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
const userNapiConfig = pkgJson.napi ?? {};
|
|
559
|
+
if (pkgJson.napi && separatedConfig) {
|
|
560
|
+
const pkgJsonPath = underline(path$1);
|
|
561
|
+
const configPathUnderline = underline(configPath);
|
|
562
|
+
console.warn(yellow(`Both napi field in ${pkgJsonPath} and [NAPI-RS config](${configPathUnderline}) file are found, the NAPI-RS config file will be used.`));
|
|
563
|
+
Object.assign(userNapiConfig, separatedConfig);
|
|
564
|
+
}
|
|
565
|
+
const napiConfig = merge({
|
|
566
|
+
binaryName: "index",
|
|
567
|
+
packageName: pkgJson.name,
|
|
568
|
+
targets: [],
|
|
569
|
+
packageJson: pkgJson,
|
|
570
|
+
npmClient: "npm"
|
|
571
|
+
}, omit(userNapiConfig, "targets"));
|
|
572
|
+
let targets = userNapiConfig.targets ?? [];
|
|
573
|
+
if (userNapiConfig?.name) {
|
|
574
|
+
console.warn(yellow(`[DEPRECATED] napi.name is deprecated, use napi.binaryName instead.`));
|
|
575
|
+
napiConfig.binaryName = userNapiConfig.name;
|
|
576
|
+
}
|
|
577
|
+
if (!targets.length) {
|
|
578
|
+
let deprecatedWarned = false;
|
|
579
|
+
const warning = yellow(`[DEPRECATED] napi.triples is deprecated, use napi.targets instead.`);
|
|
580
|
+
if (userNapiConfig.triples?.defaults) {
|
|
581
|
+
deprecatedWarned = true;
|
|
582
|
+
console.warn(warning);
|
|
583
|
+
targets = targets.concat(DEFAULT_TARGETS);
|
|
584
|
+
}
|
|
585
|
+
if (userNapiConfig.triples?.additional?.length) {
|
|
586
|
+
targets = targets.concat(userNapiConfig.triples.additional);
|
|
587
|
+
if (!deprecatedWarned) console.warn(warning);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
napiConfig.targets = targets.map(parseTriple);
|
|
591
|
+
return napiConfig;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
//#endregion
|
|
595
|
+
//#region src/utils/cargo.ts
|
|
596
|
+
function tryInstallCargoBinary(name$1, bin$1) {
|
|
597
|
+
if (detectCargoBinary(bin$1)) {
|
|
598
|
+
debug$7("Cargo binary already installed: %s", name$1);
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
try {
|
|
602
|
+
debug$7("Installing cargo binary: %s", name$1);
|
|
603
|
+
execSync(`cargo install ${name$1}`, { stdio: "inherit" });
|
|
604
|
+
} catch (e) {
|
|
605
|
+
throw new Error(`Failed to install cargo binary: ${name$1}`, { cause: e });
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
function detectCargoBinary(bin$1) {
|
|
609
|
+
debug$7("Detecting cargo binary: %s", bin$1);
|
|
610
|
+
try {
|
|
611
|
+
execSync(`cargo help ${bin$1}`, { stdio: "ignore" });
|
|
612
|
+
debug$7("Cargo binary detected: %s", bin$1);
|
|
613
|
+
return true;
|
|
614
|
+
} catch {
|
|
615
|
+
debug$7("Cargo binary not detected: %s", bin$1);
|
|
616
|
+
return false;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
//#endregion
|
|
621
|
+
//#region src/utils/typegen.ts
|
|
622
|
+
const TOP_LEVEL_NAMESPACE = "__TOP_LEVEL_MODULE__";
|
|
623
|
+
const DEFAULT_TYPE_DEF_HEADER = `/* auto-generated by NAPI-RS */
|
|
624
|
+
/* eslint-disable */
|
|
625
|
+
`;
|
|
626
|
+
var TypeDefKind = /* @__PURE__ */ function(TypeDefKind$1) {
|
|
627
|
+
TypeDefKind$1["Const"] = "const";
|
|
628
|
+
TypeDefKind$1["Enum"] = "enum";
|
|
629
|
+
TypeDefKind$1["StringEnum"] = "string_enum";
|
|
630
|
+
TypeDefKind$1["Interface"] = "interface";
|
|
631
|
+
TypeDefKind$1["Type"] = "type";
|
|
632
|
+
TypeDefKind$1["Fn"] = "fn";
|
|
633
|
+
TypeDefKind$1["Struct"] = "struct";
|
|
634
|
+
TypeDefKind$1["Impl"] = "impl";
|
|
635
|
+
return TypeDefKind$1;
|
|
636
|
+
}(TypeDefKind || {});
|
|
637
|
+
function prettyPrint(line, constEnum, ident, ambient = false) {
|
|
638
|
+
let s = line.js_doc ?? "";
|
|
639
|
+
switch (line.kind) {
|
|
640
|
+
case TypeDefKind.Interface:
|
|
641
|
+
s += `export interface ${line.name} {\n${line.def}\n}`;
|
|
642
|
+
break;
|
|
643
|
+
case TypeDefKind.Type:
|
|
644
|
+
s += `export type ${line.name} = \n${line.def}`;
|
|
645
|
+
break;
|
|
646
|
+
case TypeDefKind.Enum:
|
|
647
|
+
const enumName = constEnum ? "const enum" : "enum";
|
|
648
|
+
s += `${exportDeclare(ambient)} ${enumName} ${line.name} {\n${line.def}\n}`;
|
|
649
|
+
break;
|
|
650
|
+
case TypeDefKind.StringEnum:
|
|
651
|
+
if (constEnum) s += `${exportDeclare(ambient)} const enum ${line.name} {\n${line.def}\n}`;
|
|
652
|
+
else s += `export type ${line.name} = ${line.def.replaceAll(/.*=/g, "").replaceAll(",", "|")};`;
|
|
653
|
+
break;
|
|
654
|
+
case TypeDefKind.Struct:
|
|
655
|
+
s += `${exportDeclare(ambient)} class ${line.name} {\n${line.def}\n}`;
|
|
656
|
+
if (line.original_name && line.original_name !== line.name) s += `\nexport type ${line.original_name} = ${line.name}`;
|
|
657
|
+
break;
|
|
658
|
+
case TypeDefKind.Fn:
|
|
659
|
+
s += `${exportDeclare(ambient)} ${line.def}`;
|
|
660
|
+
break;
|
|
661
|
+
default: s += line.def;
|
|
662
|
+
}
|
|
663
|
+
return correctStringIdent(s, ident);
|
|
664
|
+
}
|
|
665
|
+
function exportDeclare(ambient) {
|
|
666
|
+
if (ambient) return "export";
|
|
667
|
+
return "export declare";
|
|
668
|
+
}
|
|
669
|
+
async function processTypeDef(intermediateTypeFile, constEnum) {
|
|
670
|
+
const exports$1 = [];
|
|
671
|
+
const defs = await readIntermediateTypeFile(intermediateTypeFile);
|
|
672
|
+
const groupedDefs = preprocessTypeDef(defs);
|
|
673
|
+
const dts = sortBy(Array.from(groupedDefs), ([namespace]) => namespace).map(([namespace, defs$1]) => {
|
|
674
|
+
if (namespace === TOP_LEVEL_NAMESPACE) return defs$1.map((def) => {
|
|
675
|
+
switch (def.kind) {
|
|
676
|
+
case TypeDefKind.Const:
|
|
677
|
+
case TypeDefKind.Enum:
|
|
678
|
+
case TypeDefKind.StringEnum:
|
|
679
|
+
case TypeDefKind.Fn:
|
|
680
|
+
case TypeDefKind.Struct: {
|
|
681
|
+
exports$1.push(def.name);
|
|
682
|
+
if (def.original_name && def.original_name !== def.name) exports$1.push(def.original_name);
|
|
683
|
+
break;
|
|
684
|
+
}
|
|
685
|
+
default: break;
|
|
686
|
+
}
|
|
687
|
+
return prettyPrint(def, constEnum, 0);
|
|
688
|
+
}).join("\n\n");
|
|
689
|
+
else {
|
|
690
|
+
exports$1.push(namespace);
|
|
691
|
+
let declaration = "";
|
|
692
|
+
declaration += `export declare namespace ${namespace} {\n`;
|
|
693
|
+
for (const def of defs$1) declaration += prettyPrint(def, constEnum, 2, true) + "\n";
|
|
694
|
+
declaration += "}";
|
|
695
|
+
return declaration;
|
|
696
|
+
}
|
|
697
|
+
}).join("\n\n") + "\n";
|
|
698
|
+
return {
|
|
699
|
+
dts,
|
|
700
|
+
exports: exports$1
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
async function readIntermediateTypeFile(file) {
|
|
704
|
+
const content = await readFileAsync(file, "utf8");
|
|
705
|
+
const defs = content.split("\n").filter(Boolean).map((line) => {
|
|
706
|
+
line = line.trim();
|
|
707
|
+
const parsed = JSON.parse(line);
|
|
708
|
+
if (parsed.js_doc) parsed.js_doc = parsed.js_doc.replace(/\\n/g, "\n");
|
|
709
|
+
if (parsed.def) parsed.def = parsed.def.replace(/\\n/g, "\n");
|
|
710
|
+
return parsed;
|
|
711
|
+
});
|
|
712
|
+
return defs.sort((a, b) => {
|
|
713
|
+
if (a.kind === TypeDefKind.Struct) {
|
|
714
|
+
if (b.kind === TypeDefKind.Struct) return a.name.localeCompare(b.name);
|
|
715
|
+
return -1;
|
|
716
|
+
} else if (b.kind === TypeDefKind.Struct) return 1;
|
|
717
|
+
else return a.name.localeCompare(b.name);
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
function preprocessTypeDef(defs) {
|
|
721
|
+
const namespaceGrouped = new Map();
|
|
722
|
+
const classDefs = new Map();
|
|
723
|
+
for (const def of defs) {
|
|
724
|
+
const namespace = def.js_mod ?? TOP_LEVEL_NAMESPACE;
|
|
725
|
+
if (!namespaceGrouped.has(namespace)) namespaceGrouped.set(namespace, []);
|
|
726
|
+
const group = namespaceGrouped.get(namespace);
|
|
727
|
+
if (def.kind === TypeDefKind.Struct) {
|
|
728
|
+
group.push(def);
|
|
729
|
+
classDefs.set(def.name, def);
|
|
730
|
+
} else if (def.kind === TypeDefKind.Impl) {
|
|
731
|
+
const classDef = classDefs.get(def.name);
|
|
732
|
+
if (classDef) {
|
|
733
|
+
if (classDef.def) classDef.def += "\n";
|
|
734
|
+
classDef.def += def.def;
|
|
735
|
+
if (classDef.def) classDef.def = classDef.def.replace(/\\n/g, "\n");
|
|
736
|
+
}
|
|
737
|
+
} else group.push(def);
|
|
738
|
+
}
|
|
739
|
+
return namespaceGrouped;
|
|
740
|
+
}
|
|
741
|
+
function correctStringIdent(src, ident) {
|
|
742
|
+
let bracketDepth = 0;
|
|
743
|
+
const result = src.split("\n").map((line) => {
|
|
744
|
+
line = line.trim();
|
|
745
|
+
if (line === "") return "";
|
|
746
|
+
const isInMultilineComment = line.startsWith("*");
|
|
747
|
+
const isClosingBracket = line.endsWith("}");
|
|
748
|
+
const isOpeningBracket = line.endsWith("{");
|
|
749
|
+
const isTypeDeclaration = line.endsWith("=");
|
|
750
|
+
const isTypeVariant = line.startsWith("|");
|
|
751
|
+
let rightIndent = ident;
|
|
752
|
+
if ((isOpeningBracket || isTypeDeclaration) && !isInMultilineComment) {
|
|
753
|
+
bracketDepth += 1;
|
|
754
|
+
rightIndent += (bracketDepth - 1) * 2;
|
|
755
|
+
} else {
|
|
756
|
+
if (isClosingBracket && bracketDepth > 0 && !isInMultilineComment && !isTypeVariant) bracketDepth -= 1;
|
|
757
|
+
rightIndent += bracketDepth * 2;
|
|
758
|
+
}
|
|
759
|
+
if (isInMultilineComment) rightIndent += 1;
|
|
760
|
+
const s = `${" ".repeat(rightIndent)}${line}`;
|
|
761
|
+
return s;
|
|
762
|
+
}).join("\n");
|
|
763
|
+
return result;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
//#endregion
|
|
767
|
+
//#region src/utils/read-config.ts
|
|
768
|
+
async function readConfig(options) {
|
|
769
|
+
const resolvePath = (...paths) => resolve(options.cwd, ...paths);
|
|
770
|
+
const config = await readNapiConfig(resolvePath(options.configPath ?? options.packageJsonPath ?? "package.json"), options.configPath ? resolvePath(options.configPath) : void 0);
|
|
771
|
+
return config;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
//#endregion
|
|
775
|
+
//#region src/api/artifacts.ts
|
|
776
|
+
const debug$6 = debugFactory("artifacts");
|
|
777
|
+
async function collectArtifacts(userOptions) {
|
|
778
|
+
const options = applyDefaultArtifactsOptions(userOptions);
|
|
779
|
+
const packageJsonPath = join(options.cwd, options.packageJsonPath);
|
|
780
|
+
const { targets, binaryName, packageName } = await readNapiConfig(packageJsonPath);
|
|
781
|
+
const distDirs = targets.map((platform) => join(options.cwd, options.npmDir, platform.platformArchABI));
|
|
782
|
+
const universalSourceBins = new Set(targets.filter((platform) => platform.arch === "universal").flatMap((p) => UniArchsByPlatform[p.platform]?.map((a) => `${p.platform}-${a}`)).filter(Boolean));
|
|
783
|
+
await collectNodeBinaries(join(options.cwd, options.outputDir)).then((output) => Promise.all(output.map(async (filePath) => {
|
|
784
|
+
debug$6.info(`Read [${colors$1.yellowBright(filePath)}]`);
|
|
785
|
+
const sourceContent = await readFileAsync(filePath);
|
|
786
|
+
const parsedName = parse(filePath);
|
|
787
|
+
const terms = parsedName.name.split(".");
|
|
788
|
+
const platformArchABI = terms.pop();
|
|
789
|
+
const _binaryName = terms.join(".");
|
|
790
|
+
if (_binaryName !== binaryName) {
|
|
791
|
+
debug$6.warn(`[${_binaryName}] is not matched with [${binaryName}], skip`);
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
const dir = distDirs.find((dir$1) => dir$1.includes(platformArchABI));
|
|
795
|
+
if (!dir && universalSourceBins.has(platformArchABI)) {
|
|
796
|
+
debug$6.warn(`[${platformArchABI}] has no dist dir but it is source bin for universal arch, skip`);
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
if (!dir) throw new Error(`No dist dir found for ${filePath}`);
|
|
800
|
+
const distFilePath = join(dir, parsedName.base);
|
|
801
|
+
debug$6.info(`Write file content to [${colors$1.yellowBright(distFilePath)}]`);
|
|
802
|
+
await writeFileAsync(distFilePath, sourceContent);
|
|
803
|
+
const distFilePathLocal = join(parse(packageJsonPath).dir, parsedName.base);
|
|
804
|
+
debug$6.info(`Write file content to [${colors$1.yellowBright(distFilePathLocal)}]`);
|
|
805
|
+
await writeFileAsync(distFilePathLocal, sourceContent);
|
|
806
|
+
})));
|
|
807
|
+
const wasiTarget = targets.find((t) => t.platform === "wasi");
|
|
808
|
+
if (wasiTarget) {
|
|
809
|
+
const wasiDir = join(options.cwd, options.npmDir, wasiTarget.platformArchABI);
|
|
810
|
+
const cjsFile = join(options.buildOutputDir ?? options.cwd, `${binaryName}.wasi.cjs`);
|
|
811
|
+
const workerFile = join(options.buildOutputDir ?? options.cwd, `wasi-worker.mjs`);
|
|
812
|
+
const browserEntry = join(options.buildOutputDir ?? options.cwd, `${binaryName}.wasi-browser.js`);
|
|
813
|
+
const browserWorkerFile = join(options.buildOutputDir ?? options.cwd, `wasi-worker-browser.mjs`);
|
|
814
|
+
debug$6.info(`Move wasi binding file [${colors$1.yellowBright(cjsFile)}] to [${colors$1.yellowBright(wasiDir)}]`);
|
|
815
|
+
await writeFileAsync(join(wasiDir, `${binaryName}.wasi.cjs`), await readFileAsync(cjsFile));
|
|
816
|
+
debug$6.info(`Move wasi worker file [${colors$1.yellowBright(workerFile)}] to [${colors$1.yellowBright(wasiDir)}]`);
|
|
817
|
+
await writeFileAsync(join(wasiDir, `wasi-worker.mjs`), await readFileAsync(workerFile));
|
|
818
|
+
debug$6.info(`Move wasi browser entry file [${colors$1.yellowBright(browserEntry)}] to [${colors$1.yellowBright(wasiDir)}]`);
|
|
819
|
+
await writeFileAsync(join(wasiDir, `${binaryName}.wasi-browser.js`), (await readFileAsync(browserEntry, "utf8")).replace(`new URL('./wasi-worker-browser.mjs', import.meta.url)`, `new URL('${packageName}-wasm32-wasi/wasi-worker-browser.mjs', import.meta.url)`));
|
|
820
|
+
debug$6.info(`Move wasi browser worker file [${colors$1.yellowBright(browserWorkerFile)}] to [${colors$1.yellowBright(wasiDir)}]`);
|
|
821
|
+
await writeFileAsync(join(wasiDir, `wasi-worker-browser.mjs`), await readFileAsync(browserWorkerFile));
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
async function collectNodeBinaries(root) {
|
|
825
|
+
const files$1 = await readdirAsync(root, { withFileTypes: true });
|
|
826
|
+
const nodeBinaries = files$1.filter((file) => file.isFile() && (file.name.endsWith(".node") || file.name.endsWith(".wasm"))).map((file) => join(root, file.name));
|
|
827
|
+
const dirs = files$1.filter((file) => file.isDirectory());
|
|
828
|
+
for (const dir of dirs) if (dir.name !== "node_modules") nodeBinaries.push(...await collectNodeBinaries(join(root, dir.name)));
|
|
829
|
+
return nodeBinaries;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
//#endregion
|
|
833
|
+
//#region src/api/templates/js-binding.ts
|
|
834
|
+
function createCjsBinding(localName, pkgName, idents) {
|
|
835
|
+
return `${bindingHeader}
|
|
836
|
+
const { createRequire } = require('node:module')
|
|
837
|
+
require = createRequire(__filename)
|
|
838
|
+
|
|
839
|
+
${createCommonBinding(localName, pkgName)}
|
|
840
|
+
module.exports = nativeBinding
|
|
841
|
+
${idents.map((ident) => `module.exports.${ident} = nativeBinding.${ident}`).join("\n")}
|
|
842
|
+
`;
|
|
843
|
+
}
|
|
844
|
+
function createEsmBinding(localName, pkgName, idents) {
|
|
845
|
+
return `${bindingHeader}
|
|
846
|
+
import { createRequire } from 'node:module'
|
|
847
|
+
const require = createRequire(import.meta.url)
|
|
848
|
+
const __dirname = new URL('.', import.meta.url).pathname
|
|
849
|
+
|
|
850
|
+
${createCommonBinding(localName, pkgName)}
|
|
851
|
+
const { ${idents.join(", ")} } = nativeBinding
|
|
852
|
+
${idents.map((ident) => `export { ${ident} }`).join("\n")}
|
|
853
|
+
`;
|
|
854
|
+
}
|
|
855
|
+
const bindingHeader = `// prettier-ignore
|
|
856
|
+
/* eslint-disable */
|
|
857
|
+
// @ts-nocheck
|
|
858
|
+
/* auto-generated by NAPI-RS */
|
|
859
|
+
`;
|
|
860
|
+
function createCommonBinding(localName, pkgName) {
|
|
861
|
+
function requireTuple(tuple) {
|
|
862
|
+
return `try {
|
|
863
|
+
return require('./${localName}.${tuple}.node')
|
|
864
|
+
} catch (e) {
|
|
865
|
+
loadErrors.push(e)
|
|
866
|
+
}
|
|
867
|
+
try {
|
|
868
|
+
return require('${pkgName}-${tuple}')
|
|
869
|
+
} catch (e) {
|
|
870
|
+
loadErrors.push(e)
|
|
871
|
+
}
|
|
872
|
+
`;
|
|
873
|
+
}
|
|
874
|
+
return `const { readFileSync } = require('node:fs')
|
|
875
|
+
let nativeBinding = null
|
|
876
|
+
const loadErrors = []
|
|
877
|
+
|
|
878
|
+
const isMusl = () => {
|
|
879
|
+
let musl = false
|
|
880
|
+
if (process.platform === 'linux') {
|
|
881
|
+
musl = isMuslFromFilesystem()
|
|
882
|
+
if (musl === null) {
|
|
883
|
+
musl = isMuslFromReport()
|
|
884
|
+
}
|
|
885
|
+
if (musl === null) {
|
|
886
|
+
musl = isMuslFromChildProcess()
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
return musl
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-')
|
|
893
|
+
|
|
894
|
+
const isMuslFromFilesystem = () => {
|
|
895
|
+
try {
|
|
896
|
+
return readFileSync('/usr/bin/ldd', 'utf-8').includes('musl')
|
|
897
|
+
} catch {
|
|
898
|
+
return null
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
const isMuslFromReport = () => {
|
|
903
|
+
let report = null
|
|
904
|
+
if (typeof process.report?.getReport === 'function') {
|
|
905
|
+
process.report.excludeNetwork = true
|
|
906
|
+
report = process.report.getReport()
|
|
907
|
+
}
|
|
908
|
+
if (!report) {
|
|
909
|
+
return null
|
|
910
|
+
}
|
|
911
|
+
if (report.header && report.header.glibcVersionRuntime) {
|
|
912
|
+
return false
|
|
913
|
+
}
|
|
914
|
+
if (Array.isArray(report.sharedObjects)) {
|
|
915
|
+
if (report.sharedObjects.some(isFileMusl)) {
|
|
916
|
+
return true
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
return false
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
const isMuslFromChildProcess = () => {
|
|
923
|
+
try {
|
|
924
|
+
return require('child_process').execSync('ldd --version', { encoding: 'utf8' }).includes('musl')
|
|
925
|
+
} catch (e) {
|
|
926
|
+
// If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false
|
|
927
|
+
return false
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
function requireNative() {
|
|
932
|
+
if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) {
|
|
933
|
+
try {
|
|
934
|
+
nativeBinding = require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH);
|
|
935
|
+
} catch (err) {
|
|
936
|
+
loadErrors.push(err)
|
|
937
|
+
}
|
|
938
|
+
} else if (process.platform === 'android') {
|
|
939
|
+
if (process.arch === 'arm64') {
|
|
940
|
+
${requireTuple("android-arm64")}
|
|
941
|
+
} else if (process.arch === 'arm') {
|
|
942
|
+
${requireTuple("android-arm-eabi")}
|
|
943
|
+
} else {
|
|
944
|
+
loadErrors.push(new Error(\`Unsupported architecture on Android \${process.arch}\`))
|
|
945
|
+
}
|
|
946
|
+
} else if (process.platform === 'win32') {
|
|
947
|
+
if (process.arch === 'x64') {
|
|
948
|
+
${requireTuple("win32-x64-msvc")}
|
|
949
|
+
} else if (process.arch === 'ia32') {
|
|
950
|
+
${requireTuple("win32-ia32-msvc")}
|
|
951
|
+
} else if (process.arch === 'arm64') {
|
|
952
|
+
${requireTuple("win32-arm64-msvc")}
|
|
953
|
+
} else {
|
|
954
|
+
loadErrors.push(new Error(\`Unsupported architecture on Windows: \${process.arch}\`))
|
|
955
|
+
}
|
|
956
|
+
} else if (process.platform === 'darwin') {
|
|
957
|
+
${requireTuple("darwin-universal")}
|
|
958
|
+
if (process.arch === 'x64') {
|
|
959
|
+
${requireTuple("darwin-x64")}
|
|
960
|
+
} else if (process.arch === 'arm64') {
|
|
961
|
+
${requireTuple("darwin-arm64")}
|
|
962
|
+
} else {
|
|
963
|
+
loadErrors.push(new Error(\`Unsupported architecture on macOS: \${process.arch}\`))
|
|
964
|
+
}
|
|
965
|
+
} else if (process.platform === 'freebsd') {
|
|
966
|
+
if (process.arch === 'x64') {
|
|
967
|
+
${requireTuple("freebsd-x64")}
|
|
968
|
+
} else if (process.arch === 'arm64') {
|
|
969
|
+
${requireTuple("freebsd-arm64")}
|
|
970
|
+
} else {
|
|
971
|
+
loadErrors.push(new Error(\`Unsupported architecture on FreeBSD: \${process.arch}\`))
|
|
972
|
+
}
|
|
973
|
+
} else if (process.platform === 'linux') {
|
|
974
|
+
if (process.arch === 'x64') {
|
|
975
|
+
if (isMusl()) {
|
|
976
|
+
${requireTuple("linux-x64-musl")}
|
|
977
|
+
} else {
|
|
978
|
+
${requireTuple("linux-x64-gnu")}
|
|
979
|
+
}
|
|
980
|
+
} else if (process.arch === 'arm64') {
|
|
981
|
+
if (isMusl()) {
|
|
982
|
+
${requireTuple("linux-arm64-musl")}
|
|
983
|
+
} else {
|
|
984
|
+
${requireTuple("linux-arm64-gnu")}
|
|
985
|
+
}
|
|
986
|
+
} else if (process.arch === 'arm') {
|
|
987
|
+
if (isMusl()) {
|
|
988
|
+
${requireTuple("linux-arm-musleabihf")}
|
|
989
|
+
} else {
|
|
990
|
+
${requireTuple("linux-arm-gnueabihf")}
|
|
991
|
+
}
|
|
992
|
+
} else if (process.arch === 'riscv64') {
|
|
993
|
+
if (isMusl()) {
|
|
994
|
+
${requireTuple("linux-riscv64-musl")}
|
|
995
|
+
} else {
|
|
996
|
+
${requireTuple("linux-riscv64-gnu")}
|
|
997
|
+
}
|
|
998
|
+
} else if (process.arch === 'ppc64') {
|
|
999
|
+
${requireTuple("linux-ppc64-gnu")}
|
|
1000
|
+
} else if (process.arch === 's390x') {
|
|
1001
|
+
${requireTuple("linux-s390x-gnu")}
|
|
1002
|
+
} else {
|
|
1003
|
+
loadErrors.push(new Error(\`Unsupported architecture on Linux: \${process.arch}\`))
|
|
1004
|
+
}
|
|
1005
|
+
} else {
|
|
1006
|
+
loadErrors.push(new Error(\`Unsupported OS: \${process.platform}, architecture: \${process.arch}\`))
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
nativeBinding = requireNative()
|
|
1011
|
+
|
|
1012
|
+
if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) {
|
|
1013
|
+
try {
|
|
1014
|
+
nativeBinding = require('./${localName}.wasi.cjs')
|
|
1015
|
+
} catch (err) {
|
|
1016
|
+
if (process.env.NAPI_RS_FORCE_WASI) {
|
|
1017
|
+
loadErrors.push(err)
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
if (!nativeBinding) {
|
|
1021
|
+
try {
|
|
1022
|
+
nativeBinding = require('${pkgName}-wasm32-wasi')
|
|
1023
|
+
} catch (err) {
|
|
1024
|
+
if (process.env.NAPI_RS_FORCE_WASI) {
|
|
1025
|
+
loadErrors.push(err)
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
if (!nativeBinding) {
|
|
1032
|
+
if (loadErrors.length > 0) {
|
|
1033
|
+
throw new Error(
|
|
1034
|
+
\`Cannot find native binding. \` +
|
|
1035
|
+
\`npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). \` +
|
|
1036
|
+
'Please try \`npm i\` again after removing both package-lock.json and node_modules directory.',
|
|
1037
|
+
{ cause: loadErrors }
|
|
1038
|
+
)
|
|
1039
|
+
}
|
|
1040
|
+
throw new Error(\`Failed to load native binding\`)
|
|
1041
|
+
}
|
|
1042
|
+
`;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
//#endregion
|
|
1046
|
+
//#region src/api/templates/load-wasi-template.ts
|
|
1047
|
+
const createWasiBrowserBinding = (wasiFilename, initialMemory = 4e3, maximumMemory = 65536, fs$1 = false, asyncInit = false) => {
|
|
1048
|
+
const fsImport = fs$1 ? `import { memfs } from '@napi-rs/wasm-runtime/fs'` : "";
|
|
1049
|
+
const wasiCreation = fs$1 ? `
|
|
1050
|
+
export const { fs: __fs, vol: __volume } = memfs()
|
|
1051
|
+
|
|
1052
|
+
const __wasi = new __WASI({
|
|
1053
|
+
version: 'preview1',
|
|
1054
|
+
fs: __fs,
|
|
1055
|
+
preopens: {
|
|
1056
|
+
'/': '/',
|
|
1057
|
+
},
|
|
1058
|
+
})` : `
|
|
1059
|
+
const __wasi = new __WASI({
|
|
1060
|
+
version: 'preview1',
|
|
1061
|
+
})`;
|
|
1062
|
+
const workerFsHandler = fs$1 ? ` worker.addEventListener('message', __wasmCreateOnMessageForFsProxy(__fs))\n` : "";
|
|
1063
|
+
const emnapiInstantiateImport = asyncInit ? `instantiateNapiModule as __emnapiInstantiateNapiModule` : `instantiateNapiModuleSync as __emnapiInstantiateNapiModuleSync`;
|
|
1064
|
+
const emnapiInstantiateCall = asyncInit ? `await __emnapiInstantiateNapiModule` : `__emnapiInstantiateNapiModuleSync`;
|
|
1065
|
+
return `import {
|
|
1066
|
+
createOnMessage as __wasmCreateOnMessageForFsProxy,
|
|
1067
|
+
getDefaultContext as __emnapiGetDefaultContext,
|
|
1068
|
+
${emnapiInstantiateImport},
|
|
1069
|
+
WASI as __WASI,
|
|
1070
|
+
} from '@napi-rs/wasm-runtime'
|
|
1071
|
+
${fsImport}
|
|
1072
|
+
${wasiCreation}
|
|
1073
|
+
|
|
1074
|
+
const __wasmUrl = new URL('./${wasiFilename}.wasm', import.meta.url).href
|
|
1075
|
+
const __emnapiContext = __emnapiGetDefaultContext()
|
|
1076
|
+
|
|
1077
|
+
const __sharedMemory = new WebAssembly.Memory({
|
|
1078
|
+
initial: ${initialMemory},
|
|
1079
|
+
maximum: ${maximumMemory},
|
|
1080
|
+
shared: true,
|
|
1081
|
+
})
|
|
1082
|
+
|
|
1083
|
+
const __wasmFile = await fetch(__wasmUrl).then((res) => res.arrayBuffer())
|
|
1084
|
+
|
|
1085
|
+
const {
|
|
1086
|
+
instance: __napiInstance,
|
|
1087
|
+
module: __wasiModule,
|
|
1088
|
+
napiModule: __napiModule,
|
|
1089
|
+
} = ${emnapiInstantiateCall}(__wasmFile, {
|
|
1090
|
+
context: __emnapiContext,
|
|
1091
|
+
asyncWorkPoolSize: 4,
|
|
1092
|
+
wasi: __wasi,
|
|
1093
|
+
onCreateWorker() {
|
|
1094
|
+
const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {
|
|
1095
|
+
type: 'module',
|
|
1096
|
+
})
|
|
1097
|
+
${workerFsHandler}
|
|
1098
|
+
return worker
|
|
1099
|
+
},
|
|
1100
|
+
overwriteImports(importObject) {
|
|
1101
|
+
importObject.env = {
|
|
1102
|
+
...importObject.env,
|
|
1103
|
+
...importObject.napi,
|
|
1104
|
+
...importObject.emnapi,
|
|
1105
|
+
memory: __sharedMemory,
|
|
1106
|
+
}
|
|
1107
|
+
return importObject
|
|
1108
|
+
},
|
|
1109
|
+
beforeInit({ instance }) {
|
|
1110
|
+
for (const name of Object.keys(instance.exports)) {
|
|
1111
|
+
if (name.startsWith('__napi_register__')) {
|
|
1112
|
+
instance.exports[name]()
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
},
|
|
1116
|
+
})
|
|
1117
|
+
`;
|
|
1118
|
+
};
|
|
1119
|
+
const createWasiBinding = (wasmFileName, packageName, initialMemory = 4e3, maximumMemory = 65536) => `/* eslint-disable */
|
|
1120
|
+
/* prettier-ignore */
|
|
1121
|
+
|
|
1122
|
+
/* auto-generated by NAPI-RS */
|
|
1123
|
+
|
|
1124
|
+
const __nodeFs = require('node:fs')
|
|
1125
|
+
const __nodePath = require('node:path')
|
|
1126
|
+
const { WASI: __nodeWASI } = require('node:wasi')
|
|
1127
|
+
const { Worker } = require('node:worker_threads')
|
|
1128
|
+
|
|
1129
|
+
const {
|
|
1130
|
+
createOnMessage: __wasmCreateOnMessageForFsProxy,
|
|
1131
|
+
getDefaultContext: __emnapiGetDefaultContext,
|
|
1132
|
+
instantiateNapiModuleSync: __emnapiInstantiateNapiModuleSync,
|
|
1133
|
+
} = require('@napi-rs/wasm-runtime')
|
|
1134
|
+
|
|
1135
|
+
const __rootDir = __nodePath.parse(process.cwd()).root
|
|
1136
|
+
|
|
1137
|
+
const __wasi = new __nodeWASI({
|
|
1138
|
+
version: 'preview1',
|
|
1139
|
+
env: process.env,
|
|
1140
|
+
preopens: {
|
|
1141
|
+
[__rootDir]: __rootDir,
|
|
1142
|
+
}
|
|
1143
|
+
})
|
|
1144
|
+
|
|
1145
|
+
const __emnapiContext = __emnapiGetDefaultContext()
|
|
1146
|
+
|
|
1147
|
+
const __sharedMemory = new WebAssembly.Memory({
|
|
1148
|
+
initial: ${initialMemory},
|
|
1149
|
+
maximum: ${maximumMemory},
|
|
1150
|
+
shared: true,
|
|
1151
|
+
})
|
|
1152
|
+
|
|
1153
|
+
let __wasmFilePath = __nodePath.join(__dirname, '${wasmFileName}.wasm')
|
|
1154
|
+
const __wasmDebugFilePath = __nodePath.join(__dirname, '${wasmFileName}.debug.wasm')
|
|
1155
|
+
|
|
1156
|
+
if (__nodeFs.existsSync(__wasmDebugFilePath)) {
|
|
1157
|
+
__wasmFilePath = __wasmDebugFilePath
|
|
1158
|
+
} else if (!__nodeFs.existsSync(__wasmFilePath)) {
|
|
1159
|
+
try {
|
|
1160
|
+
__wasmFilePath = __nodePath.resolve('${packageName}-wasm32-wasi')
|
|
1161
|
+
} catch {
|
|
1162
|
+
throw new Error('Cannot find ${wasmFileName}.wasm file, and ${packageName}-wasm32-wasi package is not installed.')
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule } = __emnapiInstantiateNapiModuleSync(__nodeFs.readFileSync(__wasmFilePath), {
|
|
1167
|
+
context: __emnapiContext,
|
|
1168
|
+
asyncWorkPoolSize: (function() {
|
|
1169
|
+
const threadsSizeFromEnv = Number(process.env.NAPI_RS_ASYNC_WORK_POOL_SIZE ?? process.env.UV_THREADPOOL_SIZE)
|
|
1170
|
+
// NaN > 0 is false
|
|
1171
|
+
if (threadsSizeFromEnv > 0) {
|
|
1172
|
+
return threadsSizeFromEnv
|
|
1173
|
+
} else {
|
|
1174
|
+
return 4
|
|
1175
|
+
}
|
|
1176
|
+
})(),
|
|
1177
|
+
reuseWorker: true,
|
|
1178
|
+
wasi: __wasi,
|
|
1179
|
+
onCreateWorker() {
|
|
1180
|
+
const worker = new Worker(__nodePath.join(__dirname, 'wasi-worker.mjs'), {
|
|
1181
|
+
env: process.env,
|
|
1182
|
+
})
|
|
1183
|
+
worker.onmessage = ({ data }) => {
|
|
1184
|
+
__wasmCreateOnMessageForFsProxy(__nodeFs)(data)
|
|
1185
|
+
}
|
|
1186
|
+
return worker
|
|
1187
|
+
},
|
|
1188
|
+
overwriteImports(importObject) {
|
|
1189
|
+
importObject.env = {
|
|
1190
|
+
...importObject.env,
|
|
1191
|
+
...importObject.napi,
|
|
1192
|
+
...importObject.emnapi,
|
|
1193
|
+
memory: __sharedMemory,
|
|
1194
|
+
}
|
|
1195
|
+
return importObject
|
|
1196
|
+
},
|
|
1197
|
+
beforeInit({ instance }) {
|
|
1198
|
+
for (const name of Object.keys(instance.exports)) {
|
|
1199
|
+
if (name.startsWith('__napi_register__')) {
|
|
1200
|
+
instance.exports[name]()
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
},
|
|
1204
|
+
})
|
|
1205
|
+
`;
|
|
1206
|
+
|
|
1207
|
+
//#endregion
|
|
1208
|
+
//#region src/api/templates/wasi-worker-template.ts
|
|
1209
|
+
const WASI_WORKER_TEMPLATE = `import fs from "node:fs";
|
|
1210
|
+
import { createRequire } from "node:module";
|
|
1211
|
+
import { parse } from "node:path";
|
|
1212
|
+
import { WASI } from "node:wasi";
|
|
1213
|
+
import { parentPort, Worker } from "node:worker_threads";
|
|
1214
|
+
|
|
1215
|
+
const require = createRequire(import.meta.url);
|
|
1216
|
+
|
|
1217
|
+
const { instantiateNapiModuleSync, MessageHandler, getDefaultContext } = require("@napi-rs/wasm-runtime");
|
|
1218
|
+
|
|
1219
|
+
if (parentPort) {
|
|
1220
|
+
parentPort.on("message", (data) => {
|
|
1221
|
+
globalThis.onmessage({ data });
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
Object.assign(globalThis, {
|
|
1226
|
+
self: globalThis,
|
|
1227
|
+
require,
|
|
1228
|
+
Worker,
|
|
1229
|
+
importScripts: function (f) {
|
|
1230
|
+
;(0, eval)(fs.readFileSync(f, "utf8") + "//# sourceURL=" + f);
|
|
1231
|
+
},
|
|
1232
|
+
postMessage: function (msg) {
|
|
1233
|
+
if (parentPort) {
|
|
1234
|
+
parentPort.postMessage(msg);
|
|
1235
|
+
}
|
|
1236
|
+
},
|
|
1237
|
+
});
|
|
1238
|
+
|
|
1239
|
+
const emnapiContext = getDefaultContext();
|
|
1240
|
+
|
|
1241
|
+
const __rootDir = parse(process.cwd()).root;
|
|
1242
|
+
|
|
1243
|
+
const handler = new MessageHandler({
|
|
1244
|
+
onLoad({ wasmModule, wasmMemory }) {
|
|
1245
|
+
const wasi = new WASI({
|
|
1246
|
+
version: 'preview1',
|
|
1247
|
+
env: process.env,
|
|
1248
|
+
preopens: {
|
|
1249
|
+
[__rootDir]: __rootDir,
|
|
1250
|
+
},
|
|
1251
|
+
});
|
|
1252
|
+
|
|
1253
|
+
return instantiateNapiModuleSync(wasmModule, {
|
|
1254
|
+
childThread: true,
|
|
1255
|
+
wasi,
|
|
1256
|
+
context: emnapiContext,
|
|
1257
|
+
overwriteImports(importObject) {
|
|
1258
|
+
importObject.env = {
|
|
1259
|
+
...importObject.env,
|
|
1260
|
+
...importObject.napi,
|
|
1261
|
+
...importObject.emnapi,
|
|
1262
|
+
memory: wasmMemory
|
|
1263
|
+
};
|
|
1264
|
+
},
|
|
1265
|
+
});
|
|
1266
|
+
},
|
|
1267
|
+
});
|
|
1268
|
+
|
|
1269
|
+
globalThis.onmessage = function (e) {
|
|
1270
|
+
handler.handle(e);
|
|
1271
|
+
};
|
|
1272
|
+
`;
|
|
1273
|
+
const createWasiBrowserWorkerBinding = (fs$1) => {
|
|
1274
|
+
const fsImport = fs$1 ? `import { instantiateNapiModuleSync, MessageHandler, WASI, createFsProxy } from '@napi-rs/wasm-runtime'
|
|
1275
|
+
import { memfsExported as __memfsExported } from '@napi-rs/wasm-runtime/fs'
|
|
1276
|
+
|
|
1277
|
+
const fs = createFsProxy(__memfsExported)` : `import { instantiateNapiModuleSync, MessageHandler, WASI } from '@napi-rs/wasm-runtime'`;
|
|
1278
|
+
const wasiCreation = fs$1 ? `const wasi = new WASI({
|
|
1279
|
+
fs,
|
|
1280
|
+
preopens: {
|
|
1281
|
+
'/': '/',
|
|
1282
|
+
},
|
|
1283
|
+
print: function () {
|
|
1284
|
+
// eslint-disable-next-line no-console
|
|
1285
|
+
console.log.apply(console, arguments)
|
|
1286
|
+
},
|
|
1287
|
+
printErr: function() {
|
|
1288
|
+
// eslint-disable-next-line no-console
|
|
1289
|
+
console.error.apply(console, arguments)
|
|
1290
|
+
},
|
|
1291
|
+
})` : `const wasi = new WASI({
|
|
1292
|
+
print: function () {
|
|
1293
|
+
// eslint-disable-next-line no-console
|
|
1294
|
+
console.log.apply(console, arguments)
|
|
1295
|
+
},
|
|
1296
|
+
printErr: function() {
|
|
1297
|
+
// eslint-disable-next-line no-console
|
|
1298
|
+
console.error.apply(console, arguments)
|
|
1299
|
+
},
|
|
1300
|
+
})`;
|
|
1301
|
+
return `${fsImport}
|
|
1302
|
+
|
|
1303
|
+
const handler = new MessageHandler({
|
|
1304
|
+
onLoad({ wasmModule, wasmMemory }) {
|
|
1305
|
+
${wasiCreation}
|
|
1306
|
+
return instantiateNapiModuleSync(wasmModule, {
|
|
1307
|
+
childThread: true,
|
|
1308
|
+
wasi,
|
|
1309
|
+
overwriteImports(importObject) {
|
|
1310
|
+
importObject.env = {
|
|
1311
|
+
...importObject.env,
|
|
1312
|
+
...importObject.napi,
|
|
1313
|
+
...importObject.emnapi,
|
|
1314
|
+
memory: wasmMemory,
|
|
1315
|
+
}
|
|
1316
|
+
},
|
|
1317
|
+
})
|
|
1318
|
+
},
|
|
1319
|
+
})
|
|
1320
|
+
|
|
1321
|
+
globalThis.onmessage = function (e) {
|
|
1322
|
+
handler.handle(e)
|
|
1323
|
+
}
|
|
1324
|
+
`;
|
|
1325
|
+
};
|
|
1326
|
+
|
|
1327
|
+
//#endregion
|
|
1328
|
+
//#region src/api/build.ts
|
|
1329
|
+
var import_defineProperty$8 = __toESM(require_defineProperty(), 1);
|
|
1330
|
+
const debug$5 = debugFactory("build");
|
|
1331
|
+
const require$1 = createRequire(import.meta.url);
|
|
1332
|
+
async function buildProject(rawOptions) {
|
|
1333
|
+
debug$5("napi build command receive options: %O", rawOptions);
|
|
1334
|
+
const options = {
|
|
1335
|
+
dtsCache: true,
|
|
1336
|
+
...rawOptions,
|
|
1337
|
+
cwd: rawOptions.cwd ?? process.cwd()
|
|
1338
|
+
};
|
|
1339
|
+
const resolvePath = (...paths) => resolve(options.cwd, ...paths);
|
|
1340
|
+
const manifestPath = resolvePath(options.manifestPath ?? "Cargo.toml");
|
|
1341
|
+
const metadata = await parseMetadata(manifestPath);
|
|
1342
|
+
const crate = metadata.packages.find((p) => {
|
|
1343
|
+
if (options.package) return p.name === options.package;
|
|
1344
|
+
else return p.manifest_path === manifestPath;
|
|
1345
|
+
});
|
|
1346
|
+
if (!crate) throw new Error("Unable to find crate to build. It seems you are trying to build a crate in a workspace, try using `--package` option to specify the package to build.");
|
|
1347
|
+
const config = await readNapiConfig(resolvePath(options.configPath ?? options.packageJsonPath ?? "package.json"), options.configPath ? resolvePath(options.configPath) : void 0);
|
|
1348
|
+
const builder = new Builder(metadata, crate, config, options);
|
|
1349
|
+
return builder.build();
|
|
1350
|
+
}
|
|
1351
|
+
var Builder = class {
|
|
1352
|
+
constructor(metadata, crate, config, options) {
|
|
1353
|
+
this.metadata = metadata;
|
|
1354
|
+
this.crate = crate;
|
|
1355
|
+
this.config = config;
|
|
1356
|
+
this.options = options;
|
|
1357
|
+
(0, import_defineProperty$8.default)(this, "args", []);
|
|
1358
|
+
(0, import_defineProperty$8.default)(this, "envs", {});
|
|
1359
|
+
(0, import_defineProperty$8.default)(this, "outputs", []);
|
|
1360
|
+
(0, import_defineProperty$8.default)(this, "target", void 0);
|
|
1361
|
+
(0, import_defineProperty$8.default)(this, "crateDir", void 0);
|
|
1362
|
+
(0, import_defineProperty$8.default)(this, "outputDir", void 0);
|
|
1363
|
+
(0, import_defineProperty$8.default)(this, "targetDir", void 0);
|
|
1364
|
+
(0, import_defineProperty$8.default)(this, "enableTypeDef", false);
|
|
1365
|
+
this.target = options.target ? parseTriple(options.target) : process.env.CARGO_BUILD_TARGET ? parseTriple(process.env.CARGO_BUILD_TARGET) : getSystemDefaultTarget();
|
|
1366
|
+
this.crateDir = parse(crate.manifest_path).dir;
|
|
1367
|
+
this.outputDir = resolve(this.options.cwd, options.outputDir ?? this.crateDir);
|
|
1368
|
+
this.targetDir = options.targetDir ?? process.env.CARGO_BUILD_TARGET_DIR ?? metadata.target_directory;
|
|
1369
|
+
this.enableTypeDef = this.crate.dependencies.some((dep) => dep.name === "napi-derive" && (dep.uses_default_features || dep.features.includes("type-def")));
|
|
1370
|
+
if (!this.enableTypeDef) {
|
|
1371
|
+
const requirementWarning = "`napi-derive` crate is not used or `type-def` feature is not enabled for `napi-derive` crate";
|
|
1372
|
+
debug$5.warn(`${requirementWarning}. Will skip binding generation for \`.node\`, \`.wasi\` and \`.d.ts\` files.`);
|
|
1373
|
+
if (this.options.dts || this.options.dtsHeader || this.config.dtsHeader || this.config.dtsHeaderFile) debug$5.warn(`${requirementWarning}. \`dts\` related options are enabled but will be ignored.`);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
get cdyLibName() {
|
|
1377
|
+
return this.crate.targets.find((t) => t.crate_types.includes("cdylib"))?.name;
|
|
1378
|
+
}
|
|
1379
|
+
get binName() {
|
|
1380
|
+
return this.options.bin ?? (this.cdyLibName ? null : this.crate.targets.find((t) => t.crate_types.includes("bin"))?.name);
|
|
1381
|
+
}
|
|
1382
|
+
build() {
|
|
1383
|
+
if (!this.cdyLibName) {
|
|
1384
|
+
const warning = "Missing `crate-type = [\"cdylib\"]` in [lib] config. The build result will not be available as node addon.";
|
|
1385
|
+
if (this.binName) debug$5.warn(warning);
|
|
1386
|
+
else throw new Error(warning);
|
|
1387
|
+
}
|
|
1388
|
+
return this.pickBinary().setPackage().setFeatures().setTarget().pickCrossToolchain().setEnvs().setBypassArgs().exec();
|
|
1389
|
+
}
|
|
1390
|
+
pickCrossToolchain() {
|
|
1391
|
+
if (!this.options.useNapiCross) return this;
|
|
1392
|
+
if (this.options.useCross) debug$5.warn("You are trying to use both `--cross` and `--use-napi-cross` options, `--use-cross` will be ignored.");
|
|
1393
|
+
if (this.options.crossCompile) debug$5.warn("You are trying to use both `--cross-compile` and `--use-napi-cross` options, `--cross-compile` will be ignored.");
|
|
1394
|
+
try {
|
|
1395
|
+
const { version: version$2, download } = require$1("@napi-rs/cross-toolchain");
|
|
1396
|
+
const alias = { "s390x-unknown-linux-gnu": "s390x-ibm-linux-gnu" };
|
|
1397
|
+
const toolchainPath = join(homedir(), ".napi-rs", "cross-toolchain", version$2, this.target.triple);
|
|
1398
|
+
mkdirSync(toolchainPath, { recursive: true });
|
|
1399
|
+
if (existsSync(join(toolchainPath, "package.json"))) debug$5(`Toolchain ${toolchainPath} exists, skip extracting`);
|
|
1400
|
+
else {
|
|
1401
|
+
const tarArchive = download(process.arch, this.target.triple);
|
|
1402
|
+
tarArchive.unpack(toolchainPath);
|
|
1403
|
+
}
|
|
1404
|
+
const upperCaseTarget = targetToEnvVar(this.target.triple);
|
|
1405
|
+
const crossTargetName = alias[this.target.triple] ?? this.target.triple;
|
|
1406
|
+
const linkerEnv = `CARGO_TARGET_${upperCaseTarget}_LINKER`;
|
|
1407
|
+
this.envs[linkerEnv] = join(toolchainPath, "bin", `${crossTargetName}-gcc`);
|
|
1408
|
+
if (!process.env.TARGET_SYSROOT) this.envs[`TARGET_SYSROOT`] = join(toolchainPath, crossTargetName, "sysroot");
|
|
1409
|
+
if (!process.env.TARGET_AR) this.envs[`TARGET_AR`] = join(toolchainPath, "bin", `${crossTargetName}-ar`);
|
|
1410
|
+
if (!process.env.TARGET_RANLIB) this.envs[`TARGET_RANLIB`] = join(toolchainPath, "bin", `${crossTargetName}-ranlib`);
|
|
1411
|
+
if (!process.env.TARGET_READELF) this.envs[`TARGET_READELF`] = join(toolchainPath, "bin", `${crossTargetName}-readelf`);
|
|
1412
|
+
if (!process.env.TARGET_C_INCLUDE_PATH) this.envs[`TARGET_C_INCLUDE_PATH`] = join(toolchainPath, crossTargetName, "sysroot", "usr", "include/");
|
|
1413
|
+
if (!process.env.CC && !process.env.TARGET_CC) {
|
|
1414
|
+
this.envs[`CC`] = join(toolchainPath, "bin", `${crossTargetName}-gcc`);
|
|
1415
|
+
this.envs[`TARGET_CC`] = join(toolchainPath, "bin", `${crossTargetName}-gcc`);
|
|
1416
|
+
}
|
|
1417
|
+
if (!process.env.CXX && !process.env.TARGET_CXX) {
|
|
1418
|
+
this.envs[`CXX`] = join(toolchainPath, "bin", `${crossTargetName}-g++`);
|
|
1419
|
+
this.envs[`TARGET_CXX`] = join(toolchainPath, "bin", `${crossTargetName}-g++`);
|
|
1420
|
+
}
|
|
1421
|
+
if (process.env.CC?.startsWith("clang") && (process.env.TARGET_CC?.startsWith("clang") || !process.env.TARGET_CC) || process.env.TARGET_CC?.startsWith("clang")) {
|
|
1422
|
+
const CFLAGS = process.env.CFLAGS ?? "";
|
|
1423
|
+
this.envs.CFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT} --gcc-toolchain=${toolchainPath} ${CFLAGS}`;
|
|
1424
|
+
}
|
|
1425
|
+
if (process.env.CXX?.startsWith("clang++") && (process.env.TARGET_CXX?.startsWith("clang++") || !process.env.TARGET_CXX) || process.env.TARGET_CXX?.startsWith("clang++")) {
|
|
1426
|
+
const CXXFLAGS = process.env.CXXFLAGS ?? "";
|
|
1427
|
+
this.envs.CXXFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT} --gcc-toolchain=${toolchainPath} ${CXXFLAGS} ${CXXFLAGS}`;
|
|
1428
|
+
}
|
|
1429
|
+
this.envs.PATH = this.envs.PATH ? `${toolchainPath}/bin:${this.envs.PATH}:${process.env.PATH}` : `${toolchainPath}/bin:${process.env.PATH}`;
|
|
1430
|
+
} catch (e) {
|
|
1431
|
+
debug$5.warn("Pick cross toolchain failed", e);
|
|
1432
|
+
}
|
|
1433
|
+
return this;
|
|
1434
|
+
}
|
|
1435
|
+
exec() {
|
|
1436
|
+
debug$5(`Start building crate: ${this.crate.name}`);
|
|
1437
|
+
debug$5(" %i", `cargo ${this.args.join(" ")}`);
|
|
1438
|
+
const controller = new AbortController();
|
|
1439
|
+
const watch = this.options.watch;
|
|
1440
|
+
const buildTask = new Promise((resolve$1, reject) => {
|
|
1441
|
+
if (this.options.useCross && this.options.crossCompile) throw new Error("`--use-cross` and `--cross-compile` can not be used together");
|
|
1442
|
+
const command = process.env.CARGO ?? (this.options.useCross ? "cross" : "cargo");
|
|
1443
|
+
const buildProcess = spawn(command, this.args, {
|
|
1444
|
+
env: {
|
|
1445
|
+
...process.env,
|
|
1446
|
+
...this.envs
|
|
1447
|
+
},
|
|
1448
|
+
stdio: watch ? [
|
|
1449
|
+
"inherit",
|
|
1450
|
+
"inherit",
|
|
1451
|
+
"pipe"
|
|
1452
|
+
] : "inherit",
|
|
1453
|
+
cwd: this.options.cwd,
|
|
1454
|
+
signal: controller.signal
|
|
1455
|
+
});
|
|
1456
|
+
buildProcess.once("exit", (code) => {
|
|
1457
|
+
if (code === 0) {
|
|
1458
|
+
debug$5("%i", `Build crate ${this.crate.name} successfully!`);
|
|
1459
|
+
resolve$1();
|
|
1460
|
+
} else reject(new Error(`Build failed with exit code ${code}`));
|
|
1461
|
+
});
|
|
1462
|
+
buildProcess.once("error", (e) => {
|
|
1463
|
+
reject(new Error(`Build failed with error: ${e.message}`, { cause: e }));
|
|
1464
|
+
});
|
|
1465
|
+
buildProcess.stderr?.on("data", (data) => {
|
|
1466
|
+
const output = data.toString();
|
|
1467
|
+
console.error(output);
|
|
1468
|
+
if (/Finished\s(`dev`|`release`)/.test(output)) this.postBuild().catch(() => {});
|
|
1469
|
+
});
|
|
1470
|
+
});
|
|
1471
|
+
return {
|
|
1472
|
+
task: buildTask.then(() => this.postBuild()),
|
|
1473
|
+
abort: () => controller.abort()
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
pickBinary() {
|
|
1477
|
+
let set = false;
|
|
1478
|
+
if (this.options.watch) if (process.env.CI) debug$5.warn("Watch mode is not supported in CI environment");
|
|
1479
|
+
else {
|
|
1480
|
+
debug$5("Use %i", "cargo-watch");
|
|
1481
|
+
tryInstallCargoBinary("cargo-watch", "watch");
|
|
1482
|
+
this.args.push("watch", "--why", "-i", "*.{js,ts,node}", "-w", this.crateDir, "--", "cargo", "build");
|
|
1483
|
+
set = true;
|
|
1484
|
+
}
|
|
1485
|
+
if (this.options.crossCompile) if (this.target.platform === "win32") if (process.platform === "win32") debug$5.warn("You are trying to cross compile to win32 platform on win32 platform which is unnecessary.");
|
|
1486
|
+
else {
|
|
1487
|
+
debug$5("Use %i", "cargo-xwin");
|
|
1488
|
+
tryInstallCargoBinary("cargo-xwin", "xwin");
|
|
1489
|
+
this.args.push("xwin", "build");
|
|
1490
|
+
if (this.target.arch === "ia32") this.envs.XWIN_ARCH = "x86";
|
|
1491
|
+
set = true;
|
|
1492
|
+
}
|
|
1493
|
+
else if (this.target.platform === "linux" && process.platform === "linux" && this.target.arch === process.arch && function(abi) {
|
|
1494
|
+
const glibcVersionRuntime = process.report?.getReport()?.header?.glibcVersionRuntime;
|
|
1495
|
+
const libc = glibcVersionRuntime ? "gnu" : "musl";
|
|
1496
|
+
return abi === libc;
|
|
1497
|
+
}(this.target.abi)) debug$5.warn("You are trying to cross compile to linux target on linux platform which is unnecessary.");
|
|
1498
|
+
else if (this.target.platform === "darwin" && process.platform === "darwin") debug$5.warn("You are trying to cross compile to darwin target on darwin platform which is unnecessary.");
|
|
1499
|
+
else {
|
|
1500
|
+
debug$5("Use %i", "cargo-zigbuild");
|
|
1501
|
+
tryInstallCargoBinary("cargo-zigbuild", "zigbuild");
|
|
1502
|
+
this.args.push("zigbuild");
|
|
1503
|
+
set = true;
|
|
1504
|
+
}
|
|
1505
|
+
if (!set) this.args.push("build");
|
|
1506
|
+
return this;
|
|
1507
|
+
}
|
|
1508
|
+
setPackage() {
|
|
1509
|
+
const args = [];
|
|
1510
|
+
if (this.options.package) args.push("--package", this.options.package);
|
|
1511
|
+
if (this.binName) args.push("--bin", this.binName);
|
|
1512
|
+
if (args.length) {
|
|
1513
|
+
debug$5("Set package flags: ");
|
|
1514
|
+
debug$5(" %O", args);
|
|
1515
|
+
this.args.push(...args);
|
|
1516
|
+
}
|
|
1517
|
+
return this;
|
|
1518
|
+
}
|
|
1519
|
+
setTarget() {
|
|
1520
|
+
debug$5("Set compiling target to: ");
|
|
1521
|
+
debug$5(" %i", this.target.triple);
|
|
1522
|
+
this.args.push("--target", this.target.triple);
|
|
1523
|
+
return this;
|
|
1524
|
+
}
|
|
1525
|
+
setEnvs() {
|
|
1526
|
+
if (this.enableTypeDef) {
|
|
1527
|
+
this.envs.NAPI_TYPE_DEF_TMP_FOLDER = this.generateIntermediateTypeDefFolder();
|
|
1528
|
+
this.setForceBuildEnvs(this.envs.NAPI_TYPE_DEF_TMP_FOLDER);
|
|
1529
|
+
}
|
|
1530
|
+
let rustflags = process.env.RUSTFLAGS ?? process.env.CARGO_BUILD_RUSTFLAGS ?? "";
|
|
1531
|
+
if (this.target.abi?.includes("musl") && !rustflags.includes("target-feature=-crt-static")) rustflags += " -C target-feature=-crt-static";
|
|
1532
|
+
if (this.options.strip && !rustflags.includes("link-arg=-s")) rustflags += " -C link-arg=-s";
|
|
1533
|
+
if (rustflags.length) this.envs.RUSTFLAGS = rustflags;
|
|
1534
|
+
const linker = this.options.crossCompile ? void 0 : getTargetLinker(this.target.triple);
|
|
1535
|
+
const linkerEnv = `CARGO_TARGET_${targetToEnvVar(this.target.triple)}_LINKER`;
|
|
1536
|
+
if (linker && !process.env[linkerEnv] && !this.envs[linkerEnv]) this.envs[linkerEnv] = linker;
|
|
1537
|
+
if (this.target.platform === "android") {
|
|
1538
|
+
const { ANDROID_NDK_LATEST_HOME } = process.env;
|
|
1539
|
+
if (!ANDROID_NDK_LATEST_HOME) debug$5.warn(`${colors.red("ANDROID_NDK_LATEST_HOME")} environment variable is missing`);
|
|
1540
|
+
const targetArch = this.target.arch === "arm" ? "armv7a" : "aarch64";
|
|
1541
|
+
const targetPlatform = this.target.arch === "arm" ? "androideabi24" : "android24";
|
|
1542
|
+
const hostPlatform = process.platform === "darwin" ? "darwin" : process.platform === "win32" ? "windows" : "linux";
|
|
1543
|
+
Object.assign(this.envs, {
|
|
1544
|
+
CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-android24-clang`,
|
|
1545
|
+
CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-androideabi24-clang`,
|
|
1546
|
+
TARGET_CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang`,
|
|
1547
|
+
TARGET_CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang++`,
|
|
1548
|
+
TARGET_AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ar`,
|
|
1549
|
+
TARGET_RANLIB: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ranlib`,
|
|
1550
|
+
ANDROID_NDK: ANDROID_NDK_LATEST_HOME,
|
|
1551
|
+
PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin:${process.env.PATH}`
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1554
|
+
if (this.target.platform === "wasi") {
|
|
1555
|
+
const emnapi = join(require$1.resolve("emnapi"), "..", "lib", "wasm32-wasi-threads");
|
|
1556
|
+
this.envs.EMNAPI_LINK_DIR = emnapi;
|
|
1557
|
+
this.envs.SETJMP_LINK_DIR = lib;
|
|
1558
|
+
const { WASI_SDK_PATH } = process.env;
|
|
1559
|
+
if (WASI_SDK_PATH && existsSync(WASI_SDK_PATH)) {
|
|
1560
|
+
this.envs.CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_LINKER = join(WASI_SDK_PATH, "bin", "wasm-ld");
|
|
1561
|
+
this.envs.CARGO_TARGET_WASM32_WASIP1_LINKER = join(WASI_SDK_PATH, "bin", "wasm-ld");
|
|
1562
|
+
this.envs.CARGO_TARGET_WASM32_WASIP1_THREADS_LINKER = join(WASI_SDK_PATH, "bin", "wasm-ld");
|
|
1563
|
+
this.envs.CARGO_TARGET_WASM32_WASIP2_LINKER = join(WASI_SDK_PATH, "bin", "wasm-ld");
|
|
1564
|
+
this.setEnvIfNotExists("CC", join(WASI_SDK_PATH, "bin", "clang"));
|
|
1565
|
+
this.setEnvIfNotExists("CXX", join(WASI_SDK_PATH, "bin", "clang++"));
|
|
1566
|
+
this.setEnvIfNotExists("AR", join(WASI_SDK_PATH, "bin", "ar"));
|
|
1567
|
+
this.setEnvIfNotExists("RANLIB", join(WASI_SDK_PATH, "bin", "ranlib"));
|
|
1568
|
+
this.setEnvIfNotExists("CFLAGS", `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${include}`);
|
|
1569
|
+
this.setEnvIfNotExists("CXXFLAGS", `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${include}`);
|
|
1570
|
+
this.setEnvIfNotExists(`LDFLAGS`, `-fuse-ld=${WASI_SDK_PATH}/bin/wasm-ld --target=wasm32-wasi-threads`);
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
debug$5("Set envs: ");
|
|
1574
|
+
Object.entries(this.envs).forEach(([k, v]) => {
|
|
1575
|
+
debug$5(" %i", `${k}=${v}`);
|
|
1576
|
+
});
|
|
1577
|
+
return this;
|
|
1578
|
+
}
|
|
1579
|
+
setForceBuildEnvs(typeDefTmpFolder) {
|
|
1580
|
+
this.metadata.packages.forEach((crate) => {
|
|
1581
|
+
if (crate.dependencies.some((d) => d.name === "napi-derive") && !existsSync(join(typeDefTmpFolder, crate.name))) this.envs[`NAPI_FORCE_BUILD_${crate.name.replace(/-/g, "_").toUpperCase()}`] = Date.now().toString();
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1584
|
+
setFeatures() {
|
|
1585
|
+
const args = [];
|
|
1586
|
+
if (this.options.allFeatures && this.options.noDefaultFeatures) throw new Error("Cannot specify --all-features and --no-default-features together");
|
|
1587
|
+
if (this.options.allFeatures) args.push("--all-features");
|
|
1588
|
+
else if (this.options.noDefaultFeatures) args.push("--no-default-features");
|
|
1589
|
+
if (this.options.features) args.push("--features", ...this.options.features);
|
|
1590
|
+
debug$5("Set features flags: ");
|
|
1591
|
+
debug$5(" %O", args);
|
|
1592
|
+
this.args.push(...args);
|
|
1593
|
+
return this;
|
|
1594
|
+
}
|
|
1595
|
+
setBypassArgs() {
|
|
1596
|
+
if (this.options.release) this.args.push("--release");
|
|
1597
|
+
if (this.options.verbose) this.args.push("--verbose");
|
|
1598
|
+
if (this.options.targetDir) this.args.push("--target-dir", this.options.targetDir);
|
|
1599
|
+
if (this.options.profile) this.args.push("--profile", this.options.profile);
|
|
1600
|
+
if (this.options.manifestPath) this.args.push("--manifest-path", this.options.manifestPath);
|
|
1601
|
+
if (this.options.cargoOptions?.length) this.args.push(...this.options.cargoOptions);
|
|
1602
|
+
return this;
|
|
1603
|
+
}
|
|
1604
|
+
generateIntermediateTypeDefFolder() {
|
|
1605
|
+
let folder = join(this.targetDir, "napi-rs", `${this.crate.name}-${createHash("sha256").update(this.crate.manifest_path).update(CLI_VERSION).digest("hex").substring(0, 8)}`);
|
|
1606
|
+
if (!this.options.dtsCache) {
|
|
1607
|
+
rmSync(folder, {
|
|
1608
|
+
recursive: true,
|
|
1609
|
+
force: true
|
|
1610
|
+
});
|
|
1611
|
+
folder += `_${Date.now()}`;
|
|
1612
|
+
}
|
|
1613
|
+
mkdirAsync(folder, { recursive: true });
|
|
1614
|
+
return folder;
|
|
1615
|
+
}
|
|
1616
|
+
async postBuild() {
|
|
1617
|
+
try {
|
|
1618
|
+
debug$5(`Try to create output directory:`);
|
|
1619
|
+
debug$5(" %i", this.outputDir);
|
|
1620
|
+
await mkdirAsync(this.outputDir, { recursive: true });
|
|
1621
|
+
debug$5(`Output directory created`);
|
|
1622
|
+
} catch (e) {
|
|
1623
|
+
throw new Error(`Failed to create output directory ${this.outputDir}`, { cause: e });
|
|
1624
|
+
}
|
|
1625
|
+
const wasmBinaryName = await this.copyArtifact();
|
|
1626
|
+
if (this.cdyLibName) {
|
|
1627
|
+
const idents = await this.generateTypeDef();
|
|
1628
|
+
const jsOutput = await this.writeJsBinding(idents);
|
|
1629
|
+
const wasmBindingsOutput = await this.writeWasiBinding(wasmBinaryName, idents);
|
|
1630
|
+
if (jsOutput) this.outputs.push(jsOutput);
|
|
1631
|
+
if (wasmBindingsOutput) this.outputs.push(...wasmBindingsOutput);
|
|
1632
|
+
}
|
|
1633
|
+
return this.outputs;
|
|
1634
|
+
}
|
|
1635
|
+
async copyArtifact() {
|
|
1636
|
+
const [srcName, destName, wasmBinaryName] = this.getArtifactNames();
|
|
1637
|
+
if (!srcName || !destName) return;
|
|
1638
|
+
const profile = this.options.profile ?? (this.options.release ? "release" : "debug");
|
|
1639
|
+
const src = join(this.targetDir, this.target.triple, profile, srcName);
|
|
1640
|
+
debug$5(`Copy artifact from: [${src}]`);
|
|
1641
|
+
const dest = join(this.outputDir, destName);
|
|
1642
|
+
const isWasm = dest.endsWith(".wasm");
|
|
1643
|
+
try {
|
|
1644
|
+
if (await fileExists(dest)) {
|
|
1645
|
+
debug$5("Old artifact found, remove it first");
|
|
1646
|
+
await unlinkAsync(dest);
|
|
1647
|
+
}
|
|
1648
|
+
debug$5("Copy artifact to:");
|
|
1649
|
+
debug$5(" %i", dest);
|
|
1650
|
+
if (isWasm) {
|
|
1651
|
+
const { ModuleConfig } = await import("@napi-rs/wasm-tools");
|
|
1652
|
+
debug$5("Generate debug wasm module");
|
|
1653
|
+
try {
|
|
1654
|
+
const debugWasmModule = new ModuleConfig().generateDwarf(true).generateNameSection(true).generateProducersSection(true).preserveCodeTransform(true).strictValidate(false).parse(await readFileAsync(src));
|
|
1655
|
+
const debugWasmBinary = debugWasmModule.emitWasm(true);
|
|
1656
|
+
await writeFileAsync(dest.replace(/\.wasm$/, ".debug.wasm"), debugWasmBinary);
|
|
1657
|
+
debug$5("Generate release wasm module");
|
|
1658
|
+
const releaseWasmModule = new ModuleConfig().generateDwarf(false).generateNameSection(false).generateProducersSection(false).preserveCodeTransform(false).strictValidate(false).onlyStableFeatures(false).parse(debugWasmBinary);
|
|
1659
|
+
const releaseWasmBinary = releaseWasmModule.emitWasm(false);
|
|
1660
|
+
await writeFileAsync(dest, releaseWasmBinary);
|
|
1661
|
+
} catch (e) {
|
|
1662
|
+
debug$5.warn(`Failed to generate debug wasm module: ${e.message ?? e}`);
|
|
1663
|
+
await copyFileAsync(src, dest);
|
|
1664
|
+
}
|
|
1665
|
+
} else await copyFileAsync(src, dest);
|
|
1666
|
+
this.outputs.push({
|
|
1667
|
+
kind: dest.endsWith(".node") ? "node" : isWasm ? "wasm" : "exe",
|
|
1668
|
+
path: dest
|
|
1669
|
+
});
|
|
1670
|
+
return wasmBinaryName ? join(this.outputDir, wasmBinaryName) : null;
|
|
1671
|
+
} catch (e) {
|
|
1672
|
+
throw new Error("Failed to copy artifact", { cause: e });
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
getArtifactNames() {
|
|
1676
|
+
if (this.cdyLibName) {
|
|
1677
|
+
const cdyLib = this.cdyLibName.replace(/-/g, "_");
|
|
1678
|
+
const wasiTarget = this.config.targets.find((t) => t.platform === "wasi");
|
|
1679
|
+
const srcName = this.target.platform === "darwin" ? `lib${cdyLib}.dylib` : this.target.platform === "win32" ? `${cdyLib}.dll` : this.target.platform === "wasi" || this.target.platform === "wasm" ? `${cdyLib}.wasm` : `lib${cdyLib}.so`;
|
|
1680
|
+
let destName = this.config.binaryName;
|
|
1681
|
+
if (this.options.platform) destName += `.${this.target.platformArchABI}`;
|
|
1682
|
+
if (srcName.endsWith(".wasm")) destName += ".wasm";
|
|
1683
|
+
else destName += ".node";
|
|
1684
|
+
return [
|
|
1685
|
+
srcName,
|
|
1686
|
+
destName,
|
|
1687
|
+
wasiTarget ? `${this.config.binaryName}.${wasiTarget.platformArchABI}.wasm` : null
|
|
1688
|
+
];
|
|
1689
|
+
} else if (this.binName) {
|
|
1690
|
+
const srcName = this.target.platform === "win32" ? `${this.binName}.exe` : this.binName;
|
|
1691
|
+
return [srcName, srcName];
|
|
1692
|
+
}
|
|
1693
|
+
return [];
|
|
1694
|
+
}
|
|
1695
|
+
async generateTypeDef() {
|
|
1696
|
+
const typeDefDir = this.envs.NAPI_TYPE_DEF_TMP_FOLDER;
|
|
1697
|
+
if (!this.enableTypeDef || !await dirExistsAsync(typeDefDir)) return [];
|
|
1698
|
+
const dest = join(this.outputDir, this.options.dts ?? "index.d.ts");
|
|
1699
|
+
let header = "";
|
|
1700
|
+
let dts = "";
|
|
1701
|
+
let exports$1 = [];
|
|
1702
|
+
if (!this.options.noDtsHeader) {
|
|
1703
|
+
const dtsHeader = this.options.dtsHeader ?? this.config.dtsHeader;
|
|
1704
|
+
if (this.config.dtsHeaderFile) try {
|
|
1705
|
+
header = await readFileAsync(join(this.options.cwd, this.config.dtsHeaderFile), "utf-8");
|
|
1706
|
+
} catch (e) {
|
|
1707
|
+
debug$5.warn(`Failed to read dts header file ${this.config.dtsHeaderFile}`, e);
|
|
1708
|
+
}
|
|
1709
|
+
else if (dtsHeader) header = dtsHeader;
|
|
1710
|
+
else header = DEFAULT_TYPE_DEF_HEADER;
|
|
1711
|
+
}
|
|
1712
|
+
const files$1 = await readdirAsync(typeDefDir, { withFileTypes: true });
|
|
1713
|
+
if (!files$1.length) {
|
|
1714
|
+
debug$5("No type def files found. Skip generating dts file.");
|
|
1715
|
+
return [];
|
|
1716
|
+
}
|
|
1717
|
+
for (const file of files$1) {
|
|
1718
|
+
if (!file.isFile()) continue;
|
|
1719
|
+
const { dts: fileDts, exports: fileExports } = await processTypeDef(join(typeDefDir, file.name), this.options.constEnum ?? this.config.constEnum ?? true);
|
|
1720
|
+
dts += fileDts;
|
|
1721
|
+
exports$1.push(...fileExports);
|
|
1722
|
+
}
|
|
1723
|
+
if (dts.indexOf("ExternalObject<") > -1) header += `
|
|
1724
|
+
export declare class ExternalObject<T> {
|
|
1725
|
+
readonly '': {
|
|
1726
|
+
readonly '': unique symbol
|
|
1727
|
+
[K: symbol]: T
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
`;
|
|
1731
|
+
dts = header + dts;
|
|
1732
|
+
try {
|
|
1733
|
+
debug$5("Writing type def to:");
|
|
1734
|
+
debug$5(" %i", dest);
|
|
1735
|
+
await writeFileAsync(dest, dts, "utf-8");
|
|
1736
|
+
this.outputs.push({
|
|
1737
|
+
kind: "dts",
|
|
1738
|
+
path: dest
|
|
1739
|
+
});
|
|
1740
|
+
} catch (e) {
|
|
1741
|
+
debug$5.error("Failed to write type def file");
|
|
1742
|
+
debug$5.error(e);
|
|
1743
|
+
}
|
|
1744
|
+
return exports$1;
|
|
1745
|
+
}
|
|
1746
|
+
async writeJsBinding(idents) {
|
|
1747
|
+
if (!this.options.platform || this.options.noJsBinding || idents.length === 0) return;
|
|
1748
|
+
const name$1 = this.options.jsBinding ?? "index.js";
|
|
1749
|
+
const createBinding = this.options.esm ? createEsmBinding : createCjsBinding;
|
|
1750
|
+
const binding = createBinding(this.config.binaryName, this.config.packageName, idents);
|
|
1751
|
+
try {
|
|
1752
|
+
const dest = join(this.outputDir, name$1);
|
|
1753
|
+
debug$5("Writing js binding to:");
|
|
1754
|
+
debug$5(" %i", dest);
|
|
1755
|
+
await writeFileAsync(dest, binding, "utf-8");
|
|
1756
|
+
return {
|
|
1757
|
+
kind: "js",
|
|
1758
|
+
path: dest
|
|
1759
|
+
};
|
|
1760
|
+
} catch (e) {
|
|
1761
|
+
throw new Error("Failed to write js binding file", { cause: e });
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
async writeWasiBinding(distFileName, idents) {
|
|
1765
|
+
if (distFileName) {
|
|
1766
|
+
const { name: name$1, dir } = parse(distFileName);
|
|
1767
|
+
const bindingPath = join(dir, `${this.config.binaryName}.wasi.cjs`);
|
|
1768
|
+
const browserBindingPath = join(dir, `${this.config.binaryName}.wasi-browser.js`);
|
|
1769
|
+
const workerPath = join(dir, "wasi-worker.mjs");
|
|
1770
|
+
const browserWorkerPath = join(dir, "wasi-worker-browser.mjs");
|
|
1771
|
+
const browserEntryPath = join(dir, "browser.js");
|
|
1772
|
+
const exportsCode = `module.exports = __napiModule.exports\n` + idents.map((ident) => `module.exports.${ident} = __napiModule.exports.${ident}`).join("\n");
|
|
1773
|
+
await writeFileAsync(bindingPath, createWasiBinding(name$1, this.config.packageName, this.config.wasm?.initialMemory, this.config.wasm?.maximumMemory) + exportsCode + "\n", "utf8");
|
|
1774
|
+
await writeFileAsync(browserBindingPath, createWasiBrowserBinding(name$1, this.config.wasm?.initialMemory, this.config.wasm?.maximumMemory, this.config.wasm?.browser?.fs, this.config.wasm?.browser?.asyncInit) + `export default __napiModule.exports\n` + idents.map((ident) => `export const ${ident} = __napiModule.exports.${ident}`).join("\n") + "\n", "utf8");
|
|
1775
|
+
await writeFileAsync(workerPath, WASI_WORKER_TEMPLATE, "utf8");
|
|
1776
|
+
await writeFileAsync(browserWorkerPath, createWasiBrowserWorkerBinding(this.config.wasm?.browser?.fs ?? false), "utf8");
|
|
1777
|
+
await writeFileAsync(browserEntryPath, `export * from '${this.config.packageName}-wasm32-wasi'\n`);
|
|
1778
|
+
return [
|
|
1779
|
+
{
|
|
1780
|
+
kind: "js",
|
|
1781
|
+
path: bindingPath
|
|
1782
|
+
},
|
|
1783
|
+
{
|
|
1784
|
+
kind: "js",
|
|
1785
|
+
path: browserBindingPath
|
|
1786
|
+
},
|
|
1787
|
+
{
|
|
1788
|
+
kind: "js",
|
|
1789
|
+
path: workerPath
|
|
1790
|
+
},
|
|
1791
|
+
{
|
|
1792
|
+
kind: "js",
|
|
1793
|
+
path: browserWorkerPath
|
|
1794
|
+
},
|
|
1795
|
+
{
|
|
1796
|
+
kind: "js",
|
|
1797
|
+
path: browserEntryPath
|
|
1798
|
+
}
|
|
1799
|
+
];
|
|
1800
|
+
}
|
|
1801
|
+
return [];
|
|
1802
|
+
}
|
|
1803
|
+
setEnvIfNotExists(env, value$1) {
|
|
1804
|
+
if (!process.env[env]) this.envs[env] = value$1;
|
|
1805
|
+
}
|
|
1806
|
+
};
|
|
1807
|
+
|
|
1808
|
+
//#endregion
|
|
1809
|
+
//#region src/def/create-npm-dirs.ts
|
|
1810
|
+
var import_defineProperty$7 = __toESM(require_defineProperty(), 1);
|
|
1811
|
+
var BaseCreateNpmDirsCommand = class extends Command {
|
|
1812
|
+
constructor(..._args) {
|
|
1813
|
+
super(..._args);
|
|
1814
|
+
(0, import_defineProperty$7.default)(this, "cwd", Option.String("--cwd", process.cwd(), { description: "The working directory of where napi command will be executed in, all other paths options are relative to this path" }));
|
|
1815
|
+
(0, import_defineProperty$7.default)(this, "configPath", Option.String("--config-path,-c", { description: "Path to `napi` config json file" }));
|
|
1816
|
+
(0, import_defineProperty$7.default)(this, "packageJsonPath", Option.String("--package-json-path", "package.json", { description: "Path to `package.json`" }));
|
|
1817
|
+
(0, import_defineProperty$7.default)(this, "npmDir", Option.String("--npm-dir", "npm", { description: "Path to the folder where the npm packages put" }));
|
|
1818
|
+
(0, import_defineProperty$7.default)(this, "dryRun", Option.Boolean("--dry-run", false, { description: "Dry run without touching file system" }));
|
|
1819
|
+
}
|
|
1820
|
+
getOptions() {
|
|
1821
|
+
return {
|
|
1822
|
+
cwd: this.cwd,
|
|
1823
|
+
configPath: this.configPath,
|
|
1824
|
+
packageJsonPath: this.packageJsonPath,
|
|
1825
|
+
npmDir: this.npmDir,
|
|
1826
|
+
dryRun: this.dryRun
|
|
1827
|
+
};
|
|
1828
|
+
}
|
|
1829
|
+
};
|
|
1830
|
+
(0, import_defineProperty$7.default)(BaseCreateNpmDirsCommand, "paths", [["create-npm-dirs"]]);
|
|
1831
|
+
(0, import_defineProperty$7.default)(BaseCreateNpmDirsCommand, "usage", Command.Usage({ description: "Create npm package dirs for different platforms" }));
|
|
1832
|
+
function applyDefaultCreateNpmDirsOptions(options) {
|
|
1833
|
+
return {
|
|
1834
|
+
cwd: process.cwd(),
|
|
1835
|
+
packageJsonPath: "package.json",
|
|
1836
|
+
npmDir: "npm",
|
|
1837
|
+
dryRun: false,
|
|
1838
|
+
...options
|
|
1839
|
+
};
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
//#endregion
|
|
1843
|
+
//#region src/api/create-npm-dirs.ts
|
|
1844
|
+
const debug$4 = debugFactory("create-npm-dirs");
|
|
1845
|
+
async function createNpmDirs(userOptions) {
|
|
1846
|
+
const options = applyDefaultCreateNpmDirsOptions(userOptions);
|
|
1847
|
+
async function mkdirAsync$1(dir) {
|
|
1848
|
+
debug$4("Try to create dir: %i", dir);
|
|
1849
|
+
if (options.dryRun) return;
|
|
1850
|
+
await mkdirAsync(dir, { recursive: true });
|
|
1851
|
+
}
|
|
1852
|
+
async function writeFileAsync$1(file, content) {
|
|
1853
|
+
debug$4("Writing file %i", file);
|
|
1854
|
+
if (options.dryRun) {
|
|
1855
|
+
debug$4(content);
|
|
1856
|
+
return;
|
|
1857
|
+
}
|
|
1858
|
+
await writeFileAsync(file, content);
|
|
1859
|
+
}
|
|
1860
|
+
const packageJsonPath = resolve(options.cwd, options.packageJsonPath);
|
|
1861
|
+
const npmPath = resolve(options.cwd, options.npmDir);
|
|
1862
|
+
debug$4(`Read content from [${options.configPath ?? packageJsonPath}]`);
|
|
1863
|
+
const { targets, binaryName, packageName, packageJson } = await readNapiConfig(packageJsonPath, options.configPath ? resolve(options.cwd, options.configPath) : void 0);
|
|
1864
|
+
for (const target of targets) {
|
|
1865
|
+
const targetDir = join(npmPath, `${target.platformArchABI}`);
|
|
1866
|
+
await mkdirAsync$1(targetDir);
|
|
1867
|
+
const binaryFileName = target.arch === "wasm32" ? `${binaryName}.${target.platformArchABI}.wasm` : `${binaryName}.${target.platformArchABI}.node`;
|
|
1868
|
+
const scopedPackageJson = {
|
|
1869
|
+
name: `${packageName}-${target.platformArchABI}`,
|
|
1870
|
+
version: packageJson.version,
|
|
1871
|
+
cpu: target.arch !== "universal" ? [target.arch] : void 0,
|
|
1872
|
+
main: binaryFileName,
|
|
1873
|
+
files: [binaryFileName],
|
|
1874
|
+
...pick$1(packageJson, "description", "keywords", "author", "authors", "homepage", "license", "engines", "publishConfig", "repository", "bugs")
|
|
1875
|
+
};
|
|
1876
|
+
if (target.arch !== "wasm32") scopedPackageJson.os = [target.platform];
|
|
1877
|
+
else {
|
|
1878
|
+
const entry = `${binaryName}.wasi.cjs`;
|
|
1879
|
+
scopedPackageJson.main = entry;
|
|
1880
|
+
scopedPackageJson.browser = `${binaryName}.wasi-browser.js`;
|
|
1881
|
+
scopedPackageJson.files.push(entry, scopedPackageJson.browser, `wasi-worker.mjs`, `wasi-worker-browser.mjs`);
|
|
1882
|
+
let needRestrictNodeVersion = true;
|
|
1883
|
+
if (scopedPackageJson.engines?.node) try {
|
|
1884
|
+
const { major } = parse$1(scopedPackageJson.engines.node) ?? { major: 0 };
|
|
1885
|
+
if (major >= 14) needRestrictNodeVersion = false;
|
|
1886
|
+
} catch {}
|
|
1887
|
+
if (needRestrictNodeVersion) scopedPackageJson.engines = { node: ">=14.0.0" };
|
|
1888
|
+
const wasmRuntime = await fetch(`https://registry.npmjs.org/@napi-rs/wasm-runtime`).then((res) => res.json());
|
|
1889
|
+
scopedPackageJson.dependencies = { "@napi-rs/wasm-runtime": `^${wasmRuntime["dist-tags"].latest}` };
|
|
1890
|
+
}
|
|
1891
|
+
if (target.abi === "gnu") scopedPackageJson.libc = ["glibc"];
|
|
1892
|
+
else if (target.abi === "musl") scopedPackageJson.libc = ["musl"];
|
|
1893
|
+
const targetPackageJson = join(targetDir, "package.json");
|
|
1894
|
+
await writeFileAsync$1(targetPackageJson, JSON.stringify(scopedPackageJson, null, 2) + "\n");
|
|
1895
|
+
const targetReadme = join(targetDir, "README.md");
|
|
1896
|
+
await writeFileAsync$1(targetReadme, readme(packageName, target));
|
|
1897
|
+
debug$4.info(`${packageName} -${target.platformArchABI} created`);
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
function readme(packageName, target) {
|
|
1901
|
+
return `# \`${packageName}-${target.platformArchABI}\`
|
|
1902
|
+
|
|
1903
|
+
This is the **${target.triple}** binary for \`${packageName}\`
|
|
1904
|
+
`;
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
//#endregion
|
|
1908
|
+
//#region src/def/new.ts
|
|
1909
|
+
var import_defineProperty$6 = __toESM(require_defineProperty(), 1);
|
|
1910
|
+
var BaseNewCommand = class extends Command {
|
|
1911
|
+
constructor(..._args) {
|
|
1912
|
+
super(..._args);
|
|
1913
|
+
(0, import_defineProperty$6.default)(this, "$$path", Option.String({ required: false }));
|
|
1914
|
+
(0, import_defineProperty$6.default)(this, "$$name", Option.String("--name,-n", { description: "The name of the project, default to the name of the directory if not provided" }));
|
|
1915
|
+
(0, import_defineProperty$6.default)(this, "minNodeApiVersion", Option.String("--min-node-api,-v", "4", {
|
|
1916
|
+
validator: typanion.isNumber(),
|
|
1917
|
+
description: "The minimum Node-API version to support"
|
|
1918
|
+
}));
|
|
1919
|
+
(0, import_defineProperty$6.default)(this, "packageManager", Option.String("--package-manager", "yarn", { description: "The package manager to use. Only support yarn 4.x for now." }));
|
|
1920
|
+
(0, import_defineProperty$6.default)(this, "license", Option.String("--license,-l", "MIT", { description: "License for open-sourced project" }));
|
|
1921
|
+
(0, import_defineProperty$6.default)(this, "targets", Option.Array("--targets,-t", [], { description: "All targets the crate will be compiled for." }));
|
|
1922
|
+
(0, import_defineProperty$6.default)(this, "enableDefaultTargets", Option.Boolean("--enable-default-targets", true, { description: "Whether enable default targets" }));
|
|
1923
|
+
(0, import_defineProperty$6.default)(this, "enableAllTargets", Option.Boolean("--enable-all-targets", false, { description: "Whether enable all targets" }));
|
|
1924
|
+
(0, import_defineProperty$6.default)(this, "enableTypeDef", Option.Boolean("--enable-type-def", true, { description: "Whether enable the `type-def` feature for typescript definitions auto-generation" }));
|
|
1925
|
+
(0, import_defineProperty$6.default)(this, "enableGithubActions", Option.Boolean("--enable-github-actions", true, { description: "Whether generate preconfigured GitHub Actions workflow" }));
|
|
1926
|
+
(0, import_defineProperty$6.default)(this, "testFramework", Option.String("--test-framework", "ava", { description: "The JavaScript test framework to use, only support `ava` for now" }));
|
|
1927
|
+
(0, import_defineProperty$6.default)(this, "dryRun", Option.Boolean("--dry-run", false, { description: "Whether to run the command in dry-run mode" }));
|
|
1928
|
+
}
|
|
1929
|
+
getOptions() {
|
|
1930
|
+
return {
|
|
1931
|
+
path: this.$$path,
|
|
1932
|
+
name: this.$$name,
|
|
1933
|
+
minNodeApiVersion: this.minNodeApiVersion,
|
|
1934
|
+
packageManager: this.packageManager,
|
|
1935
|
+
license: this.license,
|
|
1936
|
+
targets: this.targets,
|
|
1937
|
+
enableDefaultTargets: this.enableDefaultTargets,
|
|
1938
|
+
enableAllTargets: this.enableAllTargets,
|
|
1939
|
+
enableTypeDef: this.enableTypeDef,
|
|
1940
|
+
enableGithubActions: this.enableGithubActions,
|
|
1941
|
+
testFramework: this.testFramework,
|
|
1942
|
+
dryRun: this.dryRun
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
};
|
|
1946
|
+
(0, import_defineProperty$6.default)(BaseNewCommand, "paths", [["new"]]);
|
|
1947
|
+
(0, import_defineProperty$6.default)(BaseNewCommand, "usage", Command.Usage({ description: "Create a new project with pre-configured boilerplate" }));
|
|
1948
|
+
function applyDefaultNewOptions(options) {
|
|
1949
|
+
return {
|
|
1950
|
+
minNodeApiVersion: 4,
|
|
1951
|
+
packageManager: "yarn",
|
|
1952
|
+
license: "MIT",
|
|
1953
|
+
targets: [],
|
|
1954
|
+
enableDefaultTargets: true,
|
|
1955
|
+
enableAllTargets: false,
|
|
1956
|
+
enableTypeDef: true,
|
|
1957
|
+
enableGithubActions: true,
|
|
1958
|
+
testFramework: "ava",
|
|
1959
|
+
dryRun: false,
|
|
1960
|
+
...options
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
//#endregion
|
|
1965
|
+
//#region ../node_modules/@oxc-project/runtime/src/helpers/checkPrivateRedeclaration.js
|
|
1966
|
+
var require_checkPrivateRedeclaration = __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/checkPrivateRedeclaration.js"(exports, module) {
|
|
1967
|
+
function _checkPrivateRedeclaration(e, t) {
|
|
1968
|
+
if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
|
|
1969
|
+
}
|
|
1970
|
+
module.exports = _checkPrivateRedeclaration, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
1971
|
+
} });
|
|
1972
|
+
|
|
1973
|
+
//#endregion
|
|
1974
|
+
//#region ../node_modules/@oxc-project/runtime/src/helpers/classPrivateMethodInitSpec.js
|
|
1975
|
+
var require_classPrivateMethodInitSpec = __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/classPrivateMethodInitSpec.js"(exports, module) {
|
|
1976
|
+
var checkPrivateRedeclaration$1 = require_checkPrivateRedeclaration();
|
|
1977
|
+
function _classPrivateMethodInitSpec$1(e, a) {
|
|
1978
|
+
checkPrivateRedeclaration$1(e, a), a.add(e);
|
|
1979
|
+
}
|
|
1980
|
+
module.exports = _classPrivateMethodInitSpec$1, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
1981
|
+
} });
|
|
1982
|
+
|
|
1983
|
+
//#endregion
|
|
1984
|
+
//#region ../node_modules/@oxc-project/runtime/src/helpers/classPrivateFieldInitSpec.js
|
|
1985
|
+
var require_classPrivateFieldInitSpec = __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/classPrivateFieldInitSpec.js"(exports, module) {
|
|
1986
|
+
var checkPrivateRedeclaration = require_checkPrivateRedeclaration();
|
|
1987
|
+
function _classPrivateFieldInitSpec$2(e, t, a) {
|
|
1988
|
+
checkPrivateRedeclaration(e, t), t.set(e, a);
|
|
1989
|
+
}
|
|
1990
|
+
module.exports = _classPrivateFieldInitSpec$2, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
1991
|
+
} });
|
|
1992
|
+
|
|
1993
|
+
//#endregion
|
|
1994
|
+
//#region ../node_modules/@oxc-project/runtime/src/helpers/assertClassBrand.js
|
|
1995
|
+
var require_assertClassBrand = __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/assertClassBrand.js"(exports, module) {
|
|
1996
|
+
function _assertClassBrand$1(e, t, n) {
|
|
1997
|
+
if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
|
|
1998
|
+
throw new TypeError("Private element is not present on this object");
|
|
1999
|
+
}
|
|
2000
|
+
module.exports = _assertClassBrand$1, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
2001
|
+
} });
|
|
2002
|
+
|
|
2003
|
+
//#endregion
|
|
2004
|
+
//#region ../node_modules/@oxc-project/runtime/src/helpers/classPrivateFieldGet2.js
|
|
2005
|
+
var require_classPrivateFieldGet2 = __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/classPrivateFieldGet2.js"(exports, module) {
|
|
2006
|
+
var assertClassBrand$1 = require_assertClassBrand();
|
|
2007
|
+
function _classPrivateFieldGet2(s, a) {
|
|
2008
|
+
return s.get(assertClassBrand$1(s, a));
|
|
2009
|
+
}
|
|
2010
|
+
module.exports = _classPrivateFieldGet2, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
2011
|
+
} });
|
|
2012
|
+
|
|
2013
|
+
//#endregion
|
|
2014
|
+
//#region ../node_modules/@std/toml/stringify.js
|
|
2015
|
+
var import_classPrivateMethodInitSpec = __toESM(require_classPrivateMethodInitSpec(), 1);
|
|
2016
|
+
var import_defineProperty$5 = __toESM(require_defineProperty(), 1);
|
|
2017
|
+
var import_classPrivateFieldInitSpec$1 = __toESM(require_classPrivateFieldInitSpec(), 1);
|
|
2018
|
+
var import_assertClassBrand = __toESM(require_assertClassBrand(), 1);
|
|
2019
|
+
var import_classPrivateFieldGet2$1 = __toESM(require_classPrivateFieldGet2(), 1);
|
|
2020
|
+
function joinKeys(keys) {
|
|
2021
|
+
return keys.map((str) => {
|
|
2022
|
+
return str.length === 0 || str.match(/[^A-Za-z0-9_-]/) ? JSON.stringify(str) : str;
|
|
2023
|
+
}).join(".");
|
|
2024
|
+
}
|
|
2025
|
+
var _arrayTypeCache = /* @__PURE__ */ new WeakMap();
|
|
2026
|
+
var _Dumper_brand = /* @__PURE__ */ new WeakSet();
|
|
2027
|
+
var Dumper = class {
|
|
2028
|
+
constructor(srcObjc) {
|
|
2029
|
+
(0, import_classPrivateMethodInitSpec.default)(this, _Dumper_brand);
|
|
2030
|
+
(0, import_defineProperty$5.default)(this, "maxPad", 0);
|
|
2031
|
+
(0, import_defineProperty$5.default)(this, "srcObject", void 0);
|
|
2032
|
+
(0, import_defineProperty$5.default)(this, "output", []);
|
|
2033
|
+
(0, import_classPrivateFieldInitSpec$1.default)(this, _arrayTypeCache, new Map());
|
|
2034
|
+
this.srcObject = srcObjc;
|
|
2035
|
+
}
|
|
2036
|
+
dump(fmtOptions = {}) {
|
|
2037
|
+
this.output = (0, import_assertClassBrand.default)(_Dumper_brand, this, _printObject).call(this, this.srcObject);
|
|
2038
|
+
this.output = (0, import_assertClassBrand.default)(_Dumper_brand, this, _format).call(this, fmtOptions);
|
|
2039
|
+
return this.output;
|
|
2040
|
+
}
|
|
2041
|
+
};
|
|
2042
|
+
function _printObject(obj, keys = []) {
|
|
2043
|
+
const out = [];
|
|
2044
|
+
const props = Object.keys(obj);
|
|
2045
|
+
const inlineProps = [];
|
|
2046
|
+
const multilineProps = [];
|
|
2047
|
+
for (const prop of props) if ((0, import_assertClassBrand.default)(_Dumper_brand, this, _isSimplySerializable).call(this, obj[prop])) inlineProps.push(prop);
|
|
2048
|
+
else multilineProps.push(prop);
|
|
2049
|
+
const sortedProps = inlineProps.concat(multilineProps);
|
|
2050
|
+
for (const prop of sortedProps) {
|
|
2051
|
+
const value$1 = obj[prop];
|
|
2052
|
+
if (value$1 instanceof Date) out.push((0, import_assertClassBrand.default)(_Dumper_brand, this, _dateDeclaration).call(this, [prop], value$1));
|
|
2053
|
+
else if (typeof value$1 === "string" || value$1 instanceof RegExp) out.push((0, import_assertClassBrand.default)(_Dumper_brand, this, _strDeclaration).call(this, [prop], value$1.toString()));
|
|
2054
|
+
else if (typeof value$1 === "number") out.push((0, import_assertClassBrand.default)(_Dumper_brand, this, _numberDeclaration).call(this, [prop], value$1));
|
|
2055
|
+
else if (typeof value$1 === "boolean") out.push((0, import_assertClassBrand.default)(_Dumper_brand, this, _boolDeclaration).call(this, [prop], value$1));
|
|
2056
|
+
else if (value$1 instanceof Array) {
|
|
2057
|
+
const arrayType = (0, import_assertClassBrand.default)(_Dumper_brand, this, _getTypeOfArray).call(this, value$1);
|
|
2058
|
+
if (arrayType === "ONLY_PRIMITIVE") out.push((0, import_assertClassBrand.default)(_Dumper_brand, this, _arrayDeclaration).call(this, [prop], value$1));
|
|
2059
|
+
else if (arrayType === "ONLY_OBJECT_EXCLUDING_ARRAY") for (let i = 0; i < value$1.length; i++) {
|
|
2060
|
+
out.push("");
|
|
2061
|
+
out.push((0, import_assertClassBrand.default)(_Dumper_brand, this, _headerGroup).call(this, [...keys, prop]));
|
|
2062
|
+
out.push(...(0, import_assertClassBrand.default)(_Dumper_brand, this, _printObject).call(this, value$1[i], [...keys, prop]));
|
|
2063
|
+
}
|
|
2064
|
+
else {
|
|
2065
|
+
const str = value$1.map((x) => (0, import_assertClassBrand.default)(_Dumper_brand, this, _printAsInlineValue).call(this, x)).join(",");
|
|
2066
|
+
out.push(`${(0, import_assertClassBrand.default)(_Dumper_brand, this, _declaration).call(this, [prop])}[${str}]`);
|
|
2067
|
+
}
|
|
2068
|
+
} else if (typeof value$1 === "object") {
|
|
2069
|
+
out.push("");
|
|
2070
|
+
out.push((0, import_assertClassBrand.default)(_Dumper_brand, this, _header).call(this, [...keys, prop]));
|
|
2071
|
+
if (value$1) {
|
|
2072
|
+
const toParse = value$1;
|
|
2073
|
+
out.push(...(0, import_assertClassBrand.default)(_Dumper_brand, this, _printObject).call(this, toParse, [...keys, prop]));
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
out.push("");
|
|
2078
|
+
return out;
|
|
2079
|
+
}
|
|
2080
|
+
function _isPrimitive(value$1) {
|
|
2081
|
+
return value$1 instanceof Date || value$1 instanceof RegExp || [
|
|
2082
|
+
"string",
|
|
2083
|
+
"number",
|
|
2084
|
+
"boolean"
|
|
2085
|
+
].includes(typeof value$1);
|
|
2086
|
+
}
|
|
2087
|
+
function _getTypeOfArray(arr) {
|
|
2088
|
+
if ((0, import_classPrivateFieldGet2$1.default)(_arrayTypeCache, this).has(arr)) return (0, import_classPrivateFieldGet2$1.default)(_arrayTypeCache, this).get(arr);
|
|
2089
|
+
const type$1 = (0, import_assertClassBrand.default)(_Dumper_brand, this, _doGetTypeOfArray).call(this, arr);
|
|
2090
|
+
(0, import_classPrivateFieldGet2$1.default)(_arrayTypeCache, this).set(arr, type$1);
|
|
2091
|
+
return type$1;
|
|
2092
|
+
}
|
|
2093
|
+
function _doGetTypeOfArray(arr) {
|
|
2094
|
+
if (!arr.length) return "ONLY_PRIMITIVE";
|
|
2095
|
+
const onlyPrimitive = (0, import_assertClassBrand.default)(_Dumper_brand, this, _isPrimitive).call(this, arr[0]);
|
|
2096
|
+
if (arr[0] instanceof Array) return "MIXED";
|
|
2097
|
+
for (let i = 1; i < arr.length; i++) if (onlyPrimitive !== (0, import_assertClassBrand.default)(_Dumper_brand, this, _isPrimitive).call(this, arr[i]) || arr[i] instanceof Array) return "MIXED";
|
|
2098
|
+
return onlyPrimitive ? "ONLY_PRIMITIVE" : "ONLY_OBJECT_EXCLUDING_ARRAY";
|
|
2099
|
+
}
|
|
2100
|
+
function _printAsInlineValue(value$1) {
|
|
2101
|
+
if (value$1 instanceof Date) return `"${(0, import_assertClassBrand.default)(_Dumper_brand, this, _printDate).call(this, value$1)}"`;
|
|
2102
|
+
else if (typeof value$1 === "string" || value$1 instanceof RegExp) return JSON.stringify(value$1.toString());
|
|
2103
|
+
else if (typeof value$1 === "number") return value$1;
|
|
2104
|
+
else if (typeof value$1 === "boolean") return value$1.toString();
|
|
2105
|
+
else if (value$1 instanceof Array) {
|
|
2106
|
+
const str = value$1.map((x) => (0, import_assertClassBrand.default)(_Dumper_brand, this, _printAsInlineValue).call(this, x)).join(",");
|
|
2107
|
+
return `[${str}]`;
|
|
2108
|
+
} else if (typeof value$1 === "object") {
|
|
2109
|
+
if (!value$1) throw new Error("Should never reach");
|
|
2110
|
+
const str = Object.keys(value$1).map((key) => {
|
|
2111
|
+
return `${joinKeys([key])} = ${(0, import_assertClassBrand.default)(_Dumper_brand, this, _printAsInlineValue).call(this, value$1[key])}`;
|
|
2112
|
+
}).join(",");
|
|
2113
|
+
return `{${str}}`;
|
|
2114
|
+
}
|
|
2115
|
+
throw new Error("Should never reach");
|
|
2116
|
+
}
|
|
2117
|
+
function _isSimplySerializable(value$1) {
|
|
2118
|
+
return typeof value$1 === "string" || typeof value$1 === "number" || typeof value$1 === "boolean" || value$1 instanceof RegExp || value$1 instanceof Date || value$1 instanceof Array && (0, import_assertClassBrand.default)(_Dumper_brand, this, _getTypeOfArray).call(this, value$1) !== "ONLY_OBJECT_EXCLUDING_ARRAY";
|
|
2119
|
+
}
|
|
2120
|
+
function _header(keys) {
|
|
2121
|
+
return `[${joinKeys(keys)}]`;
|
|
2122
|
+
}
|
|
2123
|
+
function _headerGroup(keys) {
|
|
2124
|
+
return `[[${joinKeys(keys)}]]`;
|
|
2125
|
+
}
|
|
2126
|
+
function _declaration(keys) {
|
|
2127
|
+
const title = joinKeys(keys);
|
|
2128
|
+
if (title.length > this.maxPad) this.maxPad = title.length;
|
|
2129
|
+
return `${title} = `;
|
|
2130
|
+
}
|
|
2131
|
+
function _arrayDeclaration(keys, value$1) {
|
|
2132
|
+
return `${(0, import_assertClassBrand.default)(_Dumper_brand, this, _declaration).call(this, keys)}${JSON.stringify(value$1)}`;
|
|
2133
|
+
}
|
|
2134
|
+
function _strDeclaration(keys, value$1) {
|
|
2135
|
+
return `${(0, import_assertClassBrand.default)(_Dumper_brand, this, _declaration).call(this, keys)}${JSON.stringify(value$1)}`;
|
|
2136
|
+
}
|
|
2137
|
+
function _numberDeclaration(keys, value$1) {
|
|
2138
|
+
if (Number.isNaN(value$1)) return `${(0, import_assertClassBrand.default)(_Dumper_brand, this, _declaration).call(this, keys)}nan`;
|
|
2139
|
+
switch (value$1) {
|
|
2140
|
+
case Infinity: return `${(0, import_assertClassBrand.default)(_Dumper_brand, this, _declaration).call(this, keys)}inf`;
|
|
2141
|
+
case -Infinity: return `${(0, import_assertClassBrand.default)(_Dumper_brand, this, _declaration).call(this, keys)}-inf`;
|
|
2142
|
+
default: return `${(0, import_assertClassBrand.default)(_Dumper_brand, this, _declaration).call(this, keys)}${value$1}`;
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
function _boolDeclaration(keys, value$1) {
|
|
2146
|
+
return `${(0, import_assertClassBrand.default)(_Dumper_brand, this, _declaration).call(this, keys)}${value$1}`;
|
|
2147
|
+
}
|
|
2148
|
+
function _printDate(value$1) {
|
|
2149
|
+
function dtPad(v, lPad = 2) {
|
|
2150
|
+
return v.padStart(lPad, "0");
|
|
2151
|
+
}
|
|
2152
|
+
const m = dtPad((value$1.getUTCMonth() + 1).toString());
|
|
2153
|
+
const d = dtPad(value$1.getUTCDate().toString());
|
|
2154
|
+
const h = dtPad(value$1.getUTCHours().toString());
|
|
2155
|
+
const min = dtPad(value$1.getUTCMinutes().toString());
|
|
2156
|
+
const s = dtPad(value$1.getUTCSeconds().toString());
|
|
2157
|
+
const ms = dtPad(value$1.getUTCMilliseconds().toString(), 3);
|
|
2158
|
+
const fData = `${value$1.getUTCFullYear()}-${m}-${d}T${h}:${min}:${s}.${ms}`;
|
|
2159
|
+
return fData;
|
|
2160
|
+
}
|
|
2161
|
+
function _dateDeclaration(keys, value$1) {
|
|
2162
|
+
return `${(0, import_assertClassBrand.default)(_Dumper_brand, this, _declaration).call(this, keys)}${(0, import_assertClassBrand.default)(_Dumper_brand, this, _printDate).call(this, value$1)}`;
|
|
2163
|
+
}
|
|
2164
|
+
function _format(options = {}) {
|
|
2165
|
+
const { keyAlignment = false } = options;
|
|
2166
|
+
const rDeclaration = /^(\".*\"|[^=]*)\s=/;
|
|
2167
|
+
const out = [];
|
|
2168
|
+
for (let i = 0; i < this.output.length; i++) {
|
|
2169
|
+
const l = this.output[i];
|
|
2170
|
+
if (l[0] === "[" && l[1] !== "[") {
|
|
2171
|
+
if (this.output[i + 1] === "" && this.output[i + 2]?.slice(0, l.length) === l.slice(0, -1) + ".") {
|
|
2172
|
+
i += 1;
|
|
2173
|
+
continue;
|
|
2174
|
+
}
|
|
2175
|
+
out.push(l);
|
|
2176
|
+
} else if (keyAlignment) {
|
|
2177
|
+
const m = rDeclaration.exec(l);
|
|
2178
|
+
if (m && m[1]) out.push(l.replace(m[1], m[1].padEnd(this.maxPad)));
|
|
2179
|
+
else out.push(l);
|
|
2180
|
+
} else out.push(l);
|
|
2181
|
+
}
|
|
2182
|
+
const cleanedOutput = [];
|
|
2183
|
+
for (let i = 0; i < out.length; i++) {
|
|
2184
|
+
const l = out[i];
|
|
2185
|
+
if (!(l === "" && out[i + 1] === "")) cleanedOutput.push(l);
|
|
2186
|
+
}
|
|
2187
|
+
return cleanedOutput;
|
|
2188
|
+
}
|
|
2189
|
+
/**
|
|
2190
|
+
* Converts an object to a {@link https://toml.io | TOML} string.
|
|
2191
|
+
*
|
|
2192
|
+
* @example Usage
|
|
2193
|
+
* ```ts
|
|
2194
|
+
* import { stringify } from "@std/toml/stringify";
|
|
2195
|
+
* import { assertEquals } from "@std/assert";
|
|
2196
|
+
*
|
|
2197
|
+
* const obj = {
|
|
2198
|
+
* title: "TOML Example",
|
|
2199
|
+
* owner: {
|
|
2200
|
+
* name: "Bob",
|
|
2201
|
+
* bio: "Bob is a cool guy",
|
|
2202
|
+
* }
|
|
2203
|
+
* };
|
|
2204
|
+
* const tomlString = stringify(obj);
|
|
2205
|
+
* assertEquals(tomlString, `title = "TOML Example"\n\n[owner]\nname = "Bob"\nbio = "Bob is a cool guy"\n`);
|
|
2206
|
+
* ```
|
|
2207
|
+
* @param obj Source object
|
|
2208
|
+
* @param options Options for stringifying.
|
|
2209
|
+
* @returns TOML string
|
|
2210
|
+
*/ function stringify(obj, options) {
|
|
2211
|
+
return new Dumper(obj).dump(options).join("\n");
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
//#endregion
|
|
2215
|
+
//#region ../node_modules/@jsr/std__collections/_utils.js
|
|
2216
|
+
/**
|
|
2217
|
+
* Filters the given array, removing all elements that do not match the given predicate
|
|
2218
|
+
* **in place. This means `array` will be modified!**.
|
|
2219
|
+
*/ function filterInPlace(array, predicate) {
|
|
2220
|
+
let outputIndex = 0;
|
|
2221
|
+
for (const cur of array) {
|
|
2222
|
+
if (!predicate(cur)) continue;
|
|
2223
|
+
array[outputIndex] = cur;
|
|
2224
|
+
outputIndex += 1;
|
|
2225
|
+
}
|
|
2226
|
+
array.splice(outputIndex);
|
|
2227
|
+
return array;
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
//#endregion
|
|
2231
|
+
//#region ../node_modules/@jsr/std__collections/deep_merge.js
|
|
2232
|
+
function deepMerge(record, other, options) {
|
|
2233
|
+
return deepMergeInternal(record, other, new Set(), options);
|
|
2234
|
+
}
|
|
2235
|
+
function deepMergeInternal(record, other, seen, options) {
|
|
2236
|
+
const result = {};
|
|
2237
|
+
const keys = new Set([...getKeys(record), ...getKeys(other)]);
|
|
2238
|
+
for (const key of keys) {
|
|
2239
|
+
if (key === "__proto__") continue;
|
|
2240
|
+
const a = record[key];
|
|
2241
|
+
if (!Object.hasOwn(other, key)) {
|
|
2242
|
+
result[key] = a;
|
|
2243
|
+
continue;
|
|
2244
|
+
}
|
|
2245
|
+
const b = other[key];
|
|
2246
|
+
if (isNonNullObject(a) && isNonNullObject(b) && !seen.has(a) && !seen.has(b)) {
|
|
2247
|
+
seen.add(a);
|
|
2248
|
+
seen.add(b);
|
|
2249
|
+
result[key] = mergeObjects(a, b, seen, options);
|
|
2250
|
+
continue;
|
|
2251
|
+
}
|
|
2252
|
+
result[key] = b;
|
|
2253
|
+
}
|
|
2254
|
+
return result;
|
|
2255
|
+
}
|
|
2256
|
+
function mergeObjects(left, right, seen, options = {
|
|
2257
|
+
arrays: "merge",
|
|
2258
|
+
sets: "merge",
|
|
2259
|
+
maps: "merge"
|
|
2260
|
+
}) {
|
|
2261
|
+
if (isMergeable(left) && isMergeable(right)) return deepMergeInternal(left, right, seen, options);
|
|
2262
|
+
if (isIterable(left) && isIterable(right)) {
|
|
2263
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
2264
|
+
if (options.arrays === "merge") return left.concat(right);
|
|
2265
|
+
return right;
|
|
2266
|
+
}
|
|
2267
|
+
if (left instanceof Map && right instanceof Map) {
|
|
2268
|
+
if (options.maps === "merge") return new Map([...left, ...right]);
|
|
2269
|
+
return right;
|
|
2270
|
+
}
|
|
2271
|
+
if (left instanceof Set && right instanceof Set) {
|
|
2272
|
+
if (options.sets === "merge") return new Set([...left, ...right]);
|
|
2273
|
+
return right;
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
return right;
|
|
2277
|
+
}
|
|
2278
|
+
/**
|
|
2279
|
+
* Test whether a value is mergeable or not
|
|
2280
|
+
* Builtins that look like objects, null and user defined classes
|
|
2281
|
+
* are not considered mergeable (it means that reference will be copied)
|
|
2282
|
+
*/ function isMergeable(value$1) {
|
|
2283
|
+
return Object.getPrototypeOf(value$1) === Object.prototype;
|
|
2284
|
+
}
|
|
2285
|
+
function isIterable(value$1) {
|
|
2286
|
+
return typeof value$1[Symbol.iterator] === "function";
|
|
2287
|
+
}
|
|
2288
|
+
function isNonNullObject(value$1) {
|
|
2289
|
+
return value$1 !== null && typeof value$1 === "object";
|
|
2290
|
+
}
|
|
2291
|
+
function getKeys(record) {
|
|
2292
|
+
const result = Object.getOwnPropertySymbols(record);
|
|
2293
|
+
filterInPlace(result, (key) => Object.prototype.propertyIsEnumerable.call(record, key));
|
|
2294
|
+
result.push(...Object.keys(record));
|
|
2295
|
+
return result;
|
|
2296
|
+
}
|
|
2297
|
+
|
|
2298
|
+
//#endregion
|
|
2299
|
+
//#region ../node_modules/@oxc-project/runtime/src/helpers/classPrivateFieldSet2.js
|
|
2300
|
+
var require_classPrivateFieldSet2 = __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/classPrivateFieldSet2.js"(exports, module) {
|
|
2301
|
+
var assertClassBrand = require_assertClassBrand();
|
|
2302
|
+
function _classPrivateFieldSet2(s, a, r) {
|
|
2303
|
+
return s.set(assertClassBrand(s, a), r), r;
|
|
2304
|
+
}
|
|
2305
|
+
module.exports = _classPrivateFieldSet2, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
2306
|
+
} });
|
|
2307
|
+
|
|
2308
|
+
//#endregion
|
|
2309
|
+
//#region ../node_modules/@std/toml/_parser.js
|
|
2310
|
+
var import_classPrivateFieldInitSpec = __toESM(require_classPrivateFieldInitSpec(), 1);
|
|
2311
|
+
var import_classPrivateFieldSet2 = __toESM(require_classPrivateFieldSet2(), 1);
|
|
2312
|
+
var import_classPrivateFieldGet2 = __toESM(require_classPrivateFieldGet2(), 1);
|
|
2313
|
+
/**
|
|
2314
|
+
* Copy of `import { isLeap } from "@std/datetime";` because it cannot be impoted as long as it is unstable.
|
|
2315
|
+
*/ function isLeap(yearNumber) {
|
|
2316
|
+
return yearNumber % 4 === 0 && yearNumber % 100 !== 0 || yearNumber % 400 === 0;
|
|
2317
|
+
}
|
|
2318
|
+
var _whitespace = /* @__PURE__ */ new WeakMap();
|
|
2319
|
+
var _position = /* @__PURE__ */ new WeakMap();
|
|
2320
|
+
var _source = /* @__PURE__ */ new WeakMap();
|
|
2321
|
+
var Scanner = class {
|
|
2322
|
+
constructor(source) {
|
|
2323
|
+
(0, import_classPrivateFieldInitSpec.default)(this, _whitespace, /[ \t]/);
|
|
2324
|
+
(0, import_classPrivateFieldInitSpec.default)(this, _position, 0);
|
|
2325
|
+
(0, import_classPrivateFieldInitSpec.default)(this, _source, void 0);
|
|
2326
|
+
(0, import_classPrivateFieldSet2.default)(_source, this, source);
|
|
2327
|
+
}
|
|
2328
|
+
get position() {
|
|
2329
|
+
return (0, import_classPrivateFieldGet2.default)(_position, this);
|
|
2330
|
+
}
|
|
2331
|
+
get source() {
|
|
2332
|
+
return (0, import_classPrivateFieldGet2.default)(_source, this);
|
|
2333
|
+
}
|
|
2334
|
+
/**
|
|
2335
|
+
* Get current character
|
|
2336
|
+
* @param index - relative index from current position
|
|
2337
|
+
*/ char(index = 0) {
|
|
2338
|
+
return (0, import_classPrivateFieldGet2.default)(_source, this)[(0, import_classPrivateFieldGet2.default)(_position, this) + index] ?? "";
|
|
2339
|
+
}
|
|
2340
|
+
/**
|
|
2341
|
+
* Get sliced string
|
|
2342
|
+
* @param start - start position relative from current position
|
|
2343
|
+
* @param end - end position relative from current position
|
|
2344
|
+
*/ slice(start, end) {
|
|
2345
|
+
return (0, import_classPrivateFieldGet2.default)(_source, this).slice((0, import_classPrivateFieldGet2.default)(_position, this) + start, (0, import_classPrivateFieldGet2.default)(_position, this) + end);
|
|
2346
|
+
}
|
|
2347
|
+
/**
|
|
2348
|
+
* Move position to next
|
|
2349
|
+
*/ next(count = 1) {
|
|
2350
|
+
(0, import_classPrivateFieldSet2.default)(_position, this, (0, import_classPrivateFieldGet2.default)(_position, this) + count);
|
|
2351
|
+
}
|
|
2352
|
+
skipWhitespaces() {
|
|
2353
|
+
while ((0, import_classPrivateFieldGet2.default)(_whitespace, this).test(this.char()) && !this.eof()) this.next();
|
|
2354
|
+
if (!this.isCurrentCharEOL() && /\s/.test(this.char())) {
|
|
2355
|
+
const escaped = "\\u" + this.char().charCodeAt(0).toString(16);
|
|
2356
|
+
const position = (0, import_classPrivateFieldGet2.default)(_position, this);
|
|
2357
|
+
throw new SyntaxError(`Cannot parse the TOML: It contains invalid whitespace at position '${position}': \`${escaped}\``);
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
nextUntilChar(options = { skipComments: true }) {
|
|
2361
|
+
while (!this.eof()) {
|
|
2362
|
+
const char = this.char();
|
|
2363
|
+
if ((0, import_classPrivateFieldGet2.default)(_whitespace, this).test(char) || this.isCurrentCharEOL()) this.next();
|
|
2364
|
+
else if (options.skipComments && this.char() === "#") while (!this.isCurrentCharEOL() && !this.eof()) this.next();
|
|
2365
|
+
else break;
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
/**
|
|
2369
|
+
* Position reached EOF or not
|
|
2370
|
+
*/ eof() {
|
|
2371
|
+
return (0, import_classPrivateFieldGet2.default)(_position, this) >= (0, import_classPrivateFieldGet2.default)(_source, this).length;
|
|
2372
|
+
}
|
|
2373
|
+
isCurrentCharEOL() {
|
|
2374
|
+
return this.char() === "\n" || this.startsWith("\r\n");
|
|
2375
|
+
}
|
|
2376
|
+
startsWith(searchString) {
|
|
2377
|
+
return (0, import_classPrivateFieldGet2.default)(_source, this).startsWith(searchString, (0, import_classPrivateFieldGet2.default)(_position, this));
|
|
2378
|
+
}
|
|
2379
|
+
match(regExp) {
|
|
2380
|
+
if (!regExp.sticky) throw new Error(`RegExp ${regExp} does not have a sticky 'y' flag`);
|
|
2381
|
+
regExp.lastIndex = (0, import_classPrivateFieldGet2.default)(_position, this);
|
|
2382
|
+
return (0, import_classPrivateFieldGet2.default)(_source, this).match(regExp);
|
|
2383
|
+
}
|
|
2384
|
+
};
|
|
2385
|
+
function success(body) {
|
|
2386
|
+
return {
|
|
2387
|
+
ok: true,
|
|
2388
|
+
body
|
|
2389
|
+
};
|
|
2390
|
+
}
|
|
2391
|
+
function failure() {
|
|
2392
|
+
return { ok: false };
|
|
2393
|
+
}
|
|
2394
|
+
/**
|
|
2395
|
+
* Creates a nested object from the keys and values.
|
|
2396
|
+
*
|
|
2397
|
+
* e.g. `unflat(["a", "b", "c"], 1)` returns `{ a: { b: { c: 1 } } }`
|
|
2398
|
+
*/ function unflat(keys, values = {}) {
|
|
2399
|
+
return keys.reduceRight((acc, key) => ({ [key]: acc }), values);
|
|
2400
|
+
}
|
|
2401
|
+
function isObject(value$1) {
|
|
2402
|
+
return typeof value$1 === "object" && value$1 !== null;
|
|
2403
|
+
}
|
|
2404
|
+
function getTargetValue(target, keys) {
|
|
2405
|
+
const key = keys[0];
|
|
2406
|
+
if (!key) throw new Error("Cannot parse the TOML: key length is not a positive number");
|
|
2407
|
+
return target[key];
|
|
2408
|
+
}
|
|
2409
|
+
function deepAssignTable(target, table$1) {
|
|
2410
|
+
const { keys, type: type$1, value: value$1 } = table$1;
|
|
2411
|
+
const currentValue = getTargetValue(target, keys);
|
|
2412
|
+
if (currentValue === void 0) return Object.assign(target, unflat(keys, value$1));
|
|
2413
|
+
if (Array.isArray(currentValue)) {
|
|
2414
|
+
const last = currentValue.at(-1);
|
|
2415
|
+
deepAssign(last, {
|
|
2416
|
+
type: type$1,
|
|
2417
|
+
keys: keys.slice(1),
|
|
2418
|
+
value: value$1
|
|
2419
|
+
});
|
|
2420
|
+
return target;
|
|
2421
|
+
}
|
|
2422
|
+
if (isObject(currentValue)) {
|
|
2423
|
+
deepAssign(currentValue, {
|
|
2424
|
+
type: type$1,
|
|
2425
|
+
keys: keys.slice(1),
|
|
2426
|
+
value: value$1
|
|
2427
|
+
});
|
|
2428
|
+
return target;
|
|
2429
|
+
}
|
|
2430
|
+
throw new Error("Unexpected assign");
|
|
2431
|
+
}
|
|
2432
|
+
function deepAssignTableArray(target, table$1) {
|
|
2433
|
+
const { type: type$1, keys, value: value$1 } = table$1;
|
|
2434
|
+
const currentValue = getTargetValue(target, keys);
|
|
2435
|
+
if (currentValue === void 0) return Object.assign(target, unflat(keys, [value$1]));
|
|
2436
|
+
if (Array.isArray(currentValue)) {
|
|
2437
|
+
currentValue.push(value$1);
|
|
2438
|
+
return target;
|
|
2439
|
+
}
|
|
2440
|
+
if (isObject(currentValue)) {
|
|
2441
|
+
deepAssign(currentValue, {
|
|
2442
|
+
type: type$1,
|
|
2443
|
+
keys: keys.slice(1),
|
|
2444
|
+
value: value$1
|
|
2445
|
+
});
|
|
2446
|
+
return target;
|
|
2447
|
+
}
|
|
2448
|
+
throw new Error("Unexpected assign");
|
|
2449
|
+
}
|
|
2450
|
+
function deepAssign(target, body) {
|
|
2451
|
+
switch (body.type) {
|
|
2452
|
+
case "Block": return deepMerge(target, body.value);
|
|
2453
|
+
case "Table": return deepAssignTable(target, body);
|
|
2454
|
+
case "TableArray": return deepAssignTableArray(target, body);
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
function or(parsers) {
|
|
2458
|
+
return (scanner) => {
|
|
2459
|
+
for (const parse$3 of parsers) {
|
|
2460
|
+
const result = parse$3(scanner);
|
|
2461
|
+
if (result.ok) return result;
|
|
2462
|
+
}
|
|
2463
|
+
return failure();
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2466
|
+
/** Join the parse results of the given parser into an array.
|
|
2467
|
+
*
|
|
2468
|
+
* If the parser fails at the first attempt, it will return an empty array.
|
|
2469
|
+
*/ function join$1(parser, separator) {
|
|
2470
|
+
const Separator = character(separator);
|
|
2471
|
+
return (scanner) => {
|
|
2472
|
+
const out = [];
|
|
2473
|
+
const first = parser(scanner);
|
|
2474
|
+
if (!first.ok) return success(out);
|
|
2475
|
+
out.push(first.body);
|
|
2476
|
+
while (!scanner.eof()) {
|
|
2477
|
+
if (!Separator(scanner).ok) break;
|
|
2478
|
+
const result = parser(scanner);
|
|
2479
|
+
if (!result.ok) throw new SyntaxError(`Invalid token after "${separator}"`);
|
|
2480
|
+
out.push(result.body);
|
|
2481
|
+
}
|
|
2482
|
+
return success(out);
|
|
2483
|
+
};
|
|
2484
|
+
}
|
|
2485
|
+
/** Join the parse results of the given parser into an array.
|
|
2486
|
+
*
|
|
2487
|
+
* This requires the parser to succeed at least once.
|
|
2488
|
+
*/ function join1(parser, separator) {
|
|
2489
|
+
const Separator = character(separator);
|
|
2490
|
+
return (scanner) => {
|
|
2491
|
+
const first = parser(scanner);
|
|
2492
|
+
if (!first.ok) return failure();
|
|
2493
|
+
const out = [first.body];
|
|
2494
|
+
while (!scanner.eof()) {
|
|
2495
|
+
if (!Separator(scanner).ok) break;
|
|
2496
|
+
const result = parser(scanner);
|
|
2497
|
+
if (!result.ok) throw new SyntaxError(`Invalid token after "${separator}"`);
|
|
2498
|
+
out.push(result.body);
|
|
2499
|
+
}
|
|
2500
|
+
return success(out);
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2503
|
+
function kv(keyParser, separator, valueParser) {
|
|
2504
|
+
const Separator = character(separator);
|
|
2505
|
+
return (scanner) => {
|
|
2506
|
+
const position = scanner.position;
|
|
2507
|
+
const key = keyParser(scanner);
|
|
2508
|
+
if (!key.ok) return failure();
|
|
2509
|
+
const sep = Separator(scanner);
|
|
2510
|
+
if (!sep.ok) throw new SyntaxError(`key/value pair doesn't have "${separator}"`);
|
|
2511
|
+
const value$1 = valueParser(scanner);
|
|
2512
|
+
if (!value$1.ok) {
|
|
2513
|
+
const lineEndIndex = scanner.source.indexOf("\n", scanner.position);
|
|
2514
|
+
const endPosition = lineEndIndex > 0 ? lineEndIndex : scanner.source.length;
|
|
2515
|
+
const line = scanner.source.slice(position, endPosition);
|
|
2516
|
+
throw new SyntaxError(`Cannot parse value on line '${line}'`);
|
|
2517
|
+
}
|
|
2518
|
+
return success(unflat(key.body, value$1.body));
|
|
2519
|
+
};
|
|
2520
|
+
}
|
|
2521
|
+
function merge$1(parser) {
|
|
2522
|
+
return (scanner) => {
|
|
2523
|
+
const result = parser(scanner);
|
|
2524
|
+
if (!result.ok) return failure();
|
|
2525
|
+
let body = {};
|
|
2526
|
+
for (const record of result.body) if (typeof record === "object" && record !== null) body = deepMerge(body, record);
|
|
2527
|
+
return success(body);
|
|
2528
|
+
};
|
|
2529
|
+
}
|
|
2530
|
+
function repeat(parser) {
|
|
2531
|
+
return (scanner) => {
|
|
2532
|
+
const body = [];
|
|
2533
|
+
while (!scanner.eof()) {
|
|
2534
|
+
const result = parser(scanner);
|
|
2535
|
+
if (!result.ok) break;
|
|
2536
|
+
body.push(result.body);
|
|
2537
|
+
scanner.nextUntilChar();
|
|
2538
|
+
}
|
|
2539
|
+
if (body.length === 0) return failure();
|
|
2540
|
+
return success(body);
|
|
2541
|
+
};
|
|
2542
|
+
}
|
|
2543
|
+
function surround(left, parser, right) {
|
|
2544
|
+
const Left = character(left);
|
|
2545
|
+
const Right = character(right);
|
|
2546
|
+
return (scanner) => {
|
|
2547
|
+
if (!Left(scanner).ok) return failure();
|
|
2548
|
+
const result = parser(scanner);
|
|
2549
|
+
if (!result.ok) throw new SyntaxError(`Invalid token after "${left}"`);
|
|
2550
|
+
if (!Right(scanner).ok) throw new SyntaxError(`Not closed by "${right}" after started with "${left}"`);
|
|
2551
|
+
return success(result.body);
|
|
2552
|
+
};
|
|
2553
|
+
}
|
|
2554
|
+
function character(str) {
|
|
2555
|
+
return (scanner) => {
|
|
2556
|
+
scanner.skipWhitespaces();
|
|
2557
|
+
if (!scanner.startsWith(str)) return failure();
|
|
2558
|
+
scanner.next(str.length);
|
|
2559
|
+
scanner.skipWhitespaces();
|
|
2560
|
+
return success(void 0);
|
|
2561
|
+
};
|
|
2562
|
+
}
|
|
2563
|
+
const BARE_KEY_REGEXP = /[A-Za-z0-9_-]+/y;
|
|
2564
|
+
function bareKey(scanner) {
|
|
2565
|
+
scanner.skipWhitespaces();
|
|
2566
|
+
const key = scanner.match(BARE_KEY_REGEXP)?.[0];
|
|
2567
|
+
if (!key) return failure();
|
|
2568
|
+
scanner.next(key.length);
|
|
2569
|
+
return success(key);
|
|
2570
|
+
}
|
|
2571
|
+
function escapeSequence(scanner) {
|
|
2572
|
+
if (scanner.char() !== "\\") return failure();
|
|
2573
|
+
scanner.next();
|
|
2574
|
+
switch (scanner.char()) {
|
|
2575
|
+
case "b":
|
|
2576
|
+
scanner.next();
|
|
2577
|
+
return success("\b");
|
|
2578
|
+
case "t":
|
|
2579
|
+
scanner.next();
|
|
2580
|
+
return success(" ");
|
|
2581
|
+
case "n":
|
|
2582
|
+
scanner.next();
|
|
2583
|
+
return success("\n");
|
|
2584
|
+
case "f":
|
|
2585
|
+
scanner.next();
|
|
2586
|
+
return success("\f");
|
|
2587
|
+
case "r":
|
|
2588
|
+
scanner.next();
|
|
2589
|
+
return success("\r");
|
|
2590
|
+
case "u":
|
|
2591
|
+
case "U": {
|
|
2592
|
+
const codePointLen = scanner.char() === "u" ? 4 : 6;
|
|
2593
|
+
const codePoint = parseInt("0x" + scanner.slice(1, 1 + codePointLen), 16);
|
|
2594
|
+
const str = String.fromCodePoint(codePoint);
|
|
2595
|
+
scanner.next(codePointLen + 1);
|
|
2596
|
+
return success(str);
|
|
2597
|
+
}
|
|
2598
|
+
case "\"":
|
|
2599
|
+
scanner.next();
|
|
2600
|
+
return success("\"");
|
|
2601
|
+
case "\\":
|
|
2602
|
+
scanner.next();
|
|
2603
|
+
return success("\\");
|
|
2604
|
+
default: throw new SyntaxError(`Invalid escape sequence: \\${scanner.char()}`);
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
function basicString(scanner) {
|
|
2608
|
+
scanner.skipWhitespaces();
|
|
2609
|
+
if (scanner.char() !== "\"") return failure();
|
|
2610
|
+
scanner.next();
|
|
2611
|
+
const acc = [];
|
|
2612
|
+
while (scanner.char() !== "\"" && !scanner.eof()) {
|
|
2613
|
+
if (scanner.char() === "\n") throw new SyntaxError("Single-line string cannot contain EOL");
|
|
2614
|
+
const escapedChar = escapeSequence(scanner);
|
|
2615
|
+
if (escapedChar.ok) acc.push(escapedChar.body);
|
|
2616
|
+
else {
|
|
2617
|
+
acc.push(scanner.char());
|
|
2618
|
+
scanner.next();
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
if (scanner.eof()) throw new SyntaxError(`Single-line string is not closed:\n${acc.join("")}`);
|
|
2622
|
+
scanner.next();
|
|
2623
|
+
return success(acc.join(""));
|
|
2624
|
+
}
|
|
2625
|
+
function literalString(scanner) {
|
|
2626
|
+
scanner.skipWhitespaces();
|
|
2627
|
+
if (scanner.char() !== "'") return failure();
|
|
2628
|
+
scanner.next();
|
|
2629
|
+
const acc = [];
|
|
2630
|
+
while (scanner.char() !== "'" && !scanner.eof()) {
|
|
2631
|
+
if (scanner.char() === "\n") throw new SyntaxError("Single-line string cannot contain EOL");
|
|
2632
|
+
acc.push(scanner.char());
|
|
2633
|
+
scanner.next();
|
|
2634
|
+
}
|
|
2635
|
+
if (scanner.eof()) throw new SyntaxError(`Single-line string is not closed:\n${acc.join("")}`);
|
|
2636
|
+
scanner.next();
|
|
2637
|
+
return success(acc.join(""));
|
|
2638
|
+
}
|
|
2639
|
+
function multilineBasicString(scanner) {
|
|
2640
|
+
scanner.skipWhitespaces();
|
|
2641
|
+
if (!scanner.startsWith("\"\"\"")) return failure();
|
|
2642
|
+
scanner.next(3);
|
|
2643
|
+
if (scanner.char() === "\n") scanner.next();
|
|
2644
|
+
else if (scanner.startsWith("\r\n")) scanner.next(2);
|
|
2645
|
+
const acc = [];
|
|
2646
|
+
while (!scanner.startsWith("\"\"\"") && !scanner.eof()) {
|
|
2647
|
+
if (scanner.startsWith("\\\n")) {
|
|
2648
|
+
scanner.next();
|
|
2649
|
+
scanner.nextUntilChar({ skipComments: false });
|
|
2650
|
+
continue;
|
|
2651
|
+
} else if (scanner.startsWith("\\\r\n")) {
|
|
2652
|
+
scanner.next();
|
|
2653
|
+
scanner.nextUntilChar({ skipComments: false });
|
|
2654
|
+
continue;
|
|
2655
|
+
}
|
|
2656
|
+
const escapedChar = escapeSequence(scanner);
|
|
2657
|
+
if (escapedChar.ok) acc.push(escapedChar.body);
|
|
2658
|
+
else {
|
|
2659
|
+
acc.push(scanner.char());
|
|
2660
|
+
scanner.next();
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
if (scanner.eof()) throw new SyntaxError(`Multi-line string is not closed:\n${acc.join("")}`);
|
|
2664
|
+
if (scanner.char(3) === "\"") {
|
|
2665
|
+
acc.push("\"");
|
|
2666
|
+
scanner.next();
|
|
2667
|
+
}
|
|
2668
|
+
scanner.next(3);
|
|
2669
|
+
return success(acc.join(""));
|
|
2670
|
+
}
|
|
2671
|
+
function multilineLiteralString(scanner) {
|
|
2672
|
+
scanner.skipWhitespaces();
|
|
2673
|
+
if (!scanner.startsWith("'''")) return failure();
|
|
2674
|
+
scanner.next(3);
|
|
2675
|
+
if (scanner.char() === "\n") scanner.next();
|
|
2676
|
+
else if (scanner.startsWith("\r\n")) scanner.next(2);
|
|
2677
|
+
const acc = [];
|
|
2678
|
+
while (!scanner.startsWith("'''") && !scanner.eof()) {
|
|
2679
|
+
acc.push(scanner.char());
|
|
2680
|
+
scanner.next();
|
|
2681
|
+
}
|
|
2682
|
+
if (scanner.eof()) throw new SyntaxError(`Multi-line string is not closed:\n${acc.join("")}`);
|
|
2683
|
+
if (scanner.char(3) === "'") {
|
|
2684
|
+
acc.push("'");
|
|
2685
|
+
scanner.next();
|
|
2686
|
+
}
|
|
2687
|
+
scanner.next(3);
|
|
2688
|
+
return success(acc.join(""));
|
|
2689
|
+
}
|
|
2690
|
+
const BOOLEAN_REGEXP = /(?:true|false)\b/y;
|
|
2691
|
+
function boolean(scanner) {
|
|
2692
|
+
scanner.skipWhitespaces();
|
|
2693
|
+
const match = scanner.match(BOOLEAN_REGEXP);
|
|
2694
|
+
if (!match) return failure();
|
|
2695
|
+
const string = match[0];
|
|
2696
|
+
scanner.next(string.length);
|
|
2697
|
+
const value$1 = string === "true";
|
|
2698
|
+
return success(value$1);
|
|
2699
|
+
}
|
|
2700
|
+
const INFINITY_MAP = new Map([
|
|
2701
|
+
["inf", Infinity],
|
|
2702
|
+
["+inf", Infinity],
|
|
2703
|
+
["-inf", -Infinity]
|
|
2704
|
+
]);
|
|
2705
|
+
const INFINITY_REGEXP = /[+-]?inf\b/y;
|
|
2706
|
+
function infinity(scanner) {
|
|
2707
|
+
scanner.skipWhitespaces();
|
|
2708
|
+
const match = scanner.match(INFINITY_REGEXP);
|
|
2709
|
+
if (!match) return failure();
|
|
2710
|
+
const string = match[0];
|
|
2711
|
+
scanner.next(string.length);
|
|
2712
|
+
const value$1 = INFINITY_MAP.get(string);
|
|
2713
|
+
return success(value$1);
|
|
2714
|
+
}
|
|
2715
|
+
const NAN_REGEXP = /[+-]?nan\b/y;
|
|
2716
|
+
function nan(scanner) {
|
|
2717
|
+
scanner.skipWhitespaces();
|
|
2718
|
+
const match = scanner.match(NAN_REGEXP);
|
|
2719
|
+
if (!match) return failure();
|
|
2720
|
+
const string = match[0];
|
|
2721
|
+
scanner.next(string.length);
|
|
2722
|
+
const value$1 = NaN;
|
|
2723
|
+
return success(value$1);
|
|
2724
|
+
}
|
|
2725
|
+
const dottedKey = join1(or([
|
|
2726
|
+
bareKey,
|
|
2727
|
+
basicString,
|
|
2728
|
+
literalString
|
|
2729
|
+
]), ".");
|
|
2730
|
+
const BINARY_REGEXP = /0b[01]+(?:_[01]+)*\b/y;
|
|
2731
|
+
function binary(scanner) {
|
|
2732
|
+
scanner.skipWhitespaces();
|
|
2733
|
+
const match = scanner.match(BINARY_REGEXP)?.[0];
|
|
2734
|
+
if (!match) return failure();
|
|
2735
|
+
scanner.next(match.length);
|
|
2736
|
+
const value$1 = match.slice(2).replaceAll("_", "");
|
|
2737
|
+
const number = parseInt(value$1, 2);
|
|
2738
|
+
return isNaN(number) ? failure() : success(number);
|
|
2739
|
+
}
|
|
2740
|
+
const OCTAL_REGEXP = /0o[0-7]+(?:_[0-7]+)*\b/y;
|
|
2741
|
+
function octal(scanner) {
|
|
2742
|
+
scanner.skipWhitespaces();
|
|
2743
|
+
const match = scanner.match(OCTAL_REGEXP)?.[0];
|
|
2744
|
+
if (!match) return failure();
|
|
2745
|
+
scanner.next(match.length);
|
|
2746
|
+
const value$1 = match.slice(2).replaceAll("_", "");
|
|
2747
|
+
const number = parseInt(value$1, 8);
|
|
2748
|
+
return isNaN(number) ? failure() : success(number);
|
|
2749
|
+
}
|
|
2750
|
+
const HEX_REGEXP = /0x[0-9a-f]+(?:_[0-9a-f]+)*\b/iy;
|
|
2751
|
+
function hex(scanner) {
|
|
2752
|
+
scanner.skipWhitespaces();
|
|
2753
|
+
const match = scanner.match(HEX_REGEXP)?.[0];
|
|
2754
|
+
if (!match) return failure();
|
|
2755
|
+
scanner.next(match.length);
|
|
2756
|
+
const value$1 = match.slice(2).replaceAll("_", "");
|
|
2757
|
+
const number = parseInt(value$1, 16);
|
|
2758
|
+
return isNaN(number) ? failure() : success(number);
|
|
2759
|
+
}
|
|
2760
|
+
const INTEGER_REGEXP = /[+-]?(?:0|[1-9][0-9]*(?:_[0-9]+)*)\b/y;
|
|
2761
|
+
function integer(scanner) {
|
|
2762
|
+
scanner.skipWhitespaces();
|
|
2763
|
+
const match = scanner.match(INTEGER_REGEXP)?.[0];
|
|
2764
|
+
if (!match) return failure();
|
|
2765
|
+
scanner.next(match.length);
|
|
2766
|
+
const value$1 = match.replaceAll("_", "");
|
|
2767
|
+
const int = parseInt(value$1, 10);
|
|
2768
|
+
return success(int);
|
|
2769
|
+
}
|
|
2770
|
+
const FLOAT_REGEXP = /[+-]?(?:0|[1-9][0-9]*(?:_[0-9]+)*)(?:\.[0-9]+(?:_[0-9]+)*)?(?:e[+-]?[0-9]+(?:_[0-9]+)*)?\b/iy;
|
|
2771
|
+
function float(scanner) {
|
|
2772
|
+
scanner.skipWhitespaces();
|
|
2773
|
+
const match = scanner.match(FLOAT_REGEXP)?.[0];
|
|
2774
|
+
if (!match) return failure();
|
|
2775
|
+
scanner.next(match.length);
|
|
2776
|
+
const value$1 = match.replaceAll("_", "");
|
|
2777
|
+
const float$1 = parseFloat(value$1);
|
|
2778
|
+
if (isNaN(float$1)) return failure();
|
|
2779
|
+
return success(float$1);
|
|
2780
|
+
}
|
|
2781
|
+
const DATE_TIME_REGEXP = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})(?:[ 0-9TZ.:+-]+)?\b/y;
|
|
2782
|
+
function dateTime(scanner) {
|
|
2783
|
+
scanner.skipWhitespaces();
|
|
2784
|
+
const match = scanner.match(DATE_TIME_REGEXP);
|
|
2785
|
+
if (!match) return failure();
|
|
2786
|
+
const string = match[0];
|
|
2787
|
+
scanner.next(string.length);
|
|
2788
|
+
const groups = match.groups;
|
|
2789
|
+
if (groups.month == "02") {
|
|
2790
|
+
const days = parseInt(groups.day);
|
|
2791
|
+
if (days > 29) throw new SyntaxError(`Invalid date string "${match}"`);
|
|
2792
|
+
const year = parseInt(groups.year);
|
|
2793
|
+
if (days > 28 && !isLeap(year)) throw new SyntaxError(`Invalid date string "${match}"`);
|
|
2794
|
+
}
|
|
2795
|
+
const date = new Date(string.trim());
|
|
2796
|
+
if (isNaN(date.getTime())) throw new SyntaxError(`Invalid date string "${match}"`);
|
|
2797
|
+
return success(date);
|
|
2798
|
+
}
|
|
2799
|
+
const LOCAL_TIME_REGEXP = /(\d{2}):(\d{2}):(\d{2})(?:\.[0-9]+)?\b/y;
|
|
2800
|
+
function localTime(scanner) {
|
|
2801
|
+
scanner.skipWhitespaces();
|
|
2802
|
+
const match = scanner.match(LOCAL_TIME_REGEXP)?.[0];
|
|
2803
|
+
if (!match) return failure();
|
|
2804
|
+
scanner.next(match.length);
|
|
2805
|
+
return success(match);
|
|
2806
|
+
}
|
|
2807
|
+
function arrayValue(scanner) {
|
|
2808
|
+
scanner.skipWhitespaces();
|
|
2809
|
+
if (scanner.char() !== "[") return failure();
|
|
2810
|
+
scanner.next();
|
|
2811
|
+
const array = [];
|
|
2812
|
+
while (!scanner.eof()) {
|
|
2813
|
+
scanner.nextUntilChar();
|
|
2814
|
+
const result = value(scanner);
|
|
2815
|
+
if (!result.ok) break;
|
|
2816
|
+
array.push(result.body);
|
|
2817
|
+
scanner.skipWhitespaces();
|
|
2818
|
+
if (scanner.char() !== ",") break;
|
|
2819
|
+
scanner.next();
|
|
2820
|
+
}
|
|
2821
|
+
scanner.nextUntilChar();
|
|
2822
|
+
if (scanner.char() !== "]") throw new SyntaxError("Array is not closed");
|
|
2823
|
+
scanner.next();
|
|
2824
|
+
return success(array);
|
|
2825
|
+
}
|
|
2826
|
+
function inlineTable(scanner) {
|
|
2827
|
+
scanner.nextUntilChar();
|
|
2828
|
+
if (scanner.char(1) === "}") {
|
|
2829
|
+
scanner.next(2);
|
|
2830
|
+
return success({});
|
|
2831
|
+
}
|
|
2832
|
+
const pairs = surround("{", join$1(pair, ","), "}")(scanner);
|
|
2833
|
+
if (!pairs.ok) return failure();
|
|
2834
|
+
let table$1 = {};
|
|
2835
|
+
for (const pair$1 of pairs.body) table$1 = deepMerge(table$1, pair$1);
|
|
2836
|
+
return success(table$1);
|
|
2837
|
+
}
|
|
2838
|
+
const value = or([
|
|
2839
|
+
multilineBasicString,
|
|
2840
|
+
multilineLiteralString,
|
|
2841
|
+
basicString,
|
|
2842
|
+
literalString,
|
|
2843
|
+
boolean,
|
|
2844
|
+
infinity,
|
|
2845
|
+
nan,
|
|
2846
|
+
dateTime,
|
|
2847
|
+
localTime,
|
|
2848
|
+
binary,
|
|
2849
|
+
octal,
|
|
2850
|
+
hex,
|
|
2851
|
+
float,
|
|
2852
|
+
integer,
|
|
2853
|
+
arrayValue,
|
|
2854
|
+
inlineTable
|
|
2855
|
+
]);
|
|
2856
|
+
const pair = kv(dottedKey, "=", value);
|
|
2857
|
+
function block(scanner) {
|
|
2858
|
+
scanner.nextUntilChar();
|
|
2859
|
+
const result = merge$1(repeat(pair))(scanner);
|
|
2860
|
+
if (result.ok) return success({
|
|
2861
|
+
type: "Block",
|
|
2862
|
+
value: result.body
|
|
2863
|
+
});
|
|
2864
|
+
return failure();
|
|
2865
|
+
}
|
|
2866
|
+
const tableHeader = surround("[", dottedKey, "]");
|
|
2867
|
+
function table(scanner) {
|
|
2868
|
+
scanner.nextUntilChar();
|
|
2869
|
+
const header = tableHeader(scanner);
|
|
2870
|
+
if (!header.ok) return failure();
|
|
2871
|
+
scanner.nextUntilChar();
|
|
2872
|
+
const b = block(scanner);
|
|
2873
|
+
return success({
|
|
2874
|
+
type: "Table",
|
|
2875
|
+
keys: header.body,
|
|
2876
|
+
value: b.ok ? b.body.value : {}
|
|
2877
|
+
});
|
|
2878
|
+
}
|
|
2879
|
+
const tableArrayHeader = surround("[[", dottedKey, "]]");
|
|
2880
|
+
function tableArray(scanner) {
|
|
2881
|
+
scanner.nextUntilChar();
|
|
2882
|
+
const header = tableArrayHeader(scanner);
|
|
2883
|
+
if (!header.ok) return failure();
|
|
2884
|
+
scanner.nextUntilChar();
|
|
2885
|
+
const b = block(scanner);
|
|
2886
|
+
return success({
|
|
2887
|
+
type: "TableArray",
|
|
2888
|
+
keys: header.body,
|
|
2889
|
+
value: b.ok ? b.body.value : {}
|
|
2890
|
+
});
|
|
2891
|
+
}
|
|
2892
|
+
function toml(scanner) {
|
|
2893
|
+
const blocks = repeat(or([
|
|
2894
|
+
block,
|
|
2895
|
+
tableArray,
|
|
2896
|
+
table
|
|
2897
|
+
]))(scanner);
|
|
2898
|
+
if (!blocks.ok) return success({});
|
|
2899
|
+
const body = blocks.body.reduce(deepAssign, {});
|
|
2900
|
+
return success(body);
|
|
2901
|
+
}
|
|
2902
|
+
function createParseErrorMessage(scanner, message) {
|
|
2903
|
+
const string = scanner.source.slice(0, scanner.position);
|
|
2904
|
+
const lines = string.split("\n");
|
|
2905
|
+
const row = lines.length;
|
|
2906
|
+
const column = lines.at(-1)?.length ?? 0;
|
|
2907
|
+
return `Parse error on line ${row}, column ${column}: ${message}`;
|
|
2908
|
+
}
|
|
2909
|
+
function parserFactory(parser) {
|
|
2910
|
+
return (tomlString) => {
|
|
2911
|
+
const scanner = new Scanner(tomlString);
|
|
2912
|
+
try {
|
|
2913
|
+
const result = parser(scanner);
|
|
2914
|
+
if (result.ok && scanner.eof()) return result.body;
|
|
2915
|
+
const message = `Unexpected character: "${scanner.char()}"`;
|
|
2916
|
+
throw new SyntaxError(createParseErrorMessage(scanner, message));
|
|
2917
|
+
} catch (error) {
|
|
2918
|
+
if (error instanceof Error) throw new SyntaxError(createParseErrorMessage(scanner, error.message));
|
|
2919
|
+
const message = "Invalid error type caught";
|
|
2920
|
+
throw new SyntaxError(createParseErrorMessage(scanner, message));
|
|
2921
|
+
}
|
|
2922
|
+
};
|
|
2923
|
+
}
|
|
2924
|
+
|
|
2925
|
+
//#endregion
|
|
2926
|
+
//#region ../node_modules/@std/toml/parse.js
|
|
2927
|
+
/**
|
|
2928
|
+
* Parses a {@link https://toml.io | TOML} string into an object.
|
|
2929
|
+
*
|
|
2930
|
+
* @example Usage
|
|
2931
|
+
* ```ts
|
|
2932
|
+
* import { parse } from "@std/toml/parse";
|
|
2933
|
+
* import { assertEquals } from "@std/assert";
|
|
2934
|
+
*
|
|
2935
|
+
* const tomlString = `title = "TOML Example"
|
|
2936
|
+
* [owner]
|
|
2937
|
+
* name = "Alice"
|
|
2938
|
+
* bio = "Alice is a programmer."`;
|
|
2939
|
+
*
|
|
2940
|
+
* const obj = parse(tomlString);
|
|
2941
|
+
* assertEquals(obj, { title: "TOML Example", owner: { name: "Alice", bio: "Alice is a programmer." } });
|
|
2942
|
+
* ```
|
|
2943
|
+
* @param tomlString TOML string to be parsed.
|
|
2944
|
+
* @returns The parsed JS object.
|
|
2945
|
+
*/ function parse$2(tomlString) {
|
|
2946
|
+
return parserFactory(toml)(tomlString);
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2949
|
+
//#endregion
|
|
2950
|
+
//#region src/def/rename.ts
|
|
2951
|
+
var import_defineProperty$4 = __toESM(require_defineProperty(), 1);
|
|
2952
|
+
var BaseRenameCommand = class extends Command {
|
|
2953
|
+
constructor(..._args) {
|
|
2954
|
+
super(..._args);
|
|
2955
|
+
(0, import_defineProperty$4.default)(this, "cwd", Option.String("--cwd", process.cwd(), { description: "The working directory of where napi command will be executed in, all other paths options are relative to this path" }));
|
|
2956
|
+
(0, import_defineProperty$4.default)(this, "configPath", Option.String("--config-path,-c", { description: "Path to `napi` config json file" }));
|
|
2957
|
+
(0, import_defineProperty$4.default)(this, "packageJsonPath", Option.String("--package-json-path", "package.json", { description: "Path to `package.json`" }));
|
|
2958
|
+
(0, import_defineProperty$4.default)(this, "npmDir", Option.String("--npm-dir", "npm", { description: "Path to the folder where the npm packages put" }));
|
|
2959
|
+
(0, import_defineProperty$4.default)(this, "$$name", Option.String("--name,-n", { description: "The new name of the project" }));
|
|
2960
|
+
(0, import_defineProperty$4.default)(this, "binaryName", Option.String("--binary-name,-b", { description: "The new binary name *.node files" }));
|
|
2961
|
+
(0, import_defineProperty$4.default)(this, "packageName", Option.String("--package-name", { description: "The new package name of the project" }));
|
|
2962
|
+
(0, import_defineProperty$4.default)(this, "manifestPath", Option.String("--manifest-path", "Cargo.toml", { description: "Path to `Cargo.toml`" }));
|
|
2963
|
+
(0, import_defineProperty$4.default)(this, "repository", Option.String("--repository", { description: "The new repository of the project" }));
|
|
2964
|
+
(0, import_defineProperty$4.default)(this, "description", Option.String("--description", { description: "The new description of the project" }));
|
|
2965
|
+
}
|
|
2966
|
+
getOptions() {
|
|
2967
|
+
return {
|
|
2968
|
+
cwd: this.cwd,
|
|
2969
|
+
configPath: this.configPath,
|
|
2970
|
+
packageJsonPath: this.packageJsonPath,
|
|
2971
|
+
npmDir: this.npmDir,
|
|
2972
|
+
name: this.$$name,
|
|
2973
|
+
binaryName: this.binaryName,
|
|
2974
|
+
packageName: this.packageName,
|
|
2975
|
+
manifestPath: this.manifestPath,
|
|
2976
|
+
repository: this.repository,
|
|
2977
|
+
description: this.description
|
|
2978
|
+
};
|
|
2979
|
+
}
|
|
2980
|
+
};
|
|
2981
|
+
(0, import_defineProperty$4.default)(BaseRenameCommand, "paths", [["rename"]]);
|
|
2982
|
+
(0, import_defineProperty$4.default)(BaseRenameCommand, "usage", Command.Usage({ description: "Rename the NAPI-RS project" }));
|
|
2983
|
+
function applyDefaultRenameOptions(options) {
|
|
2984
|
+
return {
|
|
2985
|
+
cwd: process.cwd(),
|
|
2986
|
+
packageJsonPath: "package.json",
|
|
2987
|
+
npmDir: "npm",
|
|
2988
|
+
manifestPath: "Cargo.toml",
|
|
2989
|
+
...options
|
|
2990
|
+
};
|
|
2991
|
+
}
|
|
2992
|
+
|
|
2993
|
+
//#endregion
|
|
2994
|
+
//#region src/api/rename.ts
|
|
2995
|
+
async function renameProject(userOptions) {
|
|
2996
|
+
const options = applyDefaultRenameOptions(userOptions);
|
|
2997
|
+
const napiConfig = await readConfig(options);
|
|
2998
|
+
const oldName = napiConfig.binaryName;
|
|
2999
|
+
const packageJsonPath = resolve(options.cwd, options.packageJsonPath);
|
|
3000
|
+
const cargoTomlPath = resolve(options.cwd, options.manifestPath);
|
|
3001
|
+
const packageJsonContent = await readFileAsync(packageJsonPath, "utf8");
|
|
3002
|
+
const packageJsonData = JSON.parse(packageJsonContent);
|
|
3003
|
+
merge(packageJsonData, omitBy(pick(options, [
|
|
3004
|
+
"name",
|
|
3005
|
+
"description",
|
|
3006
|
+
"author",
|
|
3007
|
+
"license"
|
|
3008
|
+
]), isNil), { napi: omitBy({
|
|
3009
|
+
binaryName: options.binaryName,
|
|
3010
|
+
packageName: options.packageName
|
|
3011
|
+
}, isNil) });
|
|
3012
|
+
if (options.configPath) {
|
|
3013
|
+
const configPath = resolve(options.cwd, options.configPath);
|
|
3014
|
+
const configContent = await readFileAsync(configPath, "utf8");
|
|
3015
|
+
const configData = JSON.parse(configContent);
|
|
3016
|
+
configData.binaryName = options.binaryName;
|
|
3017
|
+
configData.packageName = options.packageName;
|
|
3018
|
+
await writeFileAsync(configPath, JSON.stringify(configData, null, 2));
|
|
3019
|
+
}
|
|
3020
|
+
await writeFileAsync(packageJsonPath, JSON.stringify(packageJsonData, null, 2));
|
|
3021
|
+
const tomlContent = await readFileAsync(cargoTomlPath, "utf8");
|
|
3022
|
+
const cargoToml = parse$2(tomlContent);
|
|
3023
|
+
if (cargoToml.package && options.binaryName) {
|
|
3024
|
+
const sanitizedName = options.binaryName.replace("@", "").replace("/", "_").replace(/-/g, "_").toLowerCase();
|
|
3025
|
+
cargoToml.package.name = sanitizedName;
|
|
3026
|
+
}
|
|
3027
|
+
const updatedTomlContent = stringify(cargoToml);
|
|
3028
|
+
await writeFileAsync(cargoTomlPath, updatedTomlContent);
|
|
3029
|
+
if (oldName !== options.binaryName) {
|
|
3030
|
+
const githubActionsPath = await findUp(".github", {
|
|
3031
|
+
cwd: options.cwd,
|
|
3032
|
+
type: "directory"
|
|
3033
|
+
});
|
|
3034
|
+
if (githubActionsPath) {
|
|
3035
|
+
const githubActionsCIYmlPath = join(githubActionsPath, "workflows", "CI.yml");
|
|
3036
|
+
if (existsSync(githubActionsCIYmlPath)) {
|
|
3037
|
+
const githubActionsContent = await readFileAsync(githubActionsCIYmlPath, "utf8");
|
|
3038
|
+
const githubActionsData = load(githubActionsContent);
|
|
3039
|
+
if (githubActionsData.env?.APP_NAME) {
|
|
3040
|
+
githubActionsData.env.APP_NAME = options.binaryName;
|
|
3041
|
+
await writeFileAsync(githubActionsCIYmlPath, dump(githubActionsData, {
|
|
3042
|
+
lineWidth: -1,
|
|
3043
|
+
noRefs: true,
|
|
3044
|
+
sortKeys: false
|
|
3045
|
+
}));
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
const oldWasiBrowserBindingPath = join(options.cwd, `${oldName}.wasi-browser.js`);
|
|
3050
|
+
if (existsSync(oldWasiBrowserBindingPath)) await rename(oldWasiBrowserBindingPath, join(options.cwd, `${options.binaryName}.wasi-browser.js`));
|
|
3051
|
+
const oldWasiBindingPath = join(options.cwd, `${oldName}.wasi.cjs`);
|
|
3052
|
+
if (existsSync(oldWasiBindingPath)) await rename(oldWasiBindingPath, join(options.cwd, `${options.binaryName}.wasi.cjs`));
|
|
3053
|
+
const gitAttributesPath = join(options.cwd, ".gitattributes");
|
|
3054
|
+
if (existsSync(gitAttributesPath)) {
|
|
3055
|
+
const gitAttributesContent = await readFileAsync(gitAttributesPath, "utf8");
|
|
3056
|
+
const gitAttributesData = gitAttributesContent.split("\n").map((line) => {
|
|
3057
|
+
return line.replace(`${oldName}.wasi-browser.js`, `${options.binaryName}.wasi-browser.js`).replace(`${oldName}.wasi.cjs`, `${options.binaryName}.wasi.cjs`);
|
|
3058
|
+
}).join("\n");
|
|
3059
|
+
await writeFileAsync(gitAttributesPath, gitAttributesData);
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
|
|
3064
|
+
//#endregion
|
|
3065
|
+
//#region src/api/new.ts
|
|
3066
|
+
const debug$3 = debugFactory("new");
|
|
3067
|
+
const TEMPLATE_REPOS = {
|
|
3068
|
+
yarn: "https://github.com/napi-rs/package-template",
|
|
3069
|
+
pnpm: "https://github.com/napi-rs/package-template-pnpm"
|
|
3070
|
+
};
|
|
3071
|
+
async function checkGitCommand() {
|
|
3072
|
+
try {
|
|
3073
|
+
await new Promise((resolve$1) => {
|
|
3074
|
+
const cp = exec("git --version");
|
|
3075
|
+
cp.on("error", () => {
|
|
3076
|
+
resolve$1(false);
|
|
3077
|
+
});
|
|
3078
|
+
cp.on("exit", (code) => {
|
|
3079
|
+
if (code === 0) resolve$1(true);
|
|
3080
|
+
else resolve$1(false);
|
|
3081
|
+
});
|
|
3082
|
+
});
|
|
3083
|
+
return true;
|
|
3084
|
+
} catch {
|
|
3085
|
+
return false;
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
async function ensureCacheDir(packageManager) {
|
|
3089
|
+
const cacheDir = path.join(homedir(), ".napi-rs", "template", packageManager);
|
|
3090
|
+
await mkdirAsync(cacheDir, { recursive: true });
|
|
3091
|
+
return cacheDir;
|
|
3092
|
+
}
|
|
3093
|
+
async function downloadTemplate(packageManager, cacheDir) {
|
|
3094
|
+
const repoUrl = TEMPLATE_REPOS[packageManager];
|
|
3095
|
+
const templatePath = path.join(cacheDir, "repo");
|
|
3096
|
+
if (existsSync(templatePath)) {
|
|
3097
|
+
debug$3(`Template cache found at ${templatePath}, updating...`);
|
|
3098
|
+
try {
|
|
3099
|
+
await new Promise((resolve$1, reject) => {
|
|
3100
|
+
const cp = exec("git fetch origin", { cwd: templatePath });
|
|
3101
|
+
cp.on("error", reject);
|
|
3102
|
+
cp.on("exit", (code) => {
|
|
3103
|
+
if (code === 0) resolve$1();
|
|
3104
|
+
else reject(new Error(`Failed to fetch latest changes, git process exited with code ${code}`));
|
|
3105
|
+
});
|
|
3106
|
+
});
|
|
3107
|
+
execSync("git reset --hard origin/main", {
|
|
3108
|
+
cwd: templatePath,
|
|
3109
|
+
stdio: "ignore"
|
|
3110
|
+
});
|
|
3111
|
+
debug$3("Template updated successfully");
|
|
3112
|
+
} catch (error) {
|
|
3113
|
+
debug$3(`Failed to update template: ${error}`);
|
|
3114
|
+
throw new Error(`Failed to update template from ${repoUrl}: ${error}`);
|
|
3115
|
+
}
|
|
3116
|
+
} else {
|
|
3117
|
+
debug$3(`Cloning template from ${repoUrl}...`);
|
|
3118
|
+
try {
|
|
3119
|
+
execSync(`git clone ${repoUrl} repo`, {
|
|
3120
|
+
cwd: cacheDir,
|
|
3121
|
+
stdio: "inherit"
|
|
3122
|
+
});
|
|
3123
|
+
debug$3("Template cloned successfully");
|
|
3124
|
+
} catch (error) {
|
|
3125
|
+
throw new Error(`Failed to clone template from ${repoUrl}: ${error}`);
|
|
3126
|
+
}
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3129
|
+
async function copyDirectory(src, dest, includeWasiBindings) {
|
|
3130
|
+
await mkdirAsync(dest, { recursive: true });
|
|
3131
|
+
const entries = await promises.readdir(src, { withFileTypes: true });
|
|
3132
|
+
for (const entry of entries) {
|
|
3133
|
+
const srcPath = path.join(src, entry.name);
|
|
3134
|
+
const destPath = path.join(dest, entry.name);
|
|
3135
|
+
if (entry.name === ".git") continue;
|
|
3136
|
+
if (entry.isDirectory()) await copyDirectory(srcPath, destPath, includeWasiBindings);
|
|
3137
|
+
else {
|
|
3138
|
+
if (!includeWasiBindings && (entry.name.endsWith(".wasi-browser.js") || entry.name.endsWith(".wasi.cjs") || entry.name.endsWith("wasi-worker.browser.mjs ") || entry.name.endsWith("wasi-worker.mjs") || entry.name.endsWith("browser.js"))) continue;
|
|
3139
|
+
await promises.copyFile(srcPath, destPath);
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
}
|
|
3143
|
+
async function filterTargetsInPackageJson(filePath, enabledTargets) {
|
|
3144
|
+
const content = await promises.readFile(filePath, "utf-8");
|
|
3145
|
+
const packageJson = JSON.parse(content);
|
|
3146
|
+
if (packageJson.napi?.targets) packageJson.napi.targets = packageJson.napi.targets.filter((target) => enabledTargets.includes(target));
|
|
3147
|
+
await promises.writeFile(filePath, JSON.stringify(packageJson, null, 2) + "\n");
|
|
3148
|
+
}
|
|
3149
|
+
async function filterTargetsInGithubActions(filePath, enabledTargets) {
|
|
3150
|
+
const content = await promises.readFile(filePath, "utf-8");
|
|
3151
|
+
const yaml = load(content);
|
|
3152
|
+
const macOSAndWindowsTargets = new Set([
|
|
3153
|
+
"x86_64-pc-windows-msvc",
|
|
3154
|
+
"aarch64-pc-windows-msvc",
|
|
3155
|
+
"x86_64-apple-darwin"
|
|
3156
|
+
]);
|
|
3157
|
+
const linuxTargets = new Set([
|
|
3158
|
+
"x86_64-unknown-linux-gnu",
|
|
3159
|
+
"x86_64-unknown-linux-musl",
|
|
3160
|
+
"aarch64-unknown-linux-gnu",
|
|
3161
|
+
"aarch64-unknown-linux-musl",
|
|
3162
|
+
"armv7-unknown-linux-gnueabihf",
|
|
3163
|
+
"armv7-unknown-linux-musleabihf",
|
|
3164
|
+
"riscv64gc-unknown-linux-gnu",
|
|
3165
|
+
"powerpc64le-unknown-linux-gnu",
|
|
3166
|
+
"s390x-unknown-linux-gnu",
|
|
3167
|
+
"aarch64-linux-android",
|
|
3168
|
+
"armv7-linux-androideabi"
|
|
3169
|
+
]);
|
|
3170
|
+
const hasLinuxTargets = enabledTargets.some((target) => linuxTargets.has(target));
|
|
3171
|
+
if (yaml?.jobs?.build?.strategy?.matrix?.settings) yaml.jobs.build.strategy.matrix.settings = yaml.jobs.build.strategy.matrix.settings.filter((setting) => {
|
|
3172
|
+
if (setting.target) return enabledTargets.includes(setting.target);
|
|
3173
|
+
return true;
|
|
3174
|
+
});
|
|
3175
|
+
const jobsToRemove = [];
|
|
3176
|
+
if (enabledTargets.every((target) => !macOSAndWindowsTargets.has(target))) jobsToRemove.push("test-macOS-windows-binding");
|
|
3177
|
+
else if (yaml?.jobs?.["test-macOS-windows-binding"]?.strategy?.matrix?.settings) yaml.jobs["test-macOS-windows-binding"].strategy.matrix.settings = yaml.jobs["test-macOS-windows-binding"].strategy.matrix.settings.filter((setting) => {
|
|
3178
|
+
if (setting.target) return enabledTargets.includes(setting.target);
|
|
3179
|
+
return true;
|
|
3180
|
+
});
|
|
3181
|
+
if (!hasLinuxTargets) {
|
|
3182
|
+
if (yaml?.jobs?.["test-linux-binding"]) jobsToRemove.push("test-linux-binding");
|
|
3183
|
+
} else if (yaml?.jobs?.["test-linux-binding"]?.strategy?.matrix?.target) yaml.jobs["test-linux-binding"].strategy.matrix.target = yaml.jobs["test-linux-binding"].strategy.matrix.target.filter((target) => {
|
|
3184
|
+
if (target) return enabledTargets.includes(target);
|
|
3185
|
+
return true;
|
|
3186
|
+
});
|
|
3187
|
+
if (!enabledTargets.includes("wasm32-wasip1-threads")) jobsToRemove.push("test-wasi");
|
|
3188
|
+
if (!enabledTargets.includes("x86_64-unknown-freebsd")) jobsToRemove.push("build-freebsd");
|
|
3189
|
+
for (const [jobName, jobConfig] of Object.entries(yaml.jobs || {})) if (jobName.startsWith("test-") && jobName !== "test-macOS-windows-binding" && jobName !== "test-linux-x64-gnu-binding") {
|
|
3190
|
+
const job = jobConfig;
|
|
3191
|
+
if (job.strategy?.matrix?.settings?.[0]?.target) {
|
|
3192
|
+
const target = job.strategy.matrix.settings[0].target;
|
|
3193
|
+
if (!enabledTargets.includes(target)) jobsToRemove.push(jobName);
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
for (const jobName of jobsToRemove) delete yaml.jobs[jobName];
|
|
3197
|
+
if (Array.isArray(yaml.jobs?.publish?.needs)) yaml.jobs.publish.needs = yaml.jobs.publish.needs.filter((need) => !jobsToRemove.includes(need));
|
|
3198
|
+
const updatedYaml = dump(yaml, {
|
|
3199
|
+
lineWidth: -1,
|
|
3200
|
+
noRefs: true,
|
|
3201
|
+
sortKeys: false
|
|
3202
|
+
});
|
|
3203
|
+
await promises.writeFile(filePath, updatedYaml);
|
|
3204
|
+
}
|
|
3205
|
+
function processOptions(options) {
|
|
3206
|
+
debug$3("Processing options...");
|
|
3207
|
+
if (!options.path) throw new Error("Please provide the path as the argument");
|
|
3208
|
+
options.path = path.resolve(process.cwd(), options.path);
|
|
3209
|
+
debug$3(`Resolved target path to: ${options.path}`);
|
|
3210
|
+
if (!options.name) {
|
|
3211
|
+
options.name = path.parse(options.path).base;
|
|
3212
|
+
debug$3(`No project name provided, fix it to dir name: ${options.name}`);
|
|
3213
|
+
}
|
|
3214
|
+
if (!options.targets?.length) if (options.enableAllTargets) {
|
|
3215
|
+
options.targets = AVAILABLE_TARGETS.concat();
|
|
3216
|
+
debug$3("Enable all targets");
|
|
3217
|
+
} else if (options.enableDefaultTargets) {
|
|
3218
|
+
options.targets = DEFAULT_TARGETS.concat();
|
|
3219
|
+
debug$3("Enable default targets");
|
|
3220
|
+
} else throw new Error("At least one target must be enabled");
|
|
3221
|
+
if (options.targets.some((target) => target === "wasm32-wasi-preview1-threads")) {
|
|
3222
|
+
const out = execSync(`rustup target list`, { encoding: "utf8" });
|
|
3223
|
+
if (out.includes("wasm32-wasip1-threads")) options.targets = options.targets.map((target) => target === "wasm32-wasi-preview1-threads" ? "wasm32-wasip1-threads" : target);
|
|
3224
|
+
}
|
|
3225
|
+
return applyDefaultNewOptions(options);
|
|
3226
|
+
}
|
|
3227
|
+
async function newProject(userOptions) {
|
|
3228
|
+
debug$3("Will create napi-rs project with given options:");
|
|
3229
|
+
debug$3(userOptions);
|
|
3230
|
+
const options = processOptions(userOptions);
|
|
3231
|
+
debug$3("Targets to be enabled:");
|
|
3232
|
+
debug$3(options.targets);
|
|
3233
|
+
if (!await checkGitCommand()) throw new Error("Git is not installed or not available in PATH. Please install Git to continue.");
|
|
3234
|
+
const packageManager = options.packageManager;
|
|
3235
|
+
await ensurePath(options.path, options.dryRun);
|
|
3236
|
+
if (!options.dryRun) try {
|
|
3237
|
+
const cacheDir = await ensureCacheDir(packageManager);
|
|
3238
|
+
await downloadTemplate(packageManager, cacheDir);
|
|
3239
|
+
const templatePath = path.join(cacheDir, "repo");
|
|
3240
|
+
await copyDirectory(templatePath, options.path, options.targets.includes("wasm32-wasip1-threads"));
|
|
3241
|
+
await renameProject({
|
|
3242
|
+
cwd: options.path,
|
|
3243
|
+
name: options.name,
|
|
3244
|
+
binaryName: getBinaryName(options.name)
|
|
3245
|
+
});
|
|
3246
|
+
const packageJsonPath = path.join(options.path, "package.json");
|
|
3247
|
+
if (existsSync(packageJsonPath)) await filterTargetsInPackageJson(packageJsonPath, options.targets);
|
|
3248
|
+
const ciPath = path.join(options.path, ".github", "workflows", "CI.yml");
|
|
3249
|
+
if (existsSync(ciPath) && options.enableGithubActions) await filterTargetsInGithubActions(ciPath, options.targets);
|
|
3250
|
+
else if (!options.enableGithubActions && existsSync(path.join(options.path, ".github"))) await promises.rm(path.join(options.path, ".github"), {
|
|
3251
|
+
recursive: true,
|
|
3252
|
+
force: true
|
|
3253
|
+
});
|
|
3254
|
+
const pkgJsonContent = await promises.readFile(packageJsonPath, "utf-8");
|
|
3255
|
+
const pkgJson = JSON.parse(pkgJsonContent);
|
|
3256
|
+
if (!pkgJson.engines) pkgJson.engines = {};
|
|
3257
|
+
pkgJson.engines.node = napiEngineRequirement(options.minNodeApiVersion);
|
|
3258
|
+
if (options.license && pkgJson.license !== options.license) pkgJson.license = options.license;
|
|
3259
|
+
if (options.testFramework !== "ava") debug$3(`Test framework ${options.testFramework} requested but not yet implemented`);
|
|
3260
|
+
await promises.writeFile(packageJsonPath, JSON.stringify(pkgJson, null, 2) + "\n");
|
|
3261
|
+
} catch (error) {
|
|
3262
|
+
throw new Error(`Failed to create project: ${error}`);
|
|
3263
|
+
}
|
|
3264
|
+
debug$3(`Project created at: ${options.path}`);
|
|
3265
|
+
}
|
|
3266
|
+
async function ensurePath(path$1, dryRun = false) {
|
|
3267
|
+
const stat$1 = await statAsync(path$1, {}).catch(() => void 0);
|
|
3268
|
+
if (stat$1) {
|
|
3269
|
+
if (stat$1.isFile()) throw new Error(`Path ${path$1} for creating new napi-rs project already exists and it's not a directory.`);
|
|
3270
|
+
else if (stat$1.isDirectory()) {
|
|
3271
|
+
const files$1 = await readdirAsync(path$1);
|
|
3272
|
+
if (files$1.length) throw new Error(`Path ${path$1} for creating new napi-rs project already exists and it's not empty.`);
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
if (!dryRun) try {
|
|
3276
|
+
debug$3(`Try to create target directory: ${path$1}`);
|
|
3277
|
+
if (!dryRun) await mkdirAsync(path$1, { recursive: true });
|
|
3278
|
+
} catch (e) {
|
|
3279
|
+
throw new Error(`Failed to create target directory: ${path$1}`, { cause: e });
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
3282
|
+
function getBinaryName(name$1) {
|
|
3283
|
+
return name$1.split("/").pop();
|
|
3284
|
+
}
|
|
3285
|
+
|
|
3286
|
+
//#endregion
|
|
3287
|
+
//#region src/def/pre-publish.ts
|
|
3288
|
+
var import_defineProperty$3 = __toESM(require_defineProperty(), 1);
|
|
3289
|
+
var BasePrePublishCommand = class extends Command {
|
|
3290
|
+
constructor(..._args) {
|
|
3291
|
+
super(..._args);
|
|
3292
|
+
(0, import_defineProperty$3.default)(this, "cwd", Option.String("--cwd", process.cwd(), { description: "The working directory of where napi command will be executed in, all other paths options are relative to this path" }));
|
|
3293
|
+
(0, import_defineProperty$3.default)(this, "configPath", Option.String("--config-path,-c", { description: "Path to `napi` config json file" }));
|
|
3294
|
+
(0, import_defineProperty$3.default)(this, "packageJsonPath", Option.String("--package-json-path", "package.json", { description: "Path to `package.json`" }));
|
|
3295
|
+
(0, import_defineProperty$3.default)(this, "npmDir", Option.String("--npm-dir,-p", "npm", { description: "Path to the folder where the npm packages put" }));
|
|
3296
|
+
(0, import_defineProperty$3.default)(this, "tagStyle", Option.String("--tag-style,--tagstyle,-t", "lerna", { description: "git tag style, `npm` or `lerna`" }));
|
|
3297
|
+
(0, import_defineProperty$3.default)(this, "ghRelease", Option.Boolean("--gh-release", true, { description: "Whether create GitHub release" }));
|
|
3298
|
+
(0, import_defineProperty$3.default)(this, "ghReleaseName", Option.String("--gh-release-name", { description: "GitHub release name" }));
|
|
3299
|
+
(0, import_defineProperty$3.default)(this, "ghReleaseId", Option.String("--gh-release-id", { description: "Existing GitHub release id" }));
|
|
3300
|
+
(0, import_defineProperty$3.default)(this, "dryRun", Option.Boolean("--dry-run", false, { description: "Dry run without touching file system" }));
|
|
3301
|
+
}
|
|
3302
|
+
getOptions() {
|
|
3303
|
+
return {
|
|
3304
|
+
cwd: this.cwd,
|
|
3305
|
+
configPath: this.configPath,
|
|
3306
|
+
packageJsonPath: this.packageJsonPath,
|
|
3307
|
+
npmDir: this.npmDir,
|
|
3308
|
+
tagStyle: this.tagStyle,
|
|
3309
|
+
ghRelease: this.ghRelease,
|
|
3310
|
+
ghReleaseName: this.ghReleaseName,
|
|
3311
|
+
ghReleaseId: this.ghReleaseId,
|
|
3312
|
+
dryRun: this.dryRun
|
|
3313
|
+
};
|
|
3314
|
+
}
|
|
3315
|
+
};
|
|
3316
|
+
(0, import_defineProperty$3.default)(BasePrePublishCommand, "paths", [["pre-publish"], ["prepublish"]]);
|
|
3317
|
+
(0, import_defineProperty$3.default)(BasePrePublishCommand, "usage", Command.Usage({ description: "Update package.json and copy addons into per platform packages" }));
|
|
3318
|
+
function applyDefaultPrePublishOptions(options) {
|
|
3319
|
+
return {
|
|
3320
|
+
cwd: process.cwd(),
|
|
3321
|
+
packageJsonPath: "package.json",
|
|
3322
|
+
npmDir: "npm",
|
|
3323
|
+
tagStyle: "lerna",
|
|
3324
|
+
ghRelease: true,
|
|
3325
|
+
dryRun: false,
|
|
3326
|
+
...options
|
|
3327
|
+
};
|
|
3328
|
+
}
|
|
3329
|
+
|
|
3330
|
+
//#endregion
|
|
3331
|
+
//#region src/def/version.ts
|
|
3332
|
+
var import_defineProperty$2 = __toESM(require_defineProperty(), 1);
|
|
3333
|
+
var BaseVersionCommand = class extends Command {
|
|
3334
|
+
constructor(..._args) {
|
|
3335
|
+
super(..._args);
|
|
3336
|
+
(0, import_defineProperty$2.default)(this, "cwd", Option.String("--cwd", process.cwd(), { description: "The working directory of where napi command will be executed in, all other paths options are relative to this path" }));
|
|
3337
|
+
(0, import_defineProperty$2.default)(this, "configPath", Option.String("--config-path,-c", { description: "Path to `napi` config json file" }));
|
|
3338
|
+
(0, import_defineProperty$2.default)(this, "packageJsonPath", Option.String("--package-json-path", "package.json", { description: "Path to `package.json`" }));
|
|
3339
|
+
(0, import_defineProperty$2.default)(this, "npmDir", Option.String("--npm-dir", "npm", { description: "Path to the folder where the npm packages put" }));
|
|
3340
|
+
}
|
|
3341
|
+
getOptions() {
|
|
3342
|
+
return {
|
|
3343
|
+
cwd: this.cwd,
|
|
3344
|
+
configPath: this.configPath,
|
|
3345
|
+
packageJsonPath: this.packageJsonPath,
|
|
3346
|
+
npmDir: this.npmDir
|
|
3347
|
+
};
|
|
3348
|
+
}
|
|
3349
|
+
};
|
|
3350
|
+
(0, import_defineProperty$2.default)(BaseVersionCommand, "paths", [["version"]]);
|
|
3351
|
+
(0, import_defineProperty$2.default)(BaseVersionCommand, "usage", Command.Usage({ description: "Update version in created npm packages" }));
|
|
3352
|
+
function applyDefaultVersionOptions(options) {
|
|
3353
|
+
return {
|
|
3354
|
+
cwd: process.cwd(),
|
|
3355
|
+
packageJsonPath: "package.json",
|
|
3356
|
+
npmDir: "npm",
|
|
3357
|
+
...options
|
|
3358
|
+
};
|
|
3359
|
+
}
|
|
3360
|
+
|
|
3361
|
+
//#endregion
|
|
3362
|
+
//#region src/api/version.ts
|
|
3363
|
+
const debug$2 = debugFactory("version");
|
|
3364
|
+
async function version(userOptions) {
|
|
3365
|
+
const options = applyDefaultVersionOptions(userOptions);
|
|
3366
|
+
const packageJsonPath = resolve(options.cwd, options.packageJsonPath);
|
|
3367
|
+
const config = await readNapiConfig(packageJsonPath, options.configPath ? resolve(options.cwd, options.configPath) : void 0);
|
|
3368
|
+
for (const target of config.targets) {
|
|
3369
|
+
const pkgDir = resolve(options.cwd, options.npmDir, target.platformArchABI);
|
|
3370
|
+
debug$2(`Update version to %i in [%i]`, config.packageJson.version, pkgDir);
|
|
3371
|
+
await updatePackageJson(join(pkgDir, "package.json"), { version: config.packageJson.version });
|
|
3372
|
+
}
|
|
3373
|
+
}
|
|
3374
|
+
|
|
3375
|
+
//#endregion
|
|
3376
|
+
//#region src/api/pre-publish.ts
|
|
3377
|
+
const debug$1 = debugFactory("pre-publish");
|
|
3378
|
+
async function prePublish(userOptions) {
|
|
3379
|
+
debug$1("Receive pre-publish options:");
|
|
3380
|
+
debug$1(" %O", userOptions);
|
|
3381
|
+
const options = applyDefaultPrePublishOptions(userOptions);
|
|
3382
|
+
const packageJsonPath = resolve(options.cwd, options.packageJsonPath);
|
|
3383
|
+
const { packageJson, targets, packageName, binaryName, npmClient } = await readNapiConfig(packageJsonPath, options.configPath ? resolve(options.cwd, options.configPath) : void 0);
|
|
3384
|
+
async function createGhRelease(packageName$1, version$2) {
|
|
3385
|
+
if (!options.ghRelease) return {
|
|
3386
|
+
owner: null,
|
|
3387
|
+
repo: null,
|
|
3388
|
+
pkgInfo: {
|
|
3389
|
+
name: null,
|
|
3390
|
+
version: null,
|
|
3391
|
+
tag: null
|
|
3392
|
+
}
|
|
3393
|
+
};
|
|
3394
|
+
const { repo: repo$1, owner: owner$1, pkgInfo: pkgInfo$1, octokit: octokit$1 } = getRepoInfo(packageName$1, version$2);
|
|
3395
|
+
if (!repo$1 || !owner$1) return {
|
|
3396
|
+
owner: null,
|
|
3397
|
+
repo: null,
|
|
3398
|
+
pkgInfo: {
|
|
3399
|
+
name: null,
|
|
3400
|
+
version: null,
|
|
3401
|
+
tag: null
|
|
3402
|
+
}
|
|
3403
|
+
};
|
|
3404
|
+
if (!options.dryRun) try {
|
|
3405
|
+
await octokit$1.repos.createRelease({
|
|
3406
|
+
owner: owner$1,
|
|
3407
|
+
repo: repo$1,
|
|
3408
|
+
tag_name: pkgInfo$1.tag,
|
|
3409
|
+
name: options.ghReleaseName,
|
|
3410
|
+
prerelease: version$2.includes("alpha") || version$2.includes("beta") || version$2.includes("rc")
|
|
3411
|
+
});
|
|
3412
|
+
} catch (e) {
|
|
3413
|
+
debug$1(`Params: ${JSON.stringify({
|
|
3414
|
+
owner: owner$1,
|
|
3415
|
+
repo: repo$1,
|
|
3416
|
+
tag_name: pkgInfo$1.tag
|
|
3417
|
+
}, null, 2)}`);
|
|
3418
|
+
console.error(e);
|
|
3419
|
+
}
|
|
3420
|
+
return {
|
|
3421
|
+
owner: owner$1,
|
|
3422
|
+
repo: repo$1,
|
|
3423
|
+
pkgInfo: pkgInfo$1,
|
|
3424
|
+
octokit: octokit$1
|
|
3425
|
+
};
|
|
3426
|
+
}
|
|
3427
|
+
function getRepoInfo(packageName$1, version$2) {
|
|
3428
|
+
const headCommit = execSync("git log -1 --pretty=%B", { encoding: "utf-8" }).trim();
|
|
3429
|
+
const { GITHUB_REPOSITORY } = process.env;
|
|
3430
|
+
if (!GITHUB_REPOSITORY) return {
|
|
3431
|
+
owner: null,
|
|
3432
|
+
repo: null,
|
|
3433
|
+
pkgInfo: {
|
|
3434
|
+
name: null,
|
|
3435
|
+
version: null,
|
|
3436
|
+
tag: null
|
|
3437
|
+
}
|
|
3438
|
+
};
|
|
3439
|
+
debug$1(`Github repository: ${GITHUB_REPOSITORY}`);
|
|
3440
|
+
const [owner$1, repo$1] = GITHUB_REPOSITORY.split("/");
|
|
3441
|
+
const octokit$1 = new Octokit({ auth: process.env.GITHUB_TOKEN });
|
|
3442
|
+
let pkgInfo$1;
|
|
3443
|
+
if (options.tagStyle === "lerna") {
|
|
3444
|
+
const packagesToPublish = headCommit.split("\n").map((line) => line.trim()).filter((line, index) => line.length && index).map((line) => line.substring(2)).map(parseTag);
|
|
3445
|
+
pkgInfo$1 = packagesToPublish.find((pkgInfo$2) => pkgInfo$2.name === packageName$1);
|
|
3446
|
+
if (!pkgInfo$1) throw new TypeError(`No release commit found with ${packageName$1}, original commit info: ${headCommit}`);
|
|
3447
|
+
} else pkgInfo$1 = {
|
|
3448
|
+
tag: `v${version$2}`,
|
|
3449
|
+
version: version$2,
|
|
3450
|
+
name: packageName$1
|
|
3451
|
+
};
|
|
3452
|
+
return {
|
|
3453
|
+
owner: owner$1,
|
|
3454
|
+
repo: repo$1,
|
|
3455
|
+
pkgInfo: pkgInfo$1,
|
|
3456
|
+
octokit: octokit$1
|
|
3457
|
+
};
|
|
3458
|
+
}
|
|
3459
|
+
if (!options.dryRun) {
|
|
3460
|
+
await version(userOptions);
|
|
3461
|
+
await updatePackageJson(packageJsonPath, { optionalDependencies: targets.reduce((deps, target) => {
|
|
3462
|
+
deps[`${packageName}-${target.platformArchABI}`] = packageJson.version;
|
|
3463
|
+
return deps;
|
|
3464
|
+
}, {}) });
|
|
3465
|
+
}
|
|
3466
|
+
const { owner, repo, pkgInfo, octokit } = options.ghReleaseId ? getRepoInfo(packageName, packageJson.version) : await createGhRelease(packageName, packageJson.version);
|
|
3467
|
+
for (const target of targets) {
|
|
3468
|
+
const pkgDir = resolve(options.cwd, options.npmDir, `${target.platformArchABI}`);
|
|
3469
|
+
const ext = target.platform === "wasi" || target.platform === "wasm" ? "wasm" : "node";
|
|
3470
|
+
const filename = `${binaryName}.${target.platformArchABI}.${ext}`;
|
|
3471
|
+
const dstPath = join(pkgDir, filename);
|
|
3472
|
+
if (!options.dryRun) {
|
|
3473
|
+
if (!existsSync(dstPath)) {
|
|
3474
|
+
debug$1.warn(`%s doesn't exist`, dstPath);
|
|
3475
|
+
continue;
|
|
3476
|
+
}
|
|
3477
|
+
execSync(`${npmClient} publish`, {
|
|
3478
|
+
cwd: pkgDir,
|
|
3479
|
+
env: process.env
|
|
3480
|
+
});
|
|
3481
|
+
if (options.ghRelease && repo && owner) {
|
|
3482
|
+
debug$1.info(`Creating GitHub release ${pkgInfo.tag}`);
|
|
3483
|
+
try {
|
|
3484
|
+
const releaseId = options.ghReleaseId ? Number(options.ghReleaseId) : (await octokit.repos.getReleaseByTag({
|
|
3485
|
+
repo,
|
|
3486
|
+
owner,
|
|
3487
|
+
tag: pkgInfo.tag
|
|
3488
|
+
})).data.id;
|
|
3489
|
+
const dstFileStats = statSync(dstPath);
|
|
3490
|
+
const assetInfo = await octokit.repos.uploadReleaseAsset({
|
|
3491
|
+
owner,
|
|
3492
|
+
repo,
|
|
3493
|
+
name: filename,
|
|
3494
|
+
release_id: releaseId,
|
|
3495
|
+
mediaType: { format: "raw" },
|
|
3496
|
+
headers: {
|
|
3497
|
+
"content-length": dstFileStats.size,
|
|
3498
|
+
"content-type": "application/octet-stream"
|
|
3499
|
+
},
|
|
3500
|
+
data: await readFileAsync(dstPath)
|
|
3501
|
+
});
|
|
3502
|
+
debug$1.info(`GitHub release created`);
|
|
3503
|
+
debug$1.info(`Download URL: %s`, assetInfo.data.browser_download_url);
|
|
3504
|
+
} catch (e) {
|
|
3505
|
+
debug$1.error(`Param: ${JSON.stringify({
|
|
3506
|
+
owner,
|
|
3507
|
+
repo,
|
|
3508
|
+
tag: pkgInfo.tag,
|
|
3509
|
+
filename: dstPath
|
|
3510
|
+
}, null, 2)}`);
|
|
3511
|
+
debug$1.error(e);
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3514
|
+
}
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
function parseTag(tag) {
|
|
3518
|
+
const segments = tag.split("@");
|
|
3519
|
+
const version$2 = segments.pop();
|
|
3520
|
+
const name$1 = segments.join("@");
|
|
3521
|
+
return {
|
|
3522
|
+
name: name$1,
|
|
3523
|
+
version: version$2,
|
|
3524
|
+
tag
|
|
3525
|
+
};
|
|
3526
|
+
}
|
|
3527
|
+
|
|
3528
|
+
//#endregion
|
|
3529
|
+
//#region src/def/universalize.ts
|
|
3530
|
+
var import_defineProperty$1 = __toESM(require_defineProperty(), 1);
|
|
3531
|
+
var BaseUniversalizeCommand = class extends Command {
|
|
3532
|
+
constructor(..._args) {
|
|
3533
|
+
super(..._args);
|
|
3534
|
+
(0, import_defineProperty$1.default)(this, "cwd", Option.String("--cwd", process.cwd(), { description: "The working directory of where napi command will be executed in, all other paths options are relative to this path" }));
|
|
3535
|
+
(0, import_defineProperty$1.default)(this, "configPath", Option.String("--config-path,-c", { description: "Path to `napi` config json file" }));
|
|
3536
|
+
(0, import_defineProperty$1.default)(this, "packageJsonPath", Option.String("--package-json-path", "package.json", { description: "Path to `package.json`" }));
|
|
3537
|
+
(0, import_defineProperty$1.default)(this, "outputDir", Option.String("--output-dir,-o", "./", { description: "Path to the folder where all built `.node` files put, same as `--output-dir` of build command" }));
|
|
3538
|
+
}
|
|
3539
|
+
getOptions() {
|
|
3540
|
+
return {
|
|
3541
|
+
cwd: this.cwd,
|
|
3542
|
+
configPath: this.configPath,
|
|
3543
|
+
packageJsonPath: this.packageJsonPath,
|
|
3544
|
+
outputDir: this.outputDir
|
|
3545
|
+
};
|
|
3546
|
+
}
|
|
3547
|
+
};
|
|
3548
|
+
(0, import_defineProperty$1.default)(BaseUniversalizeCommand, "paths", [["universalize"]]);
|
|
3549
|
+
(0, import_defineProperty$1.default)(BaseUniversalizeCommand, "usage", Command.Usage({ description: "Combile built binaries into one universal binary" }));
|
|
3550
|
+
function applyDefaultUniversalizeOptions(options) {
|
|
3551
|
+
return {
|
|
3552
|
+
cwd: process.cwd(),
|
|
3553
|
+
packageJsonPath: "package.json",
|
|
3554
|
+
outputDir: "./",
|
|
3555
|
+
...options
|
|
3556
|
+
};
|
|
3557
|
+
}
|
|
3558
|
+
|
|
3559
|
+
//#endregion
|
|
3560
|
+
//#region src/api/universalize.ts
|
|
3561
|
+
const debug = debugFactory("universalize");
|
|
3562
|
+
const universalizers = { darwin: (inputs, output) => {
|
|
3563
|
+
spawnSync("lipo", [
|
|
3564
|
+
"-create",
|
|
3565
|
+
"-output",
|
|
3566
|
+
output,
|
|
3567
|
+
...inputs
|
|
3568
|
+
], { stdio: "inherit" });
|
|
3569
|
+
} };
|
|
3570
|
+
async function universalizeBinaries(userOptions) {
|
|
3571
|
+
const options = applyDefaultUniversalizeOptions(userOptions);
|
|
3572
|
+
const packageJsonPath = join(options.cwd, options.packageJsonPath);
|
|
3573
|
+
const config = await readNapiConfig(packageJsonPath, options.configPath ? resolve(options.cwd, options.configPath) : void 0);
|
|
3574
|
+
const target = config.targets.find((t) => t.platform === process.platform && t.arch === "universal");
|
|
3575
|
+
if (!target) throw new Error(`'universal' arch for platform '${process.platform}' not found in config!`);
|
|
3576
|
+
const srcFiles = UniArchsByPlatform[process.platform]?.map((arch) => resolve(options.cwd, options.outputDir, `${config.binaryName}.${process.platform}-${arch}.node`));
|
|
3577
|
+
if (!srcFiles || !universalizers[process.platform]) throw new Error(`'universal' arch for platform '${process.platform}' not supported.`);
|
|
3578
|
+
debug(`Looking up source binaries to combine: `);
|
|
3579
|
+
debug(" %O", srcFiles);
|
|
3580
|
+
const srcFileLookup = await Promise.all(srcFiles.map((f) => fileExists(f)));
|
|
3581
|
+
const notFoundFiles = srcFiles.filter((_, i) => !srcFileLookup[i]);
|
|
3582
|
+
if (notFoundFiles.length) throw new Error(`Some binary files were not found: ${JSON.stringify(notFoundFiles)}`);
|
|
3583
|
+
const output = resolve(options.cwd, options.outputDir, `${config.binaryName}.${process.platform}-universal.node`);
|
|
3584
|
+
universalizers[process.platform]?.(srcFiles, output);
|
|
3585
|
+
debug(`Produced universal binary: ${output}`);
|
|
3586
|
+
}
|
|
3587
|
+
|
|
3588
|
+
//#endregion
|
|
3589
|
+
//#region src/index.ts
|
|
3590
|
+
var import_defineProperty = __toESM(require_defineProperty(), 1);
|
|
3591
|
+
/**
|
|
3592
|
+
*
|
|
3593
|
+
* @usage
|
|
3594
|
+
*
|
|
3595
|
+
* ```ts
|
|
3596
|
+
* const cli = new NapiCli()
|
|
3597
|
+
*
|
|
3598
|
+
* cli.build({
|
|
3599
|
+
* cwd: '/path/to/your/project',
|
|
3600
|
+
* })
|
|
3601
|
+
* ```
|
|
3602
|
+
*/
|
|
3603
|
+
var NapiCli = class {
|
|
3604
|
+
constructor() {
|
|
3605
|
+
(0, import_defineProperty.default)(this, "artifacts", collectArtifacts);
|
|
3606
|
+
(0, import_defineProperty.default)(this, "new", newProject);
|
|
3607
|
+
(0, import_defineProperty.default)(this, "build", buildProject);
|
|
3608
|
+
(0, import_defineProperty.default)(this, "createNpmDirs", createNpmDirs);
|
|
3609
|
+
(0, import_defineProperty.default)(this, "prePublish", prePublish);
|
|
3610
|
+
(0, import_defineProperty.default)(this, "rename", renameProject);
|
|
3611
|
+
(0, import_defineProperty.default)(this, "universalize", universalizeBinaries);
|
|
3612
|
+
(0, import_defineProperty.default)(this, "version", version);
|
|
3613
|
+
}
|
|
3614
|
+
};
|
|
3615
|
+
|
|
3616
|
+
//#endregion
|
|
3617
|
+
export { NapiCli, parseTriple };
|
|
3618
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJuYW1lcyI6WyJfdHlwZW9mIiwibyIsIl90eXBlb2YiLCJ0b1ByaW1pdGl2ZSIsInRvUHJvcGVydHlLZXkiLCJfZGVmaW5lUHJvcGVydHkiLCJvcHRpb25zOiBBcnRpZmFjdHNPcHRpb25zIiwibmFtZXNwYWNlOiBzdHJpbmciLCJkZWJ1ZyIsInBhdGg6IHN0cmluZyIsInBhdGgiLCJwaWNrIiwibzogTyIsInBhcnRpYWw6IFJlY29yZDxzdHJpbmcsIGFueT4iLCJwa2dKc29uIiwiVEFSR0VUX0xJTktFUjogUmVjb3JkPHN0cmluZywgc3RyaW5nPiIsIkNwdVRvTm9kZUFyY2g6IFJlY29yZDxzdHJpbmcsIE5vZGVKU0FyY2g+IiwiU3lzVG9Ob2RlUGxhdGZvcm06IFJlY29yZDxzdHJpbmcsIFBsYXRmb3JtPiIsIlVuaUFyY2hzQnlQbGF0Zm9ybTogUGFydGlhbDxSZWNvcmQ8UGxhdGZvcm0sIE5vZGVKU0FyY2hbXT4+IiwicmF3VHJpcGxlOiBzdHJpbmciLCJjcHU6IHN0cmluZyIsInN5czogc3RyaW5nIiwiYWJpOiBzdHJpbmcgfCBudWxsIiwidGFyZ2V0OiBzdHJpbmciLCJ2OiBzdHJpbmciLCJuYXBpVmVyc2lvbjogTmFwaVZlcnNpb24iLCJ2ZXJzaW9uczogTm9kZVZlcnNpb25bXSIsInJlcXVpcmVtZW50czogc3RyaW5nW10iLCJtYW5pZmVzdFBhdGg6IHN0cmluZyIsInJlc29sdmUiLCJwYXRoOiBzdHJpbmciLCJjb25maWdQYXRoPzogc3RyaW5nIiwicGF0aCIsInNlcGFyYXRlZENvbmZpZzogVXNlck5hcGlDb25maWcgfCB1bmRlZmluZWQiLCJuYXBpQ29uZmlnOiBOYXBpQ29uZmlnIiwidGFyZ2V0czogc3RyaW5nW10iLCJuYW1lOiBzdHJpbmciLCJiaW46IHN0cmluZyIsImJpbiIsIm5hbWUiLCJsaW5lOiBUeXBlRGVmTGluZSIsImNvbnN0RW51bTogYm9vbGVhbiIsImlkZW50OiBudW1iZXIiLCJhbWJpZW50OiBib29sZWFuIiwiaW50ZXJtZWRpYXRlVHlwZUZpbGU6IHN0cmluZyIsImV4cG9ydHM6IHN0cmluZ1tdIiwiZGVmcyIsImZpbGU6IHN0cmluZyIsImRlZnM6IFR5cGVEZWZMaW5lW10iLCJzcmM6IHN0cmluZyIsIm9wdGlvbnM6IE1pbmltYWxOYXBpT3B0aW9ucyIsImRlYnVnIiwidXNlck9wdGlvbnM6IEFydGlmYWN0c09wdGlvbnMiLCJkaXIiLCJyb290OiBzdHJpbmciLCJmaWxlcyIsImxvY2FsTmFtZTogc3RyaW5nIiwicGtnTmFtZTogc3RyaW5nIiwiaWRlbnRzOiBzdHJpbmdbXSIsInR1cGxlOiBzdHJpbmciLCJ3YXNpRmlsZW5hbWU6IHN0cmluZyIsImZzIiwid2FzbUZpbGVOYW1lOiBzdHJpbmciLCJwYWNrYWdlTmFtZTogc3RyaW5nIiwiZnM6IGJvb2xlYW4iLCJmcyIsImRlYnVnIiwicmVxdWlyZSIsInJhd09wdGlvbnM6IEJ1aWxkT3B0aW9ucyIsIm9wdGlvbnM6IFBhcnNlZEJ1aWxkT3B0aW9ucyIsIm1ldGFkYXRhOiBDYXJnb1dvcmtzcGFjZU1ldGFkYXRhIiwiY3JhdGU6IENyYXRlIiwiY29uZmlnOiBOYXBpQ29uZmlnIiwiYWxpYXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4iLCJ2ZXJzaW9uIiwicmVzb2x2ZSIsImFiaTogc3RyaW5nIHwgbnVsbCIsInNldGptcExpYiIsInNldGptcEluY2x1ZGUiLCJ0eXBlRGVmVG1wRm9sZGVyOiBzdHJpbmciLCJleHBvcnRzOiBzdHJpbmdbXSIsImZpbGVzIiwiZXhwb3J0cyIsImlkZW50czogc3RyaW5nW10iLCJuYW1lIiwiZGlzdEZpbGVOYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQgfCBudWxsIiwiZW52OiBzdHJpbmciLCJ2YWx1ZTogc3RyaW5nIiwidmFsdWUiLCJvcHRpb25zOiBDcmVhdGVOcG1EaXJzT3B0aW9ucyIsImRlYnVnIiwidXNlck9wdGlvbnM6IENyZWF0ZU5wbURpcnNPcHRpb25zIiwibWtkaXJBc3luYyIsImRpcjogc3RyaW5nIiwid3JpdGVGaWxlQXN5bmMiLCJmaWxlOiBzdHJpbmciLCJjb250ZW50OiBzdHJpbmciLCJwYWNrYWdlTmFtZTogc3RyaW5nIiwidGFyZ2V0OiBUYXJnZXQiLCJvcHRpb25zOiBOZXdPcHRpb25zIiwiY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbiIsIl9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyIsIl9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjIiwiX2Fzc2VydENsYXNzQnJhbmQiLCJhc3NlcnRDbGFzc0JyYW5kIiwidmFsdWUiLCJ0eXBlIiwidmFsdWUiLCJ2YWx1ZSIsInRhYmxlIiwicGFyc2UiLCJqb2luIiwibWVyZ2UiLCJmbG9hdCIsInBhaXIiLCJwYXJzZSIsIm9wdGlvbnM6IFJlbmFtZU9wdGlvbnMiLCJ1c2VyT3B0aW9uczogUmVuYW1lT3B0aW9ucyIsImRlYnVnIiwicmVzb2x2ZSIsInBhY2thZ2VNYW5hZ2VyOiBTdXBwb3J0ZWRQYWNrYWdlTWFuYWdlciIsImNhY2hlRGlyOiBzdHJpbmciLCJzcmM6IHN0cmluZyIsImRlc3Q6IHN0cmluZyIsImluY2x1ZGVXYXNpQmluZGluZ3M6IGJvb2xlYW4iLCJmaWxlUGF0aDogc3RyaW5nIiwiZW5hYmxlZFRhcmdldHM6IHN0cmluZ1tdIiwidGFyZ2V0OiBzdHJpbmciLCJzZXR0aW5nOiBhbnkiLCJqb2JzVG9SZW1vdmU6IHN0cmluZ1tdIiwibmVlZDogc3RyaW5nIiwib3B0aW9uczogUmF3TmV3T3B0aW9ucyIsInVzZXJPcHRpb25zOiBSYXdOZXdPcHRpb25zIiwicGF0aDogc3RyaW5nIiwic3RhdCIsInBhdGgiLCJmaWxlcyIsIm5hbWU6IHN0cmluZyIsIm9wdGlvbnM6IFByZVB1Ymxpc2hPcHRpb25zIiwib3B0aW9uczogVmVyc2lvbk9wdGlvbnMiLCJkZWJ1ZyIsInVzZXJPcHRpb25zOiBWZXJzaW9uT3B0aW9ucyIsImRlYnVnIiwidXNlck9wdGlvbnM6IFByZVB1Ymxpc2hPcHRpb25zIiwicGFja2FnZU5hbWU6IHN0cmluZyIsInZlcnNpb246IHN0cmluZyIsInBhY2thZ2VOYW1lIiwidmVyc2lvbiIsInJlcG8iLCJvd25lciIsInBrZ0luZm8iLCJvY3Rva2l0IiwicGtnSW5mbzogUGFja2FnZUluZm8gfCB1bmRlZmluZWQiLCJ0YWc6IHN0cmluZyIsIm5hbWUiLCJvcHRpb25zOiBVbml2ZXJzYWxpemVPcHRpb25zIiwidW5pdmVyc2FsaXplcnM6IFBhcnRpYWw8XG4gIFJlY29yZDxOb2RlSlMuUGxhdGZvcm0sIChpbnB1dHM6IHN0cmluZ1tdLCBvdXRwdXQ6IHN0cmluZykgPT4gdm9pZD5cbj4iLCJ1c2VyT3B0aW9uczogVW5pdmVyc2FsaXplT3B0aW9ucyJdLCJzb3VyY2VzIjpbIi4uLy4uL25vZGVfbW9kdWxlcy9Ab3hjLXByb2plY3QvcnVudGltZS9zcmMvaGVscGVycy90eXBlb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG94Yy1wcm9qZWN0L3J1bnRpbWUvc3JjL2hlbHBlcnMvdG9QcmltaXRpdmUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG94Yy1wcm9qZWN0L3J1bnRpbWUvc3JjL2hlbHBlcnMvdG9Qcm9wZXJ0eUtleS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab3hjLXByb2plY3QvcnVudGltZS9zcmMvaGVscGVycy9kZWZpbmVQcm9wZXJ0eS5qcyIsIi4uL3NyYy9kZWYvYXJ0aWZhY3RzLnRzIiwiLi4vc3JjL3V0aWxzL2xvZy50cyIsIi4uL3BhY2thZ2UuanNvbiIsIi4uL3NyYy91dGlscy9taXNjLnRzIiwiLi4vc3JjL3V0aWxzL3RhcmdldC50cyIsIi4uL3NyYy91dGlscy92ZXJzaW9uLnRzIiwiLi4vc3JjL3V0aWxzL21ldGFkYXRhLnRzIiwiLi4vc3JjL3V0aWxzL2NvbmZpZy50cyIsIi4uL3NyYy91dGlscy9jYXJnby50cyIsIi4uL3NyYy91dGlscy90eXBlZ2VuLnRzIiwiLi4vc3JjL3V0aWxzL3JlYWQtY29uZmlnLnRzIiwiLi4vc3JjL2FwaS9hcnRpZmFjdHMudHMiLCIuLi9zcmMvYXBpL3RlbXBsYXRlcy9qcy1iaW5kaW5nLnRzIiwiLi4vc3JjL2FwaS90ZW1wbGF0ZXMvbG9hZC13YXNpLXRlbXBsYXRlLnRzIiwiLi4vc3JjL2FwaS90ZW1wbGF0ZXMvd2FzaS13b3JrZXItdGVtcGxhdGUudHMiLCIuLi9zcmMvYXBpL2J1aWxkLnRzIiwiLi4vc3JjL2RlZi9jcmVhdGUtbnBtLWRpcnMudHMiLCIuLi9zcmMvYXBpL2NyZWF0ZS1ucG0tZGlycy50cyIsIi4uL3NyYy9kZWYvbmV3LnRzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BveGMtcHJvamVjdC9ydW50aW1lL3NyYy9oZWxwZXJzL2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG94Yy1wcm9qZWN0L3J1bnRpbWUvc3JjL2hlbHBlcnMvY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG94Yy1wcm9qZWN0L3J1bnRpbWUvc3JjL2hlbHBlcnMvY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab3hjLXByb2plY3QvcnVudGltZS9zcmMvaGVscGVycy9hc3NlcnRDbGFzc0JyYW5kLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BveGMtcHJvamVjdC9ydW50aW1lL3NyYy9oZWxwZXJzL2NsYXNzUHJpdmF0ZUZpZWxkR2V0Mi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ac3RkL3RvbWwvc3RyaW5naWZ5LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0Bqc3Ivc3RkX19jb2xsZWN0aW9ucy9fdXRpbHMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQGpzci9zdGRfX2NvbGxlY3Rpb25zL2RlZXBfbWVyZ2UuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG94Yy1wcm9qZWN0L3J1bnRpbWUvc3JjL2hlbHBlcnMvY2xhc3NQcml2YXRlRmllbGRTZXQyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BzdGQvdG9tbC9fcGFyc2VyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BzdGQvdG9tbC9wYXJzZS5qcyIsIi4uL3NyYy9kZWYvcmVuYW1lLnRzIiwiLi4vc3JjL2FwaS9yZW5hbWUudHMiLCIuLi9zcmMvYXBpL25ldy50cyIsIi4uL3NyYy9kZWYvcHJlLXB1Ymxpc2gudHMiLCIuLi9zcmMvZGVmL3ZlcnNpb24udHMiLCIuLi9zcmMvYXBpL3ZlcnNpb24udHMiLCIuLi9zcmMvYXBpL3ByZS1wdWJsaXNoLnRzIiwiLi4vc3JjL2RlZi91bml2ZXJzYWxpemUudHMiLCIuLi9zcmMvYXBpL3VuaXZlcnNhbGl6ZS50cyIsIi4uL3NyYy9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJmdW5jdGlvbiBfdHlwZW9mKG8pIHtcbiAgXCJAYmFiZWwvaGVscGVycyAtIHR5cGVvZlwiO1xuXG4gIHJldHVybiBtb2R1bGUuZXhwb3J0cyA9IF90eXBlb2YgPSBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIFN5bWJvbCAmJiBcInN5bWJvbFwiID09IHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPyBmdW5jdGlvbiAobykge1xuICAgIHJldHVybiB0eXBlb2YgbztcbiAgfSA6IGZ1bmN0aW9uIChvKSB7XG4gICAgcmV0dXJuIG8gJiYgXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgby5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG8gIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG87XG4gIH0sIG1vZHVsZS5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlLCBtb2R1bGUuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBtb2R1bGUuZXhwb3J0cywgX3R5cGVvZihvKTtcbn1cbm1vZHVsZS5leHBvcnRzID0gX3R5cGVvZiwgbW9kdWxlLmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWUsIG1vZHVsZS5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IG1vZHVsZS5leHBvcnRzOyIsInZhciBfdHlwZW9mID0gcmVxdWlyZShcIi4vdHlwZW9mLmpzXCIpW1wiZGVmYXVsdFwiXTtcbmZ1bmN0aW9uIHRvUHJpbWl0aXZlKHQsIHIpIHtcbiAgaWYgKFwib2JqZWN0XCIgIT0gX3R5cGVvZih0KSB8fCAhdCkgcmV0dXJuIHQ7XG4gIHZhciBlID0gdFtTeW1ib2wudG9QcmltaXRpdmVdO1xuICBpZiAodm9pZCAwICE9PSBlKSB7XG4gICAgdmFyIGkgPSBlLmNhbGwodCwgciB8fCBcImRlZmF1bHRcIik7XG4gICAgaWYgKFwib2JqZWN0XCIgIT0gX3R5cGVvZihpKSkgcmV0dXJuIGk7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkBAdG9QcmltaXRpdmUgbXVzdCByZXR1cm4gYSBwcmltaXRpdmUgdmFsdWUuXCIpO1xuICB9XG4gIHJldHVybiAoXCJzdHJpbmdcIiA9PT0gciA/IFN0cmluZyA6IE51bWJlcikodCk7XG59XG5tb2R1bGUuZXhwb3J0cyA9IHRvUHJpbWl0aXZlLCBtb2R1bGUuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZSwgbW9kdWxlLmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gbW9kdWxlLmV4cG9ydHM7IiwidmFyIF90eXBlb2YgPSByZXF1aXJlKFwiLi90eXBlb2YuanNcIilbXCJkZWZhdWx0XCJdO1xudmFyIHRvUHJpbWl0aXZlID0gcmVxdWlyZShcIi4vdG9QcmltaXRpdmUuanNcIik7XG5mdW5jdGlvbiB0b1Byb3BlcnR5S2V5KHQpIHtcbiAgdmFyIGkgPSB0b1ByaW1pdGl2ZSh0LCBcInN0cmluZ1wiKTtcbiAgcmV0dXJuIFwic3ltYm9sXCIgPT0gX3R5cGVvZihpKSA/IGkgOiBpICsgXCJcIjtcbn1cbm1vZHVsZS5leHBvcnRzID0gdG9Qcm9wZXJ0eUtleSwgbW9kdWxlLmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWUsIG1vZHVsZS5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IG1vZHVsZS5leHBvcnRzOyIsInZhciB0b1Byb3BlcnR5S2V5ID0gcmVxdWlyZShcIi4vdG9Qcm9wZXJ0eUtleS5qc1wiKTtcbmZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0eShlLCByLCB0KSB7XG4gIHJldHVybiAociA9IHRvUHJvcGVydHlLZXkocikpIGluIGUgPyBPYmplY3QuZGVmaW5lUHJvcGVydHkoZSwgciwge1xuICAgIHZhbHVlOiB0LFxuICAgIGVudW1lcmFibGU6ICEwLFxuICAgIGNvbmZpZ3VyYWJsZTogITAsXG4gICAgd3JpdGFibGU6ICEwXG4gIH0pIDogZVtyXSA9IHQsIGU7XG59XG5tb2R1bGUuZXhwb3J0cyA9IF9kZWZpbmVQcm9wZXJ0eSwgbW9kdWxlLmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWUsIG1vZHVsZS5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IG1vZHVsZS5leHBvcnRzOyIsIi8vIFRoaXMgZmlsZSBpcyBnZW5lcmF0ZWQgYnkgY29kZWdlbi9pbmRleC50c1xuLy8gRG8gbm90IGVkaXQgdGhpcyBmaWxlIG1hbnVhbGx5XG5pbXBvcnQgeyBDb21tYW5kLCBPcHRpb24gfSBmcm9tICdjbGlwYW5pb24nXG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCYXNlQXJ0aWZhY3RzQ29tbWFuZCBleHRlbmRzIENvbW1hbmQge1xuICBzdGF0aWMgcGF0aHMgPSBbWydhcnRpZmFjdHMnXV1cblxuICBzdGF0aWMgdXNhZ2UgPSBDb21tYW5kLlVzYWdlKHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgICdDb3B5IGFydGlmYWN0cyBmcm9tIEdpdGh1YiBBY3Rpb25zIGludG8gbnBtIHBhY2thZ2VzIGFuZCByZWFkeSB0byBwdWJsaXNoJyxcbiAgfSlcblxuICBjd2QgPSBPcHRpb24uU3RyaW5nKCctLWN3ZCcsIHByb2Nlc3MuY3dkKCksIHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgICdUaGUgd29ya2luZyBkaXJlY3Rvcnkgb2Ygd2hlcmUgbmFwaSBjb21tYW5kIHdpbGwgYmUgZXhlY3V0ZWQgaW4sIGFsbCBvdGhlciBwYXRocyBvcHRpb25zIGFyZSByZWxhdGl2ZSB0byB0aGlzIHBhdGgnLFxuICB9KVxuXG4gIGNvbmZpZ1BhdGg/OiBzdHJpbmcgPSBPcHRpb24uU3RyaW5nKCctLWNvbmZpZy1wYXRoLC1jJywge1xuICAgIGRlc2NyaXB0aW9uOiAnUGF0aCB0byBgbmFwaWAgY29uZmlnIGpzb24gZmlsZScsXG4gIH0pXG5cbiAgcGFja2FnZUpzb25QYXRoID0gT3B0aW9uLlN0cmluZygnLS1wYWNrYWdlLWpzb24tcGF0aCcsICdwYWNrYWdlLmpzb24nLCB7XG4gICAgZGVzY3JpcHRpb246ICdQYXRoIHRvIGBwYWNrYWdlLmpzb25gJyxcbiAgfSlcblxuICBvdXRwdXREaXIgPSBPcHRpb24uU3RyaW5nKCctLW91dHB1dC1kaXIsLW8sLWQnLCAnLi9hcnRpZmFjdHMnLCB7XG4gICAgZGVzY3JpcHRpb246XG4gICAgICAnUGF0aCB0byB0aGUgZm9sZGVyIHdoZXJlIGFsbCBidWlsdCBgLm5vZGVgIGZpbGVzIHB1dCwgc2FtZSBhcyBgLS1vdXRwdXQtZGlyYCBvZiBidWlsZCBjb21tYW5kJyxcbiAgfSlcblxuICBucG1EaXIgPSBPcHRpb24uU3RyaW5nKCctLW5wbS1kaXInLCAnbnBtJywge1xuICAgIGRlc2NyaXB0aW9uOiAnUGF0aCB0byB0aGUgZm9sZGVyIHdoZXJlIHRoZSBucG0gcGFja2FnZXMgcHV0JyxcbiAgfSlcblxuICBidWlsZE91dHB1dERpcj86IHN0cmluZyA9IE9wdGlvbi5TdHJpbmcoJy0tYnVpbGQtb3V0cHV0LWRpcicsIHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgICdQYXRoIHRvIHRoZSBidWlsZCBvdXRwdXQgZGlyLCBvbmx5IG5lZWRlZCB3aGVuIHRhcmdldHMgY29udGFpbnMgYHdhc20zMi13YXNpLSpgJyxcbiAgfSlcblxuICBnZXRPcHRpb25zKCkge1xuICAgIHJldHVybiB7XG4gICAgICBjd2Q6IHRoaXMuY3dkLFxuICAgICAgY29uZmlnUGF0aDogdGhpcy5jb25maWdQYXRoLFxuICAgICAgcGFja2FnZUpzb25QYXRoOiB0aGlzLnBhY2thZ2VKc29uUGF0aCxcbiAgICAgIG91dHB1dERpcjogdGhpcy5vdXRwdXREaXIsXG4gICAgICBucG1EaXI6IHRoaXMubnBtRGlyLFxuICAgICAgYnVpbGRPdXRwdXREaXI6IHRoaXMuYnVpbGRPdXRwdXREaXIsXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ29weSBhcnRpZmFjdHMgZnJvbSBHaXRodWIgQWN0aW9ucyBpbnRvIG5wbSBwYWNrYWdlcyBhbmQgcmVhZHkgdG8gcHVibGlzaFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFydGlmYWN0c09wdGlvbnMge1xuICAvKipcbiAgICogVGhlIHdvcmtpbmcgZGlyZWN0b3J5IG9mIHdoZXJlIG5hcGkgY29tbWFuZCB3aWxsIGJlIGV4ZWN1dGVkIGluLCBhbGwgb3RoZXIgcGF0aHMgb3B0aW9ucyBhcmUgcmVsYXRpdmUgdG8gdGhpcyBwYXRoXG4gICAqXG4gICAqIEBkZWZhdWx0IHByb2Nlc3MuY3dkKClcbiAgICovXG4gIGN3ZD86IHN0cmluZ1xuICAvKipcbiAgICogUGF0aCB0byBgbmFwaWAgY29uZmlnIGpzb24gZmlsZVxuICAgKi9cbiAgY29uZmlnUGF0aD86IHN0cmluZ1xuICAvKipcbiAgICogUGF0aCB0byBgcGFja2FnZS5qc29uYFxuICAgKlxuICAgKiBAZGVmYXVsdCAncGFja2FnZS5qc29uJ1xuICAgKi9cbiAgcGFja2FnZUpzb25QYXRoPzogc3RyaW5nXG4gIC8qKlxuICAgKiBQYXRoIHRvIHRoZSBmb2xkZXIgd2hlcmUgYWxsIGJ1aWx0IGAubm9kZWAgZmlsZXMgcHV0LCBzYW1lIGFzIGAtLW91dHB1dC1kaXJgIG9mIGJ1aWxkIGNvbW1hbmRcbiAgICpcbiAgICogQGRlZmF1bHQgJy4vYXJ0aWZhY3RzJ1xuICAgKi9cbiAgb3V0cHV0RGlyPzogc3RyaW5nXG4gIC8qKlxuICAgKiBQYXRoIHRvIHRoZSBmb2xkZXIgd2hlcmUgdGhlIG5wbSBwYWNrYWdlcyBwdXRcbiAgICpcbiAgICogQGRlZmF1bHQgJ25wbSdcbiAgICovXG4gIG5wbURpcj86IHN0cmluZ1xuICAvKipcbiAgICogUGF0aCB0byB0aGUgYnVpbGQgb3V0cHV0IGRpciwgb25seSBuZWVkZWQgd2hlbiB0YXJnZXRzIGNvbnRhaW5zIGB3YXNtMzItd2FzaS0qYFxuICAgKi9cbiAgYnVpbGRPdXRwdXREaXI/OiBzdHJpbmdcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5RGVmYXVsdEFydGlmYWN0c09wdGlvbnMob3B0aW9uczogQXJ0aWZhY3RzT3B0aW9ucykge1xuICByZXR1cm4ge1xuICAgIGN3ZDogcHJvY2Vzcy5jd2QoKSxcbiAgICBwYWNrYWdlSnNvblBhdGg6ICdwYWNrYWdlLmpzb24nLFxuICAgIG91dHB1dERpcjogJy4vYXJ0aWZhY3RzJyxcbiAgICBucG1EaXI6ICducG0nLFxuICAgIC4uLm9wdGlvbnMsXG4gIH1cbn1cbiIsImltcG9ydCAqIGFzIGNvbG9ycyBmcm9tICdjb2xvcmV0dGUnXG5pbXBvcnQgcmF3RGVidWcgZnJvbSAnZGVidWcnXG5cbi8vIGRlYnVnKCclaScsICdUaGlzIGlzIGFuIGluZm8nKVxucmF3RGVidWcuZm9ybWF0dGVycy5pID0gKHYpID0+IHtcbiAgcmV0dXJuIGNvbG9ycy5ncmVlbih2KVxufVxuXG5kZWNsYXJlIG1vZHVsZSAnZGVidWcnIHtcbiAgaW50ZXJmYWNlIERlYnVnZ2VyIHtcbiAgICBpbmZvOiB0eXBlb2YgY29uc29sZS5lcnJvclxuICAgIHdhcm46IHR5cGVvZiBjb25zb2xlLmVycm9yXG4gICAgZXJyb3I6IHR5cGVvZiBjb25zb2xlLmVycm9yXG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGRlYnVnRmFjdG9yeSA9IChuYW1lc3BhY2U6IHN0cmluZykgPT4ge1xuICBjb25zdCBkZWJ1ZyA9IHJhd0RlYnVnKGBuYXBpOiR7bmFtZXNwYWNlfWApXG5cbiAgZGVidWcuaW5mbyA9ICguLi5hcmdzOiBhbnlbXSkgPT5cbiAgICBjb25zb2xlLmVycm9yKGNvbG9ycy5ibGFjayhjb2xvcnMuYmdHcmVlbignIElORk8gJykpLCAuLi5hcmdzKVxuICBkZWJ1Zy53YXJuID0gKC4uLmFyZ3M6IGFueVtdKSA9PlxuICAgIGNvbnNvbGUuZXJyb3IoY29sb3JzLmJsYWNrKGNvbG9ycy5iZ1llbGxvdygnIFdBUk5JTkcgJykpLCAuLi5hcmdzKVxuICBkZWJ1Zy5lcnJvciA9ICguLi5hcmdzOiBhbnlbXSkgPT5cbiAgICBjb25zb2xlLmVycm9yKFxuICAgICAgY29sb3JzLndoaXRlKGNvbG9ycy5iZ1JlZCgnIEVSUk9SICcpKSxcbiAgICAgIC4uLmFyZ3MubWFwKChhcmcpID0+XG4gICAgICAgIGFyZyBpbnN0YW5jZW9mIEVycm9yID8gKGFyZy5zdGFjayA/PyBhcmcubWVzc2FnZSkgOiBhcmcsXG4gICAgICApLFxuICAgIClcblxuICByZXR1cm4gZGVidWdcbn1cbmV4cG9ydCBjb25zdCBkZWJ1ZyA9IGRlYnVnRmFjdG9yeSgndXRpbHMnKVxuIiwie1xuICBcIm5hbWVcIjogXCJAbmFwaS1ycy9jbGlcIixcbiAgXCJ2ZXJzaW9uXCI6IFwiMy4wLjAtYWxwaGEuOTFcIixcbiAgXCJkZXNjcmlwdGlvblwiOiBcIkNsaSB0b29scyBmb3IgbmFwaS1yc1wiLFxuICBcImF1dGhvclwiOiBcIkxvbmdZaW5hbiA8bHlud2VrbG1AZ21haWwuY29tPlwiLFxuICBcImhvbWVwYWdlXCI6IFwiaHR0cHM6Ly9naXRodWIuY29tL25hcGktcnMvbmFwaS1yc1wiLFxuICBcImxpY2Vuc2VcIjogXCJNSVRcIixcbiAgXCJ0eXBlXCI6IFwibW9kdWxlXCIsXG4gIFwiZW5naW5lc1wiOiB7XG4gICAgXCJub2RlXCI6IFwiPj0gMTZcIlxuICB9LFxuICBcImJpblwiOiB7XG4gICAgXCJuYXBpXCI6IFwiLi9kaXN0L2NsaS5qc1wiLFxuICAgIFwibmFwaS1yYXdcIjogXCIuL2NsaS5tanNcIlxuICB9LFxuICBcIm1haW5cIjogXCIuL2Rpc3QvaW5kZXguY2pzXCIsXG4gIFwibW9kdWxlXCI6IFwiLi9kaXN0L2luZGV4LmpzXCIsXG4gIFwiZXhwb3J0c1wiOiB7XG4gICAgXCIuXCI6IHtcbiAgICAgIFwiaW1wb3J0XCI6IHtcbiAgICAgICAgXCJ0eXBlc1wiOiBcIi4vZGlzdC9pbmRleC5kLnRzXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBcIi4vZGlzdC9pbmRleC5qc1wiXG4gICAgICB9LFxuICAgICAgXCJyZXF1aXJlXCI6IHtcbiAgICAgICAgXCJ0eXBlc1wiOiBcIi4vZGlzdC9pbmRleC5kLnRzXCIsXG4gICAgICAgIFwiZGVmYXVsdFwiOiBcIi4vZGlzdC9pbmRleC5janNcIlxuICAgICAgfVxuICAgIH0sXG4gICAgXCIuL3BhY2thZ2UuanNvblwiOiB7XG4gICAgICBcImltcG9ydFwiOiBcIi4vcGFja2FnZS5qc29uXCIsXG4gICAgICBcInJlcXVpcmVcIjogXCIuL3BhY2thZ2UuanNvblwiXG4gICAgfVxuICB9LFxuICBcImZpbGVzXCI6IFtcbiAgICBcImRpc3RcIixcbiAgICBcInNyY1wiXG4gIF0sXG4gIFwia2V5d29yZHNcIjogW1xuICAgIFwiY2xpXCIsXG4gICAgXCJydXN0XCIsXG4gICAgXCJuYXBpXCIsXG4gICAgXCJuLWFwaVwiLFxuICAgIFwibm9kZS1hcGlcIixcbiAgICBcIm5vZGUtYWRkb25cIixcbiAgICBcIm5lb25cIlxuICBdLFxuICBcIm1haW50YWluZXJzXCI6IFtcbiAgICB7XG4gICAgICBcIm5hbWVcIjogXCJMb25nWWluYW5cIixcbiAgICAgIFwiZW1haWxcIjogXCJseW53ZWtsbUBnbWFpbC5jb21cIixcbiAgICAgIFwiaG9tZXBhZ2VcIjogXCJodHRwczovL2dpdGh1Yi5jb20vQnJvb29vb29rbHluXCJcbiAgICB9LFxuICAgIHtcbiAgICAgIFwibmFtZVwiOiBcImZvcmVoYWxvXCIsXG4gICAgICBcImhvbWVwYWdlXCI6IFwiaHR0cHM6Ly9naXRodWIuY29tL2ZvcmVoYWxvXCJcbiAgICB9XG4gIF0sXG4gIFwicmVwb3NpdG9yeVwiOiB7XG4gICAgXCJ0eXBlXCI6IFwiZ2l0XCIsXG4gICAgXCJ1cmxcIjogXCJnaXQraHR0cHM6Ly9naXRodWIuY29tL25hcGktcnMvbmFwaS1ycy5naXRcIlxuICB9LFxuICBcInB1Ymxpc2hDb25maWdcIjoge1xuICAgIFwicmVnaXN0cnlcIjogXCJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9cIixcbiAgICBcImFjY2Vzc1wiOiBcInB1YmxpY1wiXG4gIH0sXG4gIFwiYnVnc1wiOiB7XG4gICAgXCJ1cmxcIjogXCJodHRwczovL2dpdGh1Yi5jb20vbmFwaS1ycy9uYXBpLXJzL2lzc3Vlc1wiXG4gIH0sXG4gIFwiZGVwZW5kZW5jaWVzXCI6IHtcbiAgICBcIkBpbnF1aXJlci9wcm9tcHRzXCI6IFwiXjcuNC4wXCIsXG4gICAgXCJAbmFwaS1ycy9jcm9zcy10b29sY2hhaW5cIjogXCJeMC4wLjE5XCIsXG4gICAgXCJAbmFwaS1ycy93YXNtLXRvb2xzXCI6IFwiXjAuMC4zXCIsXG4gICAgXCJAb2N0b2tpdC9yZXN0XCI6IFwiXjIyLjAuMFwiLFxuICAgIFwiY2xpcGFuaW9uXCI6IFwiXjQuMC4wLXJjLjRcIixcbiAgICBcImNvbG9yZXR0ZVwiOiBcIl4yLjAuMjBcIixcbiAgICBcImRlYnVnXCI6IFwiXjQuNC4wXCIsXG4gICAgXCJlbW5hcGlcIjogXCJeMS40LjBcIixcbiAgICBcImZpbmQtdXBcIjogXCJeNy4wLjBcIixcbiAgICBcImpzLXlhbWxcIjogXCJeNC4xLjBcIixcbiAgICBcImxvZGFzaC1lc1wiOiBcIl40LjE3LjIxXCIsXG4gICAgXCJzZW12ZXJcIjogXCJeNy43LjFcIixcbiAgICBcInR5cGFuaW9uXCI6IFwiXjMuMTQuMFwiLFxuICAgIFwid2FzbS1zamxqXCI6IFwiXjEuMC42XCJcbiAgfSxcbiAgXCJkZXZEZXBlbmRlbmNpZXNcIjoge1xuICAgIFwiQGVtbmFwaS9jb3JlXCI6IFwiXjEuNC4wXCIsXG4gICAgXCJAZW1uYXBpL3J1bnRpbWVcIjogXCJeMS40LjBcIixcbiAgICBcIkBveGMtbm9kZS9jb3JlXCI6IFwiXjAuMC4yOVwiLFxuICAgIFwiQHN0ZC90b21sXCI6IFwibnBtOkBqc3Ivc3RkX190b21sQF4xLjAuOFwiLFxuICAgIFwiQHR5cGVzL2RlYnVnXCI6IFwiXjQuMS4xMlwiLFxuICAgIFwiQHR5cGVzL2lucXVpcmVyXCI6IFwiXjkuMC43XCIsXG4gICAgXCJAdHlwZXMvanMteWFtbFwiOiBcIl40LjAuOVwiLFxuICAgIFwiQHR5cGVzL2xvZGFzaC1lc1wiOiBcIl40LjE3LjEyXCIsXG4gICAgXCJAdHlwZXMvbm9kZVwiOiBcIl4yMi4xMy4xNlwiLFxuICAgIFwiQHR5cGVzL3NlbXZlclwiOiBcIl43LjcuMFwiLFxuICAgIFwiYXZhXCI6IFwiXjYuMi4wXCIsXG4gICAgXCJlbnYtcGF0aHNcIjogXCJeMy4wLjBcIixcbiAgICBcInByZXR0aWVyXCI6IFwiXjMuNS4zXCIsXG4gICAgXCJyb2xsZG93blwiOiBcIl4xLjAuMC1iZXRhLjE5XCIsXG4gICAgXCJ0c2xpYlwiOiBcIl4yLjguMVwiLFxuICAgIFwidHlwZXNjcmlwdFwiOiBcIl41LjguMlwiXG4gIH0sXG4gIFwicGVlckRlcGVuZGVuY2llc1wiOiB7XG4gICAgXCJAZW1uYXBpL3J1bnRpbWVcIjogXCJeMS4xLjBcIixcbiAgICBcImVtbmFwaVwiOiBcIl4xLjEuMFwiXG4gIH0sXG4gIFwicGVlckRlcGVuZGVuY2llc01ldGFcIjoge1xuICAgIFwiQGVtbmFwaS9ydW50aW1lXCI6IHtcbiAgICAgIFwib3B0aW9uYWxcIjogdHJ1ZVxuICAgIH0sXG4gICAgXCJlbW5hcGlcIjoge1xuICAgICAgXCJvcHRpb25hbFwiOiB0cnVlXG4gICAgfVxuICB9LFxuICBcImZ1bmRpbmdcIjoge1xuICAgIFwidHlwZVwiOiBcImdpdGh1YlwiLFxuICAgIFwidXJsXCI6IFwiaHR0cHM6Ly9naXRodWIuY29tL3Nwb25zb3JzL0Jyb29vb29va2x5blwiXG4gIH0sXG4gIFwic2NyaXB0c1wiOiB7XG4gICAgXCJjbGVhblwiOiBcIm5vZGUgLS1pbXBvcnQgQG94Yy1ub2RlL2NvcmUvcmVnaXN0ZXIgLi9jbGVhbi50c1wiLFxuICAgIFwiY29kZWdlblwiOiBcIm5vZGUgLS1pbXBvcnQgQG94Yy1ub2RlL2NvcmUvcmVnaXN0ZXIgLi9jb2RlZ2VuL2luZGV4LnRzXCIsXG4gICAgXCJidWlsZFwiOiBcInRzYyAmJiB5YXJuIGNsZWFuICYmIHJvbGxkb3duIC1jIHJvbGxkb3duLmNvbmZpZy5qc1wiLFxuICAgIFwidGVzdFwiOiBcIm5vZGUgLS1pbXBvcnQgQG94Yy1ub2RlL2NvcmUvcmVnaXN0ZXIgLi4vbm9kZV9tb2R1bGVzL2F2YS9lbnRyeXBvaW50cy9jbGkubWpzXCJcbiAgfSxcbiAgXCJhdmFcIjoge1xuICAgIFwiZXh0ZW5zaW9uc1wiOiB7XG4gICAgICBcInRzXCI6IFwibW9kdWxlXCJcbiAgICB9LFxuICAgIFwidGltZW91dFwiOiBcIjFtXCIsXG4gICAgXCJmaWxlc1wiOiBbXG4gICAgICBcIioqL19fdGVzdHNfXy8qKi8qLnNwZWMudHNcIixcbiAgICAgIFwiZTJlLyoqLyouc3BlYy50c1wiXG4gICAgXVxuICB9LFxuICBcImdpdEhlYWRcIjogXCI3MWRhNWI2ZGMxNzA2NGU0NzhlNWJlYjBmZmE3MWY3M2Q2MjM4ZjdkXCJcbn1cbiIsImltcG9ydCB7XG4gIHJlYWRGaWxlLFxuICB3cml0ZUZpbGUsXG4gIGNvcHlGaWxlLFxuICBta2RpcixcbiAgdW5saW5rLFxuICBzdGF0LFxuICByZWFkZGlyLFxufSBmcm9tICdub2RlOmZzJ1xuaW1wb3J0IHsgcHJvbWlzaWZ5IH0gZnJvbSAnbm9kZTp1dGlsJ1xuXG5pbXBvcnQgcGtnSnNvbiBmcm9tICcuLi8uLi9wYWNrYWdlLmpzb24nIHdpdGggeyB0eXBlOiAnanNvbicgfVxuaW1wb3J0IHsgZGVidWcgfSBmcm9tICcuL2xvZy5qcydcblxuZXhwb3J0IGNvbnN0IHJlYWRGaWxlQXN5bmMgPSBwcm9taXNpZnkocmVhZEZpbGUpXG5leHBvcnQgY29uc3Qgd3JpdGVGaWxlQXN5bmMgPSBwcm9taXNpZnkod3JpdGVGaWxlKVxuZXhwb3J0IGNvbnN0IHVubGlua0FzeW5jID0gcHJvbWlzaWZ5KHVubGluaylcbmV4cG9ydCBjb25zdCBjb3B5RmlsZUFzeW5jID0gcHJvbWlzaWZ5KGNvcHlGaWxlKVxuZXhwb3J0IGNvbnN0IG1rZGlyQXN5bmMgPSBwcm9taXNpZnkobWtkaXIpXG5leHBvcnQgY29uc3Qgc3RhdEFzeW5jID0gcHJvbWlzaWZ5KHN0YXQpXG5leHBvcnQgY29uc3QgcmVhZGRpckFzeW5jID0gcHJvbWlzaWZ5KHJlYWRkaXIpXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmaWxlRXhpc3RzKHBhdGg6IHN0cmluZykge1xuICBjb25zdCBleGlzdHMgPSBhd2FpdCBzdGF0QXN5bmMocGF0aClcbiAgICAudGhlbigoKSA9PiB0cnVlKVxuICAgIC5jYXRjaCgoKSA9PiBmYWxzZSlcbiAgcmV0dXJuIGV4aXN0c1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGlyRXhpc3RzQXN5bmMocGF0aDogc3RyaW5nKSB7XG4gIHRyeSB7XG4gICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBzdGF0QXN5bmMocGF0aClcbiAgICByZXR1cm4gc3RhdHMuaXNEaXJlY3RvcnkoKVxuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcGljazxPLCBLIGV4dGVuZHMga2V5b2YgTz4obzogTywgLi4ua2V5czogS1tdKTogUGljazxPLCBLPiB7XG4gIHJldHVybiBrZXlzLnJlZHVjZSgoYWNjLCBrZXkpID0+IHtcbiAgICBhY2Nba2V5XSA9IG9ba2V5XVxuICAgIHJldHVybiBhY2NcbiAgfSwge30gYXMgTylcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZVBhY2thZ2VKc29uKFxuICBwYXRoOiBzdHJpbmcsXG4gIHBhcnRpYWw6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4pIHtcbiAgY29uc3QgZXhpc3RzID0gYXdhaXQgZmlsZUV4aXN0cyhwYXRoKVxuICBpZiAoIWV4aXN0cykge1xuICAgIGRlYnVnKGBGaWxlIG5vdCBleGlzdHMgJHtwYXRofWApXG4gICAgcmV0dXJuXG4gIH1cbiAgY29uc3Qgb2xkID0gSlNPTi5wYXJzZShhd2FpdCByZWFkRmlsZUFzeW5jKHBhdGgsICd1dGY4JykpXG4gIGF3YWl0IHdyaXRlRmlsZUFzeW5jKHBhdGgsIEpTT04uc3RyaW5naWZ5KHsgLi4ub2xkLCAuLi5wYXJ0aWFsIH0sIG51bGwsIDIpKVxufVxuXG5leHBvcnQgY29uc3QgQ0xJX1ZFUlNJT04gPSBwa2dKc29uLnZlcnNpb25cbiIsImltcG9ydCB7IGV4ZWNTeW5jIH0gZnJvbSAnbm9kZTpjaGlsZF9wcm9jZXNzJ1xuXG5leHBvcnQgdHlwZSBQbGF0Zm9ybSA9IE5vZGVKUy5QbGF0Zm9ybSB8ICd3YXNtJyB8ICd3YXNpJ1xuXG5leHBvcnQgY29uc3QgVU5JVkVSU0FMX1RBUkdFVFMgPSB7XG4gICd1bml2ZXJzYWwtYXBwbGUtZGFyd2luJzogWydhYXJjaDY0LWFwcGxlLWRhcndpbicsICd4ODZfNjQtYXBwbGUtZGFyd2luJ10sXG59IGFzIGNvbnN0XG5cbmV4cG9ydCBjb25zdCBBVkFJTEFCTEVfVEFSR0VUUyA9IFtcbiAgJ2FhcmNoNjQtYXBwbGUtZGFyd2luJyxcbiAgJ2FhcmNoNjQtbGludXgtYW5kcm9pZCcsXG4gICdhYXJjaDY0LXVua25vd24tbGludXgtZ251JyxcbiAgJ2FhcmNoNjQtdW5rbm93bi1saW51eC1tdXNsJyxcbiAgJ2FhcmNoNjQtcGMtd2luZG93cy1tc3ZjJyxcbiAgJ3g4Nl82NC1hcHBsZS1kYXJ3aW4nLFxuICAneDg2XzY0LXBjLXdpbmRvd3MtbXN2YycsXG4gICd4ODZfNjQtdW5rbm93bi1saW51eC1nbnUnLFxuICAneDg2XzY0LXVua25vd24tbGludXgtbXVzbCcsXG4gICd4ODZfNjQtdW5rbm93bi1mcmVlYnNkJyxcbiAgJ2k2ODYtcGMtd2luZG93cy1tc3ZjJyxcbiAgJ2FybXY3LXVua25vd24tbGludXgtZ251ZWFiaWhmJyxcbiAgJ2FybXY3LXVua25vd24tbGludXgtbXVzbGVhYmloZicsXG4gICdhcm12Ny1saW51eC1hbmRyb2lkZWFiaScsXG4gICd1bml2ZXJzYWwtYXBwbGUtZGFyd2luJyxcbiAgJ3Jpc2N2NjRnYy11bmtub3duLWxpbnV4LWdudScsXG4gICdwb3dlcnBjNjRsZS11bmtub3duLWxpbnV4LWdudScsXG4gICdzMzkweC11bmtub3duLWxpbnV4LWdudScsXG4gICd3YXNtMzItd2FzaS1wcmV2aWV3MS10aHJlYWRzJyxcbl0gYXMgY29uc3RcblxuZXhwb3J0IHR5cGUgVGFyZ2V0VHJpcGxlID0gKHR5cGVvZiBBVkFJTEFCTEVfVEFSR0VUUylbbnVtYmVyXVxuXG5leHBvcnQgY29uc3QgREVGQVVMVF9UQVJHRVRTID0gW1xuICAneDg2XzY0LWFwcGxlLWRhcndpbicsXG4gICdhYXJjaDY0LWFwcGxlLWRhcndpbicsXG4gICd4ODZfNjQtcGMtd2luZG93cy1tc3ZjJyxcbiAgJ3g4Nl82NC11bmtub3duLWxpbnV4LWdudScsXG5dIGFzIGNvbnN0XG5cbmV4cG9ydCBjb25zdCBUQVJHRVRfTElOS0VSOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAnYWFyY2g2NC11bmtub3duLWxpbnV4LW11c2wnOiAnYWFyY2g2NC1saW51eC1tdXNsLWdjYycsXG4gICdyaXNjdjY0Z2MtdW5rbm93bi1saW51eC1nbnUnOiAncmlzY3Y2NC1saW51eC1nbnUtZ2NjJyxcbiAgJ3Bvd2VycGM2NGxlLXVua25vd24tbGludXgtZ251JzogJ3Bvd2VycGM2NGxlLWxpbnV4LWdudS1nY2MnLFxuICAnczM5MHgtdW5rbm93bi1saW51eC1nbnUnOiAnczM5MHgtbGludXgtZ251LWdjYycsXG59XG5cbi8vIGh0dHBzOi8vbm9kZWpzLm9yZy9hcGkvcHJvY2Vzcy5odG1sI3Byb2Nlc3NfcHJvY2Vzc19hcmNoXG50eXBlIE5vZGVKU0FyY2ggPVxuICB8ICdhcm0nXG4gIHwgJ2FybTY0J1xuICB8ICdpYTMyJ1xuICB8ICdtaXBzJ1xuICB8ICdtaXBzZWwnXG4gIHwgJ3BwYydcbiAgfCAncHBjNjQnXG4gIHwgJ3Jpc2N2NjQnXG4gIHwgJ3MzOTAnXG4gIHwgJ3MzOTB4J1xuICB8ICd4MzInXG4gIHwgJ3g2NCdcbiAgfCAndW5pdmVyc2FsJ1xuICB8ICd3YXNtMzInXG5cbmNvbnN0IENwdVRvTm9kZUFyY2g6IFJlY29yZDxzdHJpbmcsIE5vZGVKU0FyY2g+ID0ge1xuICB4ODZfNjQ6ICd4NjQnLFxuICBhYXJjaDY0OiAnYXJtNjQnLFxuICBpNjg2OiAnaWEzMicsXG4gIGFybXY3OiAnYXJtJyxcbiAgcmlzY3Y2NGdjOiAncmlzY3Y2NCcsXG4gIHBvd2VycGM2NGxlOiAncHBjNjQnLFxufVxuXG5leHBvcnQgY29uc3QgTm9kZUFyY2hUb0NwdTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgeDY0OiAneDg2XzY0JyxcbiAgYXJtNjQ6ICdhYXJjaDY0JyxcbiAgaWEzMjogJ2k2ODYnLFxuICBhcm06ICdhcm12NycsXG4gIHJpc2N2NjQ6ICdyaXNjdjY0Z2MnLFxuICBwcGM2NDogJ3Bvd2VycGM2NGxlJyxcbn1cblxuY29uc3QgU3lzVG9Ob2RlUGxhdGZvcm06IFJlY29yZDxzdHJpbmcsIFBsYXRmb3JtPiA9IHtcbiAgbGludXg6ICdsaW51eCcsXG4gIGZyZWVic2Q6ICdmcmVlYnNkJyxcbiAgZGFyd2luOiAnZGFyd2luJyxcbiAgd2luZG93czogJ3dpbjMyJyxcbn1cblxuZXhwb3J0IGNvbnN0IFVuaUFyY2hzQnlQbGF0Zm9ybTogUGFydGlhbDxSZWNvcmQ8UGxhdGZvcm0sIE5vZGVKU0FyY2hbXT4+ID0ge1xuICBkYXJ3aW46IFsneDY0JywgJ2FybTY0J10sXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGFyZ2V0IHtcbiAgdHJpcGxlOiBzdHJpbmdcbiAgcGxhdGZvcm1BcmNoQUJJOiBzdHJpbmdcbiAgcGxhdGZvcm06IFBsYXRmb3JtXG4gIGFyY2g6IE5vZGVKU0FyY2hcbiAgYWJpOiBzdHJpbmcgfCBudWxsXG59XG5cbi8qKlxuICogQSB0cmlwbGUgaXMgYSBzcGVjaWZpYyBmb3JtYXQgZm9yIHNwZWNpZnlpbmcgYSB0YXJnZXQgYXJjaGl0ZWN0dXJlLlxuICogVHJpcGxlcyBtYXkgYmUgcmVmZXJyZWQgdG8gYXMgYSB0YXJnZXQgdHJpcGxlIHdoaWNoIGlzIHRoZSBhcmNoaXRlY3R1cmUgZm9yIHRoZSBhcnRpZmFjdCBwcm9kdWNlZCwgYW5kIHRoZSBob3N0IHRyaXBsZSB3aGljaCBpcyB0aGUgYXJjaGl0ZWN0dXJlIHRoYXQgdGhlIGNvbXBpbGVyIGlzIHJ1bm5pbmcgb24uXG4gKiBUaGUgZ2VuZXJhbCBmb3JtYXQgb2YgdGhlIHRyaXBsZSBpcyBgPGFyY2g+PHN1Yj4tPHZlbmRvcj4tPHN5cz4tPGFiaT5gIHdoZXJlOlxuICogICAtIGBhcmNoYCA9IFRoZSBiYXNlIENQVSBhcmNoaXRlY3R1cmUsIGZvciBleGFtcGxlIGB4ODZfNjRgLCBgaTY4NmAsIGBhcm1gLCBgdGh1bWJgLCBgbWlwc2AsIGV0Yy5cbiAqICAgLSBgc3ViYCA9IFRoZSBDUFUgc3ViLWFyY2hpdGVjdHVyZSwgZm9yIGV4YW1wbGUgYGFybWAgaGFzIGB2N2AsIGB2N3NgLCBgdjV0ZWAsIGV0Yy5cbiAqICAgLSBgdmVuZG9yYCA9IFRoZSB2ZW5kb3IsIGZvciBleGFtcGxlIGB1bmtub3duYCwgYGFwcGxlYCwgYHBjYCwgYG52aWRpYWAsIGV0Yy5cbiAqICAgLSBgc3lzYCA9IFRoZSBzeXN0ZW0gbmFtZSwgZm9yIGV4YW1wbGUgYGxpbnV4YCwgYHdpbmRvd3NgLCBgZGFyd2luYCwgZXRjLiBub25lIGlzIHR5cGljYWxseSB1c2VkIGZvciBiYXJlLW1ldGFsIHdpdGhvdXQgYW4gT1MuXG4gKiAgIC0gYGFiaWAgPSBUaGUgQUJJLCBmb3IgZXhhbXBsZSBgZ251YCwgYGFuZHJvaWRgLCBgZWFiaWAsIGV0Yy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlVHJpcGxlKHJhd1RyaXBsZTogc3RyaW5nKTogVGFyZ2V0IHtcbiAgaWYgKFxuICAgIHJhd1RyaXBsZSA9PT0gJ3dhc20zMi13YXNpJyB8fFxuICAgIHJhd1RyaXBsZSA9PT0gJ3dhc20zMi13YXNpLXByZXZpZXcxLXRocmVhZHMnIHx8XG4gICAgcmF3VHJpcGxlLnN0YXJ0c1dpdGgoJ3dhc20zMi13YXNpcCcpXG4gICkge1xuICAgIHJldHVybiB7XG4gICAgICB0cmlwbGU6IHJhd1RyaXBsZSxcbiAgICAgIHBsYXRmb3JtQXJjaEFCSTogJ3dhc20zMi13YXNpJyxcbiAgICAgIHBsYXRmb3JtOiAnd2FzaScsXG4gICAgICBhcmNoOiAnd2FzbTMyJyxcbiAgICAgIGFiaTogJ3dhc2knLFxuICAgIH1cbiAgfVxuICBjb25zdCB0cmlwbGUgPSByYXdUcmlwbGUuZW5kc1dpdGgoJ2VhYmknKVxuICAgID8gYCR7cmF3VHJpcGxlLnNsaWNlKDAsIC00KX0tZWFiaWBcbiAgICA6IHJhd1RyaXBsZVxuICBjb25zdCB0cmlwbGVzID0gdHJpcGxlLnNwbGl0KCctJylcbiAgbGV0IGNwdTogc3RyaW5nXG4gIGxldCBzeXM6IHN0cmluZ1xuICBsZXQgYWJpOiBzdHJpbmcgfCBudWxsID0gbnVsbFxuICBpZiAodHJpcGxlcy5sZW5ndGggPT09IDIpIHtcbiAgICAvLyBhYXJjaDY0LWZ1Y2hzaWFcbiAgICAvLyBeIGNwdSAgIF4gc3lzXG4gICAgO1tjcHUsIHN5c10gPSB0cmlwbGVzXG4gIH0gZWxzZSB7XG4gICAgLy8gYWFyY2g2NC11bmtub3duLWxpbnV4LW11c2xcbiAgICAvLyBeIGNwdSAgICAgICAgICAgXiBzeXMgXiBhYmlcbiAgICAvLyBhYXJjaDY0LWFwcGxlLWRhcndpblxuICAgIC8vIF4gY3B1ICAgICAgICAgXiBzeXMgIChhYmkgaXMgTm9uZSlcbiAgICA7W2NwdSwgLCBzeXMsIGFiaSA9IG51bGxdID0gdHJpcGxlc1xuICB9XG5cbiAgY29uc3QgcGxhdGZvcm0gPSBTeXNUb05vZGVQbGF0Zm9ybVtzeXNdID8/IChzeXMgYXMgUGxhdGZvcm0pXG4gIGNvbnN0IGFyY2ggPSBDcHVUb05vZGVBcmNoW2NwdV0gPz8gKGNwdSBhcyBOb2RlSlNBcmNoKVxuICByZXR1cm4ge1xuICAgIHRyaXBsZTogcmF3VHJpcGxlLFxuICAgIHBsYXRmb3JtQXJjaEFCSTogYWJpID8gYCR7cGxhdGZvcm19LSR7YXJjaH0tJHthYml9YCA6IGAke3BsYXRmb3JtfS0ke2FyY2h9YCxcbiAgICBwbGF0Zm9ybSxcbiAgICBhcmNoLFxuICAgIGFiaSxcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3lzdGVtRGVmYXVsdFRhcmdldCgpOiBUYXJnZXQge1xuICBjb25zdCBob3N0ID0gZXhlY1N5bmMoYHJ1c3RjIC12VmAsIHtcbiAgICBlbnY6IHByb2Nlc3MuZW52LFxuICB9KVxuICAgIC50b1N0cmluZygndXRmOCcpXG4gICAgLnNwbGl0KCdcXG4nKVxuICAgIC5maW5kKChsaW5lKSA9PiBsaW5lLnN0YXJ0c1dpdGgoJ2hvc3Q6ICcpKVxuICBjb25zdCB0cmlwbGUgPSBob3N0Py5zbGljZSgnaG9zdDogJy5sZW5ndGgpXG4gIGlmICghdHJpcGxlKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgQ2FuIG5vdCBwYXJzZSB0YXJnZXQgdHJpcGxlIGZyb20gaG9zdGApXG4gIH1cbiAgcmV0dXJuIHBhcnNlVHJpcGxlKHRyaXBsZSlcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFRhcmdldExpbmtlcih0YXJnZXQ6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBUQVJHRVRfTElOS0VSW3RhcmdldF1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRhcmdldFRvRW52VmFyKHRhcmdldDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHRhcmdldC5yZXBsYWNlKC8tL2csICdfJykudG9VcHBlckNhc2UoKVxufVxuIiwiZXhwb3J0IGVudW0gTmFwaVZlcnNpb24ge1xuICBOYXBpMSA9IDEsXG4gIE5hcGkyLFxuICBOYXBpMyxcbiAgTmFwaTQsXG4gIE5hcGk1LFxuICBOYXBpNixcbiAgTmFwaTcsXG4gIE5hcGk4LFxuICBOYXBpOSxcbn1cblxuLy8vIGJlY2F1c2Ugbm9kZSBzdXBwb3J0IG5ldyBuYXBpIHZlcnNpb24gaW4gc29tZSBtaW5vciB2ZXJzaW9uIHVwZGF0ZXMsIHNvIHdlIG1pZ2h0IG1lZXQgc3VjaCBzaXR1YXRpb246XG4vLy8gYG5vZGUgdjEwLjIwLjBgIHN1cHBvcnRzIGBuYXBpNWAgYW5kIGBuYXBpNmAsIGJ1dCBgbm9kZSB2MTIuMC4wYCBvbmx5IHN1cHBvcnQgYG5hcGk0YCxcbi8vLyBieSB3aGljaCwgd2UgY2FuIG5vdCB0ZWxsIGRpcmVjdGx5IG5hcGkgdmVyc2lvbiBzdXBwb3J0bGVzcyBmcm9tIG5vZGUgdmVyc2lvbiBkaXJlY3RseS5cbmNvbnN0IE5BUElfVkVSU0lPTl9NQVRSSVggPSBuZXcgTWFwPE5hcGlWZXJzaW9uLCBzdHJpbmc+KFtcbiAgW05hcGlWZXJzaW9uLk5hcGkxLCAnOC42LjAgfCA5LjAuMCB8IDEwLjAuMCddLFxuICBbTmFwaVZlcnNpb24uTmFwaTIsICc4LjEwLjAgfCA5LjMuMCB8IDEwLjAuMCddLFxuICBbTmFwaVZlcnNpb24uTmFwaTMsICc2LjE0LjIgfCA4LjExLjIgfCA5LjExLjAgfCAxMC4wLjAnXSxcbiAgW05hcGlWZXJzaW9uLk5hcGk0LCAnMTAuMTYuMCB8IDExLjguMCB8IDEyLjAuMCddLFxuICBbTmFwaVZlcnNpb24uTmFwaTUsICcxMC4xNy4wIHwgMTIuMTEuMCB8IDEzLjAuMCddLFxuICBbTmFwaVZlcnNpb24uTmFwaTYsICcxMC4yMC4wIHwgMTIuMTcuMCB8IDE0LjAuMCddLFxuICBbTmFwaVZlcnNpb24uTmFwaTcsICcxMC4yMy4wIHwgMTIuMTkuMCB8IDE0LjEyLjAgfCAxNS4wLjAnXSxcbiAgW05hcGlWZXJzaW9uLk5hcGk4LCAnMTIuMjIuMCB8IDE0LjE3LjAgfCAxNS4xMi4wIHwgMTYuMC4wJ10sXG4gIFtOYXBpVmVyc2lvbi5OYXBpOSwgJzE4LjE3LjAgfCAyMC4zLjAgfCAyMS4xLjAnXSxcbl0pXG5cbmludGVyZmFjZSBOb2RlVmVyc2lvbiB7XG4gIG1ham9yOiBudW1iZXJcbiAgbWlub3I6IG51bWJlclxuICBwYXRjaDogbnVtYmVyXG59XG5cbmZ1bmN0aW9uIHBhcnNlTm9kZVZlcnNpb24odjogc3RyaW5nKTogTm9kZVZlcnNpb24ge1xuICBjb25zdCBtYXRjaGVzID0gdi5tYXRjaCgvdj8oWzAtOV0rKVxcLihbMC05XSspXFwuKFswLTldKykvaSlcblxuICBpZiAoIW1hdGNoZXMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gbm9kZSB2ZXJzaW9uIG51bWJlcjogJyArIHYpXG4gIH1cblxuICBjb25zdCBbLCBtYWpvciwgbWlub3IsIHBhdGNoXSA9IG1hdGNoZXNcblxuICByZXR1cm4ge1xuICAgIG1ham9yOiBwYXJzZUludChtYWpvciksXG4gICAgbWlub3I6IHBhcnNlSW50KG1pbm9yKSxcbiAgICBwYXRjaDogcGFyc2VJbnQocGF0Y2gpLFxuICB9XG59XG5cbmZ1bmN0aW9uIHJlcXVpcmVkTm9kZVZlcnNpb25zKG5hcGlWZXJzaW9uOiBOYXBpVmVyc2lvbik6IE5vZGVWZXJzaW9uW10ge1xuICBjb25zdCByZXF1aXJlbWVudCA9IE5BUElfVkVSU0lPTl9NQVRSSVguZ2V0KG5hcGlWZXJzaW9uKVxuXG4gIGlmICghcmVxdWlyZW1lbnQpIHtcbiAgICByZXR1cm4gW3BhcnNlTm9kZVZlcnNpb24oJzEwLjAuMCcpXVxuICB9XG5cbiAgcmV0dXJuIHJlcXVpcmVtZW50LnNwbGl0KCd8JykubWFwKHBhcnNlTm9kZVZlcnNpb24pXG59XG5cbmZ1bmN0aW9uIHRvRW5naW5lUmVxdWlyZW1lbnQodmVyc2lvbnM6IE5vZGVWZXJzaW9uW10pOiBzdHJpbmcge1xuICBjb25zdCByZXF1aXJlbWVudHM6IHN0cmluZ1tdID0gW11cbiAgdmVyc2lvbnMuZm9yRWFjaCgodiwgaSkgPT4ge1xuICAgIGxldCByZXEgPSAnJ1xuICAgIGlmIChpICE9PSAwKSB7XG4gICAgICBjb25zdCBsYXN0VmVyc2lvbiA9IHZlcnNpb25zW2kgLSAxXVxuICAgICAgcmVxICs9IGA8ICR7bGFzdFZlcnNpb24ubWFqb3IgKyAxfWBcbiAgICB9XG5cbiAgICByZXEgKz0gYCR7aSA9PT0gMCA/ICcnIDogJyB8fCAnfT49ICR7di5tYWpvcn0uJHt2Lm1pbm9yfS4ke3YucGF0Y2h9YFxuICAgIHJlcXVpcmVtZW50cy5wdXNoKHJlcSlcbiAgfSlcblxuICByZXR1cm4gcmVxdWlyZW1lbnRzLmpvaW4oJyAnKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbmFwaUVuZ2luZVJlcXVpcmVtZW50KG5hcGlWZXJzaW9uOiBOYXBpVmVyc2lvbik6IHN0cmluZyB7XG4gIHJldHVybiB0b0VuZ2luZVJlcXVpcmVtZW50KHJlcXVpcmVkTm9kZVZlcnNpb25zKG5hcGlWZXJzaW9uKSlcbn1cbiIsImltcG9ydCB7IHNwYXduIH0gZnJvbSAnbm9kZTpjaGlsZF9wcm9jZXNzJ1xuaW1wb3J0IGZzIGZyb20gJ25vZGU6ZnMnXG5cbmV4cG9ydCB0eXBlIENyYXRlVGFyZ2V0S2luZCA9XG4gIHwgJ2JpbidcbiAgfCAnZXhhbXBsZSdcbiAgfCAndGVzdCdcbiAgfCAnYmVuY2gnXG4gIHwgJ2xpYidcbiAgfCAncmxpYidcbiAgfCAnY2R5bGliJ1xuICB8ICdjdXN0b20tYnVpbGQnXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3JhdGVUYXJnZXQge1xuICBuYW1lOiBzdHJpbmdcbiAga2luZDogQ3JhdGVUYXJnZXRLaW5kW11cbiAgY3JhdGVfdHlwZXM6IENyYXRlVGFyZ2V0S2luZFtdXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3JhdGUge1xuICBpZDogc3RyaW5nXG4gIG5hbWU6IHN0cmluZ1xuICBzcmNfcGF0aDogc3RyaW5nXG4gIHZlcnNpb246IHN0cmluZ1xuICBlZGl0aW9uOiBzdHJpbmdcbiAgdGFyZ2V0czogQ3JhdGVUYXJnZXRbXVxuICBmZWF0dXJlczogUmVjb3JkPHN0cmluZywgc3RyaW5nW10+XG4gIG1hbmlmZXN0X3BhdGg6IHN0cmluZ1xuICBkZXBlbmRlbmNpZXM6IEFycmF5PHtcbiAgICBuYW1lOiBzdHJpbmdcbiAgICBzb3VyY2U6IHN0cmluZ1xuICAgIHJlcTogc3RyaW5nXG4gICAga2luZDogc3RyaW5nIHwgbnVsbFxuICAgIHJlbmFtZTogc3RyaW5nIHwgbnVsbFxuICAgIG9wdGlvbmFsOiBib29sZWFuXG4gICAgdXNlc19kZWZhdWx0X2ZlYXR1cmVzOiBib29sZWFuXG4gICAgZmVhdHVyZXM6IHN0cmluZ1tdXG4gICAgdGFyZ2V0OiBzdHJpbmcgfCBudWxsXG4gICAgcmVnaXN0cnk6IHN0cmluZyB8IG51bGxcbiAgfT5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBDYXJnb1dvcmtzcGFjZU1ldGFkYXRhIHtcbiAgdmVyc2lvbjogbnVtYmVyXG4gIHBhY2thZ2VzOiBDcmF0ZVtdXG4gIHdvcmtzcGFjZV9tZW1iZXJzOiBzdHJpbmdbXVxuICB0YXJnZXRfZGlyZWN0b3J5OiBzdHJpbmdcbiAgd29ya3NwYWNlX3Jvb3Q6IHN0cmluZ1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcGFyc2VNZXRhZGF0YShtYW5pZmVzdFBhdGg6IHN0cmluZykge1xuICBpZiAoIWZzLmV4aXN0c1N5bmMobWFuaWZlc3RQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgTm8gY3JhdGUgZm91bmQgaW4gbWFuaWZlc3Q6ICR7bWFuaWZlc3RQYXRofWApXG4gIH1cblxuICBjb25zdCBjaGlsZFByb2Nlc3MgPSBzcGF3bihcbiAgICAnY2FyZ28nLFxuICAgIFsnbWV0YWRhdGEnLCAnLS1tYW5pZmVzdC1wYXRoJywgbWFuaWZlc3RQYXRoLCAnLS1mb3JtYXQtdmVyc2lvbicsICcxJ10sXG4gICAgeyBzdGRpbzogJ3BpcGUnIH0sXG4gIClcblxuICBsZXQgc3Rkb3V0ID0gJydcbiAgbGV0IHN0ZGVyciA9ICcnXG4gIGxldCBzdGF0dXMgPSAwXG4gIGxldCBlcnJvciA9IG51bGxcblxuICBjaGlsZFByb2Nlc3Muc3Rkb3V0Lm9uKCdkYXRhJywgKGRhdGEpID0+IHtcbiAgICBzdGRvdXQgKz0gZGF0YVxuICB9KVxuXG4gIGNoaWxkUHJvY2Vzcy5zdGRlcnIub24oJ2RhdGEnLCAoZGF0YSkgPT4ge1xuICAgIHN0ZGVyciArPSBkYXRhXG4gIH0pXG5cbiAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICBjaGlsZFByb2Nlc3Mub24oJ2Nsb3NlJywgKGNvZGUpID0+IHtcbiAgICAgIHN0YXR1cyA9IGNvZGUgPz8gMFxuICAgICAgcmVzb2x2ZSgpXG4gICAgfSlcbiAgfSlcblxuICBpZiAoZXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NhcmdvIG1ldGFkYXRhIGZhaWxlZCB0byBydW4nLCB7IGNhdXNlOiBlcnJvciB9KVxuICB9XG4gIGlmIChzdGF0dXMgIT09IDApIHtcbiAgICBjb25zdCBzaW1wbGVNZXNzYWdlID0gYGNhcmdvIG1ldGFkYXRhIGV4aXRlZCB3aXRoIGNvZGUgJHtzdGF0dXN9YFxuICAgIHRocm93IG5ldyBFcnJvcihgJHtzaW1wbGVNZXNzYWdlfSBhbmQgZXJyb3IgbWVzc2FnZTpcXG5cXG4ke3N0ZGVycn1gLCB7XG4gICAgICBjYXVzZTogbmV3IEVycm9yKHNpbXBsZU1lc3NhZ2UpLFxuICAgIH0pXG4gIH1cblxuICB0cnkge1xuICAgIHJldHVybiBKU09OLnBhcnNlKHN0ZG91dCkgYXMgQ2FyZ29Xb3Jrc3BhY2VNZXRhZGF0YVxuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gcGFyc2UgY2FyZ28gbWV0YWRhdGEgSlNPTicsIHsgY2F1c2U6IGUgfSlcbiAgfVxufVxuIiwiaW1wb3J0IHsgdW5kZXJsaW5lLCB5ZWxsb3cgfSBmcm9tICdjb2xvcmV0dGUnXG5pbXBvcnQgeyBtZXJnZSwgb21pdCB9IGZyb20gJ2xvZGFzaC1lcydcblxuaW1wb3J0IHsgZmlsZUV4aXN0cywgcmVhZEZpbGVBc3luYyB9IGZyb20gJy4vbWlzYy5qcydcbmltcG9ydCB7IERFRkFVTFRfVEFSR0VUUywgcGFyc2VUcmlwbGUsIFRhcmdldCB9IGZyb20gJy4vdGFyZ2V0LmpzJ1xuXG5leHBvcnQgdHlwZSBWYWx1ZU9mQ29uc3RBcnJheTxUPiA9IFRbRXhjbHVkZTxrZXlvZiBULCBrZXlvZiBBcnJheTxhbnk+Pl1cblxuZXhwb3J0IGNvbnN0IFN1cHBvcnRlZFBhY2thZ2VNYW5hZ2VycyA9IFsneWFybicsICdwbnBtJ10gYXMgY29uc3RcbmV4cG9ydCBjb25zdCBTdXBwb3J0ZWRUZXN0RnJhbWV3b3JrcyA9IFsnYXZhJ10gYXMgY29uc3RcblxuZXhwb3J0IHR5cGUgU3VwcG9ydGVkUGFja2FnZU1hbmFnZXIgPSBWYWx1ZU9mQ29uc3RBcnJheTxcbiAgdHlwZW9mIFN1cHBvcnRlZFBhY2thZ2VNYW5hZ2Vyc1xuPlxuZXhwb3J0IHR5cGUgU3VwcG9ydGVkVGVzdEZyYW1ld29yayA9IFZhbHVlT2ZDb25zdEFycmF5PFxuICB0eXBlb2YgU3VwcG9ydGVkVGVzdEZyYW1ld29ya3Ncbj5cblxuZXhwb3J0IGludGVyZmFjZSBVc2VyTmFwaUNvbmZpZyB7XG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBiaW5hcnkgdG8gYmUgZ2VuZXJhdGVkLCBkZWZhdWx0IHRvIGBpbmRleGBcbiAgICovXG4gIGJpbmFyeU5hbWU/OiBzdHJpbmdcbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIG5wbSBwYWNrYWdlLCBkZWZhdWx0IHRvIHRoZSBuYW1lIG9mIHJvb3QgcGFja2FnZS5qc29uIG5hbWVcbiAgICpcbiAgICogQWx3YXlzIGdpdmVuIGBAc2NvcGUvcGtnYCBhbmQgYXJjaCBzdWZmaXggd2lsbCBiZSBhcHBlbmRlZCBsaWtlIGBAc2NvcGUvcGtnLWxpbnV4LWdudS14NjRgXG4gICAqL1xuICBwYWNrYWdlTmFtZT86IHN0cmluZ1xuICAvKipcbiAgICogQWxsIHRhcmdldHMgdGhlIGNyYXRlIHdpbGwgYmUgY29tcGlsZWQgZm9yXG4gICAqL1xuICB0YXJnZXRzPzogc3RyaW5nW11cblxuICAvKipcbiAgICogVGhlIG5wbSBjbGllbnQgcHJvamVjdCB1c2VzLlxuICAgKi9cbiAgbnBtQ2xpZW50Pzogc3RyaW5nXG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgZ2VuZXJhdGUgY29uc3QgZW51bSBmb3IgdHlwZXNjcmlwdCBiaW5kaW5nc1xuICAgKi9cbiAgY29uc3RFbnVtPzogYm9vbGVhblxuXG4gIC8qKlxuICAgKiBkdHMgaGVhZGVyIHByZXBlbmQgdG8gdGhlIGdlbmVyYXRlZCBkdHMgZmlsZVxuICAgKi9cbiAgZHRzSGVhZGVyPzogc3RyaW5nXG5cbiAgLyoqXG4gICAqIGR0cyBoZWFkZXIgZmlsZSBwYXRoIHRvIGJlIHByZXBlbmRlZCB0byB0aGUgZ2VuZXJhdGVkIGR0cyBmaWxlXG4gICAqIGlmIGJvdGggZHRzSGVhZGVyIGFuZCBkdHNIZWFkZXJGaWxlIGFyZSBwcm92aWRlZCwgZHRzSGVhZGVyRmlsZSB3aWxsIGJlIHVzZWRcbiAgICovXG4gIGR0c0hlYWRlckZpbGU/OiBzdHJpbmdcblxuICAvKipcbiAgICogd2FzbSBjb21waWxhdGlvbiBvcHRpb25zXG4gICAqL1xuICB3YXNtPzoge1xuICAgIC8qKlxuICAgICAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViQXNzZW1ibHkvSmF2YVNjcmlwdF9pbnRlcmZhY2UvTWVtb3J5XG4gICAgICogQGRlZmF1bHQgNDAwMCBwYWdlcyAoMjU2TWlCKVxuICAgICAqL1xuICAgIGluaXRpYWxNZW1vcnk/OiBudW1iZXJcbiAgICAvKipcbiAgICAgKiBAZGVmYXVsdCA2NTUzNiBwYWdlcyAoNEdpQilcbiAgICAgKi9cbiAgICBtYXhpbXVtTWVtb3J5PzogbnVtYmVyXG5cbiAgICAvKipcbiAgICAgKiBCcm93c2VyIHdhc20gYmluZGluZyBjb25maWd1cmF0aW9uXG4gICAgICovXG4gICAgYnJvd3Nlcjoge1xuICAgICAgLyoqXG4gICAgICAgKiBXaGV0aGVyIHRvIHVzZSBmcyBtb2R1bGUgaW4gYnJvd3NlclxuICAgICAgICovXG4gICAgICBmcz86IGJvb2xlYW5cbiAgICAgIC8qKlxuICAgICAgICogV2hldGhlciB0byBpbml0aWFsaXplIHdhc20gYXN5bmNocm9ub3VzbHlcbiAgICAgICAqL1xuICAgICAgYXN5bmNJbml0PzogYm9vbGVhblxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVwcmVjYXRlZCBiaW5hcnlOYW1lIGluc3RlYWRcbiAgICovXG4gIG5hbWU/OiBzdHJpbmdcbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIHVzZSBwYWNrYWdlTmFtZSBpbnN0ZWFkXG4gICAqL1xuICBwYWNrYWdlPzoge1xuICAgIG5hbWU/OiBzdHJpbmdcbiAgfVxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgdXNlIHRhcmdldHMgaW5zdGVhZFxuICAgKi9cbiAgdHJpcGxlcz86IHtcbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIGVuYWJsZSBkZWZhdWx0IHRhcmdldHNcbiAgICAgKi9cbiAgICBkZWZhdWx0czogYm9vbGVhblxuICAgIC8qKlxuICAgICAqIEFkZGl0aW9uYWwgdGFyZ2V0cyB0byBiZSBjb21waWxlZCBmb3JcbiAgICAgKi9cbiAgICBhZGRpdGlvbmFsPzogc3RyaW5nW11cbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbW1vblBhY2thZ2VKc29uRmllbGRzIHtcbiAgbmFtZTogc3RyaW5nXG4gIHZlcnNpb246IHN0cmluZ1xuICBkZXNjcmlwdGlvbj86IHN0cmluZ1xuICBrZXl3b3Jkcz86IHN0cmluZ1tdXG4gIGF1dGhvcj86IHN0cmluZ1xuICBhdXRob3JzPzogc3RyaW5nW11cbiAgbGljZW5zZT86IHN0cmluZ1xuICByZXBvc2l0b3J5PzogYW55XG4gIGhvbWVwYWdlPzogYW55XG4gIGVuZ2luZXM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+XG4gIHB1Ymxpc2hDb25maWc/OiBhbnlcbiAgYnVncz86IGFueVxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdXNlLWJlZm9yZS1kZWZpbmVcbiAgbmFwaT86IFVzZXJOYXBpQ29uZmlnXG4gIHR5cGU/OiAnbW9kdWxlJyB8ICdjb21tb25qcydcbiAgc2NyaXB0cz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cblxuICAvLyBtb2R1bGVzXG4gIG1haW4/OiBzdHJpbmdcbiAgbW9kdWxlPzogc3RyaW5nXG4gIHR5cGVzPzogc3RyaW5nXG4gIGJyb3dzZXI/OiBzdHJpbmdcbiAgZXhwb3J0cz86IGFueVxuXG4gIGRlcGVuZGVuY2llcz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cbiAgZGV2RGVwZW5kZW5jaWVzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPlxuXG4gIGF2YT86IHtcbiAgICB0aW1lb3V0Pzogc3RyaW5nXG4gIH1cbn1cblxuZXhwb3J0IHR5cGUgTmFwaUNvbmZpZyA9IFJlcXVpcmVkPFxuICBQaWNrPFVzZXJOYXBpQ29uZmlnLCAnYmluYXJ5TmFtZScgfCAncGFja2FnZU5hbWUnIHwgJ25wbUNsaWVudCc+XG4+ICZcbiAgUGljazxVc2VyTmFwaUNvbmZpZywgJ3dhc20nIHwgJ2R0c0hlYWRlcicgfCAnZHRzSGVhZGVyRmlsZScgfCAnY29uc3RFbnVtJz4gJiB7XG4gICAgdGFyZ2V0czogVGFyZ2V0W11cbiAgICBwYWNrYWdlSnNvbjogQ29tbW9uUGFja2FnZUpzb25GaWVsZHNcbiAgfVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZE5hcGlDb25maWcoXG4gIHBhdGg6IHN0cmluZyxcbiAgY29uZmlnUGF0aD86IHN0cmluZyxcbik6IFByb21pc2U8TmFwaUNvbmZpZz4ge1xuICBpZiAoY29uZmlnUGF0aCAmJiAhKGF3YWl0IGZpbGVFeGlzdHMoY29uZmlnUGF0aCkpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBOQVBJLVJTIGNvbmZpZyBub3QgZm91bmQgYXQgJHtjb25maWdQYXRofWApXG4gIH1cbiAgaWYgKCEoYXdhaXQgZmlsZUV4aXN0cyhwYXRoKSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHBhY2thZ2UuanNvbiBub3QgZm91bmQgYXQgJHtwYXRofWApXG4gIH1cbiAgLy8gTWF5IHN1cHBvcnQgbXVsdGlwbGUgY29uZmlnIHNvdXJjZXMgbGF0ZXIgb24uXG4gIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCByZWFkRmlsZUFzeW5jKHBhdGgsICd1dGY4JylcbiAgbGV0IHBrZ0pzb25cbiAgdHJ5IHtcbiAgICBwa2dKc29uID0gSlNPTi5wYXJzZShjb250ZW50KSBhcyBDb21tb25QYWNrYWdlSnNvbkZpZWxkc1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcGFyc2UgcGFja2FnZS5qc29uIGF0ICR7cGF0aH1gLCB7XG4gICAgICBjYXVzZTogZSxcbiAgICB9KVxuICB9XG5cbiAgbGV0IHNlcGFyYXRlZENvbmZpZzogVXNlck5hcGlDb25maWcgfCB1bmRlZmluZWRcbiAgaWYgKGNvbmZpZ1BhdGgpIHtcbiAgICBjb25zdCBjb25maWdDb250ZW50ID0gYXdhaXQgcmVhZEZpbGVBc3luYyhjb25maWdQYXRoLCAndXRmOCcpXG4gICAgdHJ5IHtcbiAgICAgIHNlcGFyYXRlZENvbmZpZyA9IEpTT04ucGFyc2UoY29uZmlnQ29udGVudCkgYXMgVXNlck5hcGlDb25maWdcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBwYXJzZSBOQVBJLVJTIGNvbmZpZyBhdCAke2NvbmZpZ1BhdGh9YCwge1xuICAgICAgICBjYXVzZTogZSxcbiAgICAgIH0pXG4gICAgfVxuICB9XG5cbiAgY29uc3QgdXNlck5hcGlDb25maWcgPSBwa2dKc29uLm5hcGkgPz8ge31cbiAgaWYgKHBrZ0pzb24ubmFwaSAmJiBzZXBhcmF0ZWRDb25maWcpIHtcbiAgICBjb25zdCBwa2dKc29uUGF0aCA9IHVuZGVybGluZShwYXRoKVxuICAgIGNvbnN0IGNvbmZpZ1BhdGhVbmRlcmxpbmUgPSB1bmRlcmxpbmUoY29uZmlnUGF0aCEpXG4gICAgY29uc29sZS53YXJuKFxuICAgICAgeWVsbG93KFxuICAgICAgICBgQm90aCBuYXBpIGZpZWxkIGluICR7cGtnSnNvblBhdGh9IGFuZCBbTkFQSS1SUyBjb25maWddKCR7Y29uZmlnUGF0aFVuZGVybGluZX0pIGZpbGUgYXJlIGZvdW5kLCB0aGUgTkFQSS1SUyBjb25maWcgZmlsZSB3aWxsIGJlIHVzZWQuYCxcbiAgICAgICksXG4gICAgKVxuICAgIE9iamVjdC5hc3NpZ24odXNlck5hcGlDb25maWcsIHNlcGFyYXRlZENvbmZpZylcbiAgfVxuICBjb25zdCBuYXBpQ29uZmlnOiBOYXBpQ29uZmlnID0gbWVyZ2UoXG4gICAge1xuICAgICAgYmluYXJ5TmFtZTogJ2luZGV4JyxcbiAgICAgIHBhY2thZ2VOYW1lOiBwa2dKc29uLm5hbWUsXG4gICAgICB0YXJnZXRzOiBbXSxcbiAgICAgIHBhY2thZ2VKc29uOiBwa2dKc29uLFxuICAgICAgbnBtQ2xpZW50OiAnbnBtJyxcbiAgICB9LFxuICAgIG9taXQodXNlck5hcGlDb25maWcsICd0YXJnZXRzJyksXG4gIClcblxuICBsZXQgdGFyZ2V0czogc3RyaW5nW10gPSB1c2VyTmFwaUNvbmZpZy50YXJnZXRzID8/IFtdXG5cbiAgLy8gY29tcGF0aWJsZSB3aXRoIG9sZCBjb25maWdcbiAgaWYgKHVzZXJOYXBpQ29uZmlnPy5uYW1lKSB7XG4gICAgY29uc29sZS53YXJuKFxuICAgICAgeWVsbG93KFxuICAgICAgICBgW0RFUFJFQ0FURURdIG5hcGkubmFtZSBpcyBkZXByZWNhdGVkLCB1c2UgbmFwaS5iaW5hcnlOYW1lIGluc3RlYWQuYCxcbiAgICAgICksXG4gICAgKVxuICAgIG5hcGlDb25maWcuYmluYXJ5TmFtZSA9IHVzZXJOYXBpQ29uZmlnLm5hbWVcbiAgfVxuXG4gIGlmICghdGFyZ2V0cy5sZW5ndGgpIHtcbiAgICBsZXQgZGVwcmVjYXRlZFdhcm5lZCA9IGZhbHNlXG4gICAgY29uc3Qgd2FybmluZyA9IHllbGxvdyhcbiAgICAgIGBbREVQUkVDQVRFRF0gbmFwaS50cmlwbGVzIGlzIGRlcHJlY2F0ZWQsIHVzZSBuYXBpLnRhcmdldHMgaW5zdGVhZC5gLFxuICAgIClcbiAgICBpZiAodXNlck5hcGlDb25maWcudHJpcGxlcz8uZGVmYXVsdHMpIHtcbiAgICAgIGRlcHJlY2F0ZWRXYXJuZWQgPSB0cnVlXG4gICAgICBjb25zb2xlLndhcm4od2FybmluZylcbiAgICAgIHRhcmdldHMgPSB0YXJnZXRzLmNvbmNhdChERUZBVUxUX1RBUkdFVFMpXG4gICAgfVxuXG4gICAgaWYgKHVzZXJOYXBpQ29uZmlnLnRyaXBsZXM/LmFkZGl0aW9uYWw/Lmxlbmd0aCkge1xuICAgICAgdGFyZ2V0cyA9IHRhcmdldHMuY29uY2F0KHVzZXJOYXBpQ29uZmlnLnRyaXBsZXMuYWRkaXRpb25hbClcbiAgICAgIGlmICghZGVwcmVjYXRlZFdhcm5lZCkge1xuICAgICAgICBjb25zb2xlLndhcm4od2FybmluZylcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBuYXBpQ29uZmlnLnRhcmdldHMgPSB0YXJnZXRzLm1hcChwYXJzZVRyaXBsZSlcblxuICByZXR1cm4gbmFwaUNvbmZpZ1xufVxuIiwiaW1wb3J0IHsgZXhlY1N5bmMgfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnXG5cbmltcG9ydCB7IGRlYnVnIH0gZnJvbSAnLi9sb2cuanMnXG5cbmV4cG9ydCBmdW5jdGlvbiB0cnlJbnN0YWxsQ2FyZ29CaW5hcnkobmFtZTogc3RyaW5nLCBiaW46IHN0cmluZykge1xuICBpZiAoZGV0ZWN0Q2FyZ29CaW5hcnkoYmluKSkge1xuICAgIGRlYnVnKCdDYXJnbyBiaW5hcnkgYWxyZWFkeSBpbnN0YWxsZWQ6ICVzJywgbmFtZSlcbiAgICByZXR1cm5cbiAgfVxuXG4gIHRyeSB7XG4gICAgZGVidWcoJ0luc3RhbGxpbmcgY2FyZ28gYmluYXJ5OiAlcycsIG5hbWUpXG4gICAgZXhlY1N5bmMoYGNhcmdvIGluc3RhbGwgJHtuYW1lfWAsIHtcbiAgICAgIHN0ZGlvOiAnaW5oZXJpdCcsXG4gICAgfSlcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGluc3RhbGwgY2FyZ28gYmluYXJ5OiAke25hbWV9YCwge1xuICAgICAgY2F1c2U6IGUsXG4gICAgfSlcbiAgfVxufVxuXG5mdW5jdGlvbiBkZXRlY3RDYXJnb0JpbmFyeShiaW46IHN0cmluZykge1xuICBkZWJ1ZygnRGV0ZWN0aW5nIGNhcmdvIGJpbmFyeTogJXMnLCBiaW4pXG4gIHRyeSB7XG4gICAgZXhlY1N5bmMoYGNhcmdvIGhlbHAgJHtiaW59YCwge1xuICAgICAgc3RkaW86ICdpZ25vcmUnLFxuICAgIH0pXG4gICAgZGVidWcoJ0NhcmdvIGJpbmFyeSBkZXRlY3RlZDogJXMnLCBiaW4pXG4gICAgcmV0dXJuIHRydWVcbiAgfSBjYXRjaCB7XG4gICAgZGVidWcoJ0NhcmdvIGJpbmFyeSBub3QgZGV0ZWN0ZWQ6ICVzJywgYmluKVxuICAgIHJldHVybiBmYWxzZVxuICB9XG59XG4iLCJpbXBvcnQgeyBzb3J0QnkgfSBmcm9tICdsb2Rhc2gtZXMnXG5cbmltcG9ydCB7IHJlYWRGaWxlQXN5bmMgfSBmcm9tICcuL21pc2MuanMnXG5cbmNvbnN0IFRPUF9MRVZFTF9OQU1FU1BBQ0UgPSAnX19UT1BfTEVWRUxfTU9EVUxFX18nXG5leHBvcnQgY29uc3QgREVGQVVMVF9UWVBFX0RFRl9IRUFERVIgPSBgLyogYXV0by1nZW5lcmF0ZWQgYnkgTkFQSS1SUyAqL1xuLyogZXNsaW50LWRpc2FibGUgKi9cbmBcblxuZW51bSBUeXBlRGVmS2luZCB7XG4gIENvbnN0ID0gJ2NvbnN0JyxcbiAgRW51bSA9ICdlbnVtJyxcbiAgU3RyaW5nRW51bSA9ICdzdHJpbmdfZW51bScsXG4gIEludGVyZmFjZSA9ICdpbnRlcmZhY2UnLFxuICBUeXBlID0gJ3R5cGUnLFxuICBGbiA9ICdmbicsXG4gIFN0cnVjdCA9ICdzdHJ1Y3QnLFxuICBJbXBsID0gJ2ltcGwnLFxufVxuXG5pbnRlcmZhY2UgVHlwZURlZkxpbmUge1xuICBraW5kOiBUeXBlRGVmS2luZFxuICBuYW1lOiBzdHJpbmdcbiAgb3JpZ2luYWxfbmFtZT86IHN0cmluZ1xuICBkZWY6IHN0cmluZ1xuICBqc19kb2M/OiBzdHJpbmdcbiAganNfbW9kPzogc3RyaW5nXG59XG5cbmZ1bmN0aW9uIHByZXR0eVByaW50KFxuICBsaW5lOiBUeXBlRGVmTGluZSxcbiAgY29uc3RFbnVtOiBib29sZWFuLFxuICBpZGVudDogbnVtYmVyLFxuICBhbWJpZW50ID0gZmFsc2UsXG4pOiBzdHJpbmcge1xuICBsZXQgcyA9IGxpbmUuanNfZG9jID8/ICcnXG4gIHN3aXRjaCAobGluZS5raW5kKSB7XG4gICAgY2FzZSBUeXBlRGVmS2luZC5JbnRlcmZhY2U6XG4gICAgICBzICs9IGBleHBvcnQgaW50ZXJmYWNlICR7bGluZS5uYW1lfSB7XFxuJHtsaW5lLmRlZn1cXG59YFxuICAgICAgYnJlYWtcblxuICAgIGNhc2UgVHlwZURlZktpbmQuVHlwZTpcbiAgICAgIHMgKz0gYGV4cG9ydCB0eXBlICR7bGluZS5uYW1lfSA9IFxcbiR7bGluZS5kZWZ9YFxuICAgICAgYnJlYWtcblxuICAgIGNhc2UgVHlwZURlZktpbmQuRW51bTpcbiAgICAgIGNvbnN0IGVudW1OYW1lID0gY29uc3RFbnVtID8gJ2NvbnN0IGVudW0nIDogJ2VudW0nXG4gICAgICBzICs9IGAke2V4cG9ydERlY2xhcmUoYW1iaWVudCl9ICR7ZW51bU5hbWV9ICR7bGluZS5uYW1lfSB7XFxuJHtsaW5lLmRlZn1cXG59YFxuICAgICAgYnJlYWtcblxuICAgIGNhc2UgVHlwZURlZktpbmQuU3RyaW5nRW51bTpcbiAgICAgIGlmIChjb25zdEVudW0pIHtcbiAgICAgICAgcyArPSBgJHtleHBvcnREZWNsYXJlKGFtYmllbnQpfSBjb25zdCBlbnVtICR7bGluZS5uYW1lfSB7XFxuJHtsaW5lLmRlZn1cXG59YFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcyArPSBgZXhwb3J0IHR5cGUgJHtsaW5lLm5hbWV9ID0gJHtsaW5lLmRlZi5yZXBsYWNlQWxsKC8uKj0vZywgJycpLnJlcGxhY2VBbGwoJywnLCAnfCcpfTtgXG4gICAgICB9XG4gICAgICBicmVha1xuXG4gICAgY2FzZSBUeXBlRGVmS2luZC5TdHJ1Y3Q6XG4gICAgICBzICs9IGAke2V4cG9ydERlY2xhcmUoYW1iaWVudCl9IGNsYXNzICR7bGluZS5uYW1lfSB7XFxuJHtsaW5lLmRlZn1cXG59YFxuICAgICAgaWYgKGxpbmUub3JpZ2luYWxfbmFtZSAmJiBsaW5lLm9yaWdpbmFsX25hbWUgIT09IGxpbmUubmFtZSkge1xuICAgICAgICBzICs9IGBcXG5leHBvcnQgdHlwZSAke2xpbmUub3JpZ2luYWxfbmFtZX0gPSAke2xpbmUubmFtZX1gXG4gICAgICB9XG4gICAgICBicmVha1xuXG4gICAgY2FzZSBUeXBlRGVmS2luZC5GbjpcbiAgICAgIHMgKz0gYCR7ZXhwb3J0RGVjbGFyZShhbWJpZW50KX0gJHtsaW5lLmRlZn1gXG4gICAgICBicmVha1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHMgKz0gbGluZS5kZWZcbiAgfVxuXG4gIHJldHVybiBjb3JyZWN0U3RyaW5nSWRlbnQocywgaWRlbnQpXG59XG5cbmZ1bmN0aW9uIGV4cG9ydERlY2xhcmUoYW1iaWVudDogYm9vbGVhbik6IHN0cmluZyB7XG4gIGlmIChhbWJpZW50KSB7XG4gICAgcmV0dXJuICdleHBvcnQnXG4gIH1cblxuICByZXR1cm4gJ2V4cG9ydCBkZWNsYXJlJ1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc1R5cGVEZWYoXG4gIGludGVybWVkaWF0ZVR5cGVGaWxlOiBzdHJpbmcsXG4gIGNvbnN0RW51bTogYm9vbGVhbixcbikge1xuICBjb25zdCBleHBvcnRzOiBzdHJpbmdbXSA9IFtdXG4gIGNvbnN0IGRlZnMgPSBhd2FpdCByZWFkSW50ZXJtZWRpYXRlVHlwZUZpbGUoaW50ZXJtZWRpYXRlVHlwZUZpbGUpXG4gIGNvbnN0IGdyb3VwZWREZWZzID0gcHJlcHJvY2Vzc1R5cGVEZWYoZGVmcylcblxuICBjb25zdCBkdHMgPVxuICAgIHNvcnRCeShBcnJheS5mcm9tKGdyb3VwZWREZWZzKSwgKFtuYW1lc3BhY2VdKSA9PiBuYW1lc3BhY2UpXG4gICAgICAubWFwKChbbmFtZXNwYWNlLCBkZWZzXSkgPT4ge1xuICAgICAgICBpZiAobmFtZXNwYWNlID09PSBUT1BfTEVWRUxfTkFNRVNQQUNFKSB7XG4gICAgICAgICAgcmV0dXJuIGRlZnNcbiAgICAgICAgICAgIC5tYXAoKGRlZikgPT4ge1xuICAgICAgICAgICAgICBzd2l0Y2ggKGRlZi5raW5kKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBUeXBlRGVmS2luZC5Db25zdDpcbiAgICAgICAgICAgICAgICBjYXNlIFR5cGVEZWZLaW5kLkVudW06XG4gICAgICAgICAgICAgICAgY2FzZSBUeXBlRGVmS2luZC5TdHJpbmdFbnVtOlxuICAgICAgICAgICAgICAgIGNhc2UgVHlwZURlZktpbmQuRm46XG4gICAgICAgICAgICAgICAgY2FzZSBUeXBlRGVmS2luZC5TdHJ1Y3Q6IHtcbiAgICAgICAgICAgICAgICAgIGV4cG9ydHMucHVzaChkZWYubmFtZSlcbiAgICAgICAgICAgICAgICAgIGlmIChkZWYub3JpZ2luYWxfbmFtZSAmJiBkZWYub3JpZ2luYWxfbmFtZSAhPT0gZGVmLm5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0cy5wdXNoKGRlZi5vcmlnaW5hbF9uYW1lKVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIHByZXR0eVByaW50KGRlZiwgY29uc3RFbnVtLCAwKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5qb2luKCdcXG5cXG4nKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGV4cG9ydHMucHVzaChuYW1lc3BhY2UpXG4gICAgICAgICAgbGV0IGRlY2xhcmF0aW9uID0gJydcbiAgICAgICAgICBkZWNsYXJhdGlvbiArPSBgZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlICR7bmFtZXNwYWNlfSB7XFxuYFxuICAgICAgICAgIGZvciAoY29uc3QgZGVmIG9mIGRlZnMpIHtcbiAgICAgICAgICAgIGRlY2xhcmF0aW9uICs9IHByZXR0eVByaW50KGRlZiwgY29uc3RFbnVtLCAyLCB0cnVlKSArICdcXG4nXG4gICAgICAgICAgfVxuICAgICAgICAgIGRlY2xhcmF0aW9uICs9ICd9J1xuICAgICAgICAgIHJldHVybiBkZWNsYXJhdGlvblxuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLmpvaW4oJ1xcblxcbicpICsgJ1xcbidcblxuICByZXR1cm4ge1xuICAgIGR0cyxcbiAgICBleHBvcnRzLFxuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRJbnRlcm1lZGlhdGVUeXBlRmlsZShmaWxlOiBzdHJpbmcpIHtcbiAgY29uc3QgY29udGVudCA9IGF3YWl0IHJlYWRGaWxlQXN5bmMoZmlsZSwgJ3V0ZjgnKVxuXG4gIGNvbnN0IGRlZnMgPSBjb250ZW50XG4gICAgLnNwbGl0KCdcXG4nKVxuICAgIC5maWx0ZXIoQm9vbGVhbilcbiAgICAubWFwKChsaW5lKSA9PiB7XG4gICAgICBsaW5lID0gbGluZS50cmltKClcbiAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UobGluZSkgYXMgVHlwZURlZkxpbmVcbiAgICAgIC8vIENvbnZlcnQgZXNjYXBlZCBuZXdsaW5lcyBiYWNrIHRvIGFjdHVhbCBuZXdsaW5lcyBpbiBqc19kb2MgZmllbGRzXG4gICAgICBpZiAocGFyc2VkLmpzX2RvYykge1xuICAgICAgICBwYXJzZWQuanNfZG9jID0gcGFyc2VkLmpzX2RvYy5yZXBsYWNlKC9cXFxcbi9nLCAnXFxuJylcbiAgICAgIH1cbiAgICAgIC8vIENvbnZlcnQgZXNjYXBlZCBuZXdsaW5lcyB0byBhY3R1YWwgbmV3bGluZXMgaW4gZGVmIGZpZWxkcyBmb3Igc3RydWN0L2NsYXNzL2ludGVyZmFjZS90eXBlIHR5cGVzXG4gICAgICAvLyB3aGVyZSBcXG4gcmVwcmVzZW50cyBtZXRob2QvZmllbGQgc2VwYXJhdG9ycyB0aGF0IHNob3VsZCBiZSBhY3R1YWwgbmV3bGluZXNcbiAgICAgIGlmIChwYXJzZWQuZGVmKSB7XG4gICAgICAgIHBhcnNlZC5kZWYgPSBwYXJzZWQuZGVmLnJlcGxhY2UoL1xcXFxuL2csICdcXG4nKVxuICAgICAgfVxuICAgICAgcmV0dXJuIHBhcnNlZFxuICAgIH0pXG5cbiAgLy8gbW92ZSBhbGwgYHN0cnVjdGAgZGVmIHRvIHRoZSB2ZXJ5IHRvcFxuICAvLyBhbmQgb3JkZXIgdGhlIHJlc3QgYWxwaGFiZXRpY2FsbHkuXG4gIHJldHVybiBkZWZzLnNvcnQoKGEsIGIpID0+IHtcbiAgICBpZiAoYS5raW5kID09PSBUeXBlRGVmS2luZC5TdHJ1Y3QpIHtcbiAgICAgIGlmIChiLmtpbmQgPT09IFR5cGVEZWZLaW5kLlN0cnVjdCkge1xuICAgICAgICByZXR1cm4gYS5uYW1lLmxvY2FsZUNvbXBhcmUoYi5uYW1lKVxuICAgICAgfVxuICAgICAgcmV0dXJuIC0xXG4gICAgfSBlbHNlIGlmIChiLmtpbmQgPT09IFR5cGVEZWZLaW5kLlN0cnVjdCkge1xuICAgICAgcmV0dXJuIDFcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGEubmFtZS5sb2NhbGVDb21wYXJlKGIubmFtZSlcbiAgICB9XG4gIH0pXG59XG5cbmZ1bmN0aW9uIHByZXByb2Nlc3NUeXBlRGVmKGRlZnM6IFR5cGVEZWZMaW5lW10pOiBNYXA8c3RyaW5nLCBUeXBlRGVmTGluZVtdPiB7XG4gIGNvbnN0IG5hbWVzcGFjZUdyb3VwZWQgPSBuZXcgTWFwPHN0cmluZywgVHlwZURlZkxpbmVbXT4oKVxuICBjb25zdCBjbGFzc0RlZnMgPSBuZXcgTWFwPHN0cmluZywgVHlwZURlZkxpbmU+KClcblxuICBmb3IgKGNvbnN0IGRlZiBvZiBkZWZzKSB7XG4gICAgY29uc3QgbmFtZXNwYWNlID0gZGVmLmpzX21vZCA/PyBUT1BfTEVWRUxfTkFNRVNQQUNFXG4gICAgaWYgKCFuYW1lc3BhY2VHcm91cGVkLmhhcyhuYW1lc3BhY2UpKSB7XG4gICAgICBuYW1lc3BhY2VHcm91cGVkLnNldChuYW1lc3BhY2UsIFtdKVxuICAgIH1cblxuICAgIGNvbnN0IGdyb3VwID0gbmFtZXNwYWNlR3JvdXBlZC5nZXQobmFtZXNwYWNlKSFcblxuICAgIGlmIChkZWYua2luZCA9PT0gVHlwZURlZktpbmQuU3RydWN0KSB7XG4gICAgICBncm91cC5wdXNoKGRlZilcbiAgICAgIGNsYXNzRGVmcy5zZXQoZGVmLm5hbWUsIGRlZilcbiAgICB9IGVsc2UgaWYgKGRlZi5raW5kID09PSBUeXBlRGVmS2luZC5JbXBsKSB7XG4gICAgICAvLyBtZXJnZSBgaW1wbGAgaW50byBjbGFzcyBkZWZpbml0aW9uXG4gICAgICBjb25zdCBjbGFzc0RlZiA9IGNsYXNzRGVmcy5nZXQoZGVmLm5hbWUpXG4gICAgICBpZiAoY2xhc3NEZWYpIHtcbiAgICAgICAgaWYgKGNsYXNzRGVmLmRlZikge1xuICAgICAgICAgIGNsYXNzRGVmLmRlZiArPSAnXFxuJ1xuICAgICAgICB9XG5cbiAgICAgICAgY2xhc3NEZWYuZGVmICs9IGRlZi5kZWZcbiAgICAgICAgLy8gQ29udmVydCBhbnkgcmVtYWluaW5nIFxcbiBzZXF1ZW5jZXMgaW4gdGhlIG1lcmdlZCBkZWYgdG8gYWN0dWFsIG5ld2xpbmVzXG4gICAgICAgIGlmIChjbGFzc0RlZi5kZWYpIHtcbiAgICAgICAgICBjbGFzc0RlZi5kZWYgPSBjbGFzc0RlZi5kZWYucmVwbGFjZSgvXFxcXG4vZywgJ1xcbicpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZ3JvdXAucHVzaChkZWYpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5hbWVzcGFjZUdyb3VwZWRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvcnJlY3RTdHJpbmdJZGVudChzcmM6IHN0cmluZywgaWRlbnQ6IG51bWJlcik6IHN0cmluZyB7XG4gIGxldCBicmFja2V0RGVwdGggPSAwXG4gIGNvbnN0IHJlc3VsdCA9IHNyY1xuICAgIC5zcGxpdCgnXFxuJylcbiAgICAubWFwKChsaW5lKSA9PiB7XG4gICAgICBsaW5lID0gbGluZS50cmltKClcbiAgICAgIGlmIChsaW5lID09PSAnJykge1xuICAgICAgICByZXR1cm4gJydcbiAgICAgIH1cblxuICAgICAgY29uc3QgaXNJbk11bHRpbGluZUNvbW1lbnQgPSBsaW5lLnN0YXJ0c1dpdGgoJyonKVxuICAgICAgY29uc3QgaXNDbG9zaW5nQnJhY2tldCA9IGxpbmUuZW5kc1dpdGgoJ30nKVxuICAgICAgY29uc3QgaXNPcGVuaW5nQnJhY2tldCA9IGxpbmUuZW5kc1dpdGgoJ3snKVxuICAgICAgY29uc3QgaXNUeXBlRGVjbGFyYXRpb24gPSBsaW5lLmVuZHNXaXRoKCc9JylcbiAgICAgIGNvbnN0IGlzVHlwZVZhcmlhbnQgPSBsaW5lLnN0YXJ0c1dpdGgoJ3wnKVxuXG4gICAgICBsZXQgcmlnaHRJbmRlbnQgPSBpZGVudFxuICAgICAgaWYgKChpc09wZW5pbmdCcmFja2V0IHx8IGlzVHlwZURlY2xhcmF0aW9uKSAmJiAhaXNJbk11bHRpbGluZUNvbW1lbnQpIHtcbiAgICAgICAgYnJhY2tldERlcHRoICs9IDFcbiAgICAgICAgcmlnaHRJbmRlbnQgKz0gKGJyYWNrZXREZXB0aCAtIDEpICogMlxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGlzQ2xvc2luZ0JyYWNrZXQgJiZcbiAgICAgICAgICBicmFja2V0RGVwdGggPiAwICYmXG4gICAgICAgICAgIWlzSW5NdWx0aWxpbmVDb21tZW50ICYmXG4gICAgICAgICAgIWlzVHlwZVZhcmlhbnRcbiAgICAgICAgKSB7XG4gICAgICAgICAgYnJhY2tldERlcHRoIC09IDFcbiAgICAgICAgfVxuICAgICAgICByaWdodEluZGVudCArPSBicmFja2V0RGVwdGggKiAyXG4gICAgICB9XG5cbiAgICAgIGlmIChpc0luTXVsdGlsaW5lQ29tbWVudCkge1xuICAgICAgICByaWdodEluZGVudCArPSAxXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHMgPSBgJHsnICcucmVwZWF0KHJpZ2h0SW5kZW50KX0ke2xpbmV9YFxuXG4gICAgICByZXR1cm4gc1xuICAgIH0pXG4gICAgLmpvaW4oJ1xcbicpXG5cbiAgcmV0dXJuIHJlc3VsdFxufVxuIiwiaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gJ25vZGU6cGF0aCdcblxuaW1wb3J0IHsgcmVhZE5hcGlDb25maWcgfSBmcm9tICcuL2NvbmZpZy5qcydcblxuaW50ZXJmYWNlIE1pbmltYWxOYXBpT3B0aW9ucyB7XG4gIGN3ZDogc3RyaW5nXG4gIGNvbmZpZ1BhdGg/OiBzdHJpbmdcbiAgcGFja2FnZUpzb25QYXRoPzogc3RyaW5nXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkQ29uZmlnKG9wdGlvbnM6IE1pbmltYWxOYXBpT3B0aW9ucykge1xuICBjb25zdCByZXNvbHZlUGF0aCA9ICguLi5wYXRoczogc3RyaW5nW10pID0+IHJlc29sdmUob3B0aW9ucy5jd2QsIC4uLnBhdGhzKVxuICBjb25zdCBjb25maWcgPSBhd2FpdCByZWFkTmFwaUNvbmZpZyhcbiAgICByZXNvbHZlUGF0aChcbiAgICAgIG9wdGlvbnMuY29uZmlnUGF0aCA/PyBvcHRpb25zLnBhY2thZ2VKc29uUGF0aCA/PyAncGFja2FnZS5qc29uJyxcbiAgICApLFxuICAgIG9wdGlvbnMuY29uZmlnUGF0aCA/IHJlc29sdmVQYXRoKG9wdGlvbnMuY29uZmlnUGF0aCkgOiB1bmRlZmluZWQsXG4gIClcbiAgcmV0dXJuIGNvbmZpZ1xufVxuIiwiaW1wb3J0IHsgam9pbiwgcGFyc2UgfSBmcm9tICdub2RlOnBhdGgnXG5cbmltcG9ydCAqIGFzIGNvbG9ycyBmcm9tICdjb2xvcmV0dGUnXG5cbmltcG9ydCB7XG4gIGFwcGx5RGVmYXVsdEFydGlmYWN0c09wdGlvbnMsXG4gIEFydGlmYWN0c09wdGlvbnMsXG59IGZyb20gJy4uL2RlZi9hcnRpZmFjdHMuanMnXG5pbXBvcnQge1xuICByZWFkTmFwaUNvbmZpZyxcbiAgZGVidWdGYWN0b3J5LFxuICByZWFkRmlsZUFzeW5jLFxuICB3cml0ZUZpbGVBc3luYyxcbiAgVW5pQXJjaHNCeVBsYXRmb3JtLFxuICByZWFkZGlyQXN5bmMsXG59IGZyb20gJy4uL3V0aWxzL2luZGV4LmpzJ1xuXG5jb25zdCBkZWJ1ZyA9IGRlYnVnRmFjdG9yeSgnYXJ0aWZhY3RzJylcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbGxlY3RBcnRpZmFjdHModXNlck9wdGlvbnM6IEFydGlmYWN0c09wdGlvbnMpIHtcbiAgY29uc3Qgb3B0aW9ucyA9IGFwcGx5RGVmYXVsdEFydGlmYWN0c09wdGlvbnModXNlck9wdGlvbnMpXG5cbiAgY29uc3QgcGFja2FnZUpzb25QYXRoID0gam9pbihvcHRpb25zLmN3ZCwgb3B0aW9ucy5wYWNrYWdlSnNvblBhdGgpXG4gIGNvbnN0IHsgdGFyZ2V0cywgYmluYXJ5TmFtZSwgcGFja2FnZU5hbWUgfSA9XG4gICAgYXdhaXQgcmVhZE5hcGlDb25maWcocGFja2FnZUpzb25QYXRoKVxuXG4gIGNvbnN0IGRpc3REaXJzID0gdGFyZ2V0cy5tYXAoKHBsYXRmb3JtKSA9PlxuICAgIGpvaW4ob3B0aW9ucy5jd2QsIG9wdGlvbnMubnBtRGlyLCBwbGF0Zm9ybS5wbGF0Zm9ybUFyY2hBQkkpLFxuICApXG5cbiAgY29uc3QgdW5pdmVyc2FsU291cmNlQmlucyA9IG5ldyBTZXQoXG4gICAgdGFyZ2V0c1xuICAgICAgLmZpbHRlcigocGxhdGZvcm0pID0+IHBsYXRmb3JtLmFyY2ggPT09ICd1bml2ZXJzYWwnKVxuICAgICAgLmZsYXRNYXAoKHApID0+XG4gICAgICAgIFVuaUFyY2hzQnlQbGF0Zm9ybVtwLnBsYXRmb3JtXT8ubWFwKChhKSA9PiBgJHtwLnBsYXRmb3JtfS0ke2F9YCksXG4gICAgICApXG4gICAgICAuZmlsdGVyKEJvb2xlYW4pIGFzIHN0cmluZ1tdLFxuICApXG5cbiAgYXdhaXQgY29sbGVjdE5vZGVCaW5hcmllcyhqb2luKG9wdGlvbnMuY3dkLCBvcHRpb25zLm91dHB1dERpcikpLnRoZW4oXG4gICAgKG91dHB1dCkgPT5cbiAgICAgIFByb21pc2UuYWxsKFxuICAgICAgICBvdXRwdXQubWFwKGFzeW5jIChmaWxlUGF0aCkgPT4ge1xuICAgICAgICAgIGRlYnVnLmluZm8oYFJlYWQgWyR7Y29sb3JzLnllbGxvd0JyaWdodChmaWxlUGF0aCl9XWApXG4gICAgICAgICAgY29uc3Qgc291cmNlQ29udGVudCA9IGF3YWl0IHJlYWRGaWxlQXN5bmMoZmlsZVBhdGgpXG4gICAgICAgICAgY29uc3QgcGFyc2VkTmFtZSA9IHBhcnNlKGZpbGVQYXRoKVxuICAgICAgICAgIGNvbnN0IHRlcm1zID0gcGFyc2VkTmFtZS5uYW1lLnNwbGl0KCcuJylcbiAgICAgICAgICBjb25zdCBwbGF0Zm9ybUFyY2hBQkkgPSB0ZXJtcy5wb3AoKSFcbiAgICAgICAgICBjb25zdCBfYmluYXJ5TmFtZSA9IHRlcm1zLmpvaW4oJy4nKVxuXG4gICAgICAgICAgaWYgKF9iaW5hcnlOYW1lICE9PSBiaW5hcnlOYW1lKSB7XG4gICAgICAgICAgICBkZWJ1Zy53YXJuKFxuICAgICAgICAgICAgICBgWyR7X2JpbmFyeU5hbWV9XSBpcyBub3QgbWF0Y2hlZCB3aXRoIFske2JpbmFyeU5hbWV9XSwgc2tpcGAsXG4gICAgICAgICAgICApXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgZGlyID0gZGlzdERpcnMuZmluZCgoZGlyKSA9PiBkaXIuaW5jbHVkZXMocGxhdGZvcm1BcmNoQUJJKSlcbiAgICAgICAgICBpZiAoIWRpciAmJiB1bml2ZXJzYWxTb3VyY2VCaW5zLmhhcyhwbGF0Zm9ybUFyY2hBQkkpKSB7XG4gICAgICAgICAgICBkZWJ1Zy53YXJuKFxuICAgICAgICAgICAgICBgWyR7cGxhdGZvcm1BcmNoQUJJfV0gaGFzIG5vIGRpc3QgZGlyIGJ1dCBpdCBpcyBzb3VyY2UgYmluIGZvciB1bml2ZXJzYWwgYXJjaCwgc2tpcGAsXG4gICAgICAgICAgICApXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFkaXIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gZGlzdCBkaXIgZm91bmQgZm9yICR7ZmlsZVBhdGh9YClcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBkaXN0RmlsZVBhdGggPSBqb2luKGRpciwgcGFyc2VkTmFtZS5iYXNlKVxuICAgICAgICAgIGRlYnVnLmluZm8oXG4gICAgICAgICAgICBgV3JpdGUgZmlsZSBjb250ZW50IHRvIFske2NvbG9ycy55ZWxsb3dCcmlnaHQoZGlzdEZpbGVQYXRoKX1dYCxcbiAgICAgICAgICApXG4gICAgICAgICAgYXdhaXQgd3JpdGVGaWxlQXN5bmMoZGlzdEZpbGVQYXRoLCBzb3VyY2VDb250ZW50KVxuICAgICAgICAgIGNvbnN0IGRpc3RGaWxlUGF0aExvY2FsID0gam9pbihcbiAgICAgICAgICAgIHBhcnNlKHBhY2thZ2VKc29uUGF0aCkuZGlyLFxuICAgICAgICAgICAgcGFyc2VkTmFtZS5iYXNlLFxuICAgICAgICAgIClcbiAgICAgICAgICBkZWJ1Zy5pbmZvKFxuICAgICAgICAgICAgYFdyaXRlIGZpbGUgY29udGVudCB0byBbJHtjb2xvcnMueWVsbG93QnJpZ2h0KGRpc3RGaWxlUGF0aExvY2FsKX1dYCxcbiAgICAgICAgICApXG4gICAgICAgICAgYXdhaXQgd3JpdGVGaWxlQXN5bmMoZGlzdEZpbGVQYXRoTG9jYWwsIHNvdXJjZUNvbnRlbnQpXG4gICAgICAgIH0pLFxuICAgICAgKSxcbiAgKVxuXG4gIGNvbnN0IHdhc2lUYXJnZXQgPSB0YXJnZXRzLmZpbmQoKHQpID0+IHQucGxhdGZvcm0gPT09ICd3YXNpJylcbiAgaWYgKHdhc2lUYXJnZXQpIHtcbiAgICBjb25zdCB3YXNpRGlyID0gam9pbihcbiAgICAgIG9wdGlvbnMuY3dkLFxuICAgICAgb3B0aW9ucy5ucG1EaXIsXG4gICAgICB3YXNpVGFyZ2V0LnBsYXRmb3JtQXJjaEFCSSxcbiAgICApXG4gICAgY29uc3QgY2pzRmlsZSA9IGpvaW4oXG4gICAgICBvcHRpb25zLmJ1aWxkT3V0cHV0RGlyID8/IG9wdGlvbnMuY3dkLFxuICAgICAgYCR7YmluYXJ5TmFtZX0ud2FzaS5janNgLFxuICAgIClcbiAgICBjb25zdCB3b3JrZXJGaWxlID0gam9pbihcbiAgICAgIG9wdGlvbnMuYnVpbGRPdXRwdXREaXIgPz8gb3B0aW9ucy5jd2QsXG4gICAgICBgd2FzaS13b3JrZXIubWpzYCxcbiAgICApXG4gICAgY29uc3QgYnJvd3NlckVudHJ5ID0gam9pbihcbiAgICAgIG9wdGlvbnMuYnVpbGRPdXRwdXREaXIgPz8gb3B0aW9ucy5jd2QsXG4gICAgICBgJHtiaW5hcnlOYW1lfS53YXNpLWJyb3dzZXIuanNgLFxuICAgIClcbiAgICBjb25zdCBicm93c2VyV29ya2VyRmlsZSA9IGpvaW4oXG4gICAgICBvcHRpb25zLmJ1aWxkT3V0cHV0RGlyID8/IG9wdGlvbnMuY3dkLFxuICAgICAgYHdhc2ktd29ya2VyLWJyb3dzZXIubWpzYCxcbiAgICApXG4gICAgZGVidWcuaW5mbyhcbiAgICAgIGBNb3ZlIHdhc2kgYmluZGluZyBmaWxlIFske2NvbG9ycy55ZWxsb3dCcmlnaHQoXG4gICAgICAgIGNqc0ZpbGUsXG4gICAgICApfV0gdG8gWyR7Y29sb3JzLnllbGxvd0JyaWdodCh3YXNpRGlyKX1dYCxcbiAgICApXG4gICAgYXdhaXQgd3JpdGVGaWxlQXN5bmMoXG4gICAgICBqb2luKHdhc2lEaXIsIGAke2JpbmFyeU5hbWV9Lndhc2kuY2pzYCksXG4gICAgICBhd2FpdCByZWFkRmlsZUFzeW5jKGNqc0ZpbGUpLFxuICAgIClcbiAgICBkZWJ1Zy5pbmZvKFxuICAgICAgYE1vdmUgd2FzaSB3b3JrZXIgZmlsZSBbJHtjb2xvcnMueWVsbG93QnJpZ2h0KFxuICAgICAgICB3b3JrZXJGaWxlLFxuICAgICAgKX1dIHRvIFske2NvbG9ycy55ZWxsb3dCcmlnaHQod2FzaURpcil9XWAsXG4gICAgKVxuICAgIGF3YWl0IHdyaXRlRmlsZUFzeW5jKFxuICAgICAgam9pbih3YXNpRGlyLCBgd2FzaS13b3JrZXIubWpzYCksXG4gICAgICBhd2FpdCByZWFkRmlsZUFzeW5jKHdvcmtlckZpbGUpLFxuICAgIClcbiAgICBkZWJ1Zy5pbmZvKFxuICAgICAgYE1vdmUgd2FzaSBicm93c2VyIGVudHJ5IGZpbGUgWyR7Y29sb3JzLnllbGxvd0JyaWdodChcbiAgICAgICAgYnJvd3NlckVudHJ5LFxuICAgICAgKX1dIHRvIFske2NvbG9ycy55ZWxsb3dCcmlnaHQod2FzaURpcil9XWAsXG4gICAgKVxuICAgIGF3YWl0IHdyaXRlRmlsZUFzeW5jKFxuICAgICAgam9pbih3YXNpRGlyLCBgJHtiaW5hcnlOYW1lfS53YXNpLWJyb3dzZXIuanNgKSxcbiAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS92aXRlanMvdml0ZS9pc3N1ZXMvODQyN1xuICAgICAgKGF3YWl0IHJlYWRGaWxlQXN5bmMoYnJvd3NlckVudHJ5LCAndXRmOCcpKS5yZXBsYWNlKFxuICAgICAgICBgbmV3IFVSTCgnLi93YXNpLXdvcmtlci1icm93c2VyLm1qcycsIGltcG9ydC5tZXRhLnVybClgLFxuICAgICAgICBgbmV3IFVSTCgnJHtwYWNrYWdlTmFtZX0td2FzbTMyLXdhc2kvd2FzaS13b3JrZXItYnJvd3Nlci5tanMnLCBpbXBvcnQubWV0YS51cmwpYCxcbiAgICAgICksXG4gICAgKVxuICAgIGRlYnVnLmluZm8oXG4gICAgICBgTW92ZSB3YXNpIGJyb3dzZXIgd29ya2VyIGZpbGUgWyR7Y29sb3JzLnllbGxvd0JyaWdodChcbiAgICAgICAgYnJvd3NlcldvcmtlckZpbGUsXG4gICAgICApfV0gdG8gWyR7Y29sb3JzLnllbGxvd0JyaWdodCh3YXNpRGlyKX1dYCxcbiAgICApXG4gICAgYXdhaXQgd3JpdGVGaWxlQXN5bmMoXG4gICAgICBqb2luKHdhc2lEaXIsIGB3YXNpLXdvcmtlci1icm93c2VyLm1qc2ApLFxuICAgICAgYXdhaXQgcmVhZEZpbGVBc3luYyhicm93c2VyV29ya2VyRmlsZSksXG4gICAgKVxuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNvbGxlY3ROb2RlQmluYXJpZXMocm9vdDogc3RyaW5nKSB7XG4gIGNvbnN0IGZpbGVzID0gYXdhaXQgcmVhZGRpckFzeW5jKHJvb3QsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KVxuICBjb25zdCBub2RlQmluYXJpZXMgPSBmaWxlc1xuICAgIC5maWx0ZXIoXG4gICAgICAoZmlsZSkgPT5cbiAgICAgICAgZmlsZS5pc0ZpbGUoKSAmJlxuICAgICAgICAoZmlsZS5uYW1lLmVuZHNXaXRoKCcubm9kZScpIHx8IGZpbGUubmFtZS5lbmRzV2l0aCgnLndhc20nKSksXG4gICAgKVxuICAgIC5tYXAoKGZpbGUpID0+IGpvaW4ocm9vdCwgZmlsZS5uYW1lKSlcblxuICBjb25zdCBkaXJzID0gZmlsZXMuZmlsdGVyKChmaWxlKSA9PiBmaWxlLmlzRGlyZWN0b3J5KCkpXG4gIGZvciAoY29uc3QgZGlyIG9mIGRpcnMpIHtcbiAgICBpZiAoZGlyLm5hbWUgIT09ICdub2RlX21vZHVsZXMnKSB7XG4gICAgICBub2RlQmluYXJpZXMucHVzaCguLi4oYXdhaXQgY29sbGVjdE5vZGVCaW5hcmllcyhqb2luKHJvb3QsIGRpci5uYW1lKSkpKVxuICAgIH1cbiAgfVxuICByZXR1cm4gbm9kZUJpbmFyaWVzXG59XG4iLCJleHBvcnQgZnVuY3Rpb24gY3JlYXRlQ2pzQmluZGluZyhcbiAgbG9jYWxOYW1lOiBzdHJpbmcsXG4gIHBrZ05hbWU6IHN0cmluZyxcbiAgaWRlbnRzOiBzdHJpbmdbXSxcbik6IHN0cmluZyB7XG4gIHJldHVybiBgJHtiaW5kaW5nSGVhZGVyfVxuY29uc3QgeyBjcmVhdGVSZXF1aXJlIH0gPSByZXF1aXJlKCdub2RlOm1vZHVsZScpXG5yZXF1aXJlID0gY3JlYXRlUmVxdWlyZShfX2ZpbGVuYW1lKVxuXG4ke2NyZWF0ZUNvbW1vbkJpbmRpbmcobG9jYWxOYW1lLCBwa2dOYW1lKX1cbm1vZHVsZS5leHBvcnRzID0gbmF0aXZlQmluZGluZ1xuJHtpZGVudHNcbiAgLm1hcCgoaWRlbnQpID0+IGBtb2R1bGUuZXhwb3J0cy4ke2lkZW50fSA9IG5hdGl2ZUJpbmRpbmcuJHtpZGVudH1gKVxuICAuam9pbignXFxuJyl9XG5gXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFc21CaW5kaW5nKFxuICBsb2NhbE5hbWU6IHN0cmluZyxcbiAgcGtnTmFtZTogc3RyaW5nLFxuICBpZGVudHM6IHN0cmluZ1tdLFxuKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke2JpbmRpbmdIZWFkZXJ9XG5pbXBvcnQgeyBjcmVhdGVSZXF1aXJlIH0gZnJvbSAnbm9kZTptb2R1bGUnXG5jb25zdCByZXF1aXJlID0gY3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwpXG5jb25zdCBfX2Rpcm5hbWUgPSBuZXcgVVJMKCcuJywgaW1wb3J0Lm1ldGEudXJsKS5wYXRobmFtZVxuXG4ke2NyZWF0ZUNvbW1vbkJpbmRpbmcobG9jYWxOYW1lLCBwa2dOYW1lKX1cbmNvbnN0IHsgJHtpZGVudHMuam9pbignLCAnKX0gfSA9IG5hdGl2ZUJpbmRpbmdcbiR7aWRlbnRzLm1hcCgoaWRlbnQpID0+IGBleHBvcnQgeyAke2lkZW50fSB9YCkuam9pbignXFxuJyl9XG5gXG59XG5cbmNvbnN0IGJpbmRpbmdIZWFkZXIgPSBgLy8gcHJldHRpZXItaWdub3JlXG4vKiBlc2xpbnQtZGlzYWJsZSAqL1xuLy8gQHRzLW5vY2hlY2tcbi8qIGF1dG8tZ2VuZXJhdGVkIGJ5IE5BUEktUlMgKi9cbmBcblxuZnVuY3Rpb24gY3JlYXRlQ29tbW9uQmluZGluZyhsb2NhbE5hbWU6IHN0cmluZywgcGtnTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgZnVuY3Rpb24gcmVxdWlyZVR1cGxlKHR1cGxlOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gYHRyeSB7XG4gICAgICAgIHJldHVybiByZXF1aXJlKCcuLyR7bG9jYWxOYW1lfS4ke3R1cGxlfS5ub2RlJylcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgbG9hZEVycm9ycy5wdXNoKGUpXG4gICAgICB9XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gcmVxdWlyZSgnJHtwa2dOYW1lfS0ke3R1cGxlfScpXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGxvYWRFcnJvcnMucHVzaChlKVxuICAgICAgfVxuYFxuICB9XG5cbiAgcmV0dXJuIGBjb25zdCB7IHJlYWRGaWxlU3luYyB9ID0gcmVxdWlyZSgnbm9kZTpmcycpXG5sZXQgbmF0aXZlQmluZGluZyA9IG51bGxcbmNvbnN0IGxvYWRFcnJvcnMgPSBbXVxuXG5jb25zdCBpc011c2wgPSAoKSA9PiB7XG4gIGxldCBtdXNsID0gZmFsc2VcbiAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09ICdsaW51eCcpIHtcbiAgICBtdXNsID0gaXNNdXNsRnJvbUZpbGVzeXN0ZW0oKVxuICAgIGlmIChtdXNsID09PSBudWxsKSB7XG4gICAgICBtdXNsID0gaXNNdXNsRnJvbVJlcG9ydCgpXG4gICAgfVxuICAgIGlmIChtdXNsID09PSBudWxsKSB7XG4gICAgICBtdXNsID0gaXNNdXNsRnJvbUNoaWxkUHJvY2VzcygpXG4gICAgfVxuICB9XG4gIHJldHVybiBtdXNsXG59XG5cbmNvbnN0IGlzRmlsZU11c2wgPSAoZikgPT4gZi5pbmNsdWRlcygnbGliYy5tdXNsLScpIHx8IGYuaW5jbHVkZXMoJ2xkLW11c2wtJylcblxuY29uc3QgaXNNdXNsRnJvbUZpbGVzeXN0ZW0gPSAoKSA9PiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHJlYWRGaWxlU3luYygnL3Vzci9iaW4vbGRkJywgJ3V0Zi04JykuaW5jbHVkZXMoJ211c2wnKVxuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG59XG5cbmNvbnN0IGlzTXVzbEZyb21SZXBvcnQgPSAoKSA9PiB7XG4gIGxldCByZXBvcnQgPSBudWxsXG4gIGlmICh0eXBlb2YgcHJvY2Vzcy5yZXBvcnQ/LmdldFJlcG9ydCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHByb2Nlc3MucmVwb3J0LmV4Y2x1ZGVOZXR3b3JrID0gdHJ1ZVxuICAgIHJlcG9ydCA9IHByb2Nlc3MucmVwb3J0LmdldFJlcG9ydCgpXG4gIH1cbiAgaWYgKCFyZXBvcnQpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIGlmIChyZXBvcnQuaGVhZGVyICYmIHJlcG9ydC5oZWFkZXIuZ2xpYmNWZXJzaW9uUnVudGltZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KHJlcG9ydC5zaGFyZWRPYmplY3RzKSkge1xuICAgIGlmIChyZXBvcnQuc2hhcmVkT2JqZWN0cy5zb21lKGlzRmlsZU11c2wpKSB7XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2Vcbn1cblxuY29uc3QgaXNNdXNsRnJvbUNoaWxkUHJvY2VzcyA9ICgpID0+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpLmV4ZWNTeW5jKCdsZGQgLS12ZXJzaW9uJywgeyBlbmNvZGluZzogJ3V0ZjgnIH0pLmluY2x1ZGVzKCdtdXNsJylcbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vIElmIHdlIHJlYWNoIHRoaXMgY2FzZSwgd2UgZG9uJ3Qga25vdyBpZiB0aGUgc3lzdGVtIGlzIG11c2wgb3Igbm90LCBzbyBpcyBiZXR0ZXIgdG8ganVzdCBmYWxsYmFjayB0byBmYWxzZVxuICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbmZ1bmN0aW9uIHJlcXVpcmVOYXRpdmUoKSB7XG4gIGlmIChwcm9jZXNzLmVudi5OQVBJX1JTX05BVElWRV9MSUJSQVJZX1BBVEgpIHtcbiAgICB0cnkge1xuICAgICAgbmF0aXZlQmluZGluZyA9IHJlcXVpcmUocHJvY2Vzcy5lbnYuTkFQSV9SU19OQVRJVkVfTElCUkFSWV9QQVRIKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGxvYWRFcnJvcnMucHVzaChlcnIpXG4gICAgfVxuICB9IGVsc2UgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09ICdhbmRyb2lkJykge1xuICAgIGlmIChwcm9jZXNzLmFyY2ggPT09ICdhcm02NCcpIHtcbiAgICAgICR7cmVxdWlyZVR1cGxlKCdhbmRyb2lkLWFybTY0Jyl9XG4gICAgfSBlbHNlIGlmIChwcm9jZXNzLmFyY2ggPT09ICdhcm0nKSB7XG4gICAgICAke3JlcXVpcmVUdXBsZSgnYW5kcm9pZC1hcm0tZWFiaScpfVxuICAgIH0gZWxzZSB7XG4gICAgICBsb2FkRXJyb3JzLnB1c2gobmV3IEVycm9yKFxcYFVuc3VwcG9ydGVkIGFyY2hpdGVjdHVyZSBvbiBBbmRyb2lkIFxcJHtwcm9jZXNzLmFyY2h9XFxgKSlcbiAgICB9XG4gIH0gZWxzZSBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJykge1xuICAgIGlmIChwcm9jZXNzLmFyY2ggPT09ICd4NjQnKSB7XG4gICAgICAke3JlcXVpcmVUdXBsZSgnd2luMzIteDY0LW1zdmMnKX1cbiAgICB9IGVsc2UgaWYgKHByb2Nlc3MuYXJjaCA9PT0gJ2lhMzInKSB7XG4gICAgICAke3JlcXVpcmVUdXBsZSgnd2luMzItaWEzMi1tc3ZjJyl9XG4gICAgfSBlbHNlIGlmIChwcm9jZXNzLmFyY2ggPT09ICdhcm02NCcpIHtcbiAgICAgICR7cmVxdWlyZVR1cGxlKCd3aW4zMi1hcm02NC1tc3ZjJyl9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvYWRFcnJvcnMucHVzaChuZXcgRXJyb3IoXFxgVW5zdXBwb3J0ZWQgYXJjaGl0ZWN0dXJlIG9uIFdpbmRvd3M6IFxcJHtwcm9jZXNzLmFyY2h9XFxgKSlcbiAgICB9XG4gIH0gZWxzZSBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ2RhcndpbicpIHtcbiAgICAke3JlcXVpcmVUdXBsZSgnZGFyd2luLXVuaXZlcnNhbCcpfVxuICAgIGlmIChwcm9jZXNzLmFyY2ggPT09ICd4NjQnKSB7XG4gICAgICAke3JlcXVpcmVUdXBsZSgnZGFyd2luLXg2NCcpfVxuICAgIH0gZWxzZSBpZiAocHJvY2Vzcy5hcmNoID09PSAnYXJtNjQnKSB7XG4gICAgICAke3JlcXVpcmVUdXBsZSgnZGFyd2luLWFybTY0Jyl9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvYWRFcnJvcnMucHVzaChuZXcgRXJyb3IoXFxgVW5zdXBwb3J0ZWQgYXJjaGl0ZWN0dXJlIG9uIG1hY09TOiBcXCR7cHJvY2Vzcy5hcmNofVxcYCkpXG4gICAgfVxuICB9IGVsc2UgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09ICdmcmVlYnNkJykge1xuICAgIGlmIChwcm9jZXNzLmFyY2ggPT09ICd4NjQnKSB7XG4gICAgICAke3JlcXVpcmVUdXBsZSgnZnJlZWJzZC14NjQnKX1cbiAgICB9IGVsc2UgaWYgKHByb2Nlc3MuYXJjaCA9PT0gJ2FybTY0Jykge1xuICAgICAgJHtyZXF1aXJlVHVwbGUoJ2ZyZWVic2QtYXJtNjQnKX1cbiAgICB9IGVsc2Uge1xuICAgICAgbG9hZEVycm9ycy5wdXNoKG5ldyBFcnJvcihcXGBVbnN1cHBvcnRlZCBhcmNoaXRlY3R1cmUgb24gRnJlZUJTRDogXFwke3Byb2Nlc3MuYXJjaH1cXGApKVxuICAgIH1cbiAgfSBlbHNlIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSAnbGludXgnKSB7XG4gICAgaWYgKHByb2Nlc3MuYXJjaCA9PT0gJ3g2NCcpIHtcbiAgICAgIGlmIChpc011c2woKSkge1xuICAgICAgICAke3JlcXVpcmVUdXBsZSgnbGludXgteDY0LW11c2wnKX1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgICR7cmVxdWlyZVR1cGxlKCdsaW51eC14NjQtZ251Jyl9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChwcm9jZXNzLmFyY2ggPT09ICdhcm02NCcpIHtcbiAgICAgIGlmIChpc011c2woKSkge1xuICAgICAgICAke3JlcXVpcmVUdXBsZSgnbGludXgtYXJtNjQtbXVzbCcpfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgJHtyZXF1aXJlVHVwbGUoJ2xpbnV4LWFybTY0LWdudScpfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocHJvY2Vzcy5hcmNoID09PSAnYXJtJykge1xuICAgICAgaWYgKGlzTXVzbCgpKSB7XG4gICAgICAgICR7cmVxdWlyZVR1cGxlKCdsaW51eC1hcm0tbXVzbGVhYmloZicpfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgJHtyZXF1aXJlVHVwbGUoJ2xpbnV4LWFybS1nbnVlYWJpaGYnKX1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHByb2Nlc3MuYXJjaCA9PT0gJ3Jpc2N2NjQnKSB7XG4gICAgICBpZiAoaXNNdXNsKCkpIHtcbiAgICAgICAgJHtyZXF1aXJlVHVwbGUoJ2xpbnV4LXJpc2N2NjQtbXVzbCcpfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgJHtyZXF1aXJlVHVwbGUoJ2xpbnV4LXJpc2N2NjQtZ251Jyl9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChwcm9jZXNzLmFyY2ggPT09ICdwcGM2NCcpIHtcbiAgICAgICR7cmVxdWlyZVR1cGxlKCdsaW51eC1wcGM2NC1nbnUnKX1cbiAgICB9IGVsc2UgaWYgKHByb2Nlc3MuYXJjaCA9PT0gJ3MzOTB4Jykge1xuICAgICAgJHtyZXF1aXJlVHVwbGUoJ2xpbnV4LXMzOTB4LWdudScpfVxuICAgIH0gZWxzZSB7XG4gICAgICBsb2FkRXJyb3JzLnB1c2gobmV3IEVycm9yKFxcYFVuc3VwcG9ydGVkIGFyY2hpdGVjdHVyZSBvbiBMaW51eDogXFwke3Byb2Nlc3MuYXJjaH1cXGApKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBsb2FkRXJyb3JzLnB1c2gobmV3IEVycm9yKFxcYFVuc3VwcG9ydGVkIE9TOiBcXCR7cHJvY2Vzcy5wbGF0Zm9ybX0sIGFyY2hpdGVjdHVyZTogXFwke3Byb2Nlc3MuYXJjaH1cXGApKVxuICB9XG59XG5cbm5hdGl2ZUJpbmRpbmcgPSByZXF1aXJlTmF0aXZlKClcblxuaWYgKCFuYXRpdmVCaW5kaW5nIHx8IHByb2Nlc3MuZW52Lk5BUElfUlNfRk9SQ0VfV0FTSSkge1xuICB0cnkge1xuICAgIG5hdGl2ZUJpbmRpbmcgPSByZXF1aXJlKCcuLyR7bG9jYWxOYW1lfS53YXNpLmNqcycpXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmIChwcm9jZXNzLmVudi5OQVBJX1JTX0ZPUkNFX1dBU0kpIHtcbiAgICAgIGxvYWRFcnJvcnMucHVzaChlcnIpXG4gICAgfVxuICB9XG4gIGlmICghbmF0aXZlQmluZGluZykge1xuICAgIHRyeSB7XG4gICAgICBuYXRpdmVCaW5kaW5nID0gcmVxdWlyZSgnJHtwa2dOYW1lfS13YXNtMzItd2FzaScpXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAocHJvY2Vzcy5lbnYuTkFQSV9SU19GT1JDRV9XQVNJKSB7XG4gICAgICAgIGxvYWRFcnJvcnMucHVzaChlcnIpXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmlmICghbmF0aXZlQmluZGluZykge1xuICBpZiAobG9hZEVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgXFxgQ2Fubm90IGZpbmQgbmF0aXZlIGJpbmRpbmcuIFxcYCArXG4gICAgICAgIFxcYG5wbSBoYXMgYSBidWcgcmVsYXRlZCB0byBvcHRpb25hbCBkZXBlbmRlbmNpZXMgKGh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vY2xpL2lzc3Vlcy80ODI4KS4gXFxgICtcbiAgICAgICAgJ1BsZWFzZSB0cnkgXFxgbnBtIGlcXGAgYWdhaW4gYWZ0ZXIgcmVtb3ZpbmcgYm90aCBwYWNrYWdlLWxvY2suanNvbiBhbmQgbm9kZV9tb2R1bGVzIGRpcmVjdG9yeS4nLFxuICAgICAgeyBjYXVzZTogbG9hZEVycm9ycyB9XG4gICAgKVxuICB9XG4gIHRocm93IG5ldyBFcnJvcihcXGBGYWlsZWQgdG8gbG9hZCBuYXRpdmUgYmluZGluZ1xcYClcbn1cbmBcbn1cbiIsImV4cG9ydCBjb25zdCBjcmVhdGVXYXNpQnJvd3NlckJpbmRpbmcgPSAoXG4gIHdhc2lGaWxlbmFtZTogc3RyaW5nLFxuICBpbml0aWFsTWVtb3J5ID0gNDAwMCxcbiAgbWF4aW11bU1lbW9yeSA9IDY1NTM2LFxuICBmcyA9IGZhbHNlLFxuICBhc3luY0luaXQgPSBmYWxzZSxcbikgPT4ge1xuICBjb25zdCBmc0ltcG9ydCA9IGZzID8gYGltcG9ydCB7IG1lbWZzIH0gZnJvbSAnQG5hcGktcnMvd2FzbS1ydW50aW1lL2ZzJ2AgOiAnJ1xuICBjb25zdCB3YXNpQ3JlYXRpb24gPSBmc1xuICAgID8gYFxuZXhwb3J0IGNvbnN0IHsgZnM6IF9fZnMsIHZvbDogX192b2x1bWUgfSA9IG1lbWZzKClcblxuY29uc3QgX193YXNpID0gbmV3IF9fV0FTSSh7XG4gIHZlcnNpb246ICdwcmV2aWV3MScsXG4gIGZzOiBfX2ZzLFxuICBwcmVvcGVuczoge1xuICAgICcvJzogJy8nLFxuICB9LFxufSlgXG4gICAgOiBgXG5jb25zdCBfX3dhc2kgPSBuZXcgX19XQVNJKHtcbiAgdmVyc2lvbjogJ3ByZXZpZXcxJyxcbn0pYFxuXG4gIGNvbnN0IHdvcmtlckZzSGFuZGxlciA9IGZzXG4gICAgPyBgICAgIHdvcmtlci5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgX193YXNtQ3JlYXRlT25NZXNzYWdlRm9yRnNQcm94eShfX2ZzKSlcXG5gXG4gICAgOiAnJ1xuXG4gIGNvbnN0IGVtbmFwaUluc3RhbnRpYXRlSW1wb3J0ID0gYXN5bmNJbml0XG4gICAgPyBgaW5zdGFudGlhdGVOYXBpTW9kdWxlIGFzIF9fZW1uYXBpSW5zdGFudGlhdGVOYXBpTW9kdWxlYFxuICAgIDogYGluc3RhbnRpYXRlTmFwaU1vZHVsZVN5bmMgYXMgX19lbW5hcGlJbnN0YW50aWF0ZU5hcGlNb2R1bGVTeW5jYFxuICBjb25zdCBlbW5hcGlJbnN0YW50aWF0ZUNhbGwgPSBhc3luY0luaXRcbiAgICA/IGBhd2FpdCBfX2VtbmFwaUluc3RhbnRpYXRlTmFwaU1vZHVsZWBcbiAgICA6IGBfX2VtbmFwaUluc3RhbnRpYXRlTmFwaU1vZHVsZVN5bmNgXG5cbiAgcmV0dXJuIGBpbXBvcnQge1xuICBjcmVhdGVPbk1lc3NhZ2UgYXMgX193YXNtQ3JlYXRlT25NZXNzYWdlRm9yRnNQcm94eSxcbiAgZ2V0RGVmYXVsdENvbnRleHQgYXMgX19lbW5hcGlHZXREZWZhdWx0Q29udGV4dCxcbiAgJHtlbW5hcGlJbnN0YW50aWF0ZUltcG9ydH0sXG4gIFdBU0kgYXMgX19XQVNJLFxufSBmcm9tICdAbmFwaS1ycy93YXNtLXJ1bnRpbWUnXG4ke2ZzSW1wb3J0fVxuJHt3YXNpQ3JlYXRpb259XG5cbmNvbnN0IF9fd2FzbVVybCA9IG5ldyBVUkwoJy4vJHt3YXNpRmlsZW5hbWV9Lndhc20nLCBpbXBvcnQubWV0YS51cmwpLmhyZWZcbmNvbnN0IF9fZW1uYXBpQ29udGV4dCA9IF9fZW1uYXBpR2V0RGVmYXVsdENvbnRleHQoKVxuXG5jb25zdCBfX3NoYXJlZE1lbW9yeSA9IG5ldyBXZWJBc3NlbWJseS5NZW1vcnkoe1xuICBpbml0aWFsOiAke2luaXRpYWxNZW1vcnl9LFxuICBtYXhpbXVtOiAke21heGltdW1NZW1vcnl9LFxuICBzaGFyZWQ6IHRydWUsXG59KVxuXG5jb25zdCBfX3dhc21GaWxlID0gYXdhaXQgZmV0Y2goX193YXNtVXJsKS50aGVuKChyZXMpID0+IHJlcy5hcnJheUJ1ZmZlcigpKVxuXG5jb25zdCB7XG4gIGluc3RhbmNlOiBfX25hcGlJbnN0YW5jZSxcbiAgbW9kdWxlOiBfX3dhc2lNb2R1bGUsXG4gIG5hcGlNb2R1bGU6IF9fbmFwaU1vZHVsZSxcbn0gPSAke2VtbmFwaUluc3RhbnRpYXRlQ2FsbH0oX193YXNtRmlsZSwge1xuICBjb250ZXh0OiBfX2VtbmFwaUNvbnRleHQsXG4gIGFzeW5jV29ya1Bvb2xTaXplOiA0LFxuICB3YXNpOiBfX3dhc2ksXG4gIG9uQ3JlYXRlV29ya2VyKCkge1xuICAgIGNvbnN0IHdvcmtlciA9IG5ldyBXb3JrZXIobmV3IFVSTCgnLi93YXNpLXdvcmtlci1icm93c2VyLm1qcycsIGltcG9ydC5tZXRhLnVybCksIHtcbiAgICAgIHR5cGU6ICdtb2R1bGUnLFxuICAgIH0pXG4ke3dvcmtlckZzSGFuZGxlcn1cbiAgICByZXR1cm4gd29ya2VyXG4gIH0sXG4gIG92ZXJ3cml0ZUltcG9ydHMoaW1wb3J0T2JqZWN0KSB7XG4gICAgaW1wb3J0T2JqZWN0LmVudiA9IHtcbiAgICAgIC4uLmltcG9ydE9iamVjdC5lbnYsXG4gICAgICAuLi5pbXBvcnRPYmplY3QubmFwaSxcbiAgICAgIC4uLmltcG9ydE9iamVjdC5lbW5hcGksXG4gICAgICBtZW1vcnk6IF9fc2hhcmVkTWVtb3J5LFxuICAgIH1cbiAgICByZXR1cm4gaW1wb3J0T2JqZWN0XG4gIH0sXG4gIGJlZm9yZUluaXQoeyBpbnN0YW5jZSB9KSB7XG4gICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5rZXlzKGluc3RhbmNlLmV4cG9ydHMpKSB7XG4gICAgICBpZiAobmFtZS5zdGFydHNXaXRoKCdfX25hcGlfcmVnaXN0ZXJfXycpKSB7XG4gICAgICAgIGluc3RhbmNlLmV4cG9ydHNbbmFtZV0oKVxuICAgICAgfVxuICAgIH1cbiAgfSxcbn0pXG5gXG59XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVXYXNpQmluZGluZyA9IChcbiAgd2FzbUZpbGVOYW1lOiBzdHJpbmcsXG4gIHBhY2thZ2VOYW1lOiBzdHJpbmcsXG4gIGluaXRpYWxNZW1vcnkgPSA0MDAwLFxuICBtYXhpbXVtTWVtb3J5ID0gNjU1MzYsXG4pID0+IGAvKiBlc2xpbnQtZGlzYWJsZSAqL1xuLyogcHJldHRpZXItaWdub3JlICovXG5cbi8qIGF1dG8tZ2VuZXJhdGVkIGJ5IE5BUEktUlMgKi9cblxuY29uc3QgX19ub2RlRnMgPSByZXF1aXJlKCdub2RlOmZzJylcbmNvbnN0IF9fbm9kZVBhdGggPSByZXF1aXJlKCdub2RlOnBhdGgnKVxuY29uc3QgeyBXQVNJOiBfX25vZGVXQVNJIH0gPSByZXF1aXJlKCdub2RlOndhc2knKVxuY29uc3QgeyBXb3JrZXIgfSA9IHJlcXVpcmUoJ25vZGU6d29ya2VyX3RocmVhZHMnKVxuXG5jb25zdCB7XG4gIGNyZWF0ZU9uTWVzc2FnZTogX193YXNtQ3JlYXRlT25NZXNzYWdlRm9yRnNQcm94eSxcbiAgZ2V0RGVmYXVsdENvbnRleHQ6IF9fZW1uYXBpR2V0RGVmYXVsdENvbnRleHQsXG4gIGluc3RhbnRpYXRlTmFwaU1vZHVsZVN5bmM6IF9fZW1uYXBpSW5zdGFudGlhdGVOYXBpTW9kdWxlU3luYyxcbn0gPSByZXF1aXJlKCdAbmFwaS1ycy93YXNtLXJ1bnRpbWUnKVxuXG5jb25zdCBfX3Jvb3REaXIgPSBfX25vZGVQYXRoLnBhcnNlKHByb2Nlc3MuY3dkKCkpLnJvb3RcblxuY29uc3QgX193YXNpID0gbmV3IF9fbm9kZVdBU0koe1xuICB2ZXJzaW9uOiAncHJldmlldzEnLFxuICBlbnY6IHByb2Nlc3MuZW52LFxuICBwcmVvcGVuczoge1xuICAgIFtfX3Jvb3REaXJdOiBfX3Jvb3REaXIsXG4gIH1cbn0pXG5cbmNvbnN0IF9fZW1uYXBpQ29udGV4dCA9IF9fZW1uYXBpR2V0RGVmYXVsdENvbnRleHQoKVxuXG5jb25zdCBfX3NoYXJlZE1lbW9yeSA9IG5ldyBXZWJBc3NlbWJseS5NZW1vcnkoe1xuICBpbml0aWFsOiAke2luaXRpYWxNZW1vcnl9LFxuICBtYXhpbXVtOiAke21heGltdW1NZW1vcnl9LFxuICBzaGFyZWQ6IHRydWUsXG59KVxuXG5sZXQgX193YXNtRmlsZVBhdGggPSBfX25vZGVQYXRoLmpvaW4oX19kaXJuYW1lLCAnJHt3YXNtRmlsZU5hbWV9Lndhc20nKVxuY29uc3QgX193YXNtRGVidWdGaWxlUGF0aCA9IF9fbm9kZVBhdGguam9pbihfX2Rpcm5hbWUsICcke3dhc21GaWxlTmFtZX0uZGVidWcud2FzbScpXG5cbmlmIChfX25vZGVGcy5leGlzdHNTeW5jKF9fd2FzbURlYnVnRmlsZVBhdGgpKSB7XG4gIF9fd2FzbUZpbGVQYXRoID0gX193YXNtRGVidWdGaWxlUGF0aFxufSBlbHNlIGlmICghX19ub2RlRnMuZXhpc3RzU3luYyhfX3dhc21GaWxlUGF0aCkpIHtcbiAgdHJ5IHtcbiAgICBfX3dhc21GaWxlUGF0aCA9IF9fbm9kZVBhdGgucmVzb2x2ZSgnJHtwYWNrYWdlTmFtZX0td2FzbTMyLXdhc2knKVxuICB9IGNhdGNoIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBmaW5kICR7d2FzbUZpbGVOYW1lfS53YXNtIGZpbGUsIGFuZCAke3BhY2thZ2VOYW1lfS13YXNtMzItd2FzaSBwYWNrYWdlIGlzIG5vdCBpbnN0YWxsZWQuJylcbiAgfVxufVxuXG5jb25zdCB7IGluc3RhbmNlOiBfX25hcGlJbnN0YW5jZSwgbW9kdWxlOiBfX3dhc2lNb2R1bGUsIG5hcGlNb2R1bGU6IF9fbmFwaU1vZHVsZSB9ID0gX19lbW5hcGlJbnN0YW50aWF0ZU5hcGlNb2R1bGVTeW5jKF9fbm9kZUZzLnJlYWRGaWxlU3luYyhfX3dhc21GaWxlUGF0aCksIHtcbiAgY29udGV4dDogX19lbW5hcGlDb250ZXh0LFxuICBhc3luY1dvcmtQb29sU2l6ZTogKGZ1bmN0aW9uKCkge1xuICAgIGNvbnN0IHRocmVhZHNTaXplRnJvbUVudiA9IE51bWJlcihwcm9jZXNzLmVudi5OQVBJX1JTX0FTWU5DX1dPUktfUE9PTF9TSVpFID8/IHByb2Nlc3MuZW52LlVWX1RIUkVBRFBPT0xfU0laRSlcbiAgICAvLyBOYU4gPiAwIGlzIGZhbHNlXG4gICAgaWYgKHRocmVhZHNTaXplRnJvbUVudiA+IDApIHtcbiAgICAgIHJldHVybiB0aHJlYWRzU2l6ZUZyb21FbnZcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIDRcbiAgICB9XG4gIH0pKCksXG4gIHJldXNlV29ya2VyOiB0cnVlLFxuICB3YXNpOiBfX3dhc2ksXG4gIG9uQ3JlYXRlV29ya2VyKCkge1xuICAgIGNvbnN0IHdvcmtlciA9IG5ldyBXb3JrZXIoX19ub2RlUGF0aC5qb2luKF9fZGlybmFtZSwgJ3dhc2ktd29ya2VyLm1qcycpLCB7XG4gICAgICBlbnY6IHByb2Nlc3MuZW52LFxuICAgIH0pXG4gICAgd29ya2VyLm9ubWVzc2FnZSA9ICh7IGRhdGEgfSkgPT4ge1xuICAgICAgX193YXNtQ3JlYXRlT25NZXNzYWdlRm9yRnNQcm94eShfX25vZGVGcykoZGF0YSlcbiAgICB9XG4gICAgcmV0dXJuIHdvcmtlclxuICB9LFxuICBvdmVyd3JpdGVJbXBvcnRzKGltcG9ydE9iamVjdCkge1xuICAgIGltcG9ydE9iamVjdC5lbnYgPSB7XG4gICAgICAuLi5pbXBvcnRPYmplY3QuZW52LFxuICAgICAgLi4uaW1wb3J0T2JqZWN0Lm5hcGksXG4gICAgICAuLi5pbXBvcnRPYmplY3QuZW1uYXBpLFxuICAgICAgbWVtb3J5OiBfX3NoYXJlZE1lbW9yeSxcbiAgICB9XG4gICAgcmV0dXJuIGltcG9ydE9iamVjdFxuICB9LFxuICBiZWZvcmVJbml0KHsgaW5zdGFuY2UgfSkge1xuICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhpbnN0YW5jZS5leHBvcnRzKSkge1xuICAgICAgaWYgKG5hbWUuc3RhcnRzV2l0aCgnX19uYXBpX3JlZ2lzdGVyX18nKSkge1xuICAgICAgICBpbnN0YW5jZS5leHBvcnRzW25hbWVdKClcbiAgICAgIH1cbiAgICB9XG4gIH0sXG59KVxuYFxuIiwiZXhwb3J0IGNvbnN0IFdBU0lfV09SS0VSX1RFTVBMQVRFID0gYGltcG9ydCBmcyBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0IHsgY3JlYXRlUmVxdWlyZSB9IGZyb20gXCJub2RlOm1vZHVsZVwiO1xuaW1wb3J0IHsgcGFyc2UgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBXQVNJIH0gZnJvbSBcIm5vZGU6d2FzaVwiO1xuaW1wb3J0IHsgcGFyZW50UG9ydCwgV29ya2VyIH0gZnJvbSBcIm5vZGU6d29ya2VyX3RocmVhZHNcIjtcblxuY29uc3QgcmVxdWlyZSA9IGNyZWF0ZVJlcXVpcmUoaW1wb3J0Lm1ldGEudXJsKTtcblxuY29uc3QgeyBpbnN0YW50aWF0ZU5hcGlNb2R1bGVTeW5jLCBNZXNzYWdlSGFuZGxlciwgZ2V0RGVmYXVsdENvbnRleHQgfSA9IHJlcXVpcmUoXCJAbmFwaS1ycy93YXNtLXJ1bnRpbWVcIik7XG5cbmlmIChwYXJlbnRQb3J0KSB7XG4gIHBhcmVudFBvcnQub24oXCJtZXNzYWdlXCIsIChkYXRhKSA9PiB7XG4gICAgZ2xvYmFsVGhpcy5vbm1lc3NhZ2UoeyBkYXRhIH0pO1xuICB9KTtcbn1cblxuT2JqZWN0LmFzc2lnbihnbG9iYWxUaGlzLCB7XG4gIHNlbGY6IGdsb2JhbFRoaXMsXG4gIHJlcXVpcmUsXG4gIFdvcmtlcixcbiAgaW1wb3J0U2NyaXB0czogZnVuY3Rpb24gKGYpIHtcbiAgICA7KDAsIGV2YWwpKGZzLnJlYWRGaWxlU3luYyhmLCBcInV0ZjhcIikgKyBcIi8vIyBzb3VyY2VVUkw9XCIgKyBmKTtcbiAgfSxcbiAgcG9zdE1lc3NhZ2U6IGZ1bmN0aW9uIChtc2cpIHtcbiAgICBpZiAocGFyZW50UG9ydCkge1xuICAgICAgcGFyZW50UG9ydC5wb3N0TWVzc2FnZShtc2cpO1xuICAgIH1cbiAgfSxcbn0pO1xuXG5jb25zdCBlbW5hcGlDb250ZXh0ID0gZ2V0RGVmYXVsdENvbnRleHQoKTtcblxuY29uc3QgX19yb290RGlyID0gcGFyc2UocHJvY2Vzcy5jd2QoKSkucm9vdDtcblxuY29uc3QgaGFuZGxlciA9IG5ldyBNZXNzYWdlSGFuZGxlcih7XG4gIG9uTG9hZCh7IHdhc21Nb2R1bGUsIHdhc21NZW1vcnkgfSkge1xuICAgIGNvbnN0IHdhc2kgPSBuZXcgV0FTSSh7XG4gICAgICB2ZXJzaW9uOiAncHJldmlldzEnLFxuICAgICAgZW52OiBwcm9jZXNzLmVudixcbiAgICAgIHByZW9wZW5zOiB7XG4gICAgICAgIFtfX3Jvb3REaXJdOiBfX3Jvb3REaXIsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGluc3RhbnRpYXRlTmFwaU1vZHVsZVN5bmMod2FzbU1vZHVsZSwge1xuICAgICAgY2hpbGRUaHJlYWQ6IHRydWUsXG4gICAgICB3YXNpLFxuICAgICAgY29udGV4dDogZW1uYXBpQ29udGV4dCxcbiAgICAgIG92ZXJ3cml0ZUltcG9ydHMoaW1wb3J0T2JqZWN0KSB7XG4gICAgICAgIGltcG9ydE9iamVjdC5lbnYgPSB7XG4gICAgICAgICAgLi4uaW1wb3J0T2JqZWN0LmVudixcbiAgICAgICAgICAuLi5pbXBvcnRPYmplY3QubmFwaSxcbiAgICAgICAgICAuLi5pbXBvcnRPYmplY3QuZW1uYXBpLFxuICAgICAgICAgIG1lbW9yeTogd2FzbU1lbW9yeVxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICB9KTtcbiAgfSxcbn0pO1xuXG5nbG9iYWxUaGlzLm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChlKSB7XG4gIGhhbmRsZXIuaGFuZGxlKGUpO1xufTtcbmBcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVdhc2lCcm93c2VyV29ya2VyQmluZGluZyA9IChmczogYm9vbGVhbikgPT4ge1xuICBjb25zdCBmc0ltcG9ydCA9IGZzXG4gICAgPyBgaW1wb3J0IHsgaW5zdGFudGlhdGVOYXBpTW9kdWxlU3luYywgTWVzc2FnZUhhbmRsZXIsIFdBU0ksIGNyZWF0ZUZzUHJveHkgfSBmcm9tICdAbmFwaS1ycy93YXNtLXJ1bnRpbWUnXG5pbXBvcnQgeyBtZW1mc0V4cG9ydGVkIGFzIF9fbWVtZnNFeHBvcnRlZCB9IGZyb20gJ0BuYXBpLXJzL3dhc20tcnVudGltZS9mcydcblxuY29uc3QgZnMgPSBjcmVhdGVGc1Byb3h5KF9fbWVtZnNFeHBvcnRlZClgXG4gICAgOiBgaW1wb3J0IHsgaW5zdGFudGlhdGVOYXBpTW9kdWxlU3luYywgTWVzc2FnZUhhbmRsZXIsIFdBU0kgfSBmcm9tICdAbmFwaS1ycy93YXNtLXJ1bnRpbWUnYFxuICBjb25zdCB3YXNpQ3JlYXRpb24gPSBmc1xuICAgID8gYGNvbnN0IHdhc2kgPSBuZXcgV0FTSSh7XG4gICAgICBmcyxcbiAgICAgIHByZW9wZW5zOiB7XG4gICAgICAgICcvJzogJy8nLFxuICAgICAgfSxcbiAgICAgIHByaW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUubG9nLmFwcGx5KGNvbnNvbGUsIGFyZ3VtZW50cylcbiAgICAgIH0sXG4gICAgICBwcmludEVycjogZnVuY3Rpb24oKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUuZXJyb3IuYXBwbHkoY29uc29sZSwgYXJndW1lbnRzKVxuICAgICAgfSxcbiAgICB9KWBcbiAgICA6IGBjb25zdCB3YXNpID0gbmV3IFdBU0koe1xuICAgICAgcHJpbnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS5sb2cuYXBwbHkoY29uc29sZSwgYXJndW1lbnRzKVxuICAgICAgfSxcbiAgICAgIHByaW50RXJyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS5lcnJvci5hcHBseShjb25zb2xlLCBhcmd1bWVudHMpXG4gICAgICB9LFxuICAgIH0pYFxuICByZXR1cm4gYCR7ZnNJbXBvcnR9XG5cbmNvbnN0IGhhbmRsZXIgPSBuZXcgTWVzc2FnZUhhbmRsZXIoe1xuICBvbkxvYWQoeyB3YXNtTW9kdWxlLCB3YXNtTWVtb3J5IH0pIHtcbiAgICAke3dhc2lDcmVhdGlvbn1cbiAgICByZXR1cm4gaW5zdGFudGlhdGVOYXBpTW9kdWxlU3luYyh3YXNtTW9kdWxlLCB7XG4gICAgICBjaGlsZFRocmVhZDogdHJ1ZSxcbiAgICAgIHdhc2ksXG4gICAgICBvdmVyd3JpdGVJbXBvcnRzKGltcG9ydE9iamVjdCkge1xuICAgICAgICBpbXBvcnRPYmplY3QuZW52ID0ge1xuICAgICAgICAgIC4uLmltcG9ydE9iamVjdC5lbnYsXG4gICAgICAgICAgLi4uaW1wb3J0T2JqZWN0Lm5hcGksXG4gICAgICAgICAgLi4uaW1wb3J0T2JqZWN0LmVtbmFwaSxcbiAgICAgICAgICBtZW1vcnk6IHdhc21NZW1vcnksXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSlcbiAgfSxcbn0pXG5cbmdsb2JhbFRoaXMub25tZXNzYWdlID0gZnVuY3Rpb24gKGUpIHtcbiAgaGFuZGxlci5oYW5kbGUoZSlcbn1cbmBcbn1cbiIsImltcG9ydCB7IHNwYXduIH0gZnJvbSAnbm9kZTpjaGlsZF9wcm9jZXNzJ1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ25vZGU6Y3J5cHRvJ1xuaW1wb3J0IHsgZXhpc3RzU3luYywgbWtkaXJTeW5jLCBybVN5bmMgfSBmcm9tICdub2RlOmZzJ1xuaW1wb3J0IHsgY3JlYXRlUmVxdWlyZSB9IGZyb20gJ25vZGU6bW9kdWxlJ1xuaW1wb3J0IHsgaG9tZWRpciB9IGZyb20gJ25vZGU6b3MnXG5pbXBvcnQgeyBwYXJzZSwgam9pbiwgcmVzb2x2ZSB9IGZyb20gJ25vZGU6cGF0aCdcblxuaW1wb3J0ICogYXMgY29sb3JzIGZyb20gJ2NvbG9yZXR0ZSdcbmltcG9ydCB7IGluY2x1ZGUgYXMgc2V0am1wSW5jbHVkZSwgbGliIGFzIHNldGptcExpYiB9IGZyb20gJ3dhc20tc2psaidcblxuaW1wb3J0IHsgQnVpbGRPcHRpb25zIGFzIFJhd0J1aWxkT3B0aW9ucyB9IGZyb20gJy4uL2RlZi9idWlsZC5qcydcbmltcG9ydCB7XG4gIENMSV9WRVJTSU9OLFxuICBjb3B5RmlsZUFzeW5jLFxuICBDcmF0ZSxcbiAgZGVidWdGYWN0b3J5LFxuICBERUZBVUxUX1RZUEVfREVGX0hFQURFUixcbiAgZmlsZUV4aXN0cyxcbiAgZ2V0U3lzdGVtRGVmYXVsdFRhcmdldCxcbiAgZ2V0VGFyZ2V0TGlua2VyLFxuICBta2RpckFzeW5jLFxuICBOYXBpQ29uZmlnLFxuICBwYXJzZU1ldGFkYXRhLFxuICBwYXJzZVRyaXBsZSxcbiAgcHJvY2Vzc1R5cGVEZWYsXG4gIHJlYWRGaWxlQXN5bmMsXG4gIHJlYWROYXBpQ29uZmlnLFxuICBUYXJnZXQsXG4gIHRhcmdldFRvRW52VmFyLFxuICB0cnlJbnN0YWxsQ2FyZ29CaW5hcnksXG4gIHVubGlua0FzeW5jLFxuICB3cml0ZUZpbGVBc3luYyxcbiAgZGlyRXhpc3RzQXN5bmMsXG4gIHJlYWRkaXJBc3luYyxcbiAgQ2FyZ29Xb3Jrc3BhY2VNZXRhZGF0YSxcbn0gZnJvbSAnLi4vdXRpbHMvaW5kZXguanMnXG5cbmltcG9ydCB7IGNyZWF0ZUNqc0JpbmRpbmcsIGNyZWF0ZUVzbUJpbmRpbmcgfSBmcm9tICcuL3RlbXBsYXRlcy9pbmRleC5qcydcbmltcG9ydCB7XG4gIGNyZWF0ZVdhc2lCaW5kaW5nLFxuICBjcmVhdGVXYXNpQnJvd3NlckJpbmRpbmcsXG59IGZyb20gJy4vdGVtcGxhdGVzL2xvYWQtd2FzaS10ZW1wbGF0ZS5qcydcbmltcG9ydCB7XG4gIGNyZWF0ZVdhc2lCcm93c2VyV29ya2VyQmluZGluZyxcbiAgV0FTSV9XT1JLRVJfVEVNUExBVEUsXG59IGZyb20gJy4vdGVtcGxhdGVzL3dhc2ktd29ya2VyLXRlbXBsYXRlLmpzJ1xuXG5jb25zdCBkZWJ1ZyA9IGRlYnVnRmFjdG9yeSgnYnVpbGQnKVxuY29uc3QgcmVxdWlyZSA9IGNyZWF0ZVJlcXVpcmUoaW1wb3J0Lm1ldGEudXJsKVxuXG50eXBlIE91dHB1dEtpbmQgPSAnanMnIHwgJ2R0cycgfCAnbm9kZScgfCAnZXhlJyB8ICd3YXNtJ1xudHlwZSBPdXRwdXQgPSB7IGtpbmQ6IE91dHB1dEtpbmQ7IHBhdGg6IHN0cmluZyB9XG5cbnR5cGUgQnVpbGRPcHRpb25zID0gUmF3QnVpbGRPcHRpb25zICYgeyBjYXJnb09wdGlvbnM/OiBzdHJpbmdbXSB9XG50eXBlIFBhcnNlZEJ1aWxkT3B0aW9ucyA9IE9taXQ8QnVpbGRPcHRpb25zLCAnY3dkJz4gJiB7IGN3ZDogc3RyaW5nIH1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1aWxkUHJvamVjdChyYXdPcHRpb25zOiBCdWlsZE9wdGlvbnMpIHtcbiAgZGVidWcoJ25hcGkgYnVpbGQgY29tbWFuZCByZWNlaXZlIG9wdGlvbnM6ICVPJywgcmF3T3B0aW9ucylcblxuICBjb25zdCBvcHRpb25zOiBQYXJzZWRCdWlsZE9wdGlvbnMgPSB7XG4gICAgZHRzQ2FjaGU6IHRydWUsXG4gICAgLi4ucmF3T3B0aW9ucyxcbiAgICBjd2Q6IHJhd09wdGlvbnMuY3dkID8/IHByb2Nlc3MuY3dkKCksXG4gIH1cblxuICBjb25zdCByZXNvbHZlUGF0aCA9ICguLi5wYXRoczogc3RyaW5nW10pID0+IHJlc29sdmUob3B0aW9ucy5jd2QsIC4uLnBhdGhzKVxuXG4gIGNvbnN0IG1hbmlmZXN0UGF0aCA9IHJlc29sdmVQYXRoKG9wdGlvbnMubWFuaWZlc3RQYXRoID8/ICdDYXJnby50b21sJylcbiAgY29uc3QgbWV0YWRhdGEgPSBhd2FpdCBwYXJzZU1ldGFkYXRhKG1hbmlmZXN0UGF0aClcblxuICBjb25zdCBjcmF0ZSA9IG1ldGFkYXRhLnBhY2thZ2VzLmZpbmQoKHApID0+IHtcbiAgICAvLyBwYWNrYWdlIHdpdGggZ2l2ZW4gbmFtZVxuICAgIGlmIChvcHRpb25zLnBhY2thZ2UpIHtcbiAgICAgIHJldHVybiBwLm5hbWUgPT09IG9wdGlvbnMucGFja2FnZVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcC5tYW5pZmVzdF9wYXRoID09PSBtYW5pZmVzdFBhdGhcbiAgICB9XG4gIH0pXG5cbiAgaWYgKCFjcmF0ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICdVbmFibGUgdG8gZmluZCBjcmF0ZSB0byBidWlsZC4gSXQgc2VlbXMgeW91IGFyZSB0cnlpbmcgdG8gYnVpbGQgYSBjcmF0ZSBpbiBhIHdvcmtzcGFjZSwgdHJ5IHVzaW5nIGAtLXBhY2thZ2VgIG9wdGlvbiB0byBzcGVjaWZ5IHRoZSBwYWNrYWdlIHRvIGJ1aWxkLicsXG4gICAgKVxuICB9XG4gIGNvbnN0IGNvbmZpZyA9IGF3YWl0IHJlYWROYXBpQ29uZmlnKFxuICAgIHJlc29sdmVQYXRoKFxuICAgICAgb3B0aW9ucy5jb25maWdQYXRoID8/IG9wdGlvbnMucGFja2FnZUpzb25QYXRoID8/ICdwYWNrYWdlLmpzb24nLFxuICAgICksXG4gICAgb3B0aW9ucy5jb25maWdQYXRoID8gcmVzb2x2ZVBhdGgob3B0aW9ucy5jb25maWdQYXRoKSA6IHVuZGVmaW5lZCxcbiAgKVxuXG4gIGNvbnN0IGJ1aWxkZXIgPSBuZXcgQnVpbGRlcihtZXRhZGF0YSwgY3JhdGUsIGNvbmZpZywgb3B0aW9ucylcblxuICByZXR1cm4gYnVpbGRlci5idWlsZCgpXG59XG5cbmNsYXNzIEJ1aWxkZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IGFyZ3M6IHN0cmluZ1tdID0gW11cbiAgcHJpdmF0ZSByZWFkb25seSBlbnZzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge31cbiAgcHJpdmF0ZSByZWFkb25seSBvdXRwdXRzOiBPdXRwdXRbXSA9IFtdXG5cbiAgcHJpdmF0ZSByZWFkb25seSB0YXJnZXQ6IFRhcmdldFxuICBwcml2YXRlIHJlYWRvbmx5IGNyYXRlRGlyOiBzdHJpbmdcbiAgcHJpdmF0ZSByZWFkb25seSBvdXRwdXREaXI6IHN0cmluZ1xuICBwcml2YXRlIHJlYWRvbmx5IHRhcmdldERpcjogc3RyaW5nXG4gIHByaXZhdGUgcmVhZG9ubHkgZW5hYmxlVHlwZURlZjogYm9vbGVhbiA9IGZhbHNlXG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBtZXRhZGF0YTogQ2FyZ29Xb3Jrc3BhY2VNZXRhZGF0YSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNyYXRlOiBDcmF0ZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNvbmZpZzogTmFwaUNvbmZpZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IFBhcnNlZEJ1aWxkT3B0aW9ucyxcbiAgKSB7XG4gICAgdGhpcy50YXJnZXQgPSBvcHRpb25zLnRhcmdldFxuICAgICAgPyBwYXJzZVRyaXBsZShvcHRpb25zLnRhcmdldClcbiAgICAgIDogcHJvY2Vzcy5lbnYuQ0FSR09fQlVJTERfVEFSR0VUXG4gICAgICAgID8gcGFyc2VUcmlwbGUocHJvY2Vzcy5lbnYuQ0FSR09fQlVJTERfVEFSR0VUKVxuICAgICAgICA6IGdldFN5c3RlbURlZmF1bHRUYXJnZXQoKVxuICAgIHRoaXMuY3JhdGVEaXIgPSBwYXJzZShjcmF0ZS5tYW5pZmVzdF9wYXRoKS5kaXJcbiAgICB0aGlzLm91dHB1dERpciA9IHJlc29sdmUoXG4gICAgICB0aGlzLm9wdGlvbnMuY3dkLFxuICAgICAgb3B0aW9ucy5vdXRwdXREaXIgPz8gdGhpcy5jcmF0ZURpcixcbiAgICApXG4gICAgdGhpcy50YXJnZXREaXIgPVxuICAgICAgb3B0aW9ucy50YXJnZXREaXIgPz9cbiAgICAgIHByb2Nlc3MuZW52LkNBUkdPX0JVSUxEX1RBUkdFVF9ESVIgPz9cbiAgICAgIG1ldGFkYXRhLnRhcmdldF9kaXJlY3RvcnlcbiAgICB0aGlzLmVuYWJsZVR5cGVEZWYgPSB0aGlzLmNyYXRlLmRlcGVuZGVuY2llcy5zb21lKFxuICAgICAgKGRlcCkgPT5cbiAgICAgICAgZGVwLm5hbWUgPT09ICduYXBpLWRlcml2ZScgJiZcbiAgICAgICAgKGRlcC51c2VzX2RlZmF1bHRfZmVhdHVyZXMgfHwgZGVwLmZlYXR1cmVzLmluY2x1ZGVzKCd0eXBlLWRlZicpKSxcbiAgICApXG5cbiAgICBpZiAoIXRoaXMuZW5hYmxlVHlwZURlZikge1xuICAgICAgY29uc3QgcmVxdWlyZW1lbnRXYXJuaW5nID1cbiAgICAgICAgJ2BuYXBpLWRlcml2ZWAgY3JhdGUgaXMgbm90IHVzZWQgb3IgYHR5cGUtZGVmYCBmZWF0dXJlIGlzIG5vdCBlbmFibGVkIGZvciBgbmFwaS1kZXJpdmVgIGNyYXRlJ1xuICAgICAgZGVidWcud2FybihcbiAgICAgICAgYCR7cmVxdWlyZW1lbnRXYXJuaW5nfS4gV2lsbCBza2lwIGJpbmRpbmcgZ2VuZXJhdGlvbiBmb3IgXFxgLm5vZGVcXGAsIFxcYC53YXNpXFxgIGFuZCBcXGAuZC50c1xcYCBmaWxlcy5gLFxuICAgICAgKVxuXG4gICAgICBpZiAoXG4gICAgICAgIHRoaXMub3B0aW9ucy5kdHMgfHxcbiAgICAgICAgdGhpcy5vcHRpb25zLmR0c0hlYWRlciB8fFxuICAgICAgICB0aGlzLmNvbmZpZy5kdHNIZWFkZXIgfHxcbiAgICAgICAgdGhpcy5jb25maWcuZHRzSGVhZGVyRmlsZVxuICAgICAgKSB7XG4gICAgICAgIGRlYnVnLndhcm4oXG4gICAgICAgICAgYCR7cmVxdWlyZW1lbnRXYXJuaW5nfS4gXFxgZHRzXFxgIHJlbGF0ZWQgb3B0aW9ucyBhcmUgZW5hYmxlZCBidXQgd2lsbCBiZSBpZ25vcmVkLmAsXG4gICAgICAgIClcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBnZXQgY2R5TGliTmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5jcmF0ZS50YXJnZXRzLmZpbmQoKHQpID0+IHQuY3JhdGVfdHlwZXMuaW5jbHVkZXMoJ2NkeWxpYicpKVxuICAgICAgPy5uYW1lXG4gIH1cblxuICBnZXQgYmluTmFtZSgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5vcHRpb25zLmJpbiA/P1xuICAgICAgLy8gb25seSBhdmFpbGFibGUgaWYgbm90IGNkeWxpYiBvciBiaW4gbmFtZSBzcGVjaWZpZWRcbiAgICAgICh0aGlzLmNkeUxpYk5hbWVcbiAgICAgICAgPyBudWxsXG4gICAgICAgIDogdGhpcy5jcmF0ZS50YXJnZXRzLmZpbmQoKHQpID0+IHQuY3JhdGVfdHlwZXMuaW5jbHVkZXMoJ2JpbicpKT8ubmFtZSlcbiAgICApXG4gIH1cblxuICBidWlsZCgpIHtcbiAgICBpZiAoIXRoaXMuY2R5TGliTmFtZSkge1xuICAgICAgY29uc3Qgd2FybmluZyA9XG4gICAgICAgICdNaXNzaW5nIGBjcmF0ZS10eXBlID0gW1wiY2R5bGliXCJdYCBpbiBbbGliXSBjb25maWcuIFRoZSBidWlsZCByZXN1bHQgd2lsbCBub3QgYmUgYXZhaWxhYmxlIGFzIG5vZGUgYWRkb24uJ1xuXG4gICAgICBpZiAodGhpcy5iaW5OYW1lKSB7XG4gICAgICAgIGRlYnVnLndhcm4od2FybmluZylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcih3YXJuaW5nKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnBpY2tCaW5hcnkoKVxuICAgICAgLnNldFBhY2thZ2UoKVxuICAgICAgLnNldEZlYXR1cmVzKClcbiAgICAgIC5zZXRUYXJnZXQoKVxuICAgICAgLnBpY2tDcm9zc1Rvb2xjaGFpbigpXG4gICAgICAuc2V0RW52cygpXG4gICAgICAuc2V0QnlwYXNzQXJncygpXG4gICAgICAuZXhlYygpXG4gIH1cblxuICBwcml2YXRlIHBpY2tDcm9zc1Rvb2xjaGFpbigpIHtcbiAgICBpZiAoIXRoaXMub3B0aW9ucy51c2VOYXBpQ3Jvc3MpIHtcbiAgICAgIHJldHVybiB0aGlzXG4gICAgfVxuICAgIGlmICh0aGlzLm9wdGlvbnMudXNlQ3Jvc3MpIHtcbiAgICAgIGRlYnVnLndhcm4oXG4gICAgICAgICdZb3UgYXJlIHRyeWluZyB0byB1c2UgYm90aCBgLS1jcm9zc2AgYW5kIGAtLXVzZS1uYXBpLWNyb3NzYCBvcHRpb25zLCBgLS11c2UtY3Jvc3NgIHdpbGwgYmUgaWdub3JlZC4nLFxuICAgICAgKVxuICAgIH1cblxuICAgIGlmICh0aGlzLm9wdGlvbnMuY3Jvc3NDb21waWxlKSB7XG4gICAgICBkZWJ1Zy53YXJuKFxuICAgICAgICAnWW91IGFyZSB0cnlpbmcgdG8gdXNlIGJvdGggYC0tY3Jvc3MtY29tcGlsZWAgYW5kIGAtLXVzZS1uYXBpLWNyb3NzYCBvcHRpb25zLCBgLS1jcm9zcy1jb21waWxlYCB3aWxsIGJlIGlnbm9yZWQuJyxcbiAgICAgIClcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgeyB2ZXJzaW9uLCBkb3dubG9hZCB9ID0gcmVxdWlyZSgnQG5hcGktcnMvY3Jvc3MtdG9vbGNoYWluJylcblxuICAgICAgY29uc3QgYWxpYXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICAgICdzMzkweC11bmtub3duLWxpbnV4LWdudSc6ICdzMzkweC1pYm0tbGludXgtZ251JyxcbiAgICAgIH1cblxuICAgICAgY29uc3QgdG9vbGNoYWluUGF0aCA9IGpvaW4oXG4gICAgICAgIGhvbWVkaXIoKSxcbiAgICAgICAgJy5uYXBpLXJzJyxcbiAgICAgICAgJ2Nyb3NzLXRvb2xjaGFpbicsXG4gICAgICAgIHZlcnNpb24sXG4gICAgICAgIHRoaXMudGFyZ2V0LnRyaXBsZSxcbiAgICAgIClcbiAgICAgIG1rZGlyU3luYyh0b29sY2hhaW5QYXRoLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuICAgICAgaWYgKGV4aXN0c1N5bmMoam9pbih0b29sY2hhaW5QYXRoLCAncGFja2FnZS5qc29uJykpKSB7XG4gICAgICAgIGRlYnVnKGBUb29sY2hhaW4gJHt0b29sY2hhaW5QYXRofSBleGlzdHMsIHNraXAgZXh0cmFjdGluZ2ApXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCB0YXJBcmNoaXZlID0gZG93bmxvYWQocHJvY2Vzcy5hcmNoLCB0aGlzLnRhcmdldC50cmlwbGUpXG4gICAgICAgIHRhckFyY2hpdmUudW5wYWNrKHRvb2xjaGFpblBhdGgpXG4gICAgICB9XG4gICAgICBjb25zdCB1cHBlckNhc2VUYXJnZXQgPSB0YXJnZXRUb0VudlZhcih0aGlzLnRhcmdldC50cmlwbGUpXG4gICAgICBjb25zdCBjcm9zc1RhcmdldE5hbWUgPSBhbGlhc1t0aGlzLnRhcmdldC50cmlwbGVdID8/IHRoaXMudGFyZ2V0LnRyaXBsZVxuICAgICAgY29uc3QgbGlua2VyRW52ID0gYENBUkdPX1RBUkdFVF8ke3VwcGVyQ2FzZVRhcmdldH1fTElOS0VSYFxuICAgICAgdGhpcy5lbnZzW2xpbmtlckVudl0gPSBqb2luKFxuICAgICAgICB0b29sY2hhaW5QYXRoLFxuICAgICAgICAnYmluJyxcbiAgICAgICAgYCR7Y3Jvc3NUYXJnZXROYW1lfS1nY2NgLFxuICAgICAgKVxuICAgICAgaWYgKCFwcm9jZXNzLmVudi5UQVJHRVRfU1lTUk9PVCkge1xuICAgICAgICB0aGlzLmVudnNbYFRBUkdFVF9TWVNST09UYF0gPSBqb2luKFxuICAgICAgICAgIHRvb2xjaGFpblBhdGgsXG4gICAgICAgICAgY3Jvc3NUYXJnZXROYW1lLFxuICAgICAgICAgICdzeXNyb290JyxcbiAgICAgICAgKVxuICAgICAgfVxuICAgICAgaWYgKCFwcm9jZXNzLmVudi5UQVJHRVRfQVIpIHtcbiAgICAgICAgdGhpcy5lbnZzW2BUQVJHRVRfQVJgXSA9IGpvaW4oXG4gICAgICAgICAgdG9vbGNoYWluUGF0aCxcbiAgICAgICAgICAnYmluJyxcbiAgICAgICAgICBgJHtjcm9zc1RhcmdldE5hbWV9LWFyYCxcbiAgICAgICAgKVxuICAgICAgfVxuICAgICAgaWYgKCFwcm9jZXNzLmVudi5UQVJHRVRfUkFOTElCKSB7XG4gICAgICAgIHRoaXMuZW52c1tgVEFSR0VUX1JBTkxJQmBdID0gam9pbihcbiAgICAgICAgICB0b29sY2hhaW5QYXRoLFxuICAgICAgICAgICdiaW4nLFxuICAgICAgICAgIGAke2Nyb3NzVGFyZ2V0TmFtZX0tcmFubGliYCxcbiAgICAgICAgKVxuICAgICAgfVxuICAgICAgaWYgKCFwcm9jZXNzLmVudi5UQVJHRVRfUkVBREVMRikge1xuICAgICAgICB0aGlzLmVudnNbYFRBUkdFVF9SRUFERUxGYF0gPSBqb2luKFxuICAgICAgICAgIHRvb2xjaGFpblBhdGgsXG4gICAgICAgICAgJ2JpbicsXG4gICAgICAgICAgYCR7Y3Jvc3NUYXJnZXROYW1lfS1yZWFkZWxmYCxcbiAgICAgICAgKVxuICAgICAgfVxuICAgICAgaWYgKCFwcm9jZXNzLmVudi5UQVJHRVRfQ19JTkNMVURFX1BBVEgpIHtcbiAgICAgICAgdGhpcy5lbnZzW2BUQVJHRVRfQ19JTkNMVURFX1BBVEhgXSA9IGpvaW4oXG4gICAgICAgICAgdG9vbGNoYWluUGF0aCxcbiAgICAgICAgICBjcm9zc1RhcmdldE5hbWUsXG4gICAgICAgICAgJ3N5c3Jvb3QnLFxuICAgICAgICAgICd1c3InLFxuICAgICAgICAgICdpbmNsdWRlLycsXG4gICAgICAgIClcbiAgICAgIH1cbiAgICAgIGlmICghcHJvY2Vzcy5lbnYuQ0MgJiYgIXByb2Nlc3MuZW52LlRBUkdFVF9DQykge1xuICAgICAgICB0aGlzLmVudnNbYENDYF0gPSBqb2luKHRvb2xjaGFpblBhdGgsICdiaW4nLCBgJHtjcm9zc1RhcmdldE5hbWV9LWdjY2ApXG4gICAgICAgIHRoaXMuZW52c1tgVEFSR0VUX0NDYF0gPSBqb2luKFxuICAgICAgICAgIHRvb2xjaGFpblBhdGgsXG4gICAgICAgICAgJ2JpbicsXG4gICAgICAgICAgYCR7Y3Jvc3NUYXJnZXROYW1lfS1nY2NgLFxuICAgICAgICApXG4gICAgICB9XG4gICAgICBpZiAoIXByb2Nlc3MuZW52LkNYWCAmJiAhcHJvY2Vzcy5lbnYuVEFSR0VUX0NYWCkge1xuICAgICAgICB0aGlzLmVudnNbYENYWGBdID0gam9pbih0b29sY2hhaW5QYXRoLCAnYmluJywgYCR7Y3Jvc3NUYXJnZXROYW1lfS1nKytgKVxuICAgICAgICB0aGlzLmVudnNbYFRBUkdFVF9DWFhgXSA9IGpvaW4oXG4gICAgICAgICAgdG9vbGNoYWluUGF0aCxcbiAgICAgICAgICAnYmluJyxcbiAgICAgICAgICBgJHtjcm9zc1RhcmdldE5hbWV9LWcrK2AsXG4gICAgICAgIClcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgKHByb2Nlc3MuZW52LkNDPy5zdGFydHNXaXRoKCdjbGFuZycpICYmXG4gICAgICAgICAgKHByb2Nlc3MuZW52LlRBUkdFVF9DQz8uc3RhcnRzV2l0aCgnY2xhbmcnKSB8fFxuICAgICAgICAgICAgIXByb2Nlc3MuZW52LlRBUkdFVF9DQykpIHx8XG4gICAgICAgIHByb2Nlc3MuZW52LlRBUkdFVF9DQz8uc3RhcnRzV2l0aCgnY2xhbmcnKVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IENGTEFHUyA9IHByb2Nlc3MuZW52LkNGTEFHUyA/PyAnJ1xuICAgICAgICB0aGlzLmVudnMuQ0ZMQUdTID0gYC0tc3lzcm9vdD0ke3RoaXMuZW52cy5UQVJHRVRfU1lTUk9PVH0gLS1nY2MtdG9vbGNoYWluPSR7dG9vbGNoYWluUGF0aH0gJHtDRkxBR1N9YFxuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICAocHJvY2Vzcy5lbnYuQ1hYPy5zdGFydHNXaXRoKCdjbGFuZysrJykgJiZcbiAgICAgICAgICAocHJvY2Vzcy5lbnYuVEFSR0VUX0NYWD8uc3RhcnRzV2l0aCgnY2xhbmcrKycpIHx8XG4gICAgICAgICAgICAhcHJvY2Vzcy5lbnYuVEFSR0VUX0NYWCkpIHx8XG4gICAgICAgIHByb2Nlc3MuZW52LlRBUkdFVF9DWFg/LnN0YXJ0c1dpdGgoJ2NsYW5nKysnKVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IENYWEZMQUdTID0gcHJvY2Vzcy5lbnYuQ1hYRkxBR1MgPz8gJydcbiAgICAgICAgdGhpcy5lbnZzLkNYWEZMQUdTID0gYC0tc3lzcm9vdD0ke3RoaXMuZW52cy5UQVJHRVRfU1lTUk9PVH0gLS1nY2MtdG9vbGNoYWluPSR7dG9vbGNoYWluUGF0aH0gJHtDWFhGTEFHU30gJHtDWFhGTEFHU31gXG4gICAgICB9XG4gICAgICB0aGlzLmVudnMuUEFUSCA9IHRoaXMuZW52cy5QQVRIXG4gICAgICAgID8gYCR7dG9vbGNoYWluUGF0aH0vYmluOiR7dGhpcy5lbnZzLlBBVEh9OiR7cHJvY2Vzcy5lbnYuUEFUSH1gXG4gICAgICAgIDogYCR7dG9vbGNoYWluUGF0aH0vYmluOiR7cHJvY2Vzcy5lbnYuUEFUSH1gXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZGVidWcud2FybignUGljayBjcm9zcyB0b29sY2hhaW4gZmFpbGVkJywgZSBhcyBFcnJvcilcbiAgICAgIC8vIGlnbm9yZSwgZG8gbm90aGluZ1xuICAgIH1cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgcHJpdmF0ZSBleGVjKCkge1xuICAgIGRlYnVnKGBTdGFydCBidWlsZGluZyBjcmF0ZTogJHt0aGlzLmNyYXRlLm5hbWV9YClcbiAgICBkZWJ1ZygnICAlaScsIGBjYXJnbyAke3RoaXMuYXJncy5qb2luKCcgJyl9YClcblxuICAgIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKClcblxuICAgIGNvbnN0IHdhdGNoID0gdGhpcy5vcHRpb25zLndhdGNoXG4gICAgY29uc3QgYnVpbGRUYXNrID0gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgaWYgKHRoaXMub3B0aW9ucy51c2VDcm9zcyAmJiB0aGlzLm9wdGlvbnMuY3Jvc3NDb21waWxlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnYC0tdXNlLWNyb3NzYCBhbmQgYC0tY3Jvc3MtY29tcGlsZWAgY2FuIG5vdCBiZSB1c2VkIHRvZ2V0aGVyJyxcbiAgICAgICAgKVxuICAgICAgfVxuICAgICAgY29uc3QgY29tbWFuZCA9XG4gICAgICAgIHByb2Nlc3MuZW52LkNBUkdPID8/ICh0aGlzLm9wdGlvbnMudXNlQ3Jvc3MgPyAnY3Jvc3MnIDogJ2NhcmdvJylcbiAgICAgIGNvbnN0IGJ1aWxkUHJvY2VzcyA9IHNwYXduKGNvbW1hbmQsIHRoaXMuYXJncywge1xuICAgICAgICBlbnY6IHsgLi4ucHJvY2Vzcy5lbnYsIC4uLnRoaXMuZW52cyB9LFxuICAgICAgICBzdGRpbzogd2F0Y2ggPyBbJ2luaGVyaXQnLCAnaW5oZXJpdCcsICdwaXBlJ10gOiAnaW5oZXJpdCcsXG4gICAgICAgIGN3ZDogdGhpcy5vcHRpb25zLmN3ZCxcbiAgICAgICAgc2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCxcbiAgICAgIH0pXG5cbiAgICAgIGJ1aWxkUHJvY2Vzcy5vbmNlKCdleGl0JywgKGNvZGUpID0+IHtcbiAgICAgICAgaWYgKGNvZGUgPT09IDApIHtcbiAgICAgICAgICBkZWJ1ZygnJWknLCBgQnVpbGQgY3JhdGUgJHt0aGlzLmNyYXRlLm5hbWV9IHN1Y2Nlc3NmdWxseSFgKVxuICAgICAgICAgIHJlc29sdmUoKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEJ1aWxkIGZhaWxlZCB3aXRoIGV4aXQgY29kZSAke2NvZGV9YCkpXG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICAgIGJ1aWxkUHJvY2Vzcy5vbmNlKCdlcnJvcicsIChlKSA9PiB7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEJ1aWxkIGZhaWxlZCB3aXRoIGVycm9yOiAke2UubWVzc2FnZX1gLCB7IGNhdXNlOiBlIH0pKVxuICAgICAgfSlcblxuICAgICAgLy8gd2F0Y2ggbW9kZSBvbmx5LCB0aGV5IGFyZSBwaXBlZCB0aHJvdWdoIHN0ZGVyclxuICAgICAgYnVpbGRQcm9jZXNzLnN0ZGVycj8ub24oJ2RhdGEnLCAoZGF0YSkgPT4ge1xuICAgICAgICBjb25zdCBvdXRwdXQgPSBkYXRhLnRvU3RyaW5nKClcbiAgICAgICAgY29uc29sZS5lcnJvcihvdXRwdXQpXG4gICAgICAgIGlmICgvRmluaXNoZWRcXHMoYGRldmB8YHJlbGVhc2VgKS8udGVzdChvdXRwdXQpKSB7XG4gICAgICAgICAgdGhpcy5wb3N0QnVpbGQoKS5jYXRjaCgoKSA9PiB7fSlcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRhc2s6IGJ1aWxkVGFzay50aGVuKCgpID0+IHRoaXMucG9zdEJ1aWxkKCkpLFxuICAgICAgYWJvcnQ6ICgpID0+IGNvbnRyb2xsZXIuYWJvcnQoKSxcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHBpY2tCaW5hcnkoKSB7XG4gICAgbGV0IHNldCA9IGZhbHNlXG4gICAgaWYgKHRoaXMub3B0aW9ucy53YXRjaCkge1xuICAgICAgaWYgKHByb2Nlc3MuZW52LkNJKSB7XG4gICAgICAgIGRlYnVnLndhcm4oJ1dhdGNoIG1vZGUgaXMgbm90IHN1cHBvcnRlZCBpbiBDSSBlbnZpcm9ubWVudCcpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZWJ1ZygnVXNlICVpJywgJ2NhcmdvLXdhdGNoJylcbiAgICAgICAgdHJ5SW5zdGFsbENhcmdvQmluYXJ5KCdjYXJnby13YXRjaCcsICd3YXRjaCcpXG4gICAgICAgIC8vIHlhcm4gbmFwaSB3YXRjaCAtLXRhcmdldCB4ODZfNjQtdW5rbm93bi1saW51eC1nbnUgWy0tY3Jvc3MtY29tcGlsZV1cbiAgICAgICAgLy8gPT09PlxuICAgICAgICAvLyBjYXJnbyB3YXRjaCBbLi4uXSAtLSBidWlsZCAtLXRhcmdldCB4ODZfNjQtdW5rbm93bi1saW51eC1nbnVcbiAgICAgICAgLy8gY2FyZ28gd2F0Y2ggWy4uLl0gLS0gemlnYnVpbGQgLS10YXJnZXQgeDg2XzY0LXVua25vd24tbGludXgtZ251XG4gICAgICAgIHRoaXMuYXJncy5wdXNoKFxuICAgICAgICAgICd3YXRjaCcsXG4gICAgICAgICAgJy0td2h5JyxcbiAgICAgICAgICAnLWknLFxuICAgICAgICAgICcqLntqcyx0cyxub2RlfScsXG4gICAgICAgICAgJy13JyxcbiAgICAgICAgICB0aGlzLmNyYXRlRGlyLFxuICAgICAgICAgICctLScsXG4gICAgICAgICAgJ2NhcmdvJyxcbiAgICAgICAgICAnYnVpbGQnLFxuICAgICAgICApXG4gICAgICAgIHNldCA9IHRydWVcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLmNyb3NzQ29tcGlsZSkge1xuICAgICAgaWYgKHRoaXMudGFyZ2V0LnBsYXRmb3JtID09PSAnd2luMzInKSB7XG4gICAgICAgIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInKSB7XG4gICAgICAgICAgZGVidWcud2FybihcbiAgICAgICAgICAgICdZb3UgYXJlIHRyeWluZyB0byBjcm9zcyBjb21waWxlIHRvIHdpbjMyIHBsYXRmb3JtIG9uIHdpbjMyIHBsYXRmb3JtIHdoaWNoIGlzIHVubmVjZXNzYXJ5LicsXG4gICAgICAgICAgKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIHVzZSBjYXJnby14d2luIHRvIGNyb3NzIGNvbXBpbGUgdG8gd2luMzIgcGxhdGZvcm1cbiAgICAgICAgICBkZWJ1ZygnVXNlICVpJywgJ2NhcmdvLXh3aW4nKVxuICAgICAgICAgIHRyeUluc3RhbGxDYXJnb0JpbmFyeSgnY2FyZ28teHdpbicsICd4d2luJylcbiAgICAgICAgICB0aGlzLmFyZ3MucHVzaCgneHdpbicsICdidWlsZCcpXG4gICAgICAgICAgaWYgKHRoaXMudGFyZ2V0LmFyY2ggPT09ICdpYTMyJykge1xuICAgICAgICAgICAgdGhpcy5lbnZzLlhXSU5fQVJDSCA9ICd4ODYnXG4gICAgICAgICAgfVxuICAgICAgICAgIHNldCA9IHRydWVcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHRoaXMudGFyZ2V0LnBsYXRmb3JtID09PSAnbGludXgnICYmXG4gICAgICAgICAgcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ2xpbnV4JyAmJlxuICAgICAgICAgIHRoaXMudGFyZ2V0LmFyY2ggPT09IHByb2Nlc3MuYXJjaCAmJlxuICAgICAgICAgIChmdW5jdGlvbiAoYWJpOiBzdHJpbmcgfCBudWxsKSB7XG4gICAgICAgICAgICBjb25zdCBnbGliY1ZlcnNpb25SdW50aW1lID1cbiAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgICBwcm9jZXNzLnJlcG9ydD8uZ2V0UmVwb3J0KCk/LmhlYWRlcj8uZ2xpYmNWZXJzaW9uUnVudGltZVxuICAgICAgICAgICAgY29uc3QgbGliYyA9IGdsaWJjVmVyc2lvblJ1bnRpbWUgPyAnZ251JyA6ICdtdXNsJ1xuICAgICAgICAgICAgcmV0dXJuIGFiaSA9PT0gbGliY1xuICAgICAgICAgIH0pKHRoaXMudGFyZ2V0LmFiaSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgZGVidWcud2FybihcbiAgICAgICAgICAgICdZb3UgYXJlIHRyeWluZyB0byBjcm9zcyBjb21waWxlIHRvIGxpbnV4IHRhcmdldCBvbiBsaW51eCBwbGF0Zm9ybSB3aGljaCBpcyB1bm5lY2Vzc2FyeS4nLFxuICAgICAgICAgIClcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICB0aGlzLnRhcmdldC5wbGF0Zm9ybSA9PT0gJ2RhcndpbicgJiZcbiAgICAgICAgICBwcm9jZXNzLnBsYXRmb3JtID09PSAnZGFyd2luJ1xuICAgICAgICApIHtcbiAgICAgICAgICBkZWJ1Zy53YXJuKFxuICAgICAgICAgICAgJ1lvdSBhcmUgdHJ5aW5nIHRvIGNyb3NzIGNvbXBpbGUgdG8gZGFyd2luIHRhcmdldCBvbiBkYXJ3aW4gcGxhdGZvcm0gd2hpY2ggaXMgdW5uZWNlc3NhcnkuJyxcbiAgICAgICAgICApXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gdXNlIGNhcmdvLXppZ2J1aWxkIHRvIGNyb3NzIGNvbXBpbGUgdG8gb3RoZXIgcGxhdGZvcm1zXG4gICAgICAgICAgZGVidWcoJ1VzZSAlaScsICdjYXJnby16aWdidWlsZCcpXG4gICAgICAgICAgdHJ5SW5zdGFsbENhcmdvQmluYXJ5KCdjYXJnby16aWdidWlsZCcsICd6aWdidWlsZCcpXG4gICAgICAgICAgdGhpcy5hcmdzLnB1c2goJ3ppZ2J1aWxkJylcbiAgICAgICAgICBzZXQgPSB0cnVlXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXNldCkge1xuICAgICAgdGhpcy5hcmdzLnB1c2goJ2J1aWxkJylcbiAgICB9XG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHByaXZhdGUgc2V0UGFja2FnZSgpIHtcbiAgICBjb25zdCBhcmdzID0gW11cblxuICAgIGlmICh0aGlzLm9wdGlvbnMucGFja2FnZSkge1xuICAgICAgYXJncy5wdXNoKCctLXBhY2thZ2UnLCB0aGlzLm9wdGlvbnMucGFja2FnZSlcbiAgICB9XG5cbiAgICBpZiAodGhpcy5iaW5OYW1lKSB7XG4gICAgICBhcmdzLnB1c2goJy0tYmluJywgdGhpcy5iaW5OYW1lKVxuICAgIH1cblxuICAgIGlmIChhcmdzLmxlbmd0aCkge1xuICAgICAgZGVidWcoJ1NldCBwYWNrYWdlIGZsYWdzOiAnKVxuICAgICAgZGVidWcoJyAgJU8nLCBhcmdzKVxuICAgICAgdGhpcy5hcmdzLnB1c2goLi4uYXJncylcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRUYXJnZXQoKSB7XG4gICAgZGVidWcoJ1NldCBjb21waWxpbmcgdGFyZ2V0IHRvOiAnKVxuICAgIGRlYnVnKCcgICVpJywgdGhpcy50YXJnZXQudHJpcGxlKVxuXG4gICAgdGhpcy5hcmdzLnB1c2goJy0tdGFyZ2V0JywgdGhpcy50YXJnZXQudHJpcGxlKVxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHByaXZhdGUgc2V0RW52cygpIHtcbiAgICAvLyBUWVBFIERFRlxuICAgIGlmICh0aGlzLmVuYWJsZVR5cGVEZWYpIHtcbiAgICAgIHRoaXMuZW52cy5OQVBJX1RZUEVfREVGX1RNUF9GT0xERVIgPVxuICAgICAgICB0aGlzLmdlbmVyYXRlSW50ZXJtZWRpYXRlVHlwZURlZkZvbGRlcigpXG4gICAgICB0aGlzLnNldEZvcmNlQnVpbGRFbnZzKHRoaXMuZW52cy5OQVBJX1RZUEVfREVGX1RNUF9GT0xERVIpXG4gICAgfVxuXG4gICAgLy8gUlVTVEZMQUdTXG4gICAgbGV0IHJ1c3RmbGFncyA9XG4gICAgICBwcm9jZXNzLmVudi5SVVNURkxBR1MgPz8gcHJvY2Vzcy5lbnYuQ0FSR09fQlVJTERfUlVTVEZMQUdTID8/ICcnXG5cbiAgICBpZiAoXG4gICAgICB0aGlzLnRhcmdldC5hYmk/LmluY2x1ZGVzKCdtdXNsJykgJiZcbiAgICAgICFydXN0ZmxhZ3MuaW5jbHVkZXMoJ3RhcmdldC1mZWF0dXJlPS1jcnQtc3RhdGljJylcbiAgICApIHtcbiAgICAgIHJ1c3RmbGFncyArPSAnIC1DIHRhcmdldC1mZWF0dXJlPS1jcnQtc3RhdGljJ1xuICAgIH1cblxuICAgIGlmICh0aGlzLm9wdGlvbnMuc3RyaXAgJiYgIXJ1c3RmbGFncy5pbmNsdWRlcygnbGluay1hcmc9LXMnKSkge1xuICAgICAgcnVzdGZsYWdzICs9ICcgLUMgbGluay1hcmc9LXMnXG4gICAgfVxuXG4gICAgaWYgKHJ1c3RmbGFncy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuZW52cy5SVVNURkxBR1MgPSBydXN0ZmxhZ3NcbiAgICB9XG4gICAgLy8gRU5EIFJVU1RGTEFHU1xuXG4gICAgLy8gTElOS0VSXG4gICAgY29uc3QgbGlua2VyID0gdGhpcy5vcHRpb25zLmNyb3NzQ29tcGlsZVxuICAgICAgPyB2b2lkIDBcbiAgICAgIDogZ2V0VGFyZ2V0TGlua2VyKHRoaXMudGFyZ2V0LnRyaXBsZSlcbiAgICAvLyBUT0RPOlxuICAgIC8vICAgZGlyZWN0bHkgc2V0IENBUkdPX1RBUkdFVF88dGFyZ2V0Pl9MSU5LRVIgd2lsbCBjb3ZlciAuY2FyZ28vY29uZmlnLnRvbWxcbiAgICAvLyAgIHdpbGwgZGV0ZWN0IGJ5IGNhcmdvIGNvbmZpZyB3aGVuIGl0IGJlY29tZXMgc3RhYmxlXG4gICAgLy8gICBzZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9ydXN0LWxhbmcvY2FyZ28vaXNzdWVzLzkzMDFcbiAgICBjb25zdCBsaW5rZXJFbnYgPSBgQ0FSR09fVEFSR0VUXyR7dGFyZ2V0VG9FbnZWYXIoXG4gICAgICB0aGlzLnRhcmdldC50cmlwbGUsXG4gICAgKX1fTElOS0VSYFxuICAgIGlmIChsaW5rZXIgJiYgIXByb2Nlc3MuZW52W2xpbmtlckVudl0gJiYgIXRoaXMuZW52c1tsaW5rZXJFbnZdKSB7XG4gICAgICB0aGlzLmVudnNbbGlua2VyRW52XSA9IGxpbmtlclxuICAgIH1cblxuICAgIGlmICh0aGlzLnRhcmdldC5wbGF0Zm9ybSA9PT0gJ2FuZHJvaWQnKSB7XG4gICAgICBjb25zdCB7IEFORFJPSURfTkRLX0xBVEVTVF9IT01FIH0gPSBwcm9jZXNzLmVudlxuICAgICAgaWYgKCFBTkRST0lEX05ES19MQVRFU1RfSE9NRSkge1xuICAgICAgICBkZWJ1Zy53YXJuKFxuICAgICAgICAgIGAke2NvbG9ycy5yZWQoXG4gICAgICAgICAgICAnQU5EUk9JRF9OREtfTEFURVNUX0hPTUUnLFxuICAgICAgICAgICl9IGVudmlyb25tZW50IHZhcmlhYmxlIGlzIG1pc3NpbmdgLFxuICAgICAgICApXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRhcmdldEFyY2ggPSB0aGlzLnRhcmdldC5hcmNoID09PSAnYXJtJyA/ICdhcm12N2EnIDogJ2FhcmNoNjQnXG4gICAgICBjb25zdCB0YXJnZXRQbGF0Zm9ybSA9XG4gICAgICAgIHRoaXMudGFyZ2V0LmFyY2ggPT09ICdhcm0nID8gJ2FuZHJvaWRlYWJpMjQnIDogJ2FuZHJvaWQyNCdcbiAgICAgIGNvbnN0IGhvc3RQbGF0Zm9ybSA9XG4gICAgICAgIHByb2Nlc3MucGxhdGZvcm0gPT09ICdkYXJ3aW4nXG4gICAgICAgICAgPyAnZGFyd2luJ1xuICAgICAgICAgIDogcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJ1xuICAgICAgICAgICAgPyAnd2luZG93cydcbiAgICAgICAgICAgIDogJ2xpbnV4J1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLmVudnMsIHtcbiAgICAgICAgQ0FSR09fVEFSR0VUX0FBUkNINjRfTElOVVhfQU5EUk9JRF9MSU5LRVI6IGAke0FORFJPSURfTkRLX0xBVEVTVF9IT01FfS90b29sY2hhaW5zL2xsdm0vcHJlYnVpbHQvJHtob3N0UGxhdGZvcm19LXg4Nl82NC9iaW4vJHt0YXJnZXRBcmNofS1saW51eC1hbmRyb2lkMjQtY2xhbmdgLFxuICAgICAgICBDQVJHT19UQVJHRVRfQVJNVjdfTElOVVhfQU5EUk9JREVBQklfTElOS0VSOiBgJHtBTkRST0lEX05ES19MQVRFU1RfSE9NRX0vdG9vbGNoYWlucy9sbHZtL3ByZWJ1aWx0LyR7aG9zdFBsYXRmb3JtfS14ODZfNjQvYmluLyR7dGFyZ2V0QXJjaH0tbGludXgtYW5kcm9pZGVhYmkyNC1jbGFuZ2AsXG4gICAgICAgIFRBUkdFVF9DQzogYCR7QU5EUk9JRF9OREtfTEFURVNUX0hPTUV9L3Rvb2xjaGFpbnMvbGx2bS9wcmVidWlsdC8ke2hvc3RQbGF0Zm9ybX0teDg2XzY0L2Jpbi8ke3RhcmdldEFyY2h9LWxpbnV4LSR7dGFyZ2V0UGxhdGZvcm19LWNsYW5nYCxcbiAgICAgICAgVEFSR0VUX0NYWDogYCR7QU5EUk9JRF9OREtfTEFURVNUX0hPTUV9L3Rvb2xjaGFpbnMvbGx2bS9wcmVidWlsdC8ke2hvc3RQbGF0Zm9ybX0teDg2XzY0L2Jpbi8ke3RhcmdldEFyY2h9LWxpbnV4LSR7dGFyZ2V0UGxhdGZvcm19LWNsYW5nKytgLFxuICAgICAgICBUQVJHRVRfQVI6IGAke0FORFJPSURfTkRLX0xBVEVTVF9IT01FfS90b29sY2hhaW5zL2xsdm0vcHJlYnVpbHQvJHtob3N0UGxhdGZvcm19LXg4Nl82NC9iaW4vbGx2bS1hcmAsXG4gICAgICAgIFRBUkdFVF9SQU5MSUI6IGAke0FORFJPSURfTkRLX0xBVEVTVF9IT01FfS90b29sY2hhaW5zL2xsdm0vcHJlYnVpbHQvJHtob3N0UGxhdGZvcm19LXg4Nl82NC9iaW4vbGx2bS1yYW5saWJgLFxuICAgICAgICBBTkRST0lEX05ESzogQU5EUk9JRF9OREtfTEFURVNUX0hPTUUsXG4gICAgICAgIFBBVEg6IGAke0FORFJPSURfTkRLX0xBVEVTVF9IT01FfS90b29sY2hhaW5zL2xsdm0vcHJlYnVpbHQvJHtob3N0UGxhdGZvcm19LXg4Nl82NC9iaW46JHtwcm9jZXNzLmVudi5QQVRIfWAsXG4gICAgICB9KVxuICAgIH1cbiAgICAvLyBFTkQgTElOS0VSXG5cbiAgICBpZiAodGhpcy50YXJnZXQucGxhdGZvcm0gPT09ICd3YXNpJykge1xuICAgICAgY29uc3QgZW1uYXBpID0gam9pbihcbiAgICAgICAgcmVxdWlyZS5yZXNvbHZlKCdlbW5hcGknKSxcbiAgICAgICAgJy4uJyxcbiAgICAgICAgJ2xpYicsXG4gICAgICAgICd3YXNtMzItd2FzaS10aHJlYWRzJyxcbiAgICAgIClcbiAgICAgIHRoaXMuZW52cy5FTU5BUElfTElOS19ESVIgPSBlbW5hcGlcbiAgICAgIHRoaXMuZW52cy5TRVRKTVBfTElOS19ESVIgPSBzZXRqbXBMaWJcbiAgICAgIGNvbnN0IHsgV0FTSV9TREtfUEFUSCB9ID0gcHJvY2Vzcy5lbnZcblxuICAgICAgaWYgKFdBU0lfU0RLX1BBVEggJiYgZXhpc3RzU3luYyhXQVNJX1NES19QQVRIKSkge1xuICAgICAgICB0aGlzLmVudnMuQ0FSR09fVEFSR0VUX1dBU00zMl9XQVNJX1BSRVZJRVcxX1RIUkVBRFNfTElOS0VSID0gam9pbihcbiAgICAgICAgICBXQVNJX1NES19QQVRILFxuICAgICAgICAgICdiaW4nLFxuICAgICAgICAgICd3YXNtLWxkJyxcbiAgICAgICAgKVxuICAgICAgICB0aGlzLmVudnMuQ0FSR09fVEFSR0VUX1dBU00zMl9XQVNJUDFfTElOS0VSID0gam9pbihcbiAgICAgICAgICBXQVNJX1NES19QQVRILFxuICAgICAgICAgICdiaW4nLFxuICAgICAgICAgICd3YXNtLWxkJyxcbiAgICAgICAgKVxuICAgICAgICB0aGlzLmVudnMuQ0FSR09fVEFSR0VUX1dBU00zMl9XQVNJUDFfVEhSRUFEU19MSU5LRVIgPSBqb2luKFxuICAgICAgICAgIFdBU0lfU0RLX1BBVEgsXG4gICAgICAgICAgJ2JpbicsXG4gICAgICAgICAgJ3dhc20tbGQnLFxuICAgICAgICApXG4gICAgICAgIHRoaXMuZW52cy5DQVJHT19UQVJHRVRfV0FTTTMyX1dBU0lQMl9MSU5LRVIgPSBqb2luKFxuICAgICAgICAgIFdBU0lfU0RLX1BBVEgsXG4gICAgICAgICAgJ2JpbicsXG4gICAgICAgICAgJ3dhc20tbGQnLFxuICAgICAgICApXG4gICAgICAgIHRoaXMuc2V0RW52SWZOb3RFeGlzdHMoJ0NDJywgam9pbihXQVNJX1NES19QQVRILCAnYmluJywgJ2NsYW5nJykpXG4gICAgICAgIHRoaXMuc2V0RW52SWZOb3RFeGlzdHMoJ0NYWCcsIGpvaW4oV0FTSV9TREtfUEFUSCwgJ2JpbicsICdjbGFuZysrJykpXG4gICAgICAgIHRoaXMuc2V0RW52SWZOb3RFeGlzdHMoJ0FSJywgam9pbihXQVNJX1NES19QQVRILCAnYmluJywgJ2FyJykpXG4gICAgICAgIHRoaXMuc2V0RW52SWZOb3RFeGlzdHMoJ1JBTkxJQicsIGpvaW4oV0FTSV9TREtfUEFUSCwgJ2JpbicsICdyYW5saWInKSlcbiAgICAgICAgdGhpcy5zZXRFbnZJZk5vdEV4aXN0cyhcbiAgICAgICAgICAnQ0ZMQUdTJyxcbiAgICAgICAgICBgLS10YXJnZXQ9d2FzbTMyLXdhc2ktdGhyZWFkcyAtLXN5c3Jvb3Q9JHtXQVNJX1NES19QQVRIfS9zaGFyZS93YXNpLXN5c3Jvb3QgLXB0aHJlYWQgLW1sbHZtIC13YXNtLWVuYWJsZS1zamxqIC1JJHtzZXRqbXBJbmNsdWRlfWAsXG4gICAgICAgIClcbiAgICAgICAgdGhpcy5zZXRFbnZJZk5vdEV4aXN0cyhcbiAgICAgICAgICAnQ1hYRkxBR1MnLFxuICAgICAgICAgIGAtLXRhcmdldD13YXNtMzItd2FzaS10aHJlYWRzIC0tc3lzcm9vdD0ke1dBU0lfU0RLX1BBVEh9L3NoYXJlL3dhc2ktc3lzcm9vdCAtcHRocmVhZCAtbWxsdm0gLXdhc20tZW5hYmxlLXNqbGogLUkke3NldGptcEluY2x1ZGV9YCxcbiAgICAgICAgKVxuICAgICAgICB0aGlzLnNldEVudklmTm90RXhpc3RzKFxuICAgICAgICAgIGBMREZMQUdTYCxcbiAgICAgICAgICBgLWZ1c2UtbGQ9JHtXQVNJX1NES19QQVRIfS9iaW4vd2FzbS1sZCAtLXRhcmdldD13YXNtMzItd2FzaS10aHJlYWRzYCxcbiAgICAgICAgKVxuICAgICAgfVxuICAgIH1cblxuICAgIGRlYnVnKCdTZXQgZW52czogJylcbiAgICBPYmplY3QuZW50cmllcyh0aGlzLmVudnMpLmZvckVhY2goKFtrLCB2XSkgPT4ge1xuICAgICAgZGVidWcoJyAgJWknLCBgJHtrfT0ke3Z9YClcbiAgICB9KVxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHByaXZhdGUgc2V0Rm9yY2VCdWlsZEVudnModHlwZURlZlRtcEZvbGRlcjogc3RyaW5nKSB7XG4gICAgLy8gZHluYW1pY2FsbHkgY2hlY2sgYWxsIG5hcGktcnMgZGVwcyBhbmQgc2V0IGBOQVBJX0ZPUkNFX0JVSUxEX3t1cHBlcmNhc2Uoc25ha2VfY2FzZShuYW1lKSl9ID0gdGltZXN0YW1wYFxuICAgIHRoaXMubWV0YWRhdGEucGFja2FnZXMuZm9yRWFjaCgoY3JhdGUpID0+IHtcbiAgICAgIGlmIChcbiAgICAgICAgY3JhdGUuZGVwZW5kZW5jaWVzLnNvbWUoKGQpID0+IGQubmFtZSA9PT0gJ25hcGktZGVyaXZlJykgJiZcbiAgICAgICAgIWV4aXN0c1N5bmMoam9pbih0eXBlRGVmVG1wRm9sZGVyLCBjcmF0ZS5uYW1lKSlcbiAgICAgICkge1xuICAgICAgICB0aGlzLmVudnNbXG4gICAgICAgICAgYE5BUElfRk9SQ0VfQlVJTERfJHtjcmF0ZS5uYW1lLnJlcGxhY2UoLy0vZywgJ18nKS50b1VwcGVyQ2FzZSgpfWBcbiAgICAgICAgXSA9IERhdGUubm93KCkudG9TdHJpbmcoKVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICBwcml2YXRlIHNldEZlYXR1cmVzKCkge1xuICAgIGNvbnN0IGFyZ3MgPSBbXVxuICAgIGlmICh0aGlzLm9wdGlvbnMuYWxsRmVhdHVyZXMgJiYgdGhpcy5vcHRpb25zLm5vRGVmYXVsdEZlYXR1cmVzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdDYW5ub3Qgc3BlY2lmeSAtLWFsbC1mZWF0dXJlcyBhbmQgLS1uby1kZWZhdWx0LWZlYXR1cmVzIHRvZ2V0aGVyJyxcbiAgICAgIClcbiAgICB9XG4gICAgaWYgKHRoaXMub3B0aW9ucy5hbGxGZWF0dXJlcykge1xuICAgICAgYXJncy5wdXNoKCctLWFsbC1mZWF0dXJlcycpXG4gICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMubm9EZWZhdWx0RmVhdHVyZXMpIHtcbiAgICAgIGFyZ3MucHVzaCgnLS1uby1kZWZhdWx0LWZlYXR1cmVzJylcbiAgICB9XG4gICAgaWYgKHRoaXMub3B0aW9ucy5mZWF0dXJlcykge1xuICAgICAgYXJncy5wdXNoKCctLWZlYXR1cmVzJywgLi4udGhpcy5vcHRpb25zLmZlYXR1cmVzKVxuICAgIH1cblxuICAgIGRlYnVnKCdTZXQgZmVhdHVyZXMgZmxhZ3M6ICcpXG4gICAgZGVidWcoJyAgJU8nLCBhcmdzKVxuICAgIHRoaXMuYXJncy5wdXNoKC4uLmFyZ3MpXG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRCeXBhc3NBcmdzKCkge1xuICAgIGlmICh0aGlzLm9wdGlvbnMucmVsZWFzZSkge1xuICAgICAgdGhpcy5hcmdzLnB1c2goJy0tcmVsZWFzZScpXG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy52ZXJib3NlKSB7XG4gICAgICB0aGlzLmFyZ3MucHVzaCgnLS12ZXJib3NlJylcbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLnRhcmdldERpcikge1xuICAgICAgdGhpcy5hcmdzLnB1c2goJy0tdGFyZ2V0LWRpcicsIHRoaXMub3B0aW9ucy50YXJnZXREaXIpXG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5wcm9maWxlKSB7XG4gICAgICB0aGlzLmFyZ3MucHVzaCgnLS1wcm9maWxlJywgdGhpcy5vcHRpb25zLnByb2ZpbGUpXG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5tYW5pZmVzdFBhdGgpIHtcbiAgICAgIHRoaXMuYXJncy5wdXNoKCctLW1hbmlmZXN0LXBhdGgnLCB0aGlzLm9wdGlvbnMubWFuaWZlc3RQYXRoKVxuICAgIH1cblxuICAgIGlmICh0aGlzLm9wdGlvbnMuY2FyZ29PcHRpb25zPy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuYXJncy5wdXNoKC4uLnRoaXMub3B0aW9ucy5jYXJnb09wdGlvbnMpXG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHByaXZhdGUgZ2VuZXJhdGVJbnRlcm1lZGlhdGVUeXBlRGVmRm9sZGVyKCkge1xuICAgIGxldCBmb2xkZXIgPSBqb2luKFxuICAgICAgdGhpcy50YXJnZXREaXIsXG4gICAgICAnbmFwaS1ycycsXG4gICAgICBgJHt0aGlzLmNyYXRlLm5hbWV9LSR7Y3JlYXRlSGFzaCgnc2hhMjU2JylcbiAgICAgICAgLnVwZGF0ZSh0aGlzLmNyYXRlLm1hbmlmZXN0X3BhdGgpXG4gICAgICAgIC51cGRhdGUoQ0xJX1ZFUlNJT04pXG4gICAgICAgIC5kaWdlc3QoJ2hleCcpXG4gICAgICAgIC5zdWJzdHJpbmcoMCwgOCl9YCxcbiAgICApXG5cbiAgICBpZiAoIXRoaXMub3B0aW9ucy5kdHNDYWNoZSkge1xuICAgICAgcm1TeW5jKGZvbGRlciwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pXG4gICAgICBmb2xkZXIgKz0gYF8ke0RhdGUubm93KCl9YFxuICAgIH1cblxuICAgIG1rZGlyQXN5bmMoZm9sZGVyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuXG4gICAgcmV0dXJuIGZvbGRlclxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwb3N0QnVpbGQoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGRlYnVnKGBUcnkgdG8gY3JlYXRlIG91dHB1dCBkaXJlY3Rvcnk6YClcbiAgICAgIGRlYnVnKCcgICVpJywgdGhpcy5vdXRwdXREaXIpXG4gICAgICBhd2FpdCBta2RpckFzeW5jKHRoaXMub3V0cHV0RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuICAgICAgZGVidWcoYE91dHB1dCBkaXJlY3RvcnkgY3JlYXRlZGApXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gY3JlYXRlIG91dHB1dCBkaXJlY3RvcnkgJHt0aGlzLm91dHB1dERpcn1gLCB7XG4gICAgICAgIGNhdXNlOiBlLFxuICAgICAgfSlcbiAgICB9XG5cbiAgICBjb25zdCB3YXNtQmluYXJ5TmFtZSA9IGF3YWl0IHRoaXMuY29weUFydGlmYWN0KClcblxuICAgIC8vIG9ubHkgZm9yIGNkeWxpYlxuICAgIGlmICh0aGlzLmNkeUxpYk5hbWUpIHtcbiAgICAgIGNvbnN0IGlkZW50cyA9IGF3YWl0IHRoaXMuZ2VuZXJhdGVUeXBlRGVmKClcbiAgICAgIGNvbnN0IGpzT3V0cHV0ID0gYXdhaXQgdGhpcy53cml0ZUpzQmluZGluZyhpZGVudHMpXG4gICAgICBjb25zdCB3YXNtQmluZGluZ3NPdXRwdXQgPSBhd2FpdCB0aGlzLndyaXRlV2FzaUJpbmRpbmcoXG4gICAgICAgIHdhc21CaW5hcnlOYW1lLFxuICAgICAgICBpZGVudHMsXG4gICAgICApXG4gICAgICBpZiAoanNPdXRwdXQpIHtcbiAgICAgICAgdGhpcy5vdXRwdXRzLnB1c2goanNPdXRwdXQpXG4gICAgICB9XG4gICAgICBpZiAod2FzbUJpbmRpbmdzT3V0cHV0KSB7XG4gICAgICAgIHRoaXMub3V0cHV0cy5wdXNoKC4uLndhc21CaW5kaW5nc091dHB1dClcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5vdXRwdXRzXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNvcHlBcnRpZmFjdCgpIHtcbiAgICBjb25zdCBbc3JjTmFtZSwgZGVzdE5hbWUsIHdhc21CaW5hcnlOYW1lXSA9IHRoaXMuZ2V0QXJ0aWZhY3ROYW1lcygpXG4gICAgaWYgKCFzcmNOYW1lIHx8ICFkZXN0TmFtZSkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3QgcHJvZmlsZSA9XG4gICAgICB0aGlzLm9wdGlvbnMucHJvZmlsZSA/PyAodGhpcy5vcHRpb25zLnJlbGVhc2UgPyAncmVsZWFzZScgOiAnZGVidWcnKVxuICAgIGNvbnN0IHNyYyA9IGpvaW4odGhpcy50YXJnZXREaXIsIHRoaXMudGFyZ2V0LnRyaXBsZSwgcHJvZmlsZSwgc3JjTmFtZSlcbiAgICBkZWJ1ZyhgQ29weSBhcnRpZmFjdCBmcm9tOiBbJHtzcmN9XWApXG4gICAgY29uc3QgZGVzdCA9IGpvaW4odGhpcy5vdXRwdXREaXIsIGRlc3ROYW1lKVxuICAgIGNvbnN0IGlzV2FzbSA9IGRlc3QuZW5kc1dpdGgoJy53YXNtJylcblxuICAgIHRyeSB7XG4gICAgICBpZiAoYXdhaXQgZmlsZUV4aXN0cyhkZXN0KSkge1xuICAgICAgICBkZWJ1ZygnT2xkIGFydGlmYWN0IGZvdW5kLCByZW1vdmUgaXQgZmlyc3QnKVxuICAgICAgICBhd2FpdCB1bmxpbmtBc3luYyhkZXN0KVxuICAgICAgfVxuICAgICAgZGVidWcoJ0NvcHkgYXJ0aWZhY3QgdG86JylcbiAgICAgIGRlYnVnKCcgICVpJywgZGVzdClcbiAgICAgIGlmIChpc1dhc20pIHtcbiAgICAgICAgY29uc3QgeyBNb2R1bGVDb25maWcgfSA9IGF3YWl0IGltcG9ydCgnQG5hcGktcnMvd2FzbS10b29scycpXG4gICAgICAgIGRlYnVnKCdHZW5lcmF0ZSBkZWJ1ZyB3YXNtIG1vZHVsZScpXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZGVidWdXYXNtTW9kdWxlID0gbmV3IE1vZHVsZUNvbmZpZygpXG4gICAgICAgICAgICAuZ2VuZXJhdGVEd2FyZih0cnVlKVxuICAgICAgICAgICAgLmdlbmVyYXRlTmFtZVNlY3Rpb24odHJ1ZSlcbiAgICAgICAgICAgIC5nZW5lcmF0ZVByb2R1Y2Vyc1NlY3Rpb24odHJ1ZSlcbiAgICAgICAgICAgIC5wcmVzZXJ2ZUNvZGVUcmFuc2Zvcm0odHJ1ZSlcbiAgICAgICAgICAgIC5zdHJpY3RWYWxpZGF0ZShmYWxzZSlcbiAgICAgICAgICAgIC5wYXJzZShhd2FpdCByZWFkRmlsZUFzeW5jKHNyYykpXG4gICAgICAgICAgY29uc3QgZGVidWdXYXNtQmluYXJ5ID0gZGVidWdXYXNtTW9kdWxlLmVtaXRXYXNtKHRydWUpXG4gICAgICAgICAgYXdhaXQgd3JpdGVGaWxlQXN5bmMoXG4gICAgICAgICAgICBkZXN0LnJlcGxhY2UoL1xcLndhc20kLywgJy5kZWJ1Zy53YXNtJyksXG4gICAgICAgICAgICBkZWJ1Z1dhc21CaW5hcnksXG4gICAgICAgICAgKVxuICAgICAgICAgIGRlYnVnKCdHZW5lcmF0ZSByZWxlYXNlIHdhc20gbW9kdWxlJylcbiAgICAgICAgICBjb25zdCByZWxlYXNlV2FzbU1vZHVsZSA9IG5ldyBNb2R1bGVDb25maWcoKVxuICAgICAgICAgICAgLmdlbmVyYXRlRHdhcmYoZmFsc2UpXG4gICAgICAgICAgICAuZ2VuZXJhdGVOYW1lU2VjdGlvbihmYWxzZSlcbiAgICAgICAgICAgIC5nZW5lcmF0ZVByb2R1Y2Vyc1NlY3Rpb24oZmFsc2UpXG4gICAgICAgICAgICAucHJlc2VydmVDb2RlVHJhbnNmb3JtKGZhbHNlKVxuICAgICAgICAgICAgLnN0cmljdFZhbGlkYXRlKGZhbHNlKVxuICAgICAgICAgICAgLm9ubHlTdGFibGVGZWF0dXJlcyhmYWxzZSlcbiAgICAgICAgICAgIC5wYXJzZShkZWJ1Z1dhc21CaW5hcnkpXG4gICAgICAgICAgY29uc3QgcmVsZWFzZVdhc21CaW5hcnkgPSByZWxlYXNlV2FzbU1vZHVsZS5lbWl0V2FzbShmYWxzZSlcbiAgICAgICAgICBhd2FpdCB3cml0ZUZpbGVBc3luYyhkZXN0LCByZWxlYXNlV2FzbUJpbmFyeSlcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGRlYnVnLndhcm4oXG4gICAgICAgICAgICBgRmFpbGVkIHRvIGdlbmVyYXRlIGRlYnVnIHdhc20gbW9kdWxlOiAkeyhlIGFzIGFueSkubWVzc2FnZSA/PyBlfWAsXG4gICAgICAgICAgKVxuICAgICAgICAgIGF3YWl0IGNvcHlGaWxlQXN5bmMoc3JjLCBkZXN0KVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCBjb3B5RmlsZUFzeW5jKHNyYywgZGVzdClcbiAgICAgIH1cbiAgICAgIHRoaXMub3V0cHV0cy5wdXNoKHtcbiAgICAgICAga2luZDogZGVzdC5lbmRzV2l0aCgnLm5vZGUnKSA/ICdub2RlJyA6IGlzV2FzbSA/ICd3YXNtJyA6ICdleGUnLFxuICAgICAgICBwYXRoOiBkZXN0LFxuICAgICAgfSlcbiAgICAgIHJldHVybiB3YXNtQmluYXJ5TmFtZSA/IGpvaW4odGhpcy5vdXRwdXREaXIsIHdhc21CaW5hcnlOYW1lKSA6IG51bGxcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBjb3B5IGFydGlmYWN0JywgeyBjYXVzZTogZSB9KVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0QXJ0aWZhY3ROYW1lcygpIHtcbiAgICBpZiAodGhpcy5jZHlMaWJOYW1lKSB7XG4gICAgICBjb25zdCBjZHlMaWIgPSB0aGlzLmNkeUxpYk5hbWUucmVwbGFjZSgvLS9nLCAnXycpXG4gICAgICBjb25zdCB3YXNpVGFyZ2V0ID0gdGhpcy5jb25maWcudGFyZ2V0cy5maW5kKCh0KSA9PiB0LnBsYXRmb3JtID09PSAnd2FzaScpXG5cbiAgICAgIGNvbnN0IHNyY05hbWUgPVxuICAgICAgICB0aGlzLnRhcmdldC5wbGF0Zm9ybSA9PT0gJ2RhcndpbidcbiAgICAgICAgICA/IGBsaWIke2NkeUxpYn0uZHlsaWJgXG4gICAgICAgICAgOiB0aGlzLnRhcmdldC5wbGF0Zm9ybSA9PT0gJ3dpbjMyJ1xuICAgICAgICAgICAgPyBgJHtjZHlMaWJ9LmRsbGBcbiAgICAgICAgICAgIDogdGhpcy50YXJnZXQucGxhdGZvcm0gPT09ICd3YXNpJyB8fCB0aGlzLnRhcmdldC5wbGF0Zm9ybSA9PT0gJ3dhc20nXG4gICAgICAgICAgICAgID8gYCR7Y2R5TGlifS53YXNtYFxuICAgICAgICAgICAgICA6IGBsaWIke2NkeUxpYn0uc29gXG5cbiAgICAgIGxldCBkZXN0TmFtZSA9IHRoaXMuY29uZmlnLmJpbmFyeU5hbWVcbiAgICAgIC8vIGFkZCBwbGF0Zm9ybSBzdWZmaXggdG8gYmluYXJ5IG5hbWVcbiAgICAgIC8vIGluZGV4Wy5saW51eC14NjQtZ251XS5ub2RlXG4gICAgICAvLyAgICAgICBeXl5eXl5eXl5eXl5eXlxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5wbGF0Zm9ybSkge1xuICAgICAgICBkZXN0TmFtZSArPSBgLiR7dGhpcy50YXJnZXQucGxhdGZvcm1BcmNoQUJJfWBcbiAgICAgIH1cbiAgICAgIGlmIChzcmNOYW1lLmVuZHNXaXRoKCcud2FzbScpKSB7XG4gICAgICAgIGRlc3ROYW1lICs9ICcud2FzbSdcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlc3ROYW1lICs9ICcubm9kZSdcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIFtcbiAgICAgICAgc3JjTmFtZSxcbiAgICAgICAgZGVzdE5hbWUsXG4gICAgICAgIHdhc2lUYXJnZXRcbiAgICAgICAgICA/IGAke3RoaXMuY29uZmlnLmJpbmFyeU5hbWV9LiR7d2FzaVRhcmdldC5wbGF0Zm9ybUFyY2hBQkl9Lndhc21gXG4gICAgICAgICAgOiBudWxsLFxuICAgICAgXVxuICAgIH0gZWxzZSBpZiAodGhpcy5iaW5OYW1lKSB7XG4gICAgICBjb25zdCBzcmNOYW1lID1cbiAgICAgICAgdGhpcy50YXJnZXQucGxhdGZvcm0gPT09ICd3aW4zMicgPyBgJHt0aGlzLmJpbk5hbWV9LmV4ZWAgOiB0aGlzLmJpbk5hbWVcblxuICAgICAgcmV0dXJuIFtzcmNOYW1lLCBzcmNOYW1lXVxuICAgIH1cblxuICAgIHJldHVybiBbXVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZW5lcmF0ZVR5cGVEZWYoKSB7XG4gICAgY29uc3QgdHlwZURlZkRpciA9IHRoaXMuZW52cy5OQVBJX1RZUEVfREVGX1RNUF9GT0xERVJcbiAgICBpZiAoIXRoaXMuZW5hYmxlVHlwZURlZiB8fCAhKGF3YWl0IGRpckV4aXN0c0FzeW5jKHR5cGVEZWZEaXIpKSkge1xuICAgICAgcmV0dXJuIFtdXG4gICAgfVxuXG4gICAgY29uc3QgZGVzdCA9IGpvaW4odGhpcy5vdXRwdXREaXIsIHRoaXMub3B0aW9ucy5kdHMgPz8gJ2luZGV4LmQudHMnKVxuXG4gICAgbGV0IGhlYWRlciA9ICcnXG4gICAgbGV0IGR0cyA9ICcnXG4gICAgbGV0IGV4cG9ydHM6IHN0cmluZ1tdID0gW11cblxuICAgIGlmICghdGhpcy5vcHRpb25zLm5vRHRzSGVhZGVyKSB7XG4gICAgICBjb25zdCBkdHNIZWFkZXIgPSB0aGlzLm9wdGlvbnMuZHRzSGVhZGVyID8/IHRoaXMuY29uZmlnLmR0c0hlYWRlclxuICAgICAgLy8gYGR0c0hlYWRlckZpbGVgIGluIGNvbmZpZyA+IGBkdHNIZWFkZXJgIGluIGNsaSBmbGFnID4gYGR0c0hlYWRlcmAgaW4gY29uZmlnXG4gICAgICBpZiAodGhpcy5jb25maWcuZHRzSGVhZGVyRmlsZSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGhlYWRlciA9IGF3YWl0IHJlYWRGaWxlQXN5bmMoXG4gICAgICAgICAgICBqb2luKHRoaXMub3B0aW9ucy5jd2QsIHRoaXMuY29uZmlnLmR0c0hlYWRlckZpbGUpLFxuICAgICAgICAgICAgJ3V0Zi04JyxcbiAgICAgICAgICApXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBkZWJ1Zy53YXJuKFxuICAgICAgICAgICAgYEZhaWxlZCB0byByZWFkIGR0cyBoZWFkZXIgZmlsZSAke3RoaXMuY29uZmlnLmR0c0hlYWRlckZpbGV9YCxcbiAgICAgICAgICAgIGUsXG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGR0c0hlYWRlcikge1xuICAgICAgICBoZWFkZXIgPSBkdHNIZWFkZXJcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGhlYWRlciA9IERFRkFVTFRfVFlQRV9ERUZfSEVBREVSXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZmlsZXMgPSBhd2FpdCByZWFkZGlyQXN5bmModHlwZURlZkRpciwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pXG5cbiAgICBpZiAoIWZpbGVzLmxlbmd0aCkge1xuICAgICAgZGVidWcoJ05vIHR5cGUgZGVmIGZpbGVzIGZvdW5kLiBTa2lwIGdlbmVyYXRpbmcgZHRzIGZpbGUuJylcbiAgICAgIHJldHVybiBbXVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgaWYgKCFmaWxlLmlzRmlsZSgpKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgZHRzOiBmaWxlRHRzLCBleHBvcnRzOiBmaWxlRXhwb3J0cyB9ID0gYXdhaXQgcHJvY2Vzc1R5cGVEZWYoXG4gICAgICAgIGpvaW4odHlwZURlZkRpciwgZmlsZS5uYW1lKSxcbiAgICAgICAgdGhpcy5vcHRpb25zLmNvbnN0RW51bSA/PyB0aGlzLmNvbmZpZy5jb25zdEVudW0gPz8gdHJ1ZSxcbiAgICAgIClcblxuICAgICAgZHRzICs9IGZpbGVEdHNcbiAgICAgIGV4cG9ydHMucHVzaCguLi5maWxlRXhwb3J0cylcbiAgICB9XG5cbiAgICBpZiAoZHRzLmluZGV4T2YoJ0V4dGVybmFsT2JqZWN0PCcpID4gLTEpIHtcbiAgICAgIGhlYWRlciArPSBgXG5leHBvcnQgZGVjbGFyZSBjbGFzcyBFeHRlcm5hbE9iamVjdDxUPiB7XG4gIHJlYWRvbmx5ICcnOiB7XG4gICAgcmVhZG9ubHkgJyc6IHVuaXF1ZSBzeW1ib2xcbiAgICBbSzogc3ltYm9sXTogVFxuICB9XG59XG5gXG4gICAgfVxuXG4gICAgZHRzID0gaGVhZGVyICsgZHRzXG5cbiAgICB0cnkge1xuICAgICAgZGVidWcoJ1dyaXRpbmcgdHlwZSBkZWYgdG86JylcbiAgICAgIGRlYnVnKCcgICVpJywgZGVzdClcbiAgICAgIGF3YWl0IHdyaXRlRmlsZUFzeW5jKGRlc3QsIGR0cywgJ3V0Zi04JylcbiAgICAgIHRoaXMub3V0cHV0cy5wdXNoKHsga2luZDogJ2R0cycsIHBhdGg6IGRlc3QgfSlcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBkZWJ1Zy5lcnJvcignRmFpbGVkIHRvIHdyaXRlIHR5cGUgZGVmIGZpbGUnKVxuICAgICAgZGVidWcuZXJyb3IoZSBhcyBFcnJvcilcbiAgICB9XG5cbiAgICByZXR1cm4gZXhwb3J0c1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB3cml0ZUpzQmluZGluZyhpZGVudHM6IHN0cmluZ1tdKSB7XG4gICAgaWYgKFxuICAgICAgIXRoaXMub3B0aW9ucy5wbGF0Zm9ybSB8fFxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9wcmVmZXItbnVsbGlzaC1jb2FsZXNjaW5nXG4gICAgICB0aGlzLm9wdGlvbnMubm9Kc0JpbmRpbmcgfHxcbiAgICAgIGlkZW50cy5sZW5ndGggPT09IDBcbiAgICApIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IG5hbWUgPSB0aGlzLm9wdGlvbnMuanNCaW5kaW5nID8/ICdpbmRleC5qcydcblxuICAgIGNvbnN0IGNyZWF0ZUJpbmRpbmcgPSB0aGlzLm9wdGlvbnMuZXNtID8gY3JlYXRlRXNtQmluZGluZyA6IGNyZWF0ZUNqc0JpbmRpbmdcbiAgICBjb25zdCBiaW5kaW5nID0gY3JlYXRlQmluZGluZyhcbiAgICAgIHRoaXMuY29uZmlnLmJpbmFyeU5hbWUsXG4gICAgICB0aGlzLmNvbmZpZy5wYWNrYWdlTmFtZSxcbiAgICAgIGlkZW50cyxcbiAgICApXG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZGVzdCA9IGpvaW4odGhpcy5vdXRwdXREaXIsIG5hbWUpXG4gICAgICBkZWJ1ZygnV3JpdGluZyBqcyBiaW5kaW5nIHRvOicpXG4gICAgICBkZWJ1ZygnICAlaScsIGRlc3QpXG4gICAgICBhd2FpdCB3cml0ZUZpbGVBc3luYyhkZXN0LCBiaW5kaW5nLCAndXRmLTgnKVxuICAgICAgcmV0dXJuIHsga2luZDogJ2pzJywgcGF0aDogZGVzdCB9IHNhdGlzZmllcyBPdXRwdXRcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byB3cml0ZSBqcyBiaW5kaW5nIGZpbGUnLCB7IGNhdXNlOiBlIH0pXG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB3cml0ZVdhc2lCaW5kaW5nKFxuICAgIGRpc3RGaWxlTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkIHwgbnVsbCxcbiAgICBpZGVudHM6IHN0cmluZ1tdLFxuICApIHtcbiAgICBpZiAoZGlzdEZpbGVOYW1lKSB7XG4gICAgICBjb25zdCB7IG5hbWUsIGRpciB9ID0gcGFyc2UoZGlzdEZpbGVOYW1lKVxuICAgICAgY29uc3QgYmluZGluZ1BhdGggPSBqb2luKGRpciwgYCR7dGhpcy5jb25maWcuYmluYXJ5TmFtZX0ud2FzaS5janNgKVxuICAgICAgY29uc3QgYnJvd3NlckJpbmRpbmdQYXRoID0gam9pbihcbiAgICAgICAgZGlyLFxuICAgICAgICBgJHt0aGlzLmNvbmZpZy5iaW5hcnlOYW1lfS53YXNpLWJyb3dzZXIuanNgLFxuICAgICAgKVxuICAgICAgY29uc3Qgd29ya2VyUGF0aCA9IGpvaW4oZGlyLCAnd2FzaS13b3JrZXIubWpzJylcbiAgICAgIGNvbnN0IGJyb3dzZXJXb3JrZXJQYXRoID0gam9pbihkaXIsICd3YXNpLXdvcmtlci1icm93c2VyLm1qcycpXG4gICAgICBjb25zdCBicm93c2VyRW50cnlQYXRoID0gam9pbihkaXIsICdicm93c2VyLmpzJylcbiAgICAgIGNvbnN0IGV4cG9ydHNDb2RlID1cbiAgICAgICAgYG1vZHVsZS5leHBvcnRzID0gX19uYXBpTW9kdWxlLmV4cG9ydHNcXG5gICtcbiAgICAgICAgaWRlbnRzXG4gICAgICAgICAgLm1hcChcbiAgICAgICAgICAgIChpZGVudCkgPT5cbiAgICAgICAgICAgICAgYG1vZHVsZS5leHBvcnRzLiR7aWRlbnR9ID0gX19uYXBpTW9kdWxlLmV4cG9ydHMuJHtpZGVudH1gLFxuICAgICAgICAgIClcbiAgICAgICAgICAuam9pbignXFxuJylcbiAgICAgIGF3YWl0IHdyaXRlRmlsZUFzeW5jKFxuICAgICAgICBiaW5kaW5nUGF0aCxcbiAgICAgICAgY3JlYXRlV2FzaUJpbmRpbmcoXG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgICB0aGlzLmNvbmZpZy5wYWNrYWdlTmFtZSxcbiAgICAgICAgICB0aGlzLmNvbmZpZy53YXNtPy5pbml0aWFsTWVtb3J5LFxuICAgICAgICAgIHRoaXMuY29uZmlnLndhc20/Lm1heGltdW1NZW1vcnksXG4gICAgICAgICkgK1xuICAgICAgICAgIGV4cG9ydHNDb2RlICtcbiAgICAgICAgICAnXFxuJyxcbiAgICAgICAgJ3V0ZjgnLFxuICAgICAgKVxuICAgICAgYXdhaXQgd3JpdGVGaWxlQXN5bmMoXG4gICAgICAgIGJyb3dzZXJCaW5kaW5nUGF0aCxcbiAgICAgICAgY3JlYXRlV2FzaUJyb3dzZXJCaW5kaW5nKFxuICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgdGhpcy5jb25maWcud2FzbT8uaW5pdGlhbE1lbW9yeSxcbiAgICAgICAgICB0aGlzLmNvbmZpZy53YXNtPy5tYXhpbXVtTWVtb3J5LFxuICAgICAgICAgIHRoaXMuY29uZmlnLndhc20/LmJyb3dzZXI/LmZzLFxuICAgICAgICAgIHRoaXMuY29uZmlnLndhc20/LmJyb3dzZXI/LmFzeW5jSW5pdCxcbiAgICAgICAgKSArXG4gICAgICAgICAgYGV4cG9ydCBkZWZhdWx0IF9fbmFwaU1vZHVsZS5leHBvcnRzXFxuYCArXG4gICAgICAgICAgaWRlbnRzXG4gICAgICAgICAgICAubWFwKFxuICAgICAgICAgICAgICAoaWRlbnQpID0+XG4gICAgICAgICAgICAgICAgYGV4cG9ydCBjb25zdCAke2lkZW50fSA9IF9fbmFwaU1vZHVsZS5leHBvcnRzLiR7aWRlbnR9YCxcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5qb2luKCdcXG4nKSArXG4gICAgICAgICAgJ1xcbicsXG4gICAgICAgICd1dGY4JyxcbiAgICAgIClcbiAgICAgIGF3YWl0IHdyaXRlRmlsZUFzeW5jKHdvcmtlclBhdGgsIFdBU0lfV09SS0VSX1RFTVBMQVRFLCAndXRmOCcpXG4gICAgICBhd2FpdCB3cml0ZUZpbGVBc3luYyhcbiAgICAgICAgYnJvd3NlcldvcmtlclBhdGgsXG4gICAgICAgIGNyZWF0ZVdhc2lCcm93c2VyV29ya2VyQmluZGluZyh0aGlzLmNvbmZpZy53YXNtPy5icm93c2VyPy5mcyA/PyBmYWxzZSksXG4gICAgICAgICd1dGY4JyxcbiAgICAgIClcbiAgICAgIGF3YWl0IHdyaXRlRmlsZUFzeW5jKFxuICAgICAgICBicm93c2VyRW50cnlQYXRoLFxuICAgICAgICBgZXhwb3J0ICogZnJvbSAnJHt0aGlzLmNvbmZpZy5wYWNrYWdlTmFtZX0td2FzbTMyLXdhc2knXFxuYCxcbiAgICAgIClcbiAgICAgIHJldHVybiBbXG4gICAgICAgIHsga2luZDogJ2pzJywgcGF0aDogYmluZGluZ1BhdGggfSxcbiAgICAgICAgeyBraW5kOiAnanMnLCBwYXRoOiBicm93c2VyQmluZGluZ1BhdGggfSxcbiAgICAgICAgeyBraW5kOiAnanMnLCBwYXRoOiB3b3JrZXJQYXRoIH0sXG4gICAgICAgIHsga2luZDogJ2pzJywgcGF0aDogYnJvd3NlcldvcmtlclBhdGggfSxcbiAgICAgICAgeyBraW5kOiAnanMnLCBwYXRoOiBicm93c2VyRW50cnlQYXRoIH0sXG4gICAgICBdIHNhdGlzZmllcyBPdXRwdXRbXVxuICAgIH1cbiAgICByZXR1cm4gW11cbiAgfVxuXG4gIHByaXZhdGUgc2V0RW52SWZOb3RFeGlzdHMoZW52OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpIHtcbiAgICBpZiAoIXByb2Nlc3MuZW52W2Vudl0pIHtcbiAgICAgIHRoaXMuZW52c1tlbnZdID0gdmFsdWVcbiAgICB9XG4gIH1cbn1cbiIsIi8vIFRoaXMgZmlsZSBpcyBnZW5lcmF0ZWQgYnkgY29kZWdlbi9pbmRleC50c1xuLy8gRG8gbm90IGVkaXQgdGhpcyBmaWxlIG1hbnVhbGx5XG5pbXBvcnQgeyBDb21tYW5kLCBPcHRpb24gfSBmcm9tICdjbGlwYW5pb24nXG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCYXNlQ3JlYXRlTnBtRGlyc0NvbW1hbmQgZXh0ZW5kcyBDb21tYW5kIHtcbiAgc3RhdGljIHBhdGhzID0gW1snY3JlYXRlLW5wbS1kaXJzJ11dXG5cbiAgc3RhdGljIHVzYWdlID0gQ29tbWFuZC5Vc2FnZSh7XG4gICAgZGVzY3JpcHRpb246ICdDcmVhdGUgbnBtIHBhY2thZ2UgZGlycyBmb3IgZGlmZmVyZW50IHBsYXRmb3JtcycsXG4gIH0pXG5cbiAgY3dkID0gT3B0aW9uLlN0cmluZygnLS1jd2QnLCBwcm9jZXNzLmN3ZCgpLCB7XG4gICAgZGVzY3JpcHRpb246XG4gICAgICAnVGhlIHdvcmtpbmcgZGlyZWN0b3J5IG9mIHdoZXJlIG5hcGkgY29tbWFuZCB3aWxsIGJlIGV4ZWN1dGVkIGluLCBhbGwgb3RoZXIgcGF0aHMgb3B0aW9ucyBhcmUgcmVsYXRpdmUgdG8gdGhpcyBwYXRoJyxcbiAgfSlcblxuICBjb25maWdQYXRoPzogc3RyaW5nID0gT3B0aW9uLlN0cmluZygnLS1jb25maWctcGF0aCwtYycsIHtcbiAgICBkZXNjcmlwdGlvbjogJ1BhdGggdG8gYG5hcGlgIGNvbmZpZyBqc29uIGZpbGUnLFxuICB9KVxuXG4gIHBhY2thZ2VKc29uUGF0aCA9IE9wdGlvbi5TdHJpbmcoJy0tcGFja2FnZS1qc29uLXBhdGgnLCAncGFja2FnZS5qc29uJywge1xuICAgIGRlc2NyaXB0aW9uOiAnUGF0aCB0byBgcGFja2FnZS5qc29uYCcsXG4gIH0pXG5cbiAgbnBtRGlyID0gT3B0aW9uLlN0cmluZygnLS1ucG0tZGlyJywgJ25wbScsIHtcbiAgICBkZXNjcmlwdGlvbjogJ1BhdGggdG8gdGhlIGZvbGRlciB3aGVyZSB0aGUgbnBtIHBhY2thZ2VzIHB1dCcsXG4gIH0pXG5cbiAgZHJ5UnVuID0gT3B0aW9uLkJvb2xlYW4oJy0tZHJ5LXJ1bicsIGZhbHNlLCB7XG4gICAgZGVzY3JpcHRpb246ICdEcnkgcnVuIHdpdGhvdXQgdG91Y2hpbmcgZmlsZSBzeXN0ZW0nLFxuICB9KVxuXG4gIGdldE9wdGlvbnMoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGN3ZDogdGhpcy5jd2QsXG4gICAgICBjb25maWdQYXRoOiB0aGlzLmNvbmZpZ1BhdGgsXG4gICAgICBwYWNrYWdlSnNvblBhdGg6IHRoaXMucGFja2FnZUpzb25QYXRoLFxuICAgICAgbnBtRGlyOiB0aGlzLm5wbURpcixcbiAgICAgIGRyeVJ1bjogdGhpcy5kcnlSdW4sXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlIG5wbSBwYWNrYWdlIGRpcnMgZm9yIGRpZmZlcmVudCBwbGF0Zm9ybXNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVOcG1EaXJzT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgd29ya2luZyBkaXJlY3Rvcnkgb2Ygd2hlcmUgbmFwaSBjb21tYW5kIHdpbGwgYmUgZXhlY3V0ZWQgaW4sIGFsbCBvdGhlciBwYXRocyBvcHRpb25zIGFyZSByZWxhdGl2ZSB0byB0aGlzIHBhdGhcbiAgICpcbiAgICogQGRlZmF1bHQgcHJvY2Vzcy5jd2QoKVxuICAgKi9cbiAgY3dkPzogc3RyaW5nXG4gIC8qKlxuICAgKiBQYXRoIHRvIGBuYXBpYCBjb25maWcganNvbiBmaWxlXG4gICAqL1xuICBjb25maWdQYXRoPzogc3RyaW5nXG4gIC8qKlxuICAgKiBQYXRoIHRvIGBwYWNrYWdlLmpzb25gXG4gICAqXG4gICAqIEBkZWZhdWx0ICdwYWNrYWdlLmpzb24nXG4gICAqL1xuICBwYWNrYWdlSnNvblBhdGg/OiBzdHJpbmdcbiAgLyoqXG4gICAqIFBhdGggdG8gdGhlIGZvbGRlciB3aGVyZSB0aGUgbnBtIHBhY2thZ2VzIHB1dFxuICAgKlxuICAgKiBAZGVmYXVsdCAnbnBtJ1xuICAgKi9cbiAgbnBtRGlyPzogc3RyaW5nXG4gIC8qKlxuICAgKiBEcnkgcnVuIHdpdGhvdXQgdG91Y2hpbmcgZmlsZSBzeXN0ZW1cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIGRyeVJ1bj86IGJvb2xlYW5cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5RGVmYXVsdENyZWF0ZU5wbURpcnNPcHRpb25zKFxuICBvcHRpb25zOiBDcmVhdGVOcG1EaXJzT3B0aW9ucyxcbikge1xuICByZXR1cm4ge1xuICAgIGN3ZDogcHJvY2Vzcy5jd2QoKSxcbiAgICBwYWNrYWdlSnNvblBhdGg6ICdwYWNrYWdlLmpzb24nLFxuICAgIG5wbURpcjogJ25wbScsXG4gICAgZHJ5UnVuOiBmYWxzZSxcbiAgICAuLi5vcHRpb25zLFxuICB9XG59XG4iLCJpbXBvcnQgeyBqb2luLCByZXNvbHZlIH0gZnJvbSAnbm9kZTpwYXRoJ1xuXG5pbXBvcnQgeyBwYXJzZSB9IGZyb20gJ3NlbXZlcidcblxuaW1wb3J0IHtcbiAgYXBwbHlEZWZhdWx0Q3JlYXRlTnBtRGlyc09wdGlvbnMsXG4gIENyZWF0ZU5wbURpcnNPcHRpb25zLFxufSBmcm9tICcuLi9kZWYvY3JlYXRlLW5wbS1kaXJzLmpzJ1xuaW1wb3J0IHtcbiAgZGVidWdGYWN0b3J5LFxuICByZWFkTmFwaUNvbmZpZyxcbiAgbWtkaXJBc3luYyBhcyByYXdNa2RpckFzeW5jLFxuICBwaWNrLFxuICB3cml0ZUZpbGVBc3luYyBhcyByYXdXcml0ZUZpbGVBc3luYyxcbiAgVGFyZ2V0LFxufSBmcm9tICcuLi91dGlscy9pbmRleC5qcydcblxuaW1wb3J0IHR5cGUgeyBQYWNrYWdlTWV0YSB9IGZyb20gJy4vdGVtcGxhdGVzL3BhY2thZ2UuanNvbi5qcydcblxuY29uc3QgZGVidWcgPSBkZWJ1Z0ZhY3RvcnkoJ2NyZWF0ZS1ucG0tZGlycycpXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVOcG1EaXJzKHVzZXJPcHRpb25zOiBDcmVhdGVOcG1EaXJzT3B0aW9ucykge1xuICBjb25zdCBvcHRpb25zID0gYXBwbHlEZWZhdWx0Q3JlYXRlTnBtRGlyc09wdGlvbnModXNlck9wdGlvbnMpXG5cbiAgYXN5bmMgZnVuY3Rpb24gbWtkaXJBc3luYyhkaXI6IHN0cmluZykge1xuICAgIGRlYnVnKCdUcnkgdG8gY3JlYXRlIGRpcjogJWknLCBkaXIpXG4gICAgaWYgKG9wdGlvbnMuZHJ5UnVuKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBhd2FpdCByYXdNa2RpckFzeW5jKGRpciwge1xuICAgICAgcmVjdXJzaXZlOiB0cnVlLFxuICAgIH0pXG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiB3cml0ZUZpbGVBc3luYyhmaWxlOiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZykge1xuICAgIGRlYnVnKCdXcml0aW5nIGZpbGUgJWknLCBmaWxlKVxuXG4gICAgaWYgKG9wdGlvbnMuZHJ5UnVuKSB7XG4gICAgICBkZWJ1Zyhjb250ZW50KVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgYXdhaXQgcmF3V3JpdGVGaWxlQXN5bmMoZmlsZSwgY29udGVudClcbiAgfVxuXG4gIGNvbnN0IHBhY2thZ2VKc29uUGF0aCA9IHJlc29sdmUob3B0aW9ucy5jd2QsIG9wdGlvbnMucGFja2FnZUpzb25QYXRoKVxuICBjb25zdCBucG1QYXRoID0gcmVzb2x2ZShvcHRpb25zLmN3ZCwgb3B0aW9ucy5ucG1EaXIpXG5cbiAgZGVidWcoYFJlYWQgY29udGVudCBmcm9tIFske29wdGlvbnMuY29uZmlnUGF0aCA/PyBwYWNrYWdlSnNvblBhdGh9XWApXG5cbiAgY29uc3QgeyB0YXJnZXRzLCBiaW5hcnlOYW1lLCBwYWNrYWdlTmFtZSwgcGFja2FnZUpzb24gfSA9XG4gICAgYXdhaXQgcmVhZE5hcGlDb25maWcoXG4gICAgICBwYWNrYWdlSnNvblBhdGgsXG4gICAgICBvcHRpb25zLmNvbmZpZ1BhdGggPyByZXNvbHZlKG9wdGlvbnMuY3dkLCBvcHRpb25zLmNvbmZpZ1BhdGgpIDogdW5kZWZpbmVkLFxuICAgIClcblxuICBmb3IgKGNvbnN0IHRhcmdldCBvZiB0YXJnZXRzKSB7XG4gICAgY29uc3QgdGFyZ2V0RGlyID0gam9pbihucG1QYXRoLCBgJHt0YXJnZXQucGxhdGZvcm1BcmNoQUJJfWApXG4gICAgYXdhaXQgbWtkaXJBc3luYyh0YXJnZXREaXIpXG5cbiAgICBjb25zdCBiaW5hcnlGaWxlTmFtZSA9XG4gICAgICB0YXJnZXQuYXJjaCA9PT0gJ3dhc20zMidcbiAgICAgICAgPyBgJHtiaW5hcnlOYW1lfS4ke3RhcmdldC5wbGF0Zm9ybUFyY2hBQkl9Lndhc21gXG4gICAgICAgIDogYCR7YmluYXJ5TmFtZX0uJHt0YXJnZXQucGxhdGZvcm1BcmNoQUJJfS5ub2RlYFxuICAgIGNvbnN0IHNjb3BlZFBhY2thZ2VKc29uID0ge1xuICAgICAgbmFtZTogYCR7cGFja2FnZU5hbWV9LSR7dGFyZ2V0LnBsYXRmb3JtQXJjaEFCSX1gLFxuICAgICAgdmVyc2lvbjogcGFja2FnZUpzb24udmVyc2lvbixcbiAgICAgIGNwdTogdGFyZ2V0LmFyY2ggIT09ICd1bml2ZXJzYWwnID8gW3RhcmdldC5hcmNoXSA6IHVuZGVmaW5lZCxcbiAgICAgIG1haW46IGJpbmFyeUZpbGVOYW1lLFxuICAgICAgZmlsZXM6IFtiaW5hcnlGaWxlTmFtZV0sXG4gICAgICAuLi5waWNrKFxuICAgICAgICBwYWNrYWdlSnNvbixcbiAgICAgICAgJ2Rlc2NyaXB0aW9uJyxcbiAgICAgICAgJ2tleXdvcmRzJyxcbiAgICAgICAgJ2F1dGhvcicsXG4gICAgICAgICdhdXRob3JzJyxcbiAgICAgICAgJ2hvbWVwYWdlJyxcbiAgICAgICAgJ2xpY2Vuc2UnLFxuICAgICAgICAnZW5naW5lcycsXG4gICAgICAgICdwdWJsaXNoQ29uZmlnJyxcbiAgICAgICAgJ3JlcG9zaXRvcnknLFxuICAgICAgICAnYnVncycsXG4gICAgICApLFxuICAgIH1cbiAgICBpZiAodGFyZ2V0LmFyY2ggIT09ICd3YXNtMzInKSB7XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICBzY29wZWRQYWNrYWdlSnNvbi5vcyA9IFt0YXJnZXQucGxhdGZvcm1dXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGVudHJ5ID0gYCR7YmluYXJ5TmFtZX0ud2FzaS5janNgXG4gICAgICBzY29wZWRQYWNrYWdlSnNvbi5tYWluID0gZW50cnlcbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgIHNjb3BlZFBhY2thZ2VKc29uLmJyb3dzZXIgPSBgJHtiaW5hcnlOYW1lfS53YXNpLWJyb3dzZXIuanNgXG4gICAgICBzY29wZWRQYWNrYWdlSnNvbi5maWxlcy5wdXNoKFxuICAgICAgICBlbnRyeSxcbiAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICBzY29wZWRQYWNrYWdlSnNvbi5icm93c2VyLFxuICAgICAgICBgd2FzaS13b3JrZXIubWpzYCxcbiAgICAgICAgYHdhc2ktd29ya2VyLWJyb3dzZXIubWpzYCxcbiAgICAgIClcbiAgICAgIGxldCBuZWVkUmVzdHJpY3ROb2RlVmVyc2lvbiA9IHRydWVcbiAgICAgIGlmIChzY29wZWRQYWNrYWdlSnNvbi5lbmdpbmVzPy5ub2RlKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgeyBtYWpvciB9ID0gcGFyc2Uoc2NvcGVkUGFja2FnZUpzb24uZW5naW5lcy5ub2RlKSA/PyB7XG4gICAgICAgICAgICBtYWpvcjogMCxcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKG1ham9yID49IDE0KSB7XG4gICAgICAgICAgICBuZWVkUmVzdHJpY3ROb2RlVmVyc2lvbiA9IGZhbHNlXG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAvLyBpZ25vcmVcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKG5lZWRSZXN0cmljdE5vZGVWZXJzaW9uKSB7XG4gICAgICAgIHNjb3BlZFBhY2thZ2VKc29uLmVuZ2luZXMgPSB7XG4gICAgICAgICAgbm9kZTogJz49MTQuMC4wJyxcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY29uc3Qgd2FzbVJ1bnRpbWUgPSBhd2FpdCBmZXRjaChcbiAgICAgICAgYGh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL0BuYXBpLXJzL3dhc20tcnVudGltZWAsXG4gICAgICApLnRoZW4oKHJlcykgPT4gcmVzLmpzb24oKSBhcyBQcm9taXNlPFBhY2thZ2VNZXRhPilcbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgIHNjb3BlZFBhY2thZ2VKc29uLmRlcGVuZGVuY2llcyA9IHtcbiAgICAgICAgJ0BuYXBpLXJzL3dhc20tcnVudGltZSc6IGBeJHt3YXNtUnVudGltZVsnZGlzdC10YWdzJ10ubGF0ZXN0fWAsXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRhcmdldC5hYmkgPT09ICdnbnUnKSB7XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICBzY29wZWRQYWNrYWdlSnNvbi5saWJjID0gWydnbGliYyddXG4gICAgfSBlbHNlIGlmICh0YXJnZXQuYWJpID09PSAnbXVzbCcpIHtcbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgIHNjb3BlZFBhY2thZ2VKc29uLmxpYmMgPSBbJ211c2wnXVxuICAgIH1cblxuICAgIGNvbnN0IHRhcmdldFBhY2thZ2VKc29uID0gam9pbih0YXJnZXREaXIsICdwYWNrYWdlLmpzb24nKVxuICAgIGF3YWl0IHdyaXRlRmlsZUFzeW5jKFxuICAgICAgdGFyZ2V0UGFja2FnZUpzb24sXG4gICAgICBKU09OLnN0cmluZ2lmeShzY29wZWRQYWNrYWdlSnNvbiwgbnVsbCwgMikgKyAnXFxuJyxcbiAgICApXG4gICAgY29uc3QgdGFyZ2V0UmVhZG1lID0gam9pbih0YXJnZXREaXIsICdSRUFETUUubWQnKVxuICAgIGF3YWl0IHdyaXRlRmlsZUFzeW5jKHRhcmdldFJlYWRtZSwgcmVhZG1lKHBhY2thZ2VOYW1lLCB0YXJnZXQpKVxuXG4gICAgZGVidWcuaW5mbyhgJHtwYWNrYWdlTmFtZX0gLSR7dGFyZ2V0LnBsYXRmb3JtQXJjaEFCSX0gY3JlYXRlZGApXG4gIH1cbn1cblxuZnVuY3Rpb24gcmVhZG1lKHBhY2thZ2VOYW1lOiBzdHJpbmcsIHRhcmdldDogVGFyZ2V0KSB7XG4gIHJldHVybiBgIyBcXGAke3BhY2thZ2VOYW1lfS0ke3RhcmdldC5wbGF0Zm9ybUFyY2hBQkl9XFxgXG5cblRoaXMgaXMgdGhlICoqJHt0YXJnZXQudHJpcGxlfSoqIGJpbmFyeSBmb3IgXFxgJHtwYWNrYWdlTmFtZX1cXGBcbmBcbn1cbiIsIi8vIFRoaXMgZmlsZSBpcyBnZW5lcmF0ZWQgYnkgY29kZWdlbi9pbmRleC50c1xuLy8gRG8gbm90IGVkaXQgdGhpcyBmaWxlIG1hbnVhbGx5XG5pbXBvcnQgeyBDb21tYW5kLCBPcHRpb24gfSBmcm9tICdjbGlwYW5pb24nXG5pbXBvcnQgKiBhcyB0eXBhbmlvbiBmcm9tICd0eXBhbmlvbidcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VOZXdDb21tYW5kIGV4dGVuZHMgQ29tbWFuZCB7XG4gIHN0YXRpYyBwYXRocyA9IFtbJ25ldyddXVxuXG4gIHN0YXRpYyB1c2FnZSA9IENvbW1hbmQuVXNhZ2Uoe1xuICAgIGRlc2NyaXB0aW9uOiAnQ3JlYXRlIGEgbmV3IHByb2plY3Qgd2l0aCBwcmUtY29uZmlndXJlZCBib2lsZXJwbGF0ZScsXG4gIH0pXG5cbiAgJCRwYXRoID0gT3B0aW9uLlN0cmluZyh7IHJlcXVpcmVkOiBmYWxzZSB9KVxuXG4gICQkbmFtZT86IHN0cmluZyA9IE9wdGlvbi5TdHJpbmcoJy0tbmFtZSwtbicsIHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgICdUaGUgbmFtZSBvZiB0aGUgcHJvamVjdCwgZGVmYXVsdCB0byB0aGUgbmFtZSBvZiB0aGUgZGlyZWN0b3J5IGlmIG5vdCBwcm92aWRlZCcsXG4gIH0pXG5cbiAgbWluTm9kZUFwaVZlcnNpb24gPSBPcHRpb24uU3RyaW5nKCctLW1pbi1ub2RlLWFwaSwtdicsICc0Jywge1xuICAgIHZhbGlkYXRvcjogdHlwYW5pb24uaXNOdW1iZXIoKSxcbiAgICBkZXNjcmlwdGlvbjogJ1RoZSBtaW5pbXVtIE5vZGUtQVBJIHZlcnNpb24gdG8gc3VwcG9ydCcsXG4gIH0pXG5cbiAgcGFja2FnZU1hbmFnZXIgPSBPcHRpb24uU3RyaW5nKCctLXBhY2thZ2UtbWFuYWdlcicsICd5YXJuJywge1xuICAgIGRlc2NyaXB0aW9uOiAnVGhlIHBhY2thZ2UgbWFuYWdlciB0byB1c2UuIE9ubHkgc3VwcG9ydCB5YXJuIDQueCBmb3Igbm93LicsXG4gIH0pXG5cbiAgbGljZW5zZSA9IE9wdGlvbi5TdHJpbmcoJy0tbGljZW5zZSwtbCcsICdNSVQnLCB7XG4gICAgZGVzY3JpcHRpb246ICdMaWNlbnNlIGZvciBvcGVuLXNvdXJjZWQgcHJvamVjdCcsXG4gIH0pXG5cbiAgdGFyZ2V0cyA9IE9wdGlvbi5BcnJheSgnLS10YXJnZXRzLC10JywgW10sIHtcbiAgICBkZXNjcmlwdGlvbjogJ0FsbCB0YXJnZXRzIHRoZSBjcmF0ZSB3aWxsIGJlIGNvbXBpbGVkIGZvci4nLFxuICB9KVxuXG4gIGVuYWJsZURlZmF1bHRUYXJnZXRzID0gT3B0aW9uLkJvb2xlYW4oJy0tZW5hYmxlLWRlZmF1bHQtdGFyZ2V0cycsIHRydWUsIHtcbiAgICBkZXNjcmlwdGlvbjogJ1doZXRoZXIgZW5hYmxlIGRlZmF1bHQgdGFyZ2V0cycsXG4gIH0pXG5cbiAgZW5hYmxlQWxsVGFyZ2V0cyA9IE9wdGlvbi5Cb29sZWFuKCctLWVuYWJsZS1hbGwtdGFyZ2V0cycsIGZhbHNlLCB7XG4gICAgZGVzY3JpcHRpb246ICdXaGV0aGVyIGVuYWJsZSBhbGwgdGFyZ2V0cycsXG4gIH0pXG5cbiAgZW5hYmxlVHlwZURlZiA9IE9wdGlvbi5Cb29sZWFuKCctLWVuYWJsZS10eXBlLWRlZicsIHRydWUsIHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgICdXaGV0aGVyIGVuYWJsZSB0aGUgYHR5cGUtZGVmYCBmZWF0dXJlIGZvciB0eXBlc2NyaXB0IGRlZmluaXRpb25zIGF1dG8tZ2VuZXJhdGlvbicsXG4gIH0pXG5cbiAgZW5hYmxlR2l0aHViQWN0aW9ucyA9IE9wdGlvbi5Cb29sZWFuKCctLWVuYWJsZS1naXRodWItYWN0aW9ucycsIHRydWUsIHtcbiAgICBkZXNjcmlwdGlvbjogJ1doZXRoZXIgZ2VuZXJhdGUgcHJlY29uZmlndXJlZCBHaXRIdWIgQWN0aW9ucyB3b3JrZmxvdycsXG4gIH0pXG5cbiAgdGVzdEZyYW1ld29yayA9IE9wdGlvbi5TdHJpbmcoJy0tdGVzdC1mcmFtZXdvcmsnLCAnYXZhJywge1xuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgJ1RoZSBKYXZhU2NyaXB0IHRlc3QgZnJhbWV3b3JrIHRvIHVzZSwgb25seSBzdXBwb3J0IGBhdmFgIGZvciBub3cnLFxuICB9KVxuXG4gIGRyeVJ1biA9IE9wdGlvbi5Cb29sZWFuKCctLWRyeS1ydW4nLCBmYWxzZSwge1xuICAgIGRlc2NyaXB0aW9uOiAnV2hldGhlciB0byBydW4gdGhlIGNvbW1hbmQgaW4gZHJ5LXJ1biBtb2RlJyxcbiAgfSlcblxuICBnZXRPcHRpb25zKCkge1xuICAgIHJldHVybiB7XG4gICAgICBwYXRoOiB0aGlzLiQkcGF0aCxcbiAgICAgIG5hbWU6IHRoaXMuJCRuYW1lLFxuICAgICAgbWluTm9kZUFwaVZlcnNpb246IHRoaXMubWluTm9kZUFwaVZlcnNpb24sXG4gICAgICBwYWNrYWdlTWFuYWdlcjogdGhpcy5wYWNrYWdlTWFuYWdlcixcbiAgICAgIGxpY2Vuc2U6IHRoaXMubGljZW5zZSxcbiAgICAgIHRhcmdldHM6IHRoaXMudGFyZ2V0cyxcbiAgICAgIGVuYWJsZURlZmF1bHRUYXJnZXRzOiB0aGlzLmVuYWJsZURlZmF1bHRUYXJnZXRzLFxuICAgICAgZW5hYmxlQWxsVGFyZ2V0czogdGhpcy5lbmFibGVBbGxUYXJnZXRzLFxuICAgICAgZW5hYmxlVHlwZURlZjogdGhpcy5lbmFibGVUeXBlRGVmLFxuICAgICAgZW5hYmxlR2l0aHViQWN0aW9uczogdGhpcy5lbmFibGVHaXRodWJBY3Rpb25zLFxuICAgICAgdGVzdEZyYW1ld29yazogdGhpcy50ZXN0RnJhbWV3b3JrLFxuICAgICAgZHJ5UnVuOiB0aGlzLmRyeVJ1bixcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBuZXcgcHJvamVjdCB3aXRoIHByZS1jb25maWd1cmVkIGJvaWxlcnBsYXRlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTmV3T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgcGF0aCB3aGVyZSB0aGUgTkFQSS1SUyBwcm9qZWN0IHdpbGwgYmUgY3JlYXRlZC5cbiAgICovXG4gIHBhdGg/OiBzdHJpbmdcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9qZWN0LCBkZWZhdWx0IHRvIHRoZSBuYW1lIG9mIHRoZSBkaXJlY3RvcnkgaWYgbm90IHByb3ZpZGVkXG4gICAqL1xuICBuYW1lPzogc3RyaW5nXG4gIC8qKlxuICAgKiBUaGUgbWluaW11bSBOb2RlLUFQSSB2ZXJzaW9uIHRvIHN1cHBvcnRcbiAgICpcbiAgICogQGRlZmF1bHQgNFxuICAgKi9cbiAgbWluTm9kZUFwaVZlcnNpb24/OiBudW1iZXJcbiAgLyoqXG4gICAqIFRoZSBwYWNrYWdlIG1hbmFnZXIgdG8gdXNlLiBPbmx5IHN1cHBvcnQgeWFybiA0LnggZm9yIG5vdy5cbiAgICpcbiAgICogQGRlZmF1bHQgJ3lhcm4nXG4gICAqL1xuICBwYWNrYWdlTWFuYWdlcj86IHN0cmluZ1xuICAvKipcbiAgICogTGljZW5zZSBmb3Igb3Blbi1zb3VyY2VkIHByb2plY3RcbiAgICpcbiAgICogQGRlZmF1bHQgJ01JVCdcbiAgICovXG4gIGxpY2Vuc2U/OiBzdHJpbmdcbiAgLyoqXG4gICAqIEFsbCB0YXJnZXRzIHRoZSBjcmF0ZSB3aWxsIGJlIGNvbXBpbGVkIGZvci5cbiAgICpcbiAgICogQGRlZmF1bHQgW11cbiAgICovXG4gIHRhcmdldHM/OiBzdHJpbmdbXVxuICAvKipcbiAgICogV2hldGhlciBlbmFibGUgZGVmYXVsdCB0YXJnZXRzXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIGVuYWJsZURlZmF1bHRUYXJnZXRzPzogYm9vbGVhblxuICAvKipcbiAgICogV2hldGhlciBlbmFibGUgYWxsIHRhcmdldHNcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIGVuYWJsZUFsbFRhcmdldHM/OiBib29sZWFuXG4gIC8qKlxuICAgKiBXaGV0aGVyIGVuYWJsZSB0aGUgYHR5cGUtZGVmYCBmZWF0dXJlIGZvciB0eXBlc2NyaXB0IGRlZmluaXRpb25zIGF1dG8tZ2VuZXJhdGlvblxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICBlbmFibGVUeXBlRGVmPzogYm9vbGVhblxuICAvKipcbiAgICogV2hldGhlciBnZW5lcmF0ZSBwcmVjb25maWd1cmVkIEdpdEh1YiBBY3Rpb25zIHdvcmtmbG93XG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIGVuYWJsZUdpdGh1YkFjdGlvbnM/OiBib29sZWFuXG4gIC8qKlxuICAgKiBUaGUgSmF2YVNjcmlwdCB0ZXN0IGZyYW1ld29yayB0byB1c2UsIG9ubHkgc3VwcG9ydCBgYXZhYCBmb3Igbm93XG4gICAqXG4gICAqIEBkZWZhdWx0ICdhdmEnXG4gICAqL1xuICB0ZXN0RnJhbWV3b3JrPzogc3RyaW5nXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHJ1biB0aGUgY29tbWFuZCBpbiBkcnktcnVuIG1vZGVcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIGRyeVJ1bj86IGJvb2xlYW5cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5RGVmYXVsdE5ld09wdGlvbnMob3B0aW9uczogTmV3T3B0aW9ucykge1xuICByZXR1cm4ge1xuICAgIG1pbk5vZGVBcGlWZXJzaW9uOiA0LFxuICAgIHBhY2thZ2VNYW5hZ2VyOiAneWFybicsXG4gICAgbGljZW5zZTogJ01JVCcsXG4gICAgdGFyZ2V0czogW10sXG4gICAgZW5hYmxlRGVmYXVsdFRhcmdldHM6IHRydWUsXG4gICAgZW5hYmxlQWxsVGFyZ2V0czogZmFsc2UsXG4gICAgZW5hYmxlVHlwZURlZjogdHJ1ZSxcbiAgICBlbmFibGVHaXRodWJBY3Rpb25zOiB0cnVlLFxuICAgIHRlc3RGcmFtZXdvcms6ICdhdmEnLFxuICAgIGRyeVJ1bjogZmFsc2UsXG4gICAgLi4ub3B0aW9ucyxcbiAgfVxufVxuIiwiZnVuY3Rpb24gX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24oZSwgdCkge1xuICBpZiAodC5oYXMoZSkpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgaW5pdGlhbGl6ZSB0aGUgc2FtZSBwcml2YXRlIGVsZW1lbnRzIHR3aWNlIG9uIGFuIG9iamVjdFwiKTtcbn1cbm1vZHVsZS5leHBvcnRzID0gX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24sIG1vZHVsZS5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlLCBtb2R1bGUuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBtb2R1bGUuZXhwb3J0czsiLCJ2YXIgY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbiA9IHJlcXVpcmUoXCIuL2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24uanNcIik7XG5mdW5jdGlvbiBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWMoZSwgYSkge1xuICBjaGVja1ByaXZhdGVSZWRlY2xhcmF0aW9uKGUsIGEpLCBhLmFkZChlKTtcbn1cbm1vZHVsZS5leHBvcnRzID0gX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjLCBtb2R1bGUuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZSwgbW9kdWxlLmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gbW9kdWxlLmV4cG9ydHM7IiwidmFyIGNoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24gPSByZXF1aXJlKFwiLi9jaGVja1ByaXZhdGVSZWRlY2xhcmF0aW9uLmpzXCIpO1xuZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWMoZSwgdCwgYSkge1xuICBjaGVja1ByaXZhdGVSZWRlY2xhcmF0aW9uKGUsIHQpLCB0LnNldChlLCBhKTtcbn1cbm1vZHVsZS5leHBvcnRzID0gX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWMsIG1vZHVsZS5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlLCBtb2R1bGUuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBtb2R1bGUuZXhwb3J0czsiLCJmdW5jdGlvbiBfYXNzZXJ0Q2xhc3NCcmFuZChlLCB0LCBuKSB7XG4gIGlmIChcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIGUgPyBlID09PSB0IDogZS5oYXModCkpIHJldHVybiBhcmd1bWVudHMubGVuZ3RoIDwgMyA/IHQgOiBuO1xuICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBlbGVtZW50IGlzIG5vdCBwcmVzZW50IG9uIHRoaXMgb2JqZWN0XCIpO1xufVxubW9kdWxlLmV4cG9ydHMgPSBfYXNzZXJ0Q2xhc3NCcmFuZCwgbW9kdWxlLmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWUsIG1vZHVsZS5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IG1vZHVsZS5leHBvcnRzOyIsInZhciBhc3NlcnRDbGFzc0JyYW5kID0gcmVxdWlyZShcIi4vYXNzZXJ0Q2xhc3NCcmFuZC5qc1wiKTtcbmZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVGaWVsZEdldDIocywgYSkge1xuICByZXR1cm4gcy5nZXQoYXNzZXJ0Q2xhc3NCcmFuZChzLCBhKSk7XG59XG5tb2R1bGUuZXhwb3J0cyA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldDIsIG1vZHVsZS5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlLCBtb2R1bGUuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBtb2R1bGUuZXhwb3J0czsiLCIvLyBDb3B5cmlnaHQgMjAxOC0yMDI1IHRoZSBEZW5vIGF1dGhvcnMuIE1JVCBsaWNlbnNlLlxuLy8gVGhpcyBtb2R1bGUgaXMgYnJvd3NlciBjb21wYXRpYmxlLlxuLy8gQmFyZSBrZXlzIG1heSBvbmx5IGNvbnRhaW4gQVNDSUkgbGV0dGVycyxcbi8vIEFTQ0lJIGRpZ2l0cywgdW5kZXJzY29yZXMsIGFuZCBkYXNoZXMgKEEtWmEtejAtOV8tKS5cbmZ1bmN0aW9uIGpvaW5LZXlzKGtleXMpIHtcbiAgLy8gRG90dGVkIGtleXMgYXJlIGEgc2VxdWVuY2Ugb2YgYmFyZSBvciBxdW90ZWQga2V5cyBqb2luZWQgd2l0aCBhIGRvdC5cbiAgLy8gVGhpcyBhbGxvd3MgZm9yIGdyb3VwaW5nIHNpbWlsYXIgcHJvcGVydGllcyB0b2dldGhlcjpcbiAgcmV0dXJuIGtleXMubWFwKChzdHIpPT57XG4gICAgcmV0dXJuIHN0ci5sZW5ndGggPT09IDAgfHwgc3RyLm1hdGNoKC9bXkEtWmEtejAtOV8tXS8pID8gSlNPTi5zdHJpbmdpZnkoc3RyKSA6IHN0cjtcbiAgfSkuam9pbihcIi5cIik7XG59XG5jbGFzcyBEdW1wZXIge1xuICBtYXhQYWQgPSAwO1xuICBzcmNPYmplY3Q7XG4gIG91dHB1dCA9IFtdO1xuICAjYXJyYXlUeXBlQ2FjaGUgPSBuZXcgTWFwKCk7XG4gIGNvbnN0cnVjdG9yKHNyY09iamMpe1xuICAgIHRoaXMuc3JjT2JqZWN0ID0gc3JjT2JqYztcbiAgfVxuICBkdW1wKGZtdE9wdGlvbnMgPSB7fSkge1xuICAgIC8vIGRlbm8tbGludC1pZ25vcmUgbm8tZXhwbGljaXQtYW55XG4gICAgdGhpcy5vdXRwdXQgPSB0aGlzLiNwcmludE9iamVjdCh0aGlzLnNyY09iamVjdCk7XG4gICAgdGhpcy5vdXRwdXQgPSB0aGlzLiNmb3JtYXQoZm10T3B0aW9ucyk7XG4gICAgcmV0dXJuIHRoaXMub3V0cHV0O1xuICB9XG4gICNwcmludE9iamVjdChvYmosIGtleXMgPSBbXSkge1xuICAgIGNvbnN0IG91dCA9IFtdO1xuICAgIGNvbnN0IHByb3BzID0gT2JqZWN0LmtleXMob2JqKTtcbiAgICBjb25zdCBpbmxpbmVQcm9wcyA9IFtdO1xuICAgIGNvbnN0IG11bHRpbGluZVByb3BzID0gW107XG4gICAgZm9yIChjb25zdCBwcm9wIG9mIHByb3BzKXtcbiAgICAgIGlmICh0aGlzLiNpc1NpbXBseVNlcmlhbGl6YWJsZShvYmpbcHJvcF0pKSB7XG4gICAgICAgIGlubGluZVByb3BzLnB1c2gocHJvcCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtdWx0aWxpbmVQcm9wcy5wdXNoKHByb3ApO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBzb3J0ZWRQcm9wcyA9IGlubGluZVByb3BzLmNvbmNhdChtdWx0aWxpbmVQcm9wcyk7XG4gICAgZm9yIChjb25zdCBwcm9wIG9mIHNvcnRlZFByb3BzKXtcbiAgICAgIGNvbnN0IHZhbHVlID0gb2JqW3Byb3BdO1xuICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICBvdXQucHVzaCh0aGlzLiNkYXRlRGVjbGFyYXRpb24oW1xuICAgICAgICAgIHByb3BcbiAgICAgICAgXSwgdmFsdWUpKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiIHx8IHZhbHVlIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgIG91dC5wdXNoKHRoaXMuI3N0ckRlY2xhcmF0aW9uKFtcbiAgICAgICAgICBwcm9wXG4gICAgICAgIF0sIHZhbHVlLnRvU3RyaW5nKCkpKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgIG91dC5wdXNoKHRoaXMuI251bWJlckRlY2xhcmF0aW9uKFtcbiAgICAgICAgICBwcm9wXG4gICAgICAgIF0sIHZhbHVlKSk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJib29sZWFuXCIpIHtcbiAgICAgICAgb3V0LnB1c2godGhpcy4jYm9vbERlY2xhcmF0aW9uKFtcbiAgICAgICAgICBwcm9wXG4gICAgICAgIF0sIHZhbHVlKSk7XG4gICAgICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgY29uc3QgYXJyYXlUeXBlID0gdGhpcy4jZ2V0VHlwZU9mQXJyYXkodmFsdWUpO1xuICAgICAgICBpZiAoYXJyYXlUeXBlID09PSBcIk9OTFlfUFJJTUlUSVZFXCIpIHtcbiAgICAgICAgICBvdXQucHVzaCh0aGlzLiNhcnJheURlY2xhcmF0aW9uKFtcbiAgICAgICAgICAgIHByb3BcbiAgICAgICAgICBdLCB2YWx1ZSkpO1xuICAgICAgICB9IGVsc2UgaWYgKGFycmF5VHlwZSA9PT0gXCJPTkxZX09CSkVDVF9FWENMVURJTkdfQVJSQVlcIikge1xuICAgICAgICAgIC8vIGFycmF5IG9mIG9iamVjdHNcbiAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgdmFsdWUubGVuZ3RoOyBpKyspe1xuICAgICAgICAgICAgb3V0LnB1c2goXCJcIik7XG4gICAgICAgICAgICBvdXQucHVzaCh0aGlzLiNoZWFkZXJHcm91cChbXG4gICAgICAgICAgICAgIC4uLmtleXMsXG4gICAgICAgICAgICAgIHByb3BcbiAgICAgICAgICAgIF0pKTtcbiAgICAgICAgICAgIG91dC5wdXNoKC4uLnRoaXMuI3ByaW50T2JqZWN0KHZhbHVlW2ldLCBbXG4gICAgICAgICAgICAgIC4uLmtleXMsXG4gICAgICAgICAgICAgIHByb3BcbiAgICAgICAgICAgIF0pKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gdGhpcyBpcyBhIGNvbXBsZXggYXJyYXksIHVzZSB0aGUgaW5saW5lIGZvcm1hdC5cbiAgICAgICAgICBjb25zdCBzdHIgPSB2YWx1ZS5tYXAoKHgpPT50aGlzLiNwcmludEFzSW5saW5lVmFsdWUoeCkpLmpvaW4oXCIsXCIpO1xuICAgICAgICAgIG91dC5wdXNoKGAke3RoaXMuI2RlY2xhcmF0aW9uKFtcbiAgICAgICAgICAgIHByb3BcbiAgICAgICAgICBdKX1bJHtzdHJ9XWApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICBvdXQucHVzaChcIlwiKTtcbiAgICAgICAgb3V0LnB1c2godGhpcy4jaGVhZGVyKFtcbiAgICAgICAgICAuLi5rZXlzLFxuICAgICAgICAgIHByb3BcbiAgICAgICAgXSkpO1xuICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICBjb25zdCB0b1BhcnNlID0gdmFsdWU7XG4gICAgICAgICAgb3V0LnB1c2goLi4udGhpcy4jcHJpbnRPYmplY3QodG9QYXJzZSwgW1xuICAgICAgICAgICAgLi4ua2V5cyxcbiAgICAgICAgICAgIHByb3BcbiAgICAgICAgICBdKSk7XG4gICAgICAgIH1cbiAgICAgIC8vIG91dC5wdXNoKC4uLnRoaXMuX3BhcnNlKHZhbHVlLCBgJHtwYXRofSR7cHJvcH0uYCkpO1xuICAgICAgfVxuICAgIH1cbiAgICBvdXQucHVzaChcIlwiKTtcbiAgICByZXR1cm4gb3V0O1xuICB9XG4gICNpc1ByaW1pdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIERhdGUgfHwgdmFsdWUgaW5zdGFuY2VvZiBSZWdFeHAgfHwgW1xuICAgICAgXCJzdHJpbmdcIixcbiAgICAgIFwibnVtYmVyXCIsXG4gICAgICBcImJvb2xlYW5cIlxuICAgIF0uaW5jbHVkZXModHlwZW9mIHZhbHVlKTtcbiAgfVxuICAjZ2V0VHlwZU9mQXJyYXkoYXJyKSB7XG4gICAgaWYgKHRoaXMuI2FycmF5VHlwZUNhY2hlLmhhcyhhcnIpKSB7XG4gICAgICByZXR1cm4gdGhpcy4jYXJyYXlUeXBlQ2FjaGUuZ2V0KGFycik7XG4gICAgfVxuICAgIGNvbnN0IHR5cGUgPSB0aGlzLiNkb0dldFR5cGVPZkFycmF5KGFycik7XG4gICAgdGhpcy4jYXJyYXlUeXBlQ2FjaGUuc2V0KGFyciwgdHlwZSk7XG4gICAgcmV0dXJuIHR5cGU7XG4gIH1cbiAgI2RvR2V0VHlwZU9mQXJyYXkoYXJyKSB7XG4gICAgaWYgKCFhcnIubGVuZ3RoKSB7XG4gICAgICAvLyBhbnkgdHlwZSBzaG91bGQgYmUgZmluZVxuICAgICAgcmV0dXJuIFwiT05MWV9QUklNSVRJVkVcIjtcbiAgICB9XG4gICAgY29uc3Qgb25seVByaW1pdGl2ZSA9IHRoaXMuI2lzUHJpbWl0aXZlKGFyclswXSk7XG4gICAgaWYgKGFyclswXSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICByZXR1cm4gXCJNSVhFRFwiO1xuICAgIH1cbiAgICBmb3IobGV0IGkgPSAxOyBpIDwgYXJyLmxlbmd0aDsgaSsrKXtcbiAgICAgIGlmIChvbmx5UHJpbWl0aXZlICE9PSB0aGlzLiNpc1ByaW1pdGl2ZShhcnJbaV0pIHx8IGFycltpXSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgIHJldHVybiBcIk1JWEVEXCI7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvbmx5UHJpbWl0aXZlID8gXCJPTkxZX1BSSU1JVElWRVwiIDogXCJPTkxZX09CSkVDVF9FWENMVURJTkdfQVJSQVlcIjtcbiAgfVxuICAjcHJpbnRBc0lubGluZVZhbHVlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgcmV0dXJuIGBcIiR7dGhpcy4jcHJpbnREYXRlKHZhbHVlKX1cImA7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgfHwgdmFsdWUgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZS50b1N0cmluZygpKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSBcImJvb2xlYW5cIikge1xuICAgICAgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICBjb25zdCBzdHIgPSB2YWx1ZS5tYXAoKHgpPT50aGlzLiNwcmludEFzSW5saW5lVmFsdWUoeCkpLmpvaW4oXCIsXCIpO1xuICAgICAgcmV0dXJuIGBbJHtzdHJ9XWA7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgIGlmICghdmFsdWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU2hvdWxkIG5ldmVyIHJlYWNoXCIpO1xuICAgICAgfVxuICAgICAgY29uc3Qgc3RyID0gT2JqZWN0LmtleXModmFsdWUpLm1hcCgoa2V5KT0+e1xuICAgICAgICByZXR1cm4gYCR7am9pbktleXMoW1xuICAgICAgICAgIGtleVxuICAgICAgICBdKX0gPSAkey8vIGRlbm8tbGludC1pZ25vcmUgbm8tZXhwbGljaXQtYW55XG4gICAgICAgIHRoaXMuI3ByaW50QXNJbmxpbmVWYWx1ZSh2YWx1ZVtrZXldKX1gO1xuICAgICAgfSkuam9pbihcIixcIik7XG4gICAgICByZXR1cm4gYHske3N0cn19YDtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiU2hvdWxkIG5ldmVyIHJlYWNoXCIpO1xuICB9XG4gICNpc1NpbXBseVNlcmlhbGl6YWJsZSh2YWx1ZSkge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgfHwgdHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiIHx8IHR5cGVvZiB2YWx1ZSA9PT0gXCJib29sZWFuXCIgfHwgdmFsdWUgaW5zdGFuY2VvZiBSZWdFeHAgfHwgdmFsdWUgaW5zdGFuY2VvZiBEYXRlIHx8IHZhbHVlIGluc3RhbmNlb2YgQXJyYXkgJiYgdGhpcy4jZ2V0VHlwZU9mQXJyYXkodmFsdWUpICE9PSBcIk9OTFlfT0JKRUNUX0VYQ0xVRElOR19BUlJBWVwiO1xuICB9XG4gICNoZWFkZXIoa2V5cykge1xuICAgIHJldHVybiBgWyR7am9pbktleXMoa2V5cyl9XWA7XG4gIH1cbiAgI2hlYWRlckdyb3VwKGtleXMpIHtcbiAgICByZXR1cm4gYFtbJHtqb2luS2V5cyhrZXlzKX1dXWA7XG4gIH1cbiAgI2RlY2xhcmF0aW9uKGtleXMpIHtcbiAgICBjb25zdCB0aXRsZSA9IGpvaW5LZXlzKGtleXMpO1xuICAgIGlmICh0aXRsZS5sZW5ndGggPiB0aGlzLm1heFBhZCkge1xuICAgICAgdGhpcy5tYXhQYWQgPSB0aXRsZS5sZW5ndGg7XG4gICAgfVxuICAgIHJldHVybiBgJHt0aXRsZX0gPSBgO1xuICB9XG4gICNhcnJheURlY2xhcmF0aW9uKGtleXMsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGAke3RoaXMuI2RlY2xhcmF0aW9uKGtleXMpfSR7SlNPTi5zdHJpbmdpZnkodmFsdWUpfWA7XG4gIH1cbiAgI3N0ckRlY2xhcmF0aW9uKGtleXMsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGAke3RoaXMuI2RlY2xhcmF0aW9uKGtleXMpfSR7SlNPTi5zdHJpbmdpZnkodmFsdWUpfWA7XG4gIH1cbiAgI251bWJlckRlY2xhcmF0aW9uKGtleXMsIHZhbHVlKSB7XG4gICAgaWYgKE51bWJlci5pc05hTih2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBgJHt0aGlzLiNkZWNsYXJhdGlvbihrZXlzKX1uYW5gO1xuICAgIH1cbiAgICBzd2l0Y2godmFsdWUpe1xuICAgICAgY2FzZSBJbmZpbml0eTpcbiAgICAgICAgcmV0dXJuIGAke3RoaXMuI2RlY2xhcmF0aW9uKGtleXMpfWluZmA7XG4gICAgICBjYXNlIC1JbmZpbml0eTpcbiAgICAgICAgcmV0dXJuIGAke3RoaXMuI2RlY2xhcmF0aW9uKGtleXMpfS1pbmZgO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIGAke3RoaXMuI2RlY2xhcmF0aW9uKGtleXMpfSR7dmFsdWV9YDtcbiAgICB9XG4gIH1cbiAgI2Jvb2xEZWNsYXJhdGlvbihrZXlzLCB2YWx1ZSkge1xuICAgIHJldHVybiBgJHt0aGlzLiNkZWNsYXJhdGlvbihrZXlzKX0ke3ZhbHVlfWA7XG4gIH1cbiAgI3ByaW50RGF0ZSh2YWx1ZSkge1xuICAgIGZ1bmN0aW9uIGR0UGFkKHYsIGxQYWQgPSAyKSB7XG4gICAgICByZXR1cm4gdi5wYWRTdGFydChsUGFkLCBcIjBcIik7XG4gICAgfVxuICAgIGNvbnN0IG0gPSBkdFBhZCgodmFsdWUuZ2V0VVRDTW9udGgoKSArIDEpLnRvU3RyaW5nKCkpO1xuICAgIGNvbnN0IGQgPSBkdFBhZCh2YWx1ZS5nZXRVVENEYXRlKCkudG9TdHJpbmcoKSk7XG4gICAgY29uc3QgaCA9IGR0UGFkKHZhbHVlLmdldFVUQ0hvdXJzKCkudG9TdHJpbmcoKSk7XG4gICAgY29uc3QgbWluID0gZHRQYWQodmFsdWUuZ2V0VVRDTWludXRlcygpLnRvU3RyaW5nKCkpO1xuICAgIGNvbnN0IHMgPSBkdFBhZCh2YWx1ZS5nZXRVVENTZWNvbmRzKCkudG9TdHJpbmcoKSk7XG4gICAgY29uc3QgbXMgPSBkdFBhZCh2YWx1ZS5nZXRVVENNaWxsaXNlY29uZHMoKS50b1N0cmluZygpLCAzKTtcbiAgICAvLyBmb3JtYXR0ZWQgZGF0ZVxuICAgIGNvbnN0IGZEYXRhID0gYCR7dmFsdWUuZ2V0VVRDRnVsbFllYXIoKX0tJHttfS0ke2R9VCR7aH06JHttaW59OiR7c30uJHttc31gO1xuICAgIHJldHVybiBmRGF0YTtcbiAgfVxuICAjZGF0ZURlY2xhcmF0aW9uKGtleXMsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGAke3RoaXMuI2RlY2xhcmF0aW9uKGtleXMpfSR7dGhpcy4jcHJpbnREYXRlKHZhbHVlKX1gO1xuICB9XG4gICNmb3JtYXQob3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgeyBrZXlBbGlnbm1lbnQgPSBmYWxzZSB9ID0gb3B0aW9ucztcbiAgICBjb25zdCByRGVjbGFyYXRpb24gPSAvXihcXFwiLipcXFwifFtePV0qKVxccz0vO1xuICAgIGNvbnN0IG91dCA9IFtdO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCB0aGlzLm91dHB1dC5sZW5ndGg7IGkrKyl7XG4gICAgICBjb25zdCBsID0gdGhpcy5vdXRwdXRbaV07XG4gICAgICAvLyB3ZSBrZWVwIGVtcHR5IGVudHJ5IGZvciBhcnJheSBvZiBvYmplY3RzXG4gICAgICBpZiAobFswXSA9PT0gXCJbXCIgJiYgbFsxXSAhPT0gXCJbXCIpIHtcbiAgICAgICAgLy8gbm9uLWVtcHR5IG9iamVjdCB3aXRoIG9ubHkgc3Vib2JqZWN0cyBhcyBwcm9wZXJ0aWVzXG4gICAgICAgIGlmICh0aGlzLm91dHB1dFtpICsgMV0gPT09IFwiXCIgJiYgdGhpcy5vdXRwdXRbaSArIDJdPy5zbGljZSgwLCBsLmxlbmd0aCkgPT09IGwuc2xpY2UoMCwgLTEpICsgXCIuXCIpIHtcbiAgICAgICAgICBpICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgb3V0LnB1c2gobCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoa2V5QWxpZ25tZW50KSB7XG4gICAgICAgICAgY29uc3QgbSA9IHJEZWNsYXJhdGlvbi5leGVjKGwpO1xuICAgICAgICAgIGlmIChtICYmIG1bMV0pIHtcbiAgICAgICAgICAgIG91dC5wdXNoKGwucmVwbGFjZShtWzFdLCBtWzFdLnBhZEVuZCh0aGlzLm1heFBhZCkpKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3V0LnB1c2gobCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG91dC5wdXNoKGwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIC8vIENsZWFuaW5nIG11bHRpcGxlIHNwYWNlc1xuICAgIGNvbnN0IGNsZWFuZWRPdXRwdXQgPSBbXTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgb3V0Lmxlbmd0aDsgaSsrKXtcbiAgICAgIGNvbnN0IGwgPSBvdXRbaV07XG4gICAgICBpZiAoIShsID09PSBcIlwiICYmIG91dFtpICsgMV0gPT09IFwiXCIpKSB7XG4gICAgICAgIGNsZWFuZWRPdXRwdXQucHVzaChsKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGNsZWFuZWRPdXRwdXQ7XG4gIH1cbn1cbi8qKlxuICogQ29udmVydHMgYW4gb2JqZWN0IHRvIGEge0BsaW5rIGh0dHBzOi8vdG9tbC5pbyB8IFRPTUx9IHN0cmluZy5cbiAqXG4gKiBAZXhhbXBsZSBVc2FnZVxuICogYGBgdHNcbiAqIGltcG9ydCB7IHN0cmluZ2lmeSB9IGZyb20gXCJAc3RkL3RvbWwvc3RyaW5naWZ5XCI7XG4gKiBpbXBvcnQgeyBhc3NlcnRFcXVhbHMgfSBmcm9tIFwiQHN0ZC9hc3NlcnRcIjtcbiAqXG4gKiBjb25zdCBvYmogPSB7XG4gKiAgIHRpdGxlOiBcIlRPTUwgRXhhbXBsZVwiLFxuICogICBvd25lcjoge1xuICogICAgIG5hbWU6IFwiQm9iXCIsXG4gKiAgICAgYmlvOiBcIkJvYiBpcyBhIGNvb2wgZ3V5XCIsXG4gKiAgfVxuICogfTtcbiAqIGNvbnN0IHRvbWxTdHJpbmcgPSBzdHJpbmdpZnkob2JqKTtcbiAqIGFzc2VydEVxdWFscyh0b21sU3RyaW5nLCBgdGl0bGUgPSBcIlRPTUwgRXhhbXBsZVwiXFxuXFxuW293bmVyXVxcbm5hbWUgPSBcIkJvYlwiXFxuYmlvID0gXCJCb2IgaXMgYSBjb29sIGd1eVwiXFxuYCk7XG4gKiBgYGBcbiAqIEBwYXJhbSBvYmogU291cmNlIG9iamVjdFxuICogQHBhcmFtIG9wdGlvbnMgT3B0aW9ucyBmb3Igc3RyaW5naWZ5aW5nLlxuICogQHJldHVybnMgVE9NTCBzdHJpbmdcbiAqLyBleHBvcnQgZnVuY3Rpb24gc3RyaW5naWZ5KG9iaiwgb3B0aW9ucykge1xuICByZXR1cm4gbmV3IER1bXBlcihvYmopLmR1bXAob3B0aW9ucykuam9pbihcIlxcblwiKTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXN0cmluZ2lmeS5qcy5tYXAiLCIvLyBDb3B5cmlnaHQgMjAxOC0yMDI1IHRoZSBEZW5vIGF1dGhvcnMuIE1JVCBsaWNlbnNlLlxuLy8gVGhpcyBtb2R1bGUgaXMgYnJvd3NlciBjb21wYXRpYmxlLlxuLyoqXG4gKiBGaWx0ZXJzIHRoZSBnaXZlbiBhcnJheSwgcmVtb3ZpbmcgYWxsIGVsZW1lbnRzIHRoYXQgZG8gbm90IG1hdGNoIHRoZSBnaXZlbiBwcmVkaWNhdGVcbiAqICoqaW4gcGxhY2UuIFRoaXMgbWVhbnMgYGFycmF5YCB3aWxsIGJlIG1vZGlmaWVkISoqLlxuICovIGV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJJblBsYWNlKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgbGV0IG91dHB1dEluZGV4ID0gMDtcbiAgZm9yIChjb25zdCBjdXIgb2YgYXJyYXkpe1xuICAgIGlmICghcHJlZGljYXRlKGN1cikpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBhcnJheVtvdXRwdXRJbmRleF0gPSBjdXI7XG4gICAgb3V0cHV0SW5kZXggKz0gMTtcbiAgfVxuICBhcnJheS5zcGxpY2Uob3V0cHV0SW5kZXgpO1xuICByZXR1cm4gYXJyYXk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1fdXRpbHMuanMubWFwIiwiLy8gQ29weXJpZ2h0IDIwMTgtMjAyNSB0aGUgRGVubyBhdXRob3JzLiBNSVQgbGljZW5zZS5cbi8vIFRoaXMgbW9kdWxlIGlzIGJyb3dzZXIgY29tcGF0aWJsZS5cbmltcG9ydCB7IGZpbHRlckluUGxhY2UgfSBmcm9tIFwiLi9fdXRpbHMuanNcIjtcbmV4cG9ydCBmdW5jdGlvbiBkZWVwTWVyZ2UocmVjb3JkLCBvdGhlciwgb3B0aW9ucykge1xuICByZXR1cm4gZGVlcE1lcmdlSW50ZXJuYWwocmVjb3JkLCBvdGhlciwgbmV3IFNldCgpLCBvcHRpb25zKTtcbn1cbmZ1bmN0aW9uIGRlZXBNZXJnZUludGVybmFsKHJlY29yZCwgb3RoZXIsIHNlZW4sIG9wdGlvbnMpIHtcbiAgY29uc3QgcmVzdWx0ID0ge307XG4gIGNvbnN0IGtleXMgPSBuZXcgU2V0KFtcbiAgICAuLi5nZXRLZXlzKHJlY29yZCksXG4gICAgLi4uZ2V0S2V5cyhvdGhlcilcbiAgXSk7XG4gIC8vIEl0ZXJhdGUgdGhyb3VnaCBlYWNoIGtleSBvZiBvdGhlciBvYmplY3QgYW5kIHVzZSBjb3JyZWN0IG1lcmdpbmcgc3RyYXRlZ3lcbiAgZm9yIChjb25zdCBrZXkgb2Yga2V5cyl7XG4gICAgLy8gU2tpcCB0byBwcmV2ZW50IE9iamVjdC5wcm90b3R5cGUuX19wcm90b19fIGFjY2Vzc29yIHByb3BlcnR5IGNhbGxzIG9uIG5vbi1EZW5vIHBsYXRmb3Jtc1xuICAgIGlmIChrZXkgPT09IFwiX19wcm90b19fXCIpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBhID0gcmVjb3JkW2tleV07XG4gICAgaWYgKCFPYmplY3QuaGFzT3duKG90aGVyLCBrZXkpKSB7XG4gICAgICByZXN1bHRba2V5XSA9IGE7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgYiA9IG90aGVyW2tleV07XG4gICAgaWYgKGlzTm9uTnVsbE9iamVjdChhKSAmJiBpc05vbk51bGxPYmplY3QoYikgJiYgIXNlZW4uaGFzKGEpICYmICFzZWVuLmhhcyhiKSkge1xuICAgICAgc2Vlbi5hZGQoYSk7XG4gICAgICBzZWVuLmFkZChiKTtcbiAgICAgIHJlc3VsdFtrZXldID0gbWVyZ2VPYmplY3RzKGEsIGIsIHNlZW4sIG9wdGlvbnMpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIC8vIE92ZXJyaWRlIHZhbHVlXG4gICAgcmVzdWx0W2tleV0gPSBiO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5mdW5jdGlvbiBtZXJnZU9iamVjdHMobGVmdCwgcmlnaHQsIHNlZW4sIG9wdGlvbnMgPSB7XG4gIGFycmF5czogXCJtZXJnZVwiLFxuICBzZXRzOiBcIm1lcmdlXCIsXG4gIG1hcHM6IFwibWVyZ2VcIlxufSkge1xuICAvLyBSZWN1cnNpdmVseSBtZXJnZSBtZXJnZWFibGUgb2JqZWN0c1xuICBpZiAoaXNNZXJnZWFibGUobGVmdCkgJiYgaXNNZXJnZWFibGUocmlnaHQpKSB7XG4gICAgcmV0dXJuIGRlZXBNZXJnZUludGVybmFsKGxlZnQsIHJpZ2h0LCBzZWVuLCBvcHRpb25zKTtcbiAgfVxuICBpZiAoaXNJdGVyYWJsZShsZWZ0KSAmJiBpc0l0ZXJhYmxlKHJpZ2h0KSkge1xuICAgIC8vIEhhbmRsZSBhcnJheXNcbiAgICBpZiAoQXJyYXkuaXNBcnJheShsZWZ0KSAmJiBBcnJheS5pc0FycmF5KHJpZ2h0KSkge1xuICAgICAgaWYgKG9wdGlvbnMuYXJyYXlzID09PSBcIm1lcmdlXCIpIHtcbiAgICAgICAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByaWdodDtcbiAgICB9XG4gICAgLy8gSGFuZGxlIG1hcHNcbiAgICBpZiAobGVmdCBpbnN0YW5jZW9mIE1hcCAmJiByaWdodCBpbnN0YW5jZW9mIE1hcCkge1xuICAgICAgaWYgKG9wdGlvbnMubWFwcyA9PT0gXCJtZXJnZVwiKSB7XG4gICAgICAgIHJldHVybiBuZXcgTWFwKFtcbiAgICAgICAgICAuLi5sZWZ0LFxuICAgICAgICAgIC4uLnJpZ2h0XG4gICAgICAgIF0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJpZ2h0O1xuICAgIH1cbiAgICAvLyBIYW5kbGUgc2V0c1xuICAgIGlmIChsZWZ0IGluc3RhbmNlb2YgU2V0ICYmIHJpZ2h0IGluc3RhbmNlb2YgU2V0KSB7XG4gICAgICBpZiAob3B0aW9ucy5zZXRzID09PSBcIm1lcmdlXCIpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTZXQoW1xuICAgICAgICAgIC4uLmxlZnQsXG4gICAgICAgICAgLi4ucmlnaHRcbiAgICAgICAgXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmlnaHQ7XG4gICAgfVxuICB9XG4gIHJldHVybiByaWdodDtcbn1cbi8qKlxuICogVGVzdCB3aGV0aGVyIGEgdmFsdWUgaXMgbWVyZ2VhYmxlIG9yIG5vdFxuICogQnVpbHRpbnMgdGhhdCBsb29rIGxpa2Ugb2JqZWN0cywgbnVsbCBhbmQgdXNlciBkZWZpbmVkIGNsYXNzZXNcbiAqIGFyZSBub3QgY29uc2lkZXJlZCBtZXJnZWFibGUgKGl0IG1lYW5zIHRoYXQgcmVmZXJlbmNlIHdpbGwgYmUgY29waWVkKVxuICovIGZ1bmN0aW9uIGlzTWVyZ2VhYmxlKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpID09PSBPYmplY3QucHJvdG90eXBlO1xufVxuZnVuY3Rpb24gaXNJdGVyYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlW1N5bWJvbC5pdGVyYXRvcl0gPT09IFwiZnVuY3Rpb25cIjtcbn1cbmZ1bmN0aW9uIGlzTm9uTnVsbE9iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgIT09IG51bGwgJiYgdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiO1xufVxuZnVuY3Rpb24gZ2V0S2V5cyhyZWNvcmQpIHtcbiAgY29uc3QgcmVzdWx0ID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhyZWNvcmQpO1xuICBmaWx0ZXJJblBsYWNlKHJlc3VsdCwgKGtleSk9Pk9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChyZWNvcmQsIGtleSkpO1xuICByZXN1bHQucHVzaCguLi5PYmplY3Qua2V5cyhyZWNvcmQpKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRlZXBfbWVyZ2UuanMubWFwIiwidmFyIGFzc2VydENsYXNzQnJhbmQgPSByZXF1aXJlKFwiLi9hc3NlcnRDbGFzc0JyYW5kLmpzXCIpO1xuZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZUZpZWxkU2V0MihzLCBhLCByKSB7XG4gIHJldHVybiBzLnNldChhc3NlcnRDbGFzc0JyYW5kKHMsIGEpLCByKSwgcjtcbn1cbm1vZHVsZS5leHBvcnRzID0gX2NsYXNzUHJpdmF0ZUZpZWxkU2V0MiwgbW9kdWxlLmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWUsIG1vZHVsZS5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IG1vZHVsZS5leHBvcnRzOyIsIi8vIENvcHlyaWdodCAyMDE4LTIwMjUgdGhlIERlbm8gYXV0aG9ycy4gTUlUIGxpY2Vuc2UuXG4vLyBUaGlzIG1vZHVsZSBpcyBicm93c2VyIGNvbXBhdGlibGUuXG5pbXBvcnQgeyBkZWVwTWVyZ2UgfSBmcm9tIFwiQGpzci9zdGRfX2NvbGxlY3Rpb25zL2RlZXAtbWVyZ2VcIjtcbi8qKlxuICogQ29weSBvZiBgaW1wb3J0IHsgaXNMZWFwIH0gZnJvbSBcIkBzdGQvZGF0ZXRpbWVcIjtgIGJlY2F1c2UgaXQgY2Fubm90IGJlIGltcG90ZWQgYXMgbG9uZyBhcyBpdCBpcyB1bnN0YWJsZS5cbiAqLyBmdW5jdGlvbiBpc0xlYXAoeWVhck51bWJlcikge1xuICByZXR1cm4geWVhck51bWJlciAlIDQgPT09IDAgJiYgeWVhck51bWJlciAlIDEwMCAhPT0gMCB8fCB5ZWFyTnVtYmVyICUgNDAwID09PSAwO1xufVxuZXhwb3J0IGNsYXNzIFNjYW5uZXIge1xuICAjd2hpdGVzcGFjZSA9IC9bIFxcdF0vO1xuICAjcG9zaXRpb24gPSAwO1xuICAjc291cmNlO1xuICBjb25zdHJ1Y3Rvcihzb3VyY2Upe1xuICAgIHRoaXMuI3NvdXJjZSA9IHNvdXJjZTtcbiAgfVxuICBnZXQgcG9zaXRpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuI3Bvc2l0aW9uO1xuICB9XG4gIGdldCBzb3VyY2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuI3NvdXJjZTtcbiAgfVxuICAvKipcbiAgICogR2V0IGN1cnJlbnQgY2hhcmFjdGVyXG4gICAqIEBwYXJhbSBpbmRleCAtIHJlbGF0aXZlIGluZGV4IGZyb20gY3VycmVudCBwb3NpdGlvblxuICAgKi8gY2hhcihpbmRleCA9IDApIHtcbiAgICByZXR1cm4gdGhpcy4jc291cmNlW3RoaXMuI3Bvc2l0aW9uICsgaW5kZXhdID8/IFwiXCI7XG4gIH1cbiAgLyoqXG4gICAqIEdldCBzbGljZWQgc3RyaW5nXG4gICAqIEBwYXJhbSBzdGFydCAtIHN0YXJ0IHBvc2l0aW9uIHJlbGF0aXZlIGZyb20gY3VycmVudCBwb3NpdGlvblxuICAgKiBAcGFyYW0gZW5kIC0gZW5kIHBvc2l0aW9uIHJlbGF0aXZlIGZyb20gY3VycmVudCBwb3NpdGlvblxuICAgKi8gc2xpY2Uoc3RhcnQsIGVuZCkge1xuICAgIHJldHVybiB0aGlzLiNzb3VyY2Uuc2xpY2UodGhpcy4jcG9zaXRpb24gKyBzdGFydCwgdGhpcy4jcG9zaXRpb24gKyBlbmQpO1xuICB9XG4gIC8qKlxuICAgKiBNb3ZlIHBvc2l0aW9uIHRvIG5leHRcbiAgICovIG5leHQoY291bnQgPSAxKSB7XG4gICAgdGhpcy4jcG9zaXRpb24gKz0gY291bnQ7XG4gIH1cbiAgc2tpcFdoaXRlc3BhY2VzKCkge1xuICAgIHdoaWxlKHRoaXMuI3doaXRlc3BhY2UudGVzdCh0aGlzLmNoYXIoKSkgJiYgIXRoaXMuZW9mKCkpe1xuICAgICAgdGhpcy5uZXh0KCk7XG4gICAgfVxuICAgIC8vIEludmFsaWQgaWYgY3VycmVudCBjaGFyIGlzIG90aGVyIGtpbmRzIG9mIHdoaXRlc3BhY2VcbiAgICBpZiAoIXRoaXMuaXNDdXJyZW50Q2hhckVPTCgpICYmIC9cXHMvLnRlc3QodGhpcy5jaGFyKCkpKSB7XG4gICAgICBjb25zdCBlc2NhcGVkID0gXCJcXFxcdVwiICsgdGhpcy5jaGFyKCkuY2hhckNvZGVBdCgwKS50b1N0cmluZygxNik7XG4gICAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMuI3Bvc2l0aW9uO1xuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKGBDYW5ub3QgcGFyc2UgdGhlIFRPTUw6IEl0IGNvbnRhaW5zIGludmFsaWQgd2hpdGVzcGFjZSBhdCBwb3NpdGlvbiAnJHtwb3NpdGlvbn0nOiBcXGAke2VzY2FwZWR9XFxgYCk7XG4gICAgfVxuICB9XG4gIG5leHRVbnRpbENoYXIob3B0aW9ucyA9IHtcbiAgICBza2lwQ29tbWVudHM6IHRydWVcbiAgfSkge1xuICAgIHdoaWxlKCF0aGlzLmVvZigpKXtcbiAgICAgIGNvbnN0IGNoYXIgPSB0aGlzLmNoYXIoKTtcbiAgICAgIGlmICh0aGlzLiN3aGl0ZXNwYWNlLnRlc3QoY2hhcikgfHwgdGhpcy5pc0N1cnJlbnRDaGFyRU9MKCkpIHtcbiAgICAgICAgdGhpcy5uZXh0KCk7XG4gICAgICB9IGVsc2UgaWYgKG9wdGlvbnMuc2tpcENvbW1lbnRzICYmIHRoaXMuY2hhcigpID09PSBcIiNcIikge1xuICAgICAgICAvLyBlbnRlcmluZyBjb21tZW50XG4gICAgICAgIHdoaWxlKCF0aGlzLmlzQ3VycmVudENoYXJFT0woKSAmJiAhdGhpcy5lb2YoKSl7XG4gICAgICAgICAgdGhpcy5uZXh0KCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICAvKipcbiAgICogUG9zaXRpb24gcmVhY2hlZCBFT0Ygb3Igbm90XG4gICAqLyBlb2YoKSB7XG4gICAgcmV0dXJuIHRoaXMuI3Bvc2l0aW9uID49IHRoaXMuI3NvdXJjZS5sZW5ndGg7XG4gIH1cbiAgaXNDdXJyZW50Q2hhckVPTCgpIHtcbiAgICByZXR1cm4gdGhpcy5jaGFyKCkgPT09IFwiXFxuXCIgfHwgdGhpcy5zdGFydHNXaXRoKFwiXFxyXFxuXCIpO1xuICB9XG4gIHN0YXJ0c1dpdGgoc2VhcmNoU3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuI3NvdXJjZS5zdGFydHNXaXRoKHNlYXJjaFN0cmluZywgdGhpcy4jcG9zaXRpb24pO1xuICB9XG4gIG1hdGNoKHJlZ0V4cCkge1xuICAgIGlmICghcmVnRXhwLnN0aWNreSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZWdFeHAgJHtyZWdFeHB9IGRvZXMgbm90IGhhdmUgYSBzdGlja3kgJ3knIGZsYWdgKTtcbiAgICB9XG4gICAgcmVnRXhwLmxhc3RJbmRleCA9IHRoaXMuI3Bvc2l0aW9uO1xuICAgIHJldHVybiB0aGlzLiNzb3VyY2UubWF0Y2gocmVnRXhwKTtcbiAgfVxufVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFV0aWxpdGllc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIHN1Y2Nlc3MoYm9keSkge1xuICByZXR1cm4ge1xuICAgIG9rOiB0cnVlLFxuICAgIGJvZHlcbiAgfTtcbn1cbmZ1bmN0aW9uIGZhaWx1cmUoKSB7XG4gIHJldHVybiB7XG4gICAgb2s6IGZhbHNlXG4gIH07XG59XG4vKipcbiAqIENyZWF0ZXMgYSBuZXN0ZWQgb2JqZWN0IGZyb20gdGhlIGtleXMgYW5kIHZhbHVlcy5cbiAqXG4gKiBlLmcuIGB1bmZsYXQoW1wiYVwiLCBcImJcIiwgXCJjXCJdLCAxKWAgcmV0dXJucyBgeyBhOiB7IGI6IHsgYzogMSB9IH0gfWBcbiAqLyBleHBvcnQgZnVuY3Rpb24gdW5mbGF0KGtleXMsIHZhbHVlcyA9IHt9KSB7XG4gIHJldHVybiBrZXlzLnJlZHVjZVJpZ2h0KChhY2MsIGtleSk9Pih7XG4gICAgICBba2V5XTogYWNjXG4gICAgfSksIHZhbHVlcyk7XG59XG5mdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmIHZhbHVlICE9PSBudWxsO1xufVxuZnVuY3Rpb24gZ2V0VGFyZ2V0VmFsdWUodGFyZ2V0LCBrZXlzKSB7XG4gIGNvbnN0IGtleSA9IGtleXNbMF07XG4gIGlmICgha2V5KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IHBhcnNlIHRoZSBUT01MOiBrZXkgbGVuZ3RoIGlzIG5vdCBhIHBvc2l0aXZlIG51bWJlclwiKTtcbiAgfVxuICByZXR1cm4gdGFyZ2V0W2tleV07XG59XG5mdW5jdGlvbiBkZWVwQXNzaWduVGFibGUodGFyZ2V0LCB0YWJsZSkge1xuICBjb25zdCB7IGtleXMsIHR5cGUsIHZhbHVlIH0gPSB0YWJsZTtcbiAgY29uc3QgY3VycmVudFZhbHVlID0gZ2V0VGFyZ2V0VmFsdWUodGFyZ2V0LCBrZXlzKTtcbiAgaWYgKGN1cnJlbnRWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24odGFyZ2V0LCB1bmZsYXQoa2V5cywgdmFsdWUpKTtcbiAgfVxuICBpZiAoQXJyYXkuaXNBcnJheShjdXJyZW50VmFsdWUpKSB7XG4gICAgY29uc3QgbGFzdCA9IGN1cnJlbnRWYWx1ZS5hdCgtMSk7XG4gICAgZGVlcEFzc2lnbihsYXN0LCB7XG4gICAgICB0eXBlLFxuICAgICAga2V5czoga2V5cy5zbGljZSgxKSxcbiAgICAgIHZhbHVlXG4gICAgfSk7XG4gICAgcmV0dXJuIHRhcmdldDtcbiAgfVxuICBpZiAoaXNPYmplY3QoY3VycmVudFZhbHVlKSkge1xuICAgIGRlZXBBc3NpZ24oY3VycmVudFZhbHVlLCB7XG4gICAgICB0eXBlLFxuICAgICAga2V5czoga2V5cy5zbGljZSgxKSxcbiAgICAgIHZhbHVlXG4gICAgfSk7XG4gICAgcmV0dXJuIHRhcmdldDtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoXCJVbmV4cGVjdGVkIGFzc2lnblwiKTtcbn1cbmZ1bmN0aW9uIGRlZXBBc3NpZ25UYWJsZUFycmF5KHRhcmdldCwgdGFibGUpIHtcbiAgY29uc3QgeyB0eXBlLCBrZXlzLCB2YWx1ZSB9ID0gdGFibGU7XG4gIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IGdldFRhcmdldFZhbHVlKHRhcmdldCwga2V5cyk7XG4gIGlmIChjdXJyZW50VmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHRhcmdldCwgdW5mbGF0KGtleXMsIFtcbiAgICAgIHZhbHVlXG4gICAgXSkpO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KGN1cnJlbnRWYWx1ZSkpIHtcbiAgICBjdXJyZW50VmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRhcmdldDtcbiAgfVxuICBpZiAoaXNPYmplY3QoY3VycmVudFZhbHVlKSkge1xuICAgIGRlZXBBc3NpZ24oY3VycmVudFZhbHVlLCB7XG4gICAgICB0eXBlLFxuICAgICAga2V5czoga2V5cy5zbGljZSgxKSxcbiAgICAgIHZhbHVlXG4gICAgfSk7XG4gICAgcmV0dXJuIHRhcmdldDtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoXCJVbmV4cGVjdGVkIGFzc2lnblwiKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBkZWVwQXNzaWduKHRhcmdldCwgYm9keSkge1xuICBzd2l0Y2goYm9keS50eXBlKXtcbiAgICBjYXNlIFwiQmxvY2tcIjpcbiAgICAgIHJldHVybiBkZWVwTWVyZ2UodGFyZ2V0LCBib2R5LnZhbHVlKTtcbiAgICBjYXNlIFwiVGFibGVcIjpcbiAgICAgIHJldHVybiBkZWVwQXNzaWduVGFibGUodGFyZ2V0LCBib2R5KTtcbiAgICBjYXNlIFwiVGFibGVBcnJheVwiOlxuICAgICAgcmV0dXJuIGRlZXBBc3NpZ25UYWJsZUFycmF5KHRhcmdldCwgYm9keSk7XG4gIH1cbn1cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gUGFyc2VyIGNvbWJpbmF0b3JzIGFuZCBnZW5lcmF0b3JzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIGRlbm8tbGludC1pZ25vcmUgbm8tZXhwbGljaXQtYW55XG5mdW5jdGlvbiBvcihwYXJzZXJzKSB7XG4gIHJldHVybiAoc2Nhbm5lcik9PntcbiAgICBmb3IgKGNvbnN0IHBhcnNlIG9mIHBhcnNlcnMpe1xuICAgICAgY29uc3QgcmVzdWx0ID0gcGFyc2Uoc2Nhbm5lcik7XG4gICAgICBpZiAocmVzdWx0Lm9rKSByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICByZXR1cm4gZmFpbHVyZSgpO1xuICB9O1xufVxuLyoqIEpvaW4gdGhlIHBhcnNlIHJlc3VsdHMgb2YgdGhlIGdpdmVuIHBhcnNlciBpbnRvIGFuIGFycmF5LlxuICpcbiAqIElmIHRoZSBwYXJzZXIgZmFpbHMgYXQgdGhlIGZpcnN0IGF0dGVtcHQsIGl0IHdpbGwgcmV0dXJuIGFuIGVtcHR5IGFycmF5LlxuICovIGZ1bmN0aW9uIGpvaW4ocGFyc2VyLCBzZXBhcmF0b3IpIHtcbiAgY29uc3QgU2VwYXJhdG9yID0gY2hhcmFjdGVyKHNlcGFyYXRvcik7XG4gIHJldHVybiAoc2Nhbm5lcik9PntcbiAgICBjb25zdCBvdXQgPSBbXTtcbiAgICBjb25zdCBmaXJzdCA9IHBhcnNlcihzY2FubmVyKTtcbiAgICBpZiAoIWZpcnN0Lm9rKSByZXR1cm4gc3VjY2VzcyhvdXQpO1xuICAgIG91dC5wdXNoKGZpcnN0LmJvZHkpO1xuICAgIHdoaWxlKCFzY2FubmVyLmVvZigpKXtcbiAgICAgIGlmICghU2VwYXJhdG9yKHNjYW5uZXIpLm9rKSBicmVhaztcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHBhcnNlcihzY2FubmVyKTtcbiAgICAgIGlmICghcmVzdWx0Lm9rKSB7XG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihgSW52YWxpZCB0b2tlbiBhZnRlciBcIiR7c2VwYXJhdG9yfVwiYCk7XG4gICAgICB9XG4gICAgICBvdXQucHVzaChyZXN1bHQuYm9keSk7XG4gICAgfVxuICAgIHJldHVybiBzdWNjZXNzKG91dCk7XG4gIH07XG59XG4vKiogSm9pbiB0aGUgcGFyc2UgcmVzdWx0cyBvZiB0aGUgZ2l2ZW4gcGFyc2VyIGludG8gYW4gYXJyYXkuXG4gKlxuICogVGhpcyByZXF1aXJlcyB0aGUgcGFyc2VyIHRvIHN1Y2NlZWQgYXQgbGVhc3Qgb25jZS5cbiAqLyBmdW5jdGlvbiBqb2luMShwYXJzZXIsIHNlcGFyYXRvcikge1xuICBjb25zdCBTZXBhcmF0b3IgPSBjaGFyYWN0ZXIoc2VwYXJhdG9yKTtcbiAgcmV0dXJuIChzY2FubmVyKT0+e1xuICAgIGNvbnN0IGZpcnN0ID0gcGFyc2VyKHNjYW5uZXIpO1xuICAgIGlmICghZmlyc3Qub2spIHJldHVybiBmYWlsdXJlKCk7XG4gICAgY29uc3Qgb3V0ID0gW1xuICAgICAgZmlyc3QuYm9keVxuICAgIF07XG4gICAgd2hpbGUoIXNjYW5uZXIuZW9mKCkpe1xuICAgICAgaWYgKCFTZXBhcmF0b3Ioc2Nhbm5lcikub2spIGJyZWFrO1xuICAgICAgY29uc3QgcmVzdWx0ID0gcGFyc2VyKHNjYW5uZXIpO1xuICAgICAgaWYgKCFyZXN1bHQub2spIHtcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKGBJbnZhbGlkIHRva2VuIGFmdGVyIFwiJHtzZXBhcmF0b3J9XCJgKTtcbiAgICAgIH1cbiAgICAgIG91dC5wdXNoKHJlc3VsdC5ib2R5KTtcbiAgICB9XG4gICAgcmV0dXJuIHN1Y2Nlc3Mob3V0KTtcbiAgfTtcbn1cbmZ1bmN0aW9uIGt2KGtleVBhcnNlciwgc2VwYXJhdG9yLCB2YWx1ZVBhcnNlcikge1xuICBjb25zdCBTZXBhcmF0b3IgPSBjaGFyYWN0ZXIoc2VwYXJhdG9yKTtcbiAgcmV0dXJuIChzY2FubmVyKT0+e1xuICAgIGNvbnN0IHBvc2l0aW9uID0gc2Nhbm5lci5wb3NpdGlvbjtcbiAgICBjb25zdCBrZXkgPSBrZXlQYXJzZXIoc2Nhbm5lcik7XG4gICAgaWYgKCFrZXkub2spIHJldHVybiBmYWlsdXJlKCk7XG4gICAgY29uc3Qgc2VwID0gU2VwYXJhdG9yKHNjYW5uZXIpO1xuICAgIGlmICghc2VwLm9rKSB7XG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYGtleS92YWx1ZSBwYWlyIGRvZXNuJ3QgaGF2ZSBcIiR7c2VwYXJhdG9yfVwiYCk7XG4gICAgfVxuICAgIGNvbnN0IHZhbHVlID0gdmFsdWVQYXJzZXIoc2Nhbm5lcik7XG4gICAgaWYgKCF2YWx1ZS5vaykge1xuICAgICAgY29uc3QgbGluZUVuZEluZGV4ID0gc2Nhbm5lci5zb3VyY2UuaW5kZXhPZihcIlxcblwiLCBzY2FubmVyLnBvc2l0aW9uKTtcbiAgICAgIGNvbnN0IGVuZFBvc2l0aW9uID0gbGluZUVuZEluZGV4ID4gMCA/IGxpbmVFbmRJbmRleCA6IHNjYW5uZXIuc291cmNlLmxlbmd0aDtcbiAgICAgIGNvbnN0IGxpbmUgPSBzY2FubmVyLnNvdXJjZS5zbGljZShwb3NpdGlvbiwgZW5kUG9zaXRpb24pO1xuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKGBDYW5ub3QgcGFyc2UgdmFsdWUgb24gbGluZSAnJHtsaW5lfSdgKTtcbiAgICB9XG4gICAgcmV0dXJuIHN1Y2Nlc3ModW5mbGF0KGtleS5ib2R5LCB2YWx1ZS5ib2R5KSk7XG4gIH07XG59XG5mdW5jdGlvbiBtZXJnZShwYXJzZXIpIHtcbiAgcmV0dXJuIChzY2FubmVyKT0+e1xuICAgIGNvbnN0IHJlc3VsdCA9IHBhcnNlcihzY2FubmVyKTtcbiAgICBpZiAoIXJlc3VsdC5vaykgcmV0dXJuIGZhaWx1cmUoKTtcbiAgICBsZXQgYm9keSA9IHt9O1xuICAgIGZvciAoY29uc3QgcmVjb3JkIG9mIHJlc3VsdC5ib2R5KXtcbiAgICAgIGlmICh0eXBlb2YgcmVjb3JkID09PSBcIm9iamVjdFwiICYmIHJlY29yZCAhPT0gbnVsbCkge1xuICAgICAgICBib2R5ID0gZGVlcE1lcmdlKGJvZHksIHJlY29yZCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBzdWNjZXNzKGJvZHkpO1xuICB9O1xufVxuZnVuY3Rpb24gcmVwZWF0KHBhcnNlcikge1xuICByZXR1cm4gKHNjYW5uZXIpPT57XG4gICAgY29uc3QgYm9keSA9IFtdO1xuICAgIHdoaWxlKCFzY2FubmVyLmVvZigpKXtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHBhcnNlcihzY2FubmVyKTtcbiAgICAgIGlmICghcmVzdWx0Lm9rKSBicmVhaztcbiAgICAgIGJvZHkucHVzaChyZXN1bHQuYm9keSk7XG4gICAgICBzY2FubmVyLm5leHRVbnRpbENoYXIoKTtcbiAgICB9XG4gICAgaWYgKGJvZHkubGVuZ3RoID09PSAwKSByZXR1cm4gZmFpbHVyZSgpO1xuICAgIHJldHVybiBzdWNjZXNzKGJvZHkpO1xuICB9O1xufVxuZnVuY3Rpb24gc3Vycm91bmQobGVmdCwgcGFyc2VyLCByaWdodCkge1xuICBjb25zdCBMZWZ0ID0gY2hhcmFjdGVyKGxlZnQpO1xuICBjb25zdCBSaWdodCA9IGNoYXJhY3RlcihyaWdodCk7XG4gIHJldHVybiAoc2Nhbm5lcik9PntcbiAgICBpZiAoIUxlZnQoc2Nhbm5lcikub2spIHtcbiAgICAgIHJldHVybiBmYWlsdXJlKCk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3VsdCA9IHBhcnNlcihzY2FubmVyKTtcbiAgICBpZiAoIXJlc3VsdC5vaykge1xuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKGBJbnZhbGlkIHRva2VuIGFmdGVyIFwiJHtsZWZ0fVwiYCk7XG4gICAgfVxuICAgIGlmICghUmlnaHQoc2Nhbm5lcikub2spIHtcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihgTm90IGNsb3NlZCBieSBcIiR7cmlnaHR9XCIgYWZ0ZXIgc3RhcnRlZCB3aXRoIFwiJHtsZWZ0fVwiYCk7XG4gICAgfVxuICAgIHJldHVybiBzdWNjZXNzKHJlc3VsdC5ib2R5KTtcbiAgfTtcbn1cbmZ1bmN0aW9uIGNoYXJhY3RlcihzdHIpIHtcbiAgcmV0dXJuIChzY2FubmVyKT0+e1xuICAgIHNjYW5uZXIuc2tpcFdoaXRlc3BhY2VzKCk7XG4gICAgaWYgKCFzY2FubmVyLnN0YXJ0c1dpdGgoc3RyKSkgcmV0dXJuIGZhaWx1cmUoKTtcbiAgICBzY2FubmVyLm5leHQoc3RyLmxlbmd0aCk7XG4gICAgc2Nhbm5lci5za2lwV2hpdGVzcGFjZXMoKTtcbiAgICByZXR1cm4gc3VjY2Vzcyh1bmRlZmluZWQpO1xuICB9O1xufVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFBhcnNlciBjb21wb25lbnRzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuY29uc3QgQkFSRV9LRVlfUkVHRVhQID0gL1tBLVphLXowLTlfLV0rL3k7XG5leHBvcnQgZnVuY3Rpb24gYmFyZUtleShzY2FubmVyKSB7XG4gIHNjYW5uZXIuc2tpcFdoaXRlc3BhY2VzKCk7XG4gIGNvbnN0IGtleSA9IHNjYW5uZXIubWF0Y2goQkFSRV9LRVlfUkVHRVhQKT8uWzBdO1xuICBpZiAoIWtleSkgcmV0dXJuIGZhaWx1cmUoKTtcbiAgc2Nhbm5lci5uZXh0KGtleS5sZW5ndGgpO1xuICByZXR1cm4gc3VjY2VzcyhrZXkpO1xufVxuZnVuY3Rpb24gZXNjYXBlU2VxdWVuY2Uoc2Nhbm5lcikge1xuICBpZiAoc2Nhbm5lci5jaGFyKCkgIT09IFwiXFxcXFwiKSByZXR1cm4gZmFpbHVyZSgpO1xuICBzY2FubmVyLm5leHQoKTtcbiAgLy8gU2VlIGh0dHBzOi8vdG9tbC5pby9lbi92MS4wLjAtcmMuMyNzdHJpbmdcbiAgc3dpdGNoKHNjYW5uZXIuY2hhcigpKXtcbiAgICBjYXNlIFwiYlwiOlxuICAgICAgc2Nhbm5lci5uZXh0KCk7XG4gICAgICByZXR1cm4gc3VjY2VzcyhcIlxcYlwiKTtcbiAgICBjYXNlIFwidFwiOlxuICAgICAgc2Nhbm5lci5uZXh0KCk7XG4gICAgICByZXR1cm4gc3VjY2VzcyhcIlxcdFwiKTtcbiAgICBjYXNlIFwiblwiOlxuICAgICAgc2Nhbm5lci5uZXh0KCk7XG4gICAgICByZXR1cm4gc3VjY2VzcyhcIlxcblwiKTtcbiAgICBjYXNlIFwiZlwiOlxuICAgICAgc2Nhbm5lci5uZXh0KCk7XG4gICAgICByZXR1cm4gc3VjY2VzcyhcIlxcZlwiKTtcbiAgICBjYXNlIFwiclwiOlxuICAgICAgc2Nhbm5lci5uZXh0KCk7XG4gICAgICByZXR1cm4gc3VjY2VzcyhcIlxcclwiKTtcbiAgICBjYXNlIFwidVwiOlxuICAgIGNhc2UgXCJVXCI6XG4gICAgICB7XG4gICAgICAgIC8vIFVuaWNvZGUgY2hhcmFjdGVyXG4gICAgICAgIGNvbnN0IGNvZGVQb2ludExlbiA9IHNjYW5uZXIuY2hhcigpID09PSBcInVcIiA/IDQgOiA2O1xuICAgICAgICBjb25zdCBjb2RlUG9pbnQgPSBwYXJzZUludChcIjB4XCIgKyBzY2FubmVyLnNsaWNlKDEsIDEgKyBjb2RlUG9pbnRMZW4pLCAxNik7XG4gICAgICAgIGNvbnN0IHN0ciA9IFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVQb2ludCk7XG4gICAgICAgIHNjYW5uZXIubmV4dChjb2RlUG9pbnRMZW4gKyAxKTtcbiAgICAgICAgcmV0dXJuIHN1Y2Nlc3Moc3RyKTtcbiAgICAgIH1cbiAgICBjYXNlICdcIic6XG4gICAgICBzY2FubmVyLm5leHQoKTtcbiAgICAgIHJldHVybiBzdWNjZXNzKCdcIicpO1xuICAgIGNhc2UgXCJcXFxcXCI6XG4gICAgICBzY2FubmVyLm5leHQoKTtcbiAgICAgIHJldHVybiBzdWNjZXNzKFwiXFxcXFwiKTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKGBJbnZhbGlkIGVzY2FwZSBzZXF1ZW5jZTogXFxcXCR7c2Nhbm5lci5jaGFyKCl9YCk7XG4gIH1cbn1cbmV4cG9ydCBmdW5jdGlvbiBiYXNpY1N0cmluZyhzY2FubmVyKSB7XG4gIHNjYW5uZXIuc2tpcFdoaXRlc3BhY2VzKCk7XG4gIGlmIChzY2FubmVyLmNoYXIoKSAhPT0gJ1wiJykgcmV0dXJuIGZhaWx1cmUoKTtcbiAgc2Nhbm5lci5uZXh0KCk7XG4gIGNvbnN0IGFjYyA9IFtdO1xuICB3aGlsZShzY2FubmVyLmNoYXIoKSAhPT0gJ1wiJyAmJiAhc2Nhbm5lci5lb2YoKSl7XG4gICAgaWYgKHNjYW5uZXIuY2hhcigpID09PSBcIlxcblwiKSB7XG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJTaW5nbGUtbGluZSBzdHJpbmcgY2Fubm90IGNvbnRhaW4gRU9MXCIpO1xuICAgIH1cbiAgICBjb25zdCBlc2NhcGVkQ2hhciA9IGVzY2FwZVNlcXVlbmNlKHNjYW5uZXIpO1xuICAgIGlmIChlc2NhcGVkQ2hhci5vaykge1xuICAgICAgYWNjLnB1c2goZXNjYXBlZENoYXIuYm9keSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFjYy5wdXNoKHNjYW5uZXIuY2hhcigpKTtcbiAgICAgIHNjYW5uZXIubmV4dCgpO1xuICAgIH1cbiAgfVxuICBpZiAoc2Nhbm5lci5lb2YoKSkge1xuICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihgU2luZ2xlLWxpbmUgc3RyaW5nIGlzIG5vdCBjbG9zZWQ6XFxuJHthY2Muam9pbihcIlwiKX1gKTtcbiAgfVxuICBzY2FubmVyLm5leHQoKTsgLy8gc2tpcCBsYXN0ICdcIlwiXG4gIHJldHVybiBzdWNjZXNzKGFjYy5qb2luKFwiXCIpKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBsaXRlcmFsU3RyaW5nKHNjYW5uZXIpIHtcbiAgc2Nhbm5lci5za2lwV2hpdGVzcGFjZXMoKTtcbiAgaWYgKHNjYW5uZXIuY2hhcigpICE9PSBcIidcIikgcmV0dXJuIGZhaWx1cmUoKTtcbiAgc2Nhbm5lci5uZXh0KCk7XG4gIGNvbnN0IGFjYyA9IFtdO1xuICB3aGlsZShzY2FubmVyLmNoYXIoKSAhPT0gXCInXCIgJiYgIXNjYW5uZXIuZW9mKCkpe1xuICAgIGlmIChzY2FubmVyLmNoYXIoKSA9PT0gXCJcXG5cIikge1xuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiU2luZ2xlLWxpbmUgc3RyaW5nIGNhbm5vdCBjb250YWluIEVPTFwiKTtcbiAgICB9XG4gICAgYWNjLnB1c2goc2Nhbm5lci5jaGFyKCkpO1xuICAgIHNjYW5uZXIubmV4dCgpO1xuICB9XG4gIGlmIChzY2FubmVyLmVvZigpKSB7XG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKGBTaW5nbGUtbGluZSBzdHJpbmcgaXMgbm90IGNsb3NlZDpcXG4ke2FjYy5qb2luKFwiXCIpfWApO1xuICB9XG4gIHNjYW5uZXIubmV4dCgpOyAvLyBza2lwIGxhc3QgXCInXCJcbiAgcmV0dXJuIHN1Y2Nlc3MoYWNjLmpvaW4oXCJcIikpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIG11bHRpbGluZUJhc2ljU3RyaW5nKHNjYW5uZXIpIHtcbiAgc2Nhbm5lci5za2lwV2hpdGVzcGFjZXMoKTtcbiAgaWYgKCFzY2FubmVyLnN0YXJ0c1dpdGgoJ1wiXCJcIicpKSByZXR1cm4gZmFpbHVyZSgpO1xuICBzY2FubmVyLm5leHQoMyk7XG4gIGlmIChzY2FubmVyLmNoYXIoKSA9PT0gXCJcXG5cIikge1xuICAgIC8vIFRoZSBmaXJzdCBuZXdsaW5lIChMRikgaXMgdHJpbW1lZFxuICAgIHNjYW5uZXIubmV4dCgpO1xuICB9IGVsc2UgaWYgKHNjYW5uZXIuc3RhcnRzV2l0aChcIlxcclxcblwiKSkge1xuICAgIC8vIFRoZSBmaXJzdCBuZXdsaW5lIChDUkxGKSBpcyB0cmltbWVkXG4gICAgc2Nhbm5lci5uZXh0KDIpO1xuICB9XG4gIGNvbnN0IGFjYyA9IFtdO1xuICB3aGlsZSghc2Nhbm5lci5zdGFydHNXaXRoKCdcIlwiXCInKSAmJiAhc2Nhbm5lci5lb2YoKSl7XG4gICAgLy8gbGluZSBlbmRpbmcgYmFja3NsYXNoXG4gICAgaWYgKHNjYW5uZXIuc3RhcnRzV2l0aChcIlxcXFxcXG5cIikpIHtcbiAgICAgIHNjYW5uZXIubmV4dCgpO1xuICAgICAgc2Nhbm5lci5uZXh0VW50aWxDaGFyKHtcbiAgICAgICAgc2tpcENvbW1lbnRzOiBmYWxzZVxuICAgICAgfSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9IGVsc2UgaWYgKHNjYW5uZXIuc3RhcnRzV2l0aChcIlxcXFxcXHJcXG5cIikpIHtcbiAgICAgIHNjYW5uZXIubmV4dCgpO1xuICAgICAgc2Nhbm5lci5uZXh0VW50aWxDaGFyKHtcbiAgICAgICAgc2tpcENvbW1lbnRzOiBmYWxzZVxuICAgICAgfSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgZXNjYXBlZENoYXIgPSBlc2NhcGVTZXF1ZW5jZShzY2FubmVyKTtcbiAgICBpZiAoZXNjYXBlZENoYXIub2spIHtcbiAgICAgIGFjYy5wdXNoKGVzY2FwZWRDaGFyLmJvZHkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhY2MucHVzaChzY2FubmVyLmNoYXIoKSk7XG4gICAgICBzY2FubmVyLm5leHQoKTtcbiAgICB9XG4gIH1cbiAgaWYgKHNjYW5uZXIuZW9mKCkpIHtcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYE11bHRpLWxpbmUgc3RyaW5nIGlzIG5vdCBjbG9zZWQ6XFxuJHthY2Muam9pbihcIlwiKX1gKTtcbiAgfVxuICAvLyBpZiBlbmRzIHdpdGggNCBgXCJgLCBwdXNoIHRoZSBmaXN0IGBcImAgdG8gc3RyaW5nXG4gIGlmIChzY2FubmVyLmNoYXIoMykgPT09ICdcIicpIHtcbiAgICBhY2MucHVzaCgnXCInKTtcbiAgICBzY2FubmVyLm5leHQoKTtcbiAgfVxuICBzY2FubmVyLm5leHQoMyk7IC8vIHNraXAgbGFzdCAnXCJcIlwiXCJcbiAgcmV0dXJuIHN1Y2Nlc3MoYWNjLmpvaW4oXCJcIikpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIG11bHRpbGluZUxpdGVyYWxTdHJpbmcoc2Nhbm5lcikge1xuICBzY2FubmVyLnNraXBXaGl0ZXNwYWNlcygpO1xuICBpZiAoIXNjYW5uZXIuc3RhcnRzV2l0aChcIicnJ1wiKSkgcmV0dXJuIGZhaWx1cmUoKTtcbiAgc2Nhbm5lci5uZXh0KDMpO1xuICBpZiAoc2Nhbm5lci5jaGFyKCkgPT09IFwiXFxuXCIpIHtcbiAgICAvLyBUaGUgZmlyc3QgbmV3bGluZSAoTEYpIGlzIHRyaW1tZWRcbiAgICBzY2FubmVyLm5leHQoKTtcbiAgfSBlbHNlIGlmIChzY2FubmVyLnN0YXJ0c1dpdGgoXCJcXHJcXG5cIikpIHtcbiAgICAvLyBUaGUgZmlyc3QgbmV3bGluZSAoQ1JMRikgaXMgdHJpbW1lZFxuICAgIHNjYW5uZXIubmV4dCgyKTtcbiAgfVxuICBjb25zdCBhY2MgPSBbXTtcbiAgd2hpbGUoIXNjYW5uZXIuc3RhcnRzV2l0aChcIicnJ1wiKSAmJiAhc2Nhbm5lci5lb2YoKSl7XG4gICAgYWNjLnB1c2goc2Nhbm5lci5jaGFyKCkpO1xuICAgIHNjYW5uZXIubmV4dCgpO1xuICB9XG4gIGlmIChzY2FubmVyLmVvZigpKSB7XG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKGBNdWx0aS1saW5lIHN0cmluZyBpcyBub3QgY2xvc2VkOlxcbiR7YWNjLmpvaW4oXCJcIil9YCk7XG4gIH1cbiAgLy8gaWYgZW5kcyB3aXRoIDQgYCdgLCBwdXNoIHRoZSBmaXN0IGAnYCB0byBzdHJpbmdcbiAgaWYgKHNjYW5uZXIuY2hhcigzKSA9PT0gXCInXCIpIHtcbiAgICBhY2MucHVzaChcIidcIik7XG4gICAgc2Nhbm5lci5uZXh0KCk7XG4gIH1cbiAgc2Nhbm5lci5uZXh0KDMpOyAvLyBza2lwIGxhc3QgXCInJydcIlxuICByZXR1cm4gc3VjY2VzcyhhY2Muam9pbihcIlwiKSk7XG59XG5jb25zdCBCT09MRUFOX1JFR0VYUCA9IC8oPzp0cnVlfGZhbHNlKVxcYi95O1xuZXhwb3J0IGZ1bmN0aW9uIGJvb2xlYW4oc2Nhbm5lcikge1xuICBzY2FubmVyLnNraXBXaGl0ZXNwYWNlcygpO1xuICBjb25zdCBtYXRjaCA9IHNjYW5uZXIubWF0Y2goQk9PTEVBTl9SRUdFWFApO1xuICBpZiAoIW1hdGNoKSByZXR1cm4gZmFpbHVyZSgpO1xuICBjb25zdCBzdHJpbmcgPSBtYXRjaFswXTtcbiAgc2Nhbm5lci5uZXh0KHN0cmluZy5sZW5ndGgpO1xuICBjb25zdCB2YWx1ZSA9IHN0cmluZyA9PT0gXCJ0cnVlXCI7XG4gIHJldHVybiBzdWNjZXNzKHZhbHVlKTtcbn1cbmNvbnN0IElORklOSVRZX01BUCA9IG5ldyBNYXAoW1xuICBbXG4gICAgXCJpbmZcIixcbiAgICBJbmZpbml0eVxuICBdLFxuICBbXG4gICAgXCIraW5mXCIsXG4gICAgSW5maW5pdHlcbiAgXSxcbiAgW1xuICAgIFwiLWluZlwiLFxuICAgIC1JbmZpbml0eVxuICBdXG5dKTtcbmNvbnN0IElORklOSVRZX1JFR0VYUCA9IC9bKy1dP2luZlxcYi95O1xuZXhwb3J0IGZ1bmN0aW9uIGluZmluaXR5KHNjYW5uZXIpIHtcbiAgc2Nhbm5lci5za2lwV2hpdGVzcGFjZXMoKTtcbiAgY29uc3QgbWF0Y2ggPSBzY2FubmVyLm1hdGNoKElORklOSVRZX1JFR0VYUCk7XG4gIGlmICghbWF0Y2gpIHJldHVybiBmYWlsdXJlKCk7XG4gIGNvbnN0IHN0cmluZyA9IG1hdGNoWzBdO1xuICBzY2FubmVyLm5leHQoc3RyaW5nLmxlbmd0aCk7XG4gIGNvbnN0IHZhbHVlID0gSU5GSU5JVFlfTUFQLmdldChzdHJpbmcpO1xuICByZXR1cm4gc3VjY2Vzcyh2YWx1ZSk7XG59XG5jb25zdCBOQU5fUkVHRVhQID0gL1srLV0/bmFuXFxiL3k7XG5leHBvcnQgZnVuY3Rpb24gbmFuKHNjYW5uZXIpIHtcbiAgc2Nhbm5lci5za2lwV2hpdGVzcGFjZXMoKTtcbiAgY29uc3QgbWF0Y2ggPSBzY2FubmVyLm1hdGNoKE5BTl9SRUdFWFApO1xuICBpZiAoIW1hdGNoKSByZXR1cm4gZmFpbHVyZSgpO1xuICBjb25zdCBzdHJpbmcgPSBtYXRjaFswXTtcbiAgc2Nhbm5lci5uZXh0KHN0cmluZy5sZW5ndGgpO1xuICBjb25zdCB2YWx1ZSA9IE5hTjtcbiAgcmV0dXJuIHN1Y2Nlc3ModmFsdWUpO1xufVxuZXhwb3J0IGNvbnN0IGRvdHRlZEtleSA9IGpvaW4xKG9yKFtcbiAgYmFyZUtleSxcbiAgYmFzaWNTdHJpbmcsXG4gIGxpdGVyYWxTdHJpbmdcbl0pLCBcIi5cIik7XG5jb25zdCBCSU5BUllfUkVHRVhQID0gLzBiWzAxXSsoPzpfWzAxXSspKlxcYi95O1xuZXhwb3J0IGZ1bmN0aW9uIGJpbmFyeShzY2FubmVyKSB7XG4gIHNjYW5uZXIuc2tpcFdoaXRlc3BhY2VzKCk7XG4gIGNvbnN0IG1hdGNoID0gc2Nhbm5lci5tYXRjaChCSU5BUllfUkVHRVhQKT8uWzBdO1xuICBpZiAoIW1hdGNoKSByZXR1cm4gZmFpbHVyZSgpO1xuICBzY2FubmVyLm5leHQobWF0Y2gubGVuZ3RoKTtcbiAgY29uc3QgdmFsdWUgPSBtYXRjaC5zbGljZSgyKS5yZXBsYWNlQWxsKFwiX1wiLCBcIlwiKTtcbiAgY29uc3QgbnVtYmVyID0gcGFyc2VJbnQodmFsdWUsIDIpO1xuICByZXR1cm4gaXNOYU4obnVtYmVyKSA/IGZhaWx1cmUoKSA6IHN1Y2Nlc3MobnVtYmVyKTtcbn1cbmNvbnN0IE9DVEFMX1JFR0VYUCA9IC8wb1swLTddKyg/Ol9bMC03XSspKlxcYi95O1xuZXhwb3J0IGZ1bmN0aW9uIG9jdGFsKHNjYW5uZXIpIHtcbiAgc2Nhbm5lci5za2lwV2hpdGVzcGFjZXMoKTtcbiAgY29uc3QgbWF0Y2ggPSBzY2FubmVyLm1hdGNoKE9DVEFMX1JFR0VYUCk/LlswXTtcbiAgaWYgKCFtYXRjaCkgcmV0dXJuIGZhaWx1cmUoKTtcbiAgc2Nhbm5lci5uZXh0KG1hdGNoLmxlbmd0aCk7XG4gIGNvbnN0IHZhbHVlID0gbWF0Y2guc2xpY2UoMikucmVwbGFjZUFsbChcIl9cIiwgXCJcIik7XG4gIGNvbnN0IG51bWJlciA9IHBhcnNlSW50KHZhbHVlLCA4KTtcbiAgcmV0dXJuIGlzTmFOKG51bWJlcikgPyBmYWlsdXJlKCkgOiBzdWNjZXNzKG51bWJlcik7XG59XG5jb25zdCBIRVhfUkVHRVhQID0gLzB4WzAtOWEtZl0rKD86X1swLTlhLWZdKykqXFxiL3lpO1xuZXhwb3J0IGZ1bmN0aW9uIGhleChzY2FubmVyKSB7XG4gIHNjYW5uZXIuc2tpcFdoaXRlc3BhY2VzKCk7XG4gIGNvbnN0IG1hdGNoID0gc2Nhbm5lci5tYXRjaChIRVhfUkVHRVhQKT8uWzBdO1xuICBpZiAoIW1hdGNoKSByZXR1cm4gZmFpbHVyZSgpO1xuICBzY2FubmVyLm5leHQobWF0Y2gubGVuZ3RoKTtcbiAgY29uc3QgdmFsdWUgPSBtYXRjaC5zbGljZSgyKS5yZXBsYWNlQWxsKFwiX1wiLCBcIlwiKTtcbiAgY29uc3QgbnVtYmVyID0gcGFyc2VJbnQodmFsdWUsIDE2KTtcbiAgcmV0dXJuIGlzTmFOKG51bWJlcikgPyBmYWlsdXJlKCkgOiBzdWNjZXNzKG51bWJlcik7XG59XG5jb25zdCBJTlRFR0VSX1JFR0VYUCA9IC9bKy1dPyg/OjB8WzEtOV1bMC05XSooPzpfWzAtOV0rKSopXFxiL3k7XG5leHBvcnQgZnVuY3Rpb24gaW50ZWdlcihzY2FubmVyKSB7XG4gIHNjYW5uZXIuc2tpcFdoaXRlc3BhY2VzKCk7XG4gIGNvbnN0IG1hdGNoID0gc2Nhbm5lci5tYXRjaChJTlRFR0VSX1JFR0VYUCk/LlswXTtcbiAgaWYgKCFtYXRjaCkgcmV0dXJuIGZhaWx1cmUoKTtcbiAgc2Nhbm5lci5uZXh0KG1hdGNoLmxlbmd0aCk7XG4gIGNvbnN0IHZhbHVlID0gbWF0Y2gucmVwbGFjZUFsbChcIl9cIiwgXCJcIik7XG4gIGNvbnN0IGludCA9IHBhcnNlSW50KHZhbHVlLCAxMCk7XG4gIHJldHVybiBzdWNjZXNzKGludCk7XG59XG5jb25zdCBGTE9BVF9SRUdFWFAgPSAvWystXT8oPzowfFsxLTldWzAtOV0qKD86X1swLTldKykqKSg/OlxcLlswLTldKyg/Ol9bMC05XSspKik/KD86ZVsrLV0/WzAtOV0rKD86X1swLTldKykqKT9cXGIveWk7XG5leHBvcnQgZnVuY3Rpb24gZmxvYXQoc2Nhbm5lcikge1xuICBzY2FubmVyLnNraXBXaGl0ZXNwYWNlcygpO1xuICBjb25zdCBtYXRjaCA9IHNjYW5uZXIubWF0Y2goRkxPQVRfUkVHRVhQKT8uWzBdO1xuICBpZiAoIW1hdGNoKSByZXR1cm4gZmFpbHVyZSgpO1xuICBzY2FubmVyLm5leHQobWF0Y2gubGVuZ3RoKTtcbiAgY29uc3QgdmFsdWUgPSBtYXRjaC5yZXBsYWNlQWxsKFwiX1wiLCBcIlwiKTtcbiAgY29uc3QgZmxvYXQgPSBwYXJzZUZsb2F0KHZhbHVlKTtcbiAgaWYgKGlzTmFOKGZsb2F0KSkgcmV0dXJuIGZhaWx1cmUoKTtcbiAgcmV0dXJuIHN1Y2Nlc3MoZmxvYXQpO1xufVxuY29uc3QgREFURV9USU1FX1JFR0VYUCA9IC8oPzx5ZWFyPlxcZHs0fSktKD88bW9udGg+XFxkezJ9KS0oPzxkYXk+XFxkezJ9KSg/OlsgMC05VFouOistXSspP1xcYi95O1xuZXhwb3J0IGZ1bmN0aW9uIGRhdGVUaW1lKHNjYW5uZXIpIHtcbiAgc2Nhbm5lci5za2lwV2hpdGVzcGFjZXMoKTtcbiAgY29uc3QgbWF0Y2ggPSBzY2FubmVyLm1hdGNoKERBVEVfVElNRV9SRUdFWFApO1xuICBpZiAoIW1hdGNoKSByZXR1cm4gZmFpbHVyZSgpO1xuICBjb25zdCBzdHJpbmcgPSBtYXRjaFswXTtcbiAgc2Nhbm5lci5uZXh0KHN0cmluZy5sZW5ndGgpO1xuICBjb25zdCBncm91cHMgPSBtYXRjaC5ncm91cHM7XG4gIC8vIHNwZWNpYWwgY2FzZSBpZiBtb250aCBpcyBGZWJydWFyeVxuICBpZiAoZ3JvdXBzLm1vbnRoID09IFwiMDJcIikge1xuICAgIGNvbnN0IGRheXMgPSBwYXJzZUludChncm91cHMuZGF5KTtcbiAgICBpZiAoZGF5cyA+IDI5KSB7XG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYEludmFsaWQgZGF0ZSBzdHJpbmcgXCIke21hdGNofVwiYCk7XG4gICAgfVxuICAgIGNvbnN0IHllYXIgPSBwYXJzZUludChncm91cHMueWVhcik7XG4gICAgaWYgKGRheXMgPiAyOCAmJiAhaXNMZWFwKHllYXIpKSB7XG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYEludmFsaWQgZGF0ZSBzdHJpbmcgXCIke21hdGNofVwiYCk7XG4gICAgfVxuICB9XG4gIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZShzdHJpbmcudHJpbSgpKTtcbiAgLy8gaW52YWxpZCBkYXRlXG4gIGlmIChpc05hTihkYXRlLmdldFRpbWUoKSkpIHtcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYEludmFsaWQgZGF0ZSBzdHJpbmcgXCIke21hdGNofVwiYCk7XG4gIH1cbiAgcmV0dXJuIHN1Y2Nlc3MoZGF0ZSk7XG59XG5jb25zdCBMT0NBTF9USU1FX1JFR0VYUCA9IC8oXFxkezJ9KTooXFxkezJ9KTooXFxkezJ9KSg/OlxcLlswLTldKyk/XFxiL3k7XG5leHBvcnQgZnVuY3Rpb24gbG9jYWxUaW1lKHNjYW5uZXIpIHtcbiAgc2Nhbm5lci5za2lwV2hpdGVzcGFjZXMoKTtcbiAgY29uc3QgbWF0Y2ggPSBzY2FubmVyLm1hdGNoKExPQ0FMX1RJTUVfUkVHRVhQKT8uWzBdO1xuICBpZiAoIW1hdGNoKSByZXR1cm4gZmFpbHVyZSgpO1xuICBzY2FubmVyLm5leHQobWF0Y2gubGVuZ3RoKTtcbiAgcmV0dXJuIHN1Y2Nlc3MobWF0Y2gpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGFycmF5VmFsdWUoc2Nhbm5lcikge1xuICBzY2FubmVyLnNraXBXaGl0ZXNwYWNlcygpO1xuICBpZiAoc2Nhbm5lci5jaGFyKCkgIT09IFwiW1wiKSByZXR1cm4gZmFpbHVyZSgpO1xuICBzY2FubmVyLm5leHQoKTtcbiAgY29uc3QgYXJyYXkgPSBbXTtcbiAgd2hpbGUoIXNjYW5uZXIuZW9mKCkpe1xuICAgIHNjYW5uZXIubmV4dFVudGlsQ2hhcigpO1xuICAgIGNvbnN0IHJlc3VsdCA9IHZhbHVlKHNjYW5uZXIpO1xuICAgIGlmICghcmVzdWx0Lm9rKSBicmVhaztcbiAgICBhcnJheS5wdXNoKHJlc3VsdC5ib2R5KTtcbiAgICBzY2FubmVyLnNraXBXaGl0ZXNwYWNlcygpO1xuICAgIC8vIG1heSBoYXZlIGEgbmV4dCBpdGVtLCBidXQgdHJhaWxpbmcgY29tbWEgaXMgYWxsb3dlZCBhdCBhcnJheVxuICAgIGlmIChzY2FubmVyLmNoYXIoKSAhPT0gXCIsXCIpIGJyZWFrO1xuICAgIHNjYW5uZXIubmV4dCgpO1xuICB9XG4gIHNjYW5uZXIubmV4dFVudGlsQ2hhcigpO1xuICBpZiAoc2Nhbm5lci5jaGFyKCkgIT09IFwiXVwiKSB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJBcnJheSBpcyBub3QgY2xvc2VkXCIpO1xuICBzY2FubmVyLm5leHQoKTtcbiAgcmV0dXJuIHN1Y2Nlc3MoYXJyYXkpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGlubGluZVRhYmxlKHNjYW5uZXIpIHtcbiAgc2Nhbm5lci5uZXh0VW50aWxDaGFyKCk7XG4gIGlmIChzY2FubmVyLmNoYXIoMSkgPT09IFwifVwiKSB7XG4gICAgc2Nhbm5lci5uZXh0KDIpO1xuICAgIHJldHVybiBzdWNjZXNzKHt9KTtcbiAgfVxuICBjb25zdCBwYWlycyA9IHN1cnJvdW5kKFwie1wiLCBqb2luKHBhaXIsIFwiLFwiKSwgXCJ9XCIpKHNjYW5uZXIpO1xuICBpZiAoIXBhaXJzLm9rKSByZXR1cm4gZmFpbHVyZSgpO1xuICBsZXQgdGFibGUgPSB7fTtcbiAgZm9yIChjb25zdCBwYWlyIG9mIHBhaXJzLmJvZHkpe1xuICAgIHRhYmxlID0gZGVlcE1lcmdlKHRhYmxlLCBwYWlyKTtcbiAgfVxuICByZXR1cm4gc3VjY2Vzcyh0YWJsZSk7XG59XG5leHBvcnQgY29uc3QgdmFsdWUgPSBvcihbXG4gIG11bHRpbGluZUJhc2ljU3RyaW5nLFxuICBtdWx0aWxpbmVMaXRlcmFsU3RyaW5nLFxuICBiYXNpY1N0cmluZyxcbiAgbGl0ZXJhbFN0cmluZyxcbiAgYm9vbGVhbixcbiAgaW5maW5pdHksXG4gIG5hbixcbiAgZGF0ZVRpbWUsXG4gIGxvY2FsVGltZSxcbiAgYmluYXJ5LFxuICBvY3RhbCxcbiAgaGV4LFxuICBmbG9hdCxcbiAgaW50ZWdlcixcbiAgYXJyYXlWYWx1ZSxcbiAgaW5saW5lVGFibGVcbl0pO1xuZXhwb3J0IGNvbnN0IHBhaXIgPSBrdihkb3R0ZWRLZXksIFwiPVwiLCB2YWx1ZSk7XG5leHBvcnQgZnVuY3Rpb24gYmxvY2soc2Nhbm5lcikge1xuICBzY2FubmVyLm5leHRVbnRpbENoYXIoKTtcbiAgY29uc3QgcmVzdWx0ID0gbWVyZ2UocmVwZWF0KHBhaXIpKShzY2FubmVyKTtcbiAgaWYgKHJlc3VsdC5vaykgcmV0dXJuIHN1Y2Nlc3Moe1xuICAgIHR5cGU6IFwiQmxvY2tcIixcbiAgICB2YWx1ZTogcmVzdWx0LmJvZHlcbiAgfSk7XG4gIHJldHVybiBmYWlsdXJlKCk7XG59XG5leHBvcnQgY29uc3QgdGFibGVIZWFkZXIgPSBzdXJyb3VuZChcIltcIiwgZG90dGVkS2V5LCBcIl1cIik7XG5leHBvcnQgZnVuY3Rpb24gdGFibGUoc2Nhbm5lcikge1xuICBzY2FubmVyLm5leHRVbnRpbENoYXIoKTtcbiAgY29uc3QgaGVhZGVyID0gdGFibGVIZWFkZXIoc2Nhbm5lcik7XG4gIGlmICghaGVhZGVyLm9rKSByZXR1cm4gZmFpbHVyZSgpO1xuICBzY2FubmVyLm5leHRVbnRpbENoYXIoKTtcbiAgY29uc3QgYiA9IGJsb2NrKHNjYW5uZXIpO1xuICByZXR1cm4gc3VjY2Vzcyh7XG4gICAgdHlwZTogXCJUYWJsZVwiLFxuICAgIGtleXM6IGhlYWRlci5ib2R5LFxuICAgIHZhbHVlOiBiLm9rID8gYi5ib2R5LnZhbHVlIDoge31cbiAgfSk7XG59XG5leHBvcnQgY29uc3QgdGFibGVBcnJheUhlYWRlciA9IHN1cnJvdW5kKFwiW1tcIiwgZG90dGVkS2V5LCBcIl1dXCIpO1xuZXhwb3J0IGZ1bmN0aW9uIHRhYmxlQXJyYXkoc2Nhbm5lcikge1xuICBzY2FubmVyLm5leHRVbnRpbENoYXIoKTtcbiAgY29uc3QgaGVhZGVyID0gdGFibGVBcnJheUhlYWRlcihzY2FubmVyKTtcbiAgaWYgKCFoZWFkZXIub2spIHJldHVybiBmYWlsdXJlKCk7XG4gIHNjYW5uZXIubmV4dFVudGlsQ2hhcigpO1xuICBjb25zdCBiID0gYmxvY2soc2Nhbm5lcik7XG4gIHJldHVybiBzdWNjZXNzKHtcbiAgICB0eXBlOiBcIlRhYmxlQXJyYXlcIixcbiAgICBrZXlzOiBoZWFkZXIuYm9keSxcbiAgICB2YWx1ZTogYi5vayA/IGIuYm9keS52YWx1ZSA6IHt9XG4gIH0pO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHRvbWwoc2Nhbm5lcikge1xuICBjb25zdCBibG9ja3MgPSByZXBlYXQob3IoW1xuICAgIGJsb2NrLFxuICAgIHRhYmxlQXJyYXksXG4gICAgdGFibGVcbiAgXSkpKHNjYW5uZXIpO1xuICBpZiAoIWJsb2Nrcy5vaykgcmV0dXJuIHN1Y2Nlc3Moe30pO1xuICBjb25zdCBib2R5ID0gYmxvY2tzLmJvZHkucmVkdWNlKGRlZXBBc3NpZ24sIHt9KTtcbiAgcmV0dXJuIHN1Y2Nlc3MoYm9keSk7XG59XG5mdW5jdGlvbiBjcmVhdGVQYXJzZUVycm9yTWVzc2FnZShzY2FubmVyLCBtZXNzYWdlKSB7XG4gIGNvbnN0IHN0cmluZyA9IHNjYW5uZXIuc291cmNlLnNsaWNlKDAsIHNjYW5uZXIucG9zaXRpb24pO1xuICBjb25zdCBsaW5lcyA9IHN0cmluZy5zcGxpdChcIlxcblwiKTtcbiAgY29uc3Qgcm93ID0gbGluZXMubGVuZ3RoO1xuICBjb25zdCBjb2x1bW4gPSBsaW5lcy5hdCgtMSk/Lmxlbmd0aCA/PyAwO1xuICByZXR1cm4gYFBhcnNlIGVycm9yIG9uIGxpbmUgJHtyb3d9LCBjb2x1bW4gJHtjb2x1bW59OiAke21lc3NhZ2V9YDtcbn1cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZXJGYWN0b3J5KHBhcnNlcikge1xuICByZXR1cm4gKHRvbWxTdHJpbmcpPT57XG4gICAgY29uc3Qgc2Nhbm5lciA9IG5ldyBTY2FubmVyKHRvbWxTdHJpbmcpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBwYXJzZXIoc2Nhbm5lcik7XG4gICAgICBpZiAocmVzdWx0Lm9rICYmIHNjYW5uZXIuZW9mKCkpIHJldHVybiByZXN1bHQuYm9keTtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgVW5leHBlY3RlZCBjaGFyYWN0ZXI6IFwiJHtzY2FubmVyLmNoYXIoKX1cImA7XG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoY3JlYXRlUGFyc2VFcnJvck1lc3NhZ2Uoc2Nhbm5lciwgbWVzc2FnZSkpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoY3JlYXRlUGFyc2VFcnJvck1lc3NhZ2Uoc2Nhbm5lciwgZXJyb3IubWVzc2FnZSkpO1xuICAgICAgfVxuICAgICAgY29uc3QgbWVzc2FnZSA9IFwiSW52YWxpZCBlcnJvciB0eXBlIGNhdWdodFwiO1xuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKGNyZWF0ZVBhcnNlRXJyb3JNZXNzYWdlKHNjYW5uZXIsIG1lc3NhZ2UpKTtcbiAgICB9XG4gIH07XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1fcGFyc2VyLmpzLm1hcCIsIi8vIENvcHlyaWdodCAyMDE4LTIwMjUgdGhlIERlbm8gYXV0aG9ycy4gTUlUIGxpY2Vuc2UuXG4vLyBUaGlzIG1vZHVsZSBpcyBicm93c2VyIGNvbXBhdGlibGUuXG5pbXBvcnQgeyBwYXJzZXJGYWN0b3J5LCB0b21sIH0gZnJvbSBcIi4vX3BhcnNlci5qc1wiO1xuLyoqXG4gKiBQYXJzZXMgYSB7QGxpbmsgaHR0cHM6Ly90b21sLmlvIHwgVE9NTH0gc3RyaW5nIGludG8gYW4gb2JqZWN0LlxuICpcbiAqIEBleGFtcGxlIFVzYWdlXG4gKiBgYGB0c1xuICogaW1wb3J0IHsgcGFyc2UgfSBmcm9tIFwiQHN0ZC90b21sL3BhcnNlXCI7XG4gKiBpbXBvcnQgeyBhc3NlcnRFcXVhbHMgfSBmcm9tIFwiQHN0ZC9hc3NlcnRcIjtcbiAqXG4gKiBjb25zdCB0b21sU3RyaW5nID0gYHRpdGxlID0gXCJUT01MIEV4YW1wbGVcIlxuICogW293bmVyXVxuICogbmFtZSA9IFwiQWxpY2VcIlxuICogYmlvID0gXCJBbGljZSBpcyBhIHByb2dyYW1tZXIuXCJgO1xuICpcbiAqIGNvbnN0IG9iaiA9IHBhcnNlKHRvbWxTdHJpbmcpO1xuICogYXNzZXJ0RXF1YWxzKG9iaiwgeyB0aXRsZTogXCJUT01MIEV4YW1wbGVcIiwgb3duZXI6IHsgbmFtZTogXCJBbGljZVwiLCBiaW86IFwiQWxpY2UgaXMgYSBwcm9ncmFtbWVyLlwiIH0gfSk7XG4gKiBgYGBcbiAqIEBwYXJhbSB0b21sU3RyaW5nIFRPTUwgc3RyaW5nIHRvIGJlIHBhcnNlZC5cbiAqIEByZXR1cm5zIFRoZSBwYXJzZWQgSlMgb2JqZWN0LlxuICovIGV4cG9ydCBmdW5jdGlvbiBwYXJzZSh0b21sU3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZXJGYWN0b3J5KHRvbWwpKHRvbWxTdHJpbmcpO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cGFyc2UuanMubWFwIiwiLy8gVGhpcyBmaWxlIGlzIGdlbmVyYXRlZCBieSBjb2RlZ2VuL2luZGV4LnRzXG4vLyBEbyBub3QgZWRpdCB0aGlzIGZpbGUgbWFudWFsbHlcbmltcG9ydCB7IENvbW1hbmQsIE9wdGlvbiB9IGZyb20gJ2NsaXBhbmlvbidcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VSZW5hbWVDb21tYW5kIGV4dGVuZHMgQ29tbWFuZCB7XG4gIHN0YXRpYyBwYXRocyA9IFtbJ3JlbmFtZSddXVxuXG4gIHN0YXRpYyB1c2FnZSA9IENvbW1hbmQuVXNhZ2Uoe1xuICAgIGRlc2NyaXB0aW9uOiAnUmVuYW1lIHRoZSBOQVBJLVJTIHByb2plY3QnLFxuICB9KVxuXG4gIGN3ZCA9IE9wdGlvbi5TdHJpbmcoJy0tY3dkJywgcHJvY2Vzcy5jd2QoKSwge1xuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgJ1RoZSB3b3JraW5nIGRpcmVjdG9yeSBvZiB3aGVyZSBuYXBpIGNvbW1hbmQgd2lsbCBiZSBleGVjdXRlZCBpbiwgYWxsIG90aGVyIHBhdGhzIG9wdGlvbnMgYXJlIHJlbGF0aXZlIHRvIHRoaXMgcGF0aCcsXG4gIH0pXG5cbiAgY29uZmlnUGF0aD86IHN0cmluZyA9IE9wdGlvbi5TdHJpbmcoJy0tY29uZmlnLXBhdGgsLWMnLCB7XG4gICAgZGVzY3JpcHRpb246ICdQYXRoIHRvIGBuYXBpYCBjb25maWcganNvbiBmaWxlJyxcbiAgfSlcblxuICBwYWNrYWdlSnNvblBhdGggPSBPcHRpb24uU3RyaW5nKCctLXBhY2thZ2UtanNvbi1wYXRoJywgJ3BhY2thZ2UuanNvbicsIHtcbiAgICBkZXNjcmlwdGlvbjogJ1BhdGggdG8gYHBhY2thZ2UuanNvbmAnLFxuICB9KVxuXG4gIG5wbURpciA9IE9wdGlvbi5TdHJpbmcoJy0tbnBtLWRpcicsICducG0nLCB7XG4gICAgZGVzY3JpcHRpb246ICdQYXRoIHRvIHRoZSBmb2xkZXIgd2hlcmUgdGhlIG5wbSBwYWNrYWdlcyBwdXQnLFxuICB9KVxuXG4gICQkbmFtZT86IHN0cmluZyA9IE9wdGlvbi5TdHJpbmcoJy0tbmFtZSwtbicsIHtcbiAgICBkZXNjcmlwdGlvbjogJ1RoZSBuZXcgbmFtZSBvZiB0aGUgcHJvamVjdCcsXG4gIH0pXG5cbiAgYmluYXJ5TmFtZT86IHN0cmluZyA9IE9wdGlvbi5TdHJpbmcoJy0tYmluYXJ5LW5hbWUsLWInLCB7XG4gICAgZGVzY3JpcHRpb246ICdUaGUgbmV3IGJpbmFyeSBuYW1lICoubm9kZSBmaWxlcycsXG4gIH0pXG5cbiAgcGFja2FnZU5hbWU/OiBzdHJpbmcgPSBPcHRpb24uU3RyaW5nKCctLXBhY2thZ2UtbmFtZScsIHtcbiAgICBkZXNjcmlwdGlvbjogJ1RoZSBuZXcgcGFja2FnZSBuYW1lIG9mIHRoZSBwcm9qZWN0JyxcbiAgfSlcblxuICBtYW5pZmVzdFBhdGggPSBPcHRpb24uU3RyaW5nKCctLW1hbmlmZXN0LXBhdGgnLCAnQ2FyZ28udG9tbCcsIHtcbiAgICBkZXNjcmlwdGlvbjogJ1BhdGggdG8gYENhcmdvLnRvbWxgJyxcbiAgfSlcblxuICByZXBvc2l0b3J5Pzogc3RyaW5nID0gT3B0aW9uLlN0cmluZygnLS1yZXBvc2l0b3J5Jywge1xuICAgIGRlc2NyaXB0aW9uOiAnVGhlIG5ldyByZXBvc2l0b3J5IG9mIHRoZSBwcm9qZWN0JyxcbiAgfSlcblxuICBkZXNjcmlwdGlvbj86IHN0cmluZyA9IE9wdGlvbi5TdHJpbmcoJy0tZGVzY3JpcHRpb24nLCB7XG4gICAgZGVzY3JpcHRpb246ICdUaGUgbmV3IGRlc2NyaXB0aW9uIG9mIHRoZSBwcm9qZWN0JyxcbiAgfSlcblxuICBnZXRPcHRpb25zKCkge1xuICAgIHJldHVybiB7XG4gICAgICBjd2Q6IHRoaXMuY3dkLFxuICAgICAgY29uZmlnUGF0aDogdGhpcy5jb25maWdQYXRoLFxuICAgICAgcGFja2FnZUpzb25QYXRoOiB0aGlzLnBhY2thZ2VKc29uUGF0aCxcbiAgICAgIG5wbURpcjogdGhpcy5ucG1EaXIsXG4gICAgICBuYW1lOiB0aGlzLiQkbmFtZSxcbiAgICAgIGJpbmFyeU5hbWU6IHRoaXMuYmluYXJ5TmFtZSxcbiAgICAgIHBhY2thZ2VOYW1lOiB0aGlzLnBhY2thZ2VOYW1lLFxuICAgICAgbWFuaWZlc3RQYXRoOiB0aGlzLm1hbmlmZXN0UGF0aCxcbiAgICAgIHJlcG9zaXRvcnk6IHRoaXMucmVwb3NpdG9yeSxcbiAgICAgIGRlc2NyaXB0aW9uOiB0aGlzLmRlc2NyaXB0aW9uLFxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFJlbmFtZSB0aGUgTkFQSS1SUyBwcm9qZWN0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVuYW1lT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgd29ya2luZyBkaXJlY3Rvcnkgb2Ygd2hlcmUgbmFwaSBjb21tYW5kIHdpbGwgYmUgZXhlY3V0ZWQgaW4sIGFsbCBvdGhlciBwYXRocyBvcHRpb25zIGFyZSByZWxhdGl2ZSB0byB0aGlzIHBhdGhcbiAgICpcbiAgICogQGRlZmF1bHQgcHJvY2Vzcy5jd2QoKVxuICAgKi9cbiAgY3dkPzogc3RyaW5nXG4gIC8qKlxuICAgKiBQYXRoIHRvIGBuYXBpYCBjb25maWcganNvbiBmaWxlXG4gICAqL1xuICBjb25maWdQYXRoPzogc3RyaW5nXG4gIC8qKlxuICAgKiBQYXRoIHRvIGBwYWNrYWdlLmpzb25gXG4gICAqXG4gICAqIEBkZWZhdWx0ICdwYWNrYWdlLmpzb24nXG4gICAqL1xuICBwYWNrYWdlSnNvblBhdGg/OiBzdHJpbmdcbiAgLyoqXG4gICAqIFBhdGggdG8gdGhlIGZvbGRlciB3aGVyZSB0aGUgbnBtIHBhY2thZ2VzIHB1dFxuICAgKlxuICAgKiBAZGVmYXVsdCAnbnBtJ1xuICAgKi9cbiAgbnBtRGlyPzogc3RyaW5nXG4gIC8qKlxuICAgKiBUaGUgbmV3IG5hbWUgb2YgdGhlIHByb2plY3RcbiAgICovXG4gIG5hbWU/OiBzdHJpbmdcbiAgLyoqXG4gICAqIFRoZSBuZXcgYmluYXJ5IG5hbWUgKi5ub2RlIGZpbGVzXG4gICAqL1xuICBiaW5hcnlOYW1lPzogc3RyaW5nXG4gIC8qKlxuICAgKiBUaGUgbmV3IHBhY2thZ2UgbmFtZSBvZiB0aGUgcHJvamVjdFxuICAgKi9cbiAgcGFja2FnZU5hbWU/OiBzdHJpbmdcbiAgLyoqXG4gICAqIFBhdGggdG8gYENhcmdvLnRvbWxgXG4gICAqXG4gICAqIEBkZWZhdWx0ICdDYXJnby50b21sJ1xuICAgKi9cbiAgbWFuaWZlc3RQYXRoPzogc3RyaW5nXG4gIC8qKlxuICAgKiBUaGUgbmV3IHJlcG9zaXRvcnkgb2YgdGhlIHByb2plY3RcbiAgICovXG4gIHJlcG9zaXRvcnk/OiBzdHJpbmdcbiAgLyoqXG4gICAqIFRoZSBuZXcgZGVzY3JpcHRpb24gb2YgdGhlIHByb2plY3RcbiAgICovXG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseURlZmF1bHRSZW5hbWVPcHRpb25zKG9wdGlvbnM6IFJlbmFtZU9wdGlvbnMpIHtcbiAgcmV0dXJuIHtcbiAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgcGFja2FnZUpzb25QYXRoOiAncGFja2FnZS5qc29uJyxcbiAgICBucG1EaXI6ICducG0nLFxuICAgIG1hbmlmZXN0UGF0aDogJ0NhcmdvLnRvbWwnLFxuICAgIC4uLm9wdGlvbnMsXG4gIH1cbn1cbiIsImltcG9ydCB7IGV4aXN0c1N5bmMgfSBmcm9tICdub2RlOmZzJ1xuaW1wb3J0IHsgcmVuYW1lIH0gZnJvbSAnbm9kZTpmcy9wcm9taXNlcydcbmltcG9ydCB7IHJlc29sdmUsIGpvaW4gfSBmcm9tICdub2RlOnBhdGgnXG5cbmltcG9ydCB7IHBhcnNlIGFzIHBhcnNlVG9tbCwgc3RyaW5naWZ5IGFzIHN0cmluZ2lmeVRvbWwgfSBmcm9tICdAc3RkL3RvbWwnXG5pbXBvcnQgeyBsb2FkIGFzIHlhbWxQYXJzZSwgZHVtcCBhcyB5YW1sU3RyaW5naWZ5IH0gZnJvbSAnanMteWFtbCdcbmltcG9ydCB7IGlzTmlsLCBtZXJnZSwgb21pdEJ5LCBwaWNrIH0gZnJvbSAnbG9kYXNoLWVzJ1xuaW1wb3J0IHsgZmluZFVwIH0gZnJvbSAnZmluZC11cCdcblxuaW1wb3J0IHsgYXBwbHlEZWZhdWx0UmVuYW1lT3B0aW9ucywgUmVuYW1lT3B0aW9ucyB9IGZyb20gJy4uL2RlZi9yZW5hbWUuanMnXG5pbXBvcnQgeyByZWFkQ29uZmlnLCByZWFkRmlsZUFzeW5jLCB3cml0ZUZpbGVBc3luYyB9IGZyb20gJy4uL3V0aWxzL2luZGV4LmpzJ1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVuYW1lUHJvamVjdCh1c2VyT3B0aW9uczogUmVuYW1lT3B0aW9ucykge1xuICBjb25zdCBvcHRpb25zID0gYXBwbHlEZWZhdWx0UmVuYW1lT3B0aW9ucyh1c2VyT3B0aW9ucylcbiAgY29uc3QgbmFwaUNvbmZpZyA9IGF3YWl0IHJlYWRDb25maWcob3B0aW9ucylcbiAgY29uc3Qgb2xkTmFtZSA9IG5hcGlDb25maWcuYmluYXJ5TmFtZVxuXG4gIGNvbnN0IHBhY2thZ2VKc29uUGF0aCA9IHJlc29sdmUob3B0aW9ucy5jd2QsIG9wdGlvbnMucGFja2FnZUpzb25QYXRoKVxuICBjb25zdCBjYXJnb1RvbWxQYXRoID0gcmVzb2x2ZShvcHRpb25zLmN3ZCwgb3B0aW9ucy5tYW5pZmVzdFBhdGgpXG5cbiAgY29uc3QgcGFja2FnZUpzb25Db250ZW50ID0gYXdhaXQgcmVhZEZpbGVBc3luYyhwYWNrYWdlSnNvblBhdGgsICd1dGY4JylcbiAgY29uc3QgcGFja2FnZUpzb25EYXRhID0gSlNPTi5wYXJzZShwYWNrYWdlSnNvbkNvbnRlbnQpXG5cbiAgbWVyZ2UoXG4gICAgcGFja2FnZUpzb25EYXRhLFxuICAgIG9taXRCeShwaWNrKG9wdGlvbnMsIFsnbmFtZScsICdkZXNjcmlwdGlvbicsICdhdXRob3InLCAnbGljZW5zZSddKSwgaXNOaWwpLFxuICAgIHtcbiAgICAgIG5hcGk6IG9taXRCeShcbiAgICAgICAge1xuICAgICAgICAgIGJpbmFyeU5hbWU6IG9wdGlvbnMuYmluYXJ5TmFtZSxcbiAgICAgICAgICBwYWNrYWdlTmFtZTogb3B0aW9ucy5wYWNrYWdlTmFtZSxcbiAgICAgICAgfSxcbiAgICAgICAgaXNOaWwsXG4gICAgICApLFxuICAgIH0sXG4gIClcblxuICBpZiAob3B0aW9ucy5jb25maWdQYXRoKSB7XG4gICAgY29uc3QgY29uZmlnUGF0aCA9IHJlc29sdmUob3B0aW9ucy5jd2QsIG9wdGlvbnMuY29uZmlnUGF0aClcbiAgICBjb25zdCBjb25maWdDb250ZW50ID0gYXdhaXQgcmVhZEZpbGVBc3luYyhjb25maWdQYXRoLCAndXRmOCcpXG4gICAgY29uc3QgY29uZmlnRGF0YSA9IEpTT04ucGFyc2UoY29uZmlnQ29udGVudClcbiAgICBjb25maWdEYXRhLmJpbmFyeU5hbWUgPSBvcHRpb25zLmJpbmFyeU5hbWVcbiAgICBjb25maWdEYXRhLnBhY2thZ2VOYW1lID0gb3B0aW9ucy5wYWNrYWdlTmFtZVxuICAgIGF3YWl0IHdyaXRlRmlsZUFzeW5jKGNvbmZpZ1BhdGgsIEpTT04uc3RyaW5naWZ5KGNvbmZpZ0RhdGEsIG51bGwsIDIpKVxuICB9XG5cbiAgYXdhaXQgd3JpdGVGaWxlQXN5bmMoXG4gICAgcGFja2FnZUpzb25QYXRoLFxuICAgIEpTT04uc3RyaW5naWZ5KHBhY2thZ2VKc29uRGF0YSwgbnVsbCwgMiksXG4gIClcblxuICBjb25zdCB0b21sQ29udGVudCA9IGF3YWl0IHJlYWRGaWxlQXN5bmMoY2FyZ29Ub21sUGF0aCwgJ3V0ZjgnKVxuICBjb25zdCBjYXJnb1RvbWwgPSBwYXJzZVRvbWwodG9tbENvbnRlbnQpIGFzIGFueVxuXG4gIC8vIFVwZGF0ZSB0aGUgcGFja2FnZSBuYW1lXG4gIGlmIChjYXJnb1RvbWwucGFja2FnZSAmJiBvcHRpb25zLmJpbmFyeU5hbWUpIHtcbiAgICAvLyBTYW5pdGl6ZSB0aGUgYmluYXJ5IG5hbWUgZm9yIFJ1c3QgcGFja2FnZSBuYW1pbmcgY29udmVudGlvbnNcbiAgICBjb25zdCBzYW5pdGl6ZWROYW1lID0gb3B0aW9ucy5iaW5hcnlOYW1lXG4gICAgICAucmVwbGFjZSgnQCcsICcnKVxuICAgICAgLnJlcGxhY2UoJy8nLCAnXycpXG4gICAgICAucmVwbGFjZSgvLS9nLCAnXycpXG4gICAgICAudG9Mb3dlckNhc2UoKVxuICAgIGNhcmdvVG9tbC5wYWNrYWdlLm5hbWUgPSBzYW5pdGl6ZWROYW1lXG4gIH1cblxuICAvLyBTdHJpbmdpZnkgdGhlIHVwZGF0ZWQgVE9NTFxuICBjb25zdCB1cGRhdGVkVG9tbENvbnRlbnQgPSBzdHJpbmdpZnlUb21sKGNhcmdvVG9tbClcblxuICBhd2FpdCB3cml0ZUZpbGVBc3luYyhjYXJnb1RvbWxQYXRoLCB1cGRhdGVkVG9tbENvbnRlbnQpXG4gIGlmIChvbGROYW1lICE9PSBvcHRpb25zLmJpbmFyeU5hbWUpIHtcbiAgICBjb25zdCBnaXRodWJBY3Rpb25zUGF0aCA9IGF3YWl0IGZpbmRVcCgnLmdpdGh1YicsIHtcbiAgICAgIGN3ZDogb3B0aW9ucy5jd2QsXG4gICAgICB0eXBlOiAnZGlyZWN0b3J5JyxcbiAgICB9KVxuICAgIGlmIChnaXRodWJBY3Rpb25zUGF0aCkge1xuICAgICAgY29uc3QgZ2l0aHViQWN0aW9uc0NJWW1sUGF0aCA9IGpvaW4oXG4gICAgICAgIGdpdGh1YkFjdGlvbnNQYXRoLFxuICAgICAgICAnd29ya2Zsb3dzJyxcbiAgICAgICAgJ0NJLnltbCcsXG4gICAgICApXG4gICAgICBpZiAoZXhpc3RzU3luYyhnaXRodWJBY3Rpb25zQ0lZbWxQYXRoKSkge1xuICAgICAgICBjb25zdCBnaXRodWJBY3Rpb25zQ29udGVudCA9IGF3YWl0IHJlYWRGaWxlQXN5bmMoXG4gICAgICAgICAgZ2l0aHViQWN0aW9uc0NJWW1sUGF0aCxcbiAgICAgICAgICAndXRmOCcsXG4gICAgICAgIClcbiAgICAgICAgY29uc3QgZ2l0aHViQWN0aW9uc0RhdGEgPSB5YW1sUGFyc2UoZ2l0aHViQWN0aW9uc0NvbnRlbnQpIGFzIGFueVxuICAgICAgICBpZiAoZ2l0aHViQWN0aW9uc0RhdGEuZW52Py5BUFBfTkFNRSkge1xuICAgICAgICAgIGdpdGh1YkFjdGlvbnNEYXRhLmVudi5BUFBfTkFNRSA9IG9wdGlvbnMuYmluYXJ5TmFtZVxuICAgICAgICAgIGF3YWl0IHdyaXRlRmlsZUFzeW5jKFxuICAgICAgICAgICAgZ2l0aHViQWN0aW9uc0NJWW1sUGF0aCxcbiAgICAgICAgICAgIHlhbWxTdHJpbmdpZnkoZ2l0aHViQWN0aW9uc0RhdGEsIHtcbiAgICAgICAgICAgICAgbGluZVdpZHRoOiAtMSxcbiAgICAgICAgICAgICAgbm9SZWZzOiB0cnVlLFxuICAgICAgICAgICAgICBzb3J0S2V5czogZmFsc2UsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3Qgb2xkV2FzaUJyb3dzZXJCaW5kaW5nUGF0aCA9IGpvaW4oXG4gICAgICBvcHRpb25zLmN3ZCxcbiAgICAgIGAke29sZE5hbWV9Lndhc2ktYnJvd3Nlci5qc2AsXG4gICAgKVxuICAgIGlmIChleGlzdHNTeW5jKG9sZFdhc2lCcm93c2VyQmluZGluZ1BhdGgpKSB7XG4gICAgICBhd2FpdCByZW5hbWUoXG4gICAgICAgIG9sZFdhc2lCcm93c2VyQmluZGluZ1BhdGgsXG4gICAgICAgIGpvaW4ob3B0aW9ucy5jd2QsIGAke29wdGlvbnMuYmluYXJ5TmFtZX0ud2FzaS1icm93c2VyLmpzYCksXG4gICAgICApXG4gICAgfVxuICAgIGNvbnN0IG9sZFdhc2lCaW5kaW5nUGF0aCA9IGpvaW4ob3B0aW9ucy5jd2QsIGAke29sZE5hbWV9Lndhc2kuY2pzYClcbiAgICBpZiAoZXhpc3RzU3luYyhvbGRXYXNpQmluZGluZ1BhdGgpKSB7XG4gICAgICBhd2FpdCByZW5hbWUoXG4gICAgICAgIG9sZFdhc2lCaW5kaW5nUGF0aCxcbiAgICAgICAgam9pbihvcHRpb25zLmN3ZCwgYCR7b3B0aW9ucy5iaW5hcnlOYW1lfS53YXNpLmNqc2ApLFxuICAgICAgKVxuICAgIH1cbiAgICBjb25zdCBnaXRBdHRyaWJ1dGVzUGF0aCA9IGpvaW4ob3B0aW9ucy5jd2QsICcuZ2l0YXR0cmlidXRlcycpXG4gICAgaWYgKGV4aXN0c1N5bmMoZ2l0QXR0cmlidXRlc1BhdGgpKSB7XG4gICAgICBjb25zdCBnaXRBdHRyaWJ1dGVzQ29udGVudCA9IGF3YWl0IHJlYWRGaWxlQXN5bmMoXG4gICAgICAgIGdpdEF0dHJpYnV0ZXNQYXRoLFxuICAgICAgICAndXRmOCcsXG4gICAgICApXG4gICAgICBjb25zdCBnaXRBdHRyaWJ1dGVzRGF0YSA9IGdpdEF0dHJpYnV0ZXNDb250ZW50XG4gICAgICAgIC5zcGxpdCgnXFxuJylcbiAgICAgICAgLm1hcCgobGluZSkgPT4ge1xuICAgICAgICAgIHJldHVybiBsaW5lXG4gICAgICAgICAgICAucmVwbGFjZShcbiAgICAgICAgICAgICAgYCR7b2xkTmFtZX0ud2FzaS1icm93c2VyLmpzYCxcbiAgICAgICAgICAgICAgYCR7b3B0aW9ucy5iaW5hcnlOYW1lfS53YXNpLWJyb3dzZXIuanNgLFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnJlcGxhY2UoYCR7b2xkTmFtZX0ud2FzaS5janNgLCBgJHtvcHRpb25zLmJpbmFyeU5hbWV9Lndhc2kuY2pzYClcbiAgICAgICAgfSlcbiAgICAgICAgLmpvaW4oJ1xcbicpXG4gICAgICBhd2FpdCB3cml0ZUZpbGVBc3luYyhnaXRBdHRyaWJ1dGVzUGF0aCwgZ2l0QXR0cmlidXRlc0RhdGEpXG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQgeyBleGVjLCBleGVjU3luYyB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2VzcydcbmltcG9ydCB7IGV4aXN0c1N5bmMgfSBmcm9tICdub2RlOmZzJ1xuaW1wb3J0IHsgaG9tZWRpciB9IGZyb20gJ25vZGU6b3MnXG5pbXBvcnQgcGF0aCBmcm9tICdub2RlOnBhdGgnXG5pbXBvcnQgeyBwcm9taXNlcyBhcyBmcyB9IGZyb20gJ25vZGU6ZnMnXG5cbmltcG9ydCB7IGxvYWQgYXMgeWFtbExvYWQsIGR1bXAgYXMgeWFtbER1bXAgfSBmcm9tICdqcy15YW1sJ1xuXG5pbXBvcnQge1xuICBhcHBseURlZmF1bHROZXdPcHRpb25zLFxuICBOZXdPcHRpb25zIGFzIFJhd05ld09wdGlvbnMsXG59IGZyb20gJy4uL2RlZi9uZXcuanMnXG5pbXBvcnQge1xuICBBVkFJTEFCTEVfVEFSR0VUUyxcbiAgZGVidWdGYWN0b3J5LFxuICBERUZBVUxUX1RBUkdFVFMsXG4gIG1rZGlyQXN5bmMsXG4gIHJlYWRkaXJBc3luYyxcbiAgc3RhdEFzeW5jLFxuICBTdXBwb3J0ZWRQYWNrYWdlTWFuYWdlcixcbn0gZnJvbSAnLi4vdXRpbHMvaW5kZXguanMnXG5pbXBvcnQgeyBuYXBpRW5naW5lUmVxdWlyZW1lbnQgfSBmcm9tICcuLi91dGlscy92ZXJzaW9uLmpzJ1xuaW1wb3J0IHsgcmVuYW1lUHJvamVjdCB9IGZyb20gJy4vcmVuYW1lLmpzJ1xuXG4vLyBUZW1wbGF0ZSBpbXBvcnRzIHJlbW92ZWQgYXMgd2UncmUgbm93IHVzaW5nIGV4dGVybmFsIHRlbXBsYXRlc1xuXG5jb25zdCBkZWJ1ZyA9IGRlYnVnRmFjdG9yeSgnbmV3JylcblxudHlwZSBOZXdPcHRpb25zID0gUmVxdWlyZWQ8UmF3TmV3T3B0aW9ucz5cblxuY29uc3QgVEVNUExBVEVfUkVQT1MgPSB7XG4gIHlhcm46ICdodHRwczovL2dpdGh1Yi5jb20vbmFwaS1ycy9wYWNrYWdlLXRlbXBsYXRlJyxcbiAgcG5wbTogJ2h0dHBzOi8vZ2l0aHViLmNvbS9uYXBpLXJzL3BhY2thZ2UtdGVtcGxhdGUtcG5wbScsXG59IGFzIGNvbnN0XG5cbmFzeW5jIGZ1bmN0aW9uIGNoZWNrR2l0Q29tbWFuZCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgdHJ5IHtcbiAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgY29uc3QgY3AgPSBleGVjKCdnaXQgLS12ZXJzaW9uJylcbiAgICAgIGNwLm9uKCdlcnJvcicsICgpID0+IHtcbiAgICAgICAgcmVzb2x2ZShmYWxzZSlcbiAgICAgIH0pXG4gICAgICBjcC5vbignZXhpdCcsIChjb2RlKSA9PiB7XG4gICAgICAgIGlmIChjb2RlID09PSAwKSB7XG4gICAgICAgICAgcmVzb2x2ZSh0cnVlKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUoZmFsc2UpXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfSlcbiAgICByZXR1cm4gdHJ1ZVxuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBlbnN1cmVDYWNoZURpcihcbiAgcGFja2FnZU1hbmFnZXI6IFN1cHBvcnRlZFBhY2thZ2VNYW5hZ2VyLFxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgY2FjaGVEaXIgPSBwYXRoLmpvaW4oaG9tZWRpcigpLCAnLm5hcGktcnMnLCAndGVtcGxhdGUnLCBwYWNrYWdlTWFuYWdlcilcbiAgYXdhaXQgbWtkaXJBc3luYyhjYWNoZURpciwgeyByZWN1cnNpdmU6IHRydWUgfSlcbiAgcmV0dXJuIGNhY2hlRGlyXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRvd25sb2FkVGVtcGxhdGUoXG4gIHBhY2thZ2VNYW5hZ2VyOiBTdXBwb3J0ZWRQYWNrYWdlTWFuYWdlcixcbiAgY2FjaGVEaXI6IHN0cmluZyxcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCByZXBvVXJsID0gVEVNUExBVEVfUkVQT1NbcGFja2FnZU1hbmFnZXJdXG4gIGNvbnN0IHRlbXBsYXRlUGF0aCA9IHBhdGguam9pbihjYWNoZURpciwgJ3JlcG8nKVxuXG4gIGlmIChleGlzdHNTeW5jKHRlbXBsYXRlUGF0aCkpIHtcbiAgICBkZWJ1ZyhgVGVtcGxhdGUgY2FjaGUgZm91bmQgYXQgJHt0ZW1wbGF0ZVBhdGh9LCB1cGRhdGluZy4uLmApXG4gICAgdHJ5IHtcbiAgICAgIC8vIEZldGNoIGxhdGVzdCBjaGFuZ2VzIGFuZCByZXNldCB0byByZW1vdGVcbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgY3AgPSBleGVjKCdnaXQgZmV0Y2ggb3JpZ2luJywgeyBjd2Q6IHRlbXBsYXRlUGF0aCB9KVxuICAgICAgICBjcC5vbignZXJyb3InLCByZWplY3QpXG4gICAgICAgIGNwLm9uKCdleGl0JywgKGNvZGUpID0+IHtcbiAgICAgICAgICBpZiAoY29kZSA9PT0gMCkge1xuICAgICAgICAgICAgcmVzb2x2ZSgpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlamVjdChcbiAgICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIGBGYWlsZWQgdG8gZmV0Y2ggbGF0ZXN0IGNoYW5nZXMsIGdpdCBwcm9jZXNzIGV4aXRlZCB3aXRoIGNvZGUgJHtjb2RlfWAsXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICApXG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgfSlcbiAgICAgIGV4ZWNTeW5jKCdnaXQgcmVzZXQgLS1oYXJkIG9yaWdpbi9tYWluJywge1xuICAgICAgICBjd2Q6IHRlbXBsYXRlUGF0aCxcbiAgICAgICAgc3RkaW86ICdpZ25vcmUnLFxuICAgICAgfSlcbiAgICAgIGRlYnVnKCdUZW1wbGF0ZSB1cGRhdGVkIHN1Y2Nlc3NmdWxseScpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGRlYnVnKGBGYWlsZWQgdG8gdXBkYXRlIHRlbXBsYXRlOiAke2Vycm9yfWApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byB1cGRhdGUgdGVtcGxhdGUgZnJvbSAke3JlcG9Vcmx9OiAke2Vycm9yfWApXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGRlYnVnKGBDbG9uaW5nIHRlbXBsYXRlIGZyb20gJHtyZXBvVXJsfS4uLmApXG4gICAgdHJ5IHtcbiAgICAgIGV4ZWNTeW5jKGBnaXQgY2xvbmUgJHtyZXBvVXJsfSByZXBvYCwgeyBjd2Q6IGNhY2hlRGlyLCBzdGRpbzogJ2luaGVyaXQnIH0pXG4gICAgICBkZWJ1ZygnVGVtcGxhdGUgY2xvbmVkIHN1Y2Nlc3NmdWxseScpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGNsb25lIHRlbXBsYXRlIGZyb20gJHtyZXBvVXJsfTogJHtlcnJvcn1gKVxuICAgIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBjb3B5RGlyZWN0b3J5KFxuICBzcmM6IHN0cmluZyxcbiAgZGVzdDogc3RyaW5nLFxuICBpbmNsdWRlV2FzaUJpbmRpbmdzOiBib29sZWFuLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IG1rZGlyQXN5bmMoZGVzdCwgeyByZWN1cnNpdmU6IHRydWUgfSlcbiAgY29uc3QgZW50cmllcyA9IGF3YWl0IGZzLnJlYWRkaXIoc3JjLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSlcblxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBjb25zdCBzcmNQYXRoID0gcGF0aC5qb2luKHNyYywgZW50cnkubmFtZSlcbiAgICBjb25zdCBkZXN0UGF0aCA9IHBhdGguam9pbihkZXN0LCBlbnRyeS5uYW1lKVxuXG4gICAgLy8gU2tpcCAuZ2l0IGRpcmVjdG9yeVxuICAgIGlmIChlbnRyeS5uYW1lID09PSAnLmdpdCcpIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgaWYgKGVudHJ5LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIGF3YWl0IGNvcHlEaXJlY3Rvcnkoc3JjUGF0aCwgZGVzdFBhdGgsIGluY2x1ZGVXYXNpQmluZGluZ3MpXG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChcbiAgICAgICAgIWluY2x1ZGVXYXNpQmluZGluZ3MgJiZcbiAgICAgICAgKGVudHJ5Lm5hbWUuZW5kc1dpdGgoJy53YXNpLWJyb3dzZXIuanMnKSB8fFxuICAgICAgICAgIGVudHJ5Lm5hbWUuZW5kc1dpdGgoJy53YXNpLmNqcycpIHx8XG4gICAgICAgICAgZW50cnkubmFtZS5lbmRzV2l0aCgnd2FzaS13b3JrZXIuYnJvd3Nlci5tanMgJykgfHxcbiAgICAgICAgICBlbnRyeS5uYW1lLmVuZHNXaXRoKCd3YXNpLXdvcmtlci5tanMnKSB8fFxuICAgICAgICAgIGVudHJ5Lm5hbWUuZW5kc1dpdGgoJ2Jyb3dzZXIuanMnKSlcbiAgICAgICkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgYXdhaXQgZnMuY29weUZpbGUoc3JjUGF0aCwgZGVzdFBhdGgpXG4gICAgfVxuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbHRlclRhcmdldHNJblBhY2thZ2VKc29uKFxuICBmaWxlUGF0aDogc3RyaW5nLFxuICBlbmFibGVkVGFyZ2V0czogc3RyaW5nW10sXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgY29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVQYXRoLCAndXRmLTgnKVxuICBjb25zdCBwYWNrYWdlSnNvbiA9IEpTT04ucGFyc2UoY29udGVudClcblxuICAvLyBGaWx0ZXIgbmFwaS50YXJnZXRzXG4gIGlmIChwYWNrYWdlSnNvbi5uYXBpPy50YXJnZXRzKSB7XG4gICAgcGFja2FnZUpzb24ubmFwaS50YXJnZXRzID0gcGFja2FnZUpzb24ubmFwaS50YXJnZXRzLmZpbHRlcihcbiAgICAgICh0YXJnZXQ6IHN0cmluZykgPT4gZW5hYmxlZFRhcmdldHMuaW5jbHVkZXModGFyZ2V0KSxcbiAgICApXG4gIH1cblxuICBhd2FpdCBmcy53cml0ZUZpbGUoZmlsZVBhdGgsIEpTT04uc3RyaW5naWZ5KHBhY2thZ2VKc29uLCBudWxsLCAyKSArICdcXG4nKVxufVxuXG5hc3luYyBmdW5jdGlvbiBmaWx0ZXJUYXJnZXRzSW5HaXRodWJBY3Rpb25zKFxuICBmaWxlUGF0aDogc3RyaW5nLFxuICBlbmFibGVkVGFyZ2V0czogc3RyaW5nW10sXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgY29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVQYXRoLCAndXRmLTgnKVxuICBjb25zdCB5YW1sID0geWFtbExvYWQoY29udGVudCkgYXMgYW55XG5cbiAgY29uc3QgbWFjT1NBbmRXaW5kb3dzVGFyZ2V0cyA9IG5ldyBTZXQoW1xuICAgICd4ODZfNjQtcGMtd2luZG93cy1tc3ZjJyxcbiAgICAnYWFyY2g2NC1wYy13aW5kb3dzLW1zdmMnLFxuICAgICd4ODZfNjQtYXBwbGUtZGFyd2luJyxcbiAgXSlcblxuICBjb25zdCBsaW51eFRhcmdldHMgPSBuZXcgU2V0KFtcbiAgICAneDg2XzY0LXVua25vd24tbGludXgtZ251JyxcbiAgICAneDg2XzY0LXVua25vd24tbGludXgtbXVzbCcsXG4gICAgJ2FhcmNoNjQtdW5rbm93bi1saW51eC1nbnUnLFxuICAgICdhYXJjaDY0LXVua25vd24tbGludXgtbXVzbCcsXG4gICAgJ2FybXY3LXVua25vd24tbGludXgtZ251ZWFiaWhmJyxcbiAgICAnYXJtdjctdW5rbm93bi1saW51eC1tdXNsZWFiaWhmJyxcbiAgICAncmlzY3Y2NGdjLXVua25vd24tbGludXgtZ251JyxcbiAgICAncG93ZXJwYzY0bGUtdW5rbm93bi1saW51eC1nbnUnLFxuICAgICdzMzkweC11bmtub3duLWxpbnV4LWdudScsXG4gICAgJ2FhcmNoNjQtbGludXgtYW5kcm9pZCcsXG4gICAgJ2FybXY3LWxpbnV4LWFuZHJvaWRlYWJpJyxcbiAgXSlcblxuICAvLyBDaGVjayBpZiBhbnkgTGludXggdGFyZ2V0cyBhcmUgZW5hYmxlZFxuICBjb25zdCBoYXNMaW51eFRhcmdldHMgPSBlbmFibGVkVGFyZ2V0cy5zb21lKCh0YXJnZXQpID0+XG4gICAgbGludXhUYXJnZXRzLmhhcyh0YXJnZXQpLFxuICApXG5cbiAgLy8gRmlsdGVyIHRoZSBtYXRyaXggY29uZmlndXJhdGlvbnMgaW4gdGhlIGJ1aWxkIGpvYlxuICBpZiAoeWFtbD8uam9icz8uYnVpbGQ/LnN0cmF0ZWd5Py5tYXRyaXg/LnNldHRpbmdzKSB7XG4gICAgeWFtbC5qb2JzLmJ1aWxkLnN0cmF0ZWd5Lm1hdHJpeC5zZXR0aW5ncyA9XG4gICAgICB5YW1sLmpvYnMuYnVpbGQuc3RyYXRlZ3kubWF0cml4LnNldHRpbmdzLmZpbHRlcigoc2V0dGluZzogYW55KSA9PiB7XG4gICAgICAgIGlmIChzZXR0aW5nLnRhcmdldCkge1xuICAgICAgICAgIHJldHVybiBlbmFibGVkVGFyZ2V0cy5pbmNsdWRlcyhzZXR0aW5nLnRhcmdldClcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfSlcbiAgfVxuXG4gIGNvbnN0IGpvYnNUb1JlbW92ZTogc3RyaW5nW10gPSBbXVxuXG4gIGlmIChlbmFibGVkVGFyZ2V0cy5ldmVyeSgodGFyZ2V0KSA9PiAhbWFjT1NBbmRXaW5kb3dzVGFyZ2V0cy5oYXModGFyZ2V0KSkpIHtcbiAgICBqb2JzVG9SZW1vdmUucHVzaCgndGVzdC1tYWNPUy13aW5kb3dzLWJpbmRpbmcnKVxuICB9IGVsc2Uge1xuICAgIC8vIEZpbHRlciB0aGUgbWF0cml4IGNvbmZpZ3VyYXRpb25zIGluIHRoZSB0ZXN0LW1hY09TLXdpbmRvd3MtYmluZGluZyBqb2JcbiAgICBpZiAoXG4gICAgICB5YW1sPy5qb2JzPy5bJ3Rlc3QtbWFjT1Mtd2luZG93cy1iaW5kaW5nJ10/LnN0cmF0ZWd5Py5tYXRyaXg/LnNldHRpbmdzXG4gICAgKSB7XG4gICAgICB5YW1sLmpvYnNbJ3Rlc3QtbWFjT1Mtd2luZG93cy1iaW5kaW5nJ10uc3RyYXRlZ3kubWF0cml4LnNldHRpbmdzID1cbiAgICAgICAgeWFtbC5qb2JzWyd0ZXN0LW1hY09TLXdpbmRvd3MtYmluZGluZyddLnN0cmF0ZWd5Lm1hdHJpeC5zZXR0aW5ncy5maWx0ZXIoXG4gICAgICAgICAgKHNldHRpbmc6IGFueSkgPT4ge1xuICAgICAgICAgICAgaWYgKHNldHRpbmcudGFyZ2V0KSB7XG4gICAgICAgICAgICAgIHJldHVybiBlbmFibGVkVGFyZ2V0cy5pbmNsdWRlcyhzZXR0aW5nLnRhcmdldClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgKVxuICAgIH1cbiAgfVxuXG4gIC8vIElmIG5vIExpbnV4IHRhcmdldHMgYXJlIGVuYWJsZWQsIHJlbW92ZSBMaW51eC1zcGVjaWZpYyBqb2JzXG4gIGlmICghaGFzTGludXhUYXJnZXRzKSB7XG4gICAgLy8gUmVtb3ZlIHRlc3QtbGludXgtYmluZGluZyBqb2JcbiAgICBpZiAoeWFtbD8uam9icz8uWyd0ZXN0LWxpbnV4LWJpbmRpbmcnXSkge1xuICAgICAgam9ic1RvUmVtb3ZlLnB1c2goJ3Rlc3QtbGludXgtYmluZGluZycpXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIEZpbHRlciB0aGUgbWF0cml4IGNvbmZpZ3VyYXRpb25zIGluIHRoZSB0ZXN0LWxpbnV4LXg2NC1nbnUtYmluZGluZyBqb2JcbiAgICBpZiAoeWFtbD8uam9icz8uWyd0ZXN0LWxpbnV4LWJpbmRpbmcnXT8uc3RyYXRlZ3k/Lm1hdHJpeD8udGFyZ2V0KSB7XG4gICAgICB5YW1sLmpvYnNbJ3Rlc3QtbGludXgtYmluZGluZyddLnN0cmF0ZWd5Lm1hdHJpeC50YXJnZXQgPSB5YW1sLmpvYnNbXG4gICAgICAgICd0ZXN0LWxpbnV4LWJpbmRpbmcnXG4gICAgICBdLnN0cmF0ZWd5Lm1hdHJpeC50YXJnZXQuZmlsdGVyKCh0YXJnZXQ6IHN0cmluZykgPT4ge1xuICAgICAgICBpZiAodGFyZ2V0KSB7XG4gICAgICAgICAgcmV0dXJuIGVuYWJsZWRUYXJnZXRzLmluY2x1ZGVzKHRhcmdldClcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfSlcbiAgICB9XG4gIH1cblxuICBpZiAoIWVuYWJsZWRUYXJnZXRzLmluY2x1ZGVzKCd3YXNtMzItd2FzaXAxLXRocmVhZHMnKSkge1xuICAgIGpvYnNUb1JlbW92ZS5wdXNoKCd0ZXN0LXdhc2knKVxuICB9XG5cbiAgaWYgKCFlbmFibGVkVGFyZ2V0cy5pbmNsdWRlcygneDg2XzY0LXVua25vd24tZnJlZWJzZCcpKSB7XG4gICAgam9ic1RvUmVtb3ZlLnB1c2goJ2J1aWxkLWZyZWVic2QnKVxuICB9XG5cbiAgLy8gRmlsdGVyIG90aGVyIHRlc3Qgam9icyBiYXNlZCBvbiB0YXJnZXRcbiAgZm9yIChjb25zdCBbam9iTmFtZSwgam9iQ29uZmlnXSBvZiBPYmplY3QuZW50cmllcyh5YW1sLmpvYnMgfHwge30pKSB7XG4gICAgaWYgKFxuICAgICAgam9iTmFtZS5zdGFydHNXaXRoKCd0ZXN0LScpICYmXG4gICAgICBqb2JOYW1lICE9PSAndGVzdC1tYWNPUy13aW5kb3dzLWJpbmRpbmcnICYmXG4gICAgICBqb2JOYW1lICE9PSAndGVzdC1saW51eC14NjQtZ251LWJpbmRpbmcnXG4gICAgKSB7XG4gICAgICAvLyBFeHRyYWN0IHRhcmdldCBmcm9tIGpvYiBuYW1lIG9yIGNvbmZpZ1xuICAgICAgY29uc3Qgam9iID0gam9iQ29uZmlnIGFzIGFueVxuICAgICAgaWYgKGpvYi5zdHJhdGVneT8ubWF0cml4Py5zZXR0aW5ncz8uWzBdPy50YXJnZXQpIHtcbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gam9iLnN0cmF0ZWd5Lm1hdHJpeC5zZXR0aW5nc1swXS50YXJnZXRcbiAgICAgICAgaWYgKCFlbmFibGVkVGFyZ2V0cy5pbmNsdWRlcyh0YXJnZXQpKSB7XG4gICAgICAgICAgam9ic1RvUmVtb3ZlLnB1c2goam9iTmFtZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFJlbW92ZSBqb2JzIGZvciBkaXNhYmxlZCB0YXJnZXRzXG4gIGZvciAoY29uc3Qgam9iTmFtZSBvZiBqb2JzVG9SZW1vdmUpIHtcbiAgICBkZWxldGUgeWFtbC5qb2JzW2pvYk5hbWVdXG4gIH1cblxuICBpZiAoQXJyYXkuaXNBcnJheSh5YW1sLmpvYnM/LnB1Ymxpc2g/Lm5lZWRzKSkge1xuICAgIHlhbWwuam9icy5wdWJsaXNoLm5lZWRzID0geWFtbC5qb2JzLnB1Ymxpc2gubmVlZHMuZmlsdGVyKFxuICAgICAgKG5lZWQ6IHN0cmluZykgPT4gIWpvYnNUb1JlbW92ZS5pbmNsdWRlcyhuZWVkKSxcbiAgICApXG4gIH1cblxuICAvLyBXcml0ZSBiYWNrIHRoZSBmaWx0ZXJlZCBZQU1MXG4gIGNvbnN0IHVwZGF0ZWRZYW1sID0geWFtbER1bXAoeWFtbCwge1xuICAgIGxpbmVXaWR0aDogLTEsXG4gICAgbm9SZWZzOiB0cnVlLFxuICAgIHNvcnRLZXlzOiBmYWxzZSxcbiAgfSlcbiAgYXdhaXQgZnMud3JpdGVGaWxlKGZpbGVQYXRoLCB1cGRhdGVkWWFtbClcbn1cblxuZnVuY3Rpb24gcHJvY2Vzc09wdGlvbnMob3B0aW9uczogUmF3TmV3T3B0aW9ucykge1xuICBkZWJ1ZygnUHJvY2Vzc2luZyBvcHRpb25zLi4uJylcbiAgaWYgKCFvcHRpb25zLnBhdGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1BsZWFzZSBwcm92aWRlIHRoZSBwYXRoIGFzIHRoZSBhcmd1bWVudCcpXG4gIH1cbiAgb3B0aW9ucy5wYXRoID0gcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIG9wdGlvbnMucGF0aClcbiAgZGVidWcoYFJlc29sdmVkIHRhcmdldCBwYXRoIHRvOiAke29wdGlvbnMucGF0aH1gKVxuXG4gIGlmICghb3B0aW9ucy5uYW1lKSB7XG4gICAgb3B0aW9ucy5uYW1lID0gcGF0aC5wYXJzZShvcHRpb25zLnBhdGgpLmJhc2VcbiAgICBkZWJ1ZyhgTm8gcHJvamVjdCBuYW1lIHByb3ZpZGVkLCBmaXggaXQgdG8gZGlyIG5hbWU6ICR7b3B0aW9ucy5uYW1lfWApXG4gIH1cblxuICBpZiAoIW9wdGlvbnMudGFyZ2V0cz8ubGVuZ3RoKSB7XG4gICAgaWYgKG9wdGlvbnMuZW5hYmxlQWxsVGFyZ2V0cykge1xuICAgICAgb3B0aW9ucy50YXJnZXRzID0gQVZBSUxBQkxFX1RBUkdFVFMuY29uY2F0KClcbiAgICAgIGRlYnVnKCdFbmFibGUgYWxsIHRhcmdldHMnKVxuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5lbmFibGVEZWZhdWx0VGFyZ2V0cykge1xuICAgICAgb3B0aW9ucy50YXJnZXRzID0gREVGQVVMVF9UQVJHRVRTLmNvbmNhdCgpXG4gICAgICBkZWJ1ZygnRW5hYmxlIGRlZmF1bHQgdGFyZ2V0cycpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXQgbGVhc3Qgb25lIHRhcmdldCBtdXN0IGJlIGVuYWJsZWQnKVxuICAgIH1cbiAgfVxuICBpZiAoXG4gICAgb3B0aW9ucy50YXJnZXRzLnNvbWUoKHRhcmdldCkgPT4gdGFyZ2V0ID09PSAnd2FzbTMyLXdhc2ktcHJldmlldzEtdGhyZWFkcycpXG4gICkge1xuICAgIGNvbnN0IG91dCA9IGV4ZWNTeW5jKGBydXN0dXAgdGFyZ2V0IGxpc3RgLCB7XG4gICAgICBlbmNvZGluZzogJ3V0ZjgnLFxuICAgIH0pXG4gICAgaWYgKG91dC5pbmNsdWRlcygnd2FzbTMyLXdhc2lwMS10aHJlYWRzJykpIHtcbiAgICAgIG9wdGlvbnMudGFyZ2V0cyA9IG9wdGlvbnMudGFyZ2V0cy5tYXAoKHRhcmdldCkgPT5cbiAgICAgICAgdGFyZ2V0ID09PSAnd2FzbTMyLXdhc2ktcHJldmlldzEtdGhyZWFkcydcbiAgICAgICAgICA/ICd3YXNtMzItd2FzaXAxLXRocmVhZHMnXG4gICAgICAgICAgOiB0YXJnZXQsXG4gICAgICApXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGFwcGx5RGVmYXVsdE5ld09wdGlvbnMob3B0aW9ucykgYXMgTmV3T3B0aW9uc1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbmV3UHJvamVjdCh1c2VyT3B0aW9uczogUmF3TmV3T3B0aW9ucykge1xuICBkZWJ1ZygnV2lsbCBjcmVhdGUgbmFwaS1ycyBwcm9qZWN0IHdpdGggZ2l2ZW4gb3B0aW9uczonKVxuICBkZWJ1Zyh1c2VyT3B0aW9ucylcblxuICBjb25zdCBvcHRpb25zID0gcHJvY2Vzc09wdGlvbnModXNlck9wdGlvbnMpXG5cbiAgZGVidWcoJ1RhcmdldHMgdG8gYmUgZW5hYmxlZDonKVxuICBkZWJ1ZyhvcHRpb25zLnRhcmdldHMpXG5cbiAgLy8gQ2hlY2sgaWYgZ2l0IGlzIGF2YWlsYWJsZVxuICBpZiAoIShhd2FpdCBjaGVja0dpdENvbW1hbmQoKSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnR2l0IGlzIG5vdCBpbnN0YWxsZWQgb3Igbm90IGF2YWlsYWJsZSBpbiBQQVRILiBQbGVhc2UgaW5zdGFsbCBHaXQgdG8gY29udGludWUuJyxcbiAgICApXG4gIH1cblxuICBjb25zdCBwYWNrYWdlTWFuYWdlciA9IG9wdGlvbnMucGFja2FnZU1hbmFnZXIgYXMgU3VwcG9ydGVkUGFja2FnZU1hbmFnZXJcblxuICAvLyBFbnN1cmUgdGFyZ2V0IGRpcmVjdG9yeSBleGlzdHMgYW5kIGlzIGVtcHR5XG4gIGF3YWl0IGVuc3VyZVBhdGgob3B0aW9ucy5wYXRoLCBvcHRpb25zLmRyeVJ1bilcblxuICBpZiAoIW9wdGlvbnMuZHJ5UnVuKSB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIERvd25sb2FkIG9yIHVwZGF0ZSB0ZW1wbGF0ZVxuICAgICAgY29uc3QgY2FjaGVEaXIgPSBhd2FpdCBlbnN1cmVDYWNoZURpcihwYWNrYWdlTWFuYWdlcilcbiAgICAgIGF3YWl0IGRvd25sb2FkVGVtcGxhdGUocGFja2FnZU1hbmFnZXIsIGNhY2hlRGlyKVxuXG4gICAgICAvLyBDb3B5IHRlbXBsYXRlIGZpbGVzIHRvIHRhcmdldCBkaXJlY3RvcnlcbiAgICAgIGNvbnN0IHRlbXBsYXRlUGF0aCA9IHBhdGguam9pbihjYWNoZURpciwgJ3JlcG8nKVxuICAgICAgYXdhaXQgY29weURpcmVjdG9yeShcbiAgICAgICAgdGVtcGxhdGVQYXRoLFxuICAgICAgICBvcHRpb25zLnBhdGgsXG4gICAgICAgIG9wdGlvbnMudGFyZ2V0cy5pbmNsdWRlcygnd2FzbTMyLXdhc2lwMS10aHJlYWRzJyksXG4gICAgICApXG5cbiAgICAgIC8vIFJlbmFtZSBwcm9qZWN0IHVzaW5nIHRoZSByZW5hbWUgQVBJXG4gICAgICBhd2FpdCByZW5hbWVQcm9qZWN0KHtcbiAgICAgICAgY3dkOiBvcHRpb25zLnBhdGgsXG4gICAgICAgIG5hbWU6IG9wdGlvbnMubmFtZSxcbiAgICAgICAgYmluYXJ5TmFtZTogZ2V0QmluYXJ5TmFtZShvcHRpb25zLm5hbWUpLFxuICAgICAgfSlcblxuICAgICAgLy8gRmlsdGVyIHRhcmdldHMgaW4gcGFja2FnZS5qc29uXG4gICAgICBjb25zdCBwYWNrYWdlSnNvblBhdGggPSBwYXRoLmpvaW4ob3B0aW9ucy5wYXRoLCAncGFja2FnZS5qc29uJylcbiAgICAgIGlmIChleGlzdHNTeW5jKHBhY2thZ2VKc29uUGF0aCkpIHtcbiAgICAgICAgYXdhaXQgZmlsdGVyVGFyZ2V0c0luUGFja2FnZUpzb24ocGFja2FnZUpzb25QYXRoLCBvcHRpb25zLnRhcmdldHMpXG4gICAgICB9XG5cbiAgICAgIC8vIEZpbHRlciB0YXJnZXRzIGluIEdpdEh1YiBBY3Rpb25zIENJXG4gICAgICBjb25zdCBjaVBhdGggPSBwYXRoLmpvaW4ob3B0aW9ucy5wYXRoLCAnLmdpdGh1YicsICd3b3JrZmxvd3MnLCAnQ0kueW1sJylcbiAgICAgIGlmIChleGlzdHNTeW5jKGNpUGF0aCkgJiYgb3B0aW9ucy5lbmFibGVHaXRodWJBY3Rpb25zKSB7XG4gICAgICAgIGF3YWl0IGZpbHRlclRhcmdldHNJbkdpdGh1YkFjdGlvbnMoY2lQYXRoLCBvcHRpb25zLnRhcmdldHMpXG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAhb3B0aW9ucy5lbmFibGVHaXRodWJBY3Rpb25zICYmXG4gICAgICAgIGV4aXN0c1N5bmMocGF0aC5qb2luKG9wdGlvbnMucGF0aCwgJy5naXRodWInKSlcbiAgICAgICkge1xuICAgICAgICAvLyBSZW1vdmUgLmdpdGh1YiBkaXJlY3RvcnkgaWYgR2l0SHViIEFjdGlvbnMgaXMgbm90IGVuYWJsZWRcbiAgICAgICAgYXdhaXQgZnMucm0ocGF0aC5qb2luKG9wdGlvbnMucGF0aCwgJy5naXRodWInKSwge1xuICAgICAgICAgIHJlY3Vyc2l2ZTogdHJ1ZSxcbiAgICAgICAgICBmb3JjZTogdHJ1ZSxcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgLy8gVXBkYXRlIHBhY2thZ2UuanNvbiB3aXRoIGFkZGl0aW9uYWwgY29uZmlndXJhdGlvbnNcbiAgICAgIGNvbnN0IHBrZ0pzb25Db250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUocGFja2FnZUpzb25QYXRoLCAndXRmLTgnKVxuICAgICAgY29uc3QgcGtnSnNvbiA9IEpTT04ucGFyc2UocGtnSnNvbkNvbnRlbnQpXG5cbiAgICAgIC8vIFVwZGF0ZSBlbmdpbmUgcmVxdWlyZW1lbnRcbiAgICAgIGlmICghcGtnSnNvbi5lbmdpbmVzKSB7XG4gICAgICAgIHBrZ0pzb24uZW5naW5lcyA9IHt9XG4gICAgICB9XG4gICAgICBwa2dKc29uLmVuZ2luZXMubm9kZSA9IG5hcGlFbmdpbmVSZXF1aXJlbWVudChvcHRpb25zLm1pbk5vZGVBcGlWZXJzaW9uKVxuXG4gICAgICAvLyBVcGRhdGUgbGljZW5zZSBpZiBkaWZmZXJlbnQgZnJvbSB0ZW1wbGF0ZVxuICAgICAgaWYgKG9wdGlvbnMubGljZW5zZSAmJiBwa2dKc29uLmxpY2Vuc2UgIT09IG9wdGlvbnMubGljZW5zZSkge1xuICAgICAgICBwa2dKc29uLmxpY2Vuc2UgPSBvcHRpb25zLmxpY2Vuc2VcbiAgICAgIH1cblxuICAgICAgLy8gVXBkYXRlIHRlc3QgZnJhbWV3b3JrIGlmIG5lZWRlZFxuICAgICAgaWYgKG9wdGlvbnMudGVzdEZyYW1ld29yayAhPT0gJ2F2YScpIHtcbiAgICAgICAgLy8gVGhpcyB3b3VsZCByZXF1aXJlIG1vcmUgY29tcGxleCBsb2dpYyB0byB1cGRhdGUgdGVzdCBzY3JpcHRzIGFuZCBkZXBlbmRlbmNpZXNcbiAgICAgICAgZGVidWcoXG4gICAgICAgICAgYFRlc3QgZnJhbWV3b3JrICR7b3B0aW9ucy50ZXN0RnJhbWV3b3JrfSByZXF1ZXN0ZWQgYnV0IG5vdCB5ZXQgaW1wbGVtZW50ZWRgLFxuICAgICAgICApXG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGZzLndyaXRlRmlsZShcbiAgICAgICAgcGFja2FnZUpzb25QYXRoLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShwa2dKc29uLCBudWxsLCAyKSArICdcXG4nLFxuICAgICAgKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBjcmVhdGUgcHJvamVjdDogJHtlcnJvcn1gKVxuICAgIH1cbiAgfVxuXG4gIGRlYnVnKGBQcm9qZWN0IGNyZWF0ZWQgYXQ6ICR7b3B0aW9ucy5wYXRofWApXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGVuc3VyZVBhdGgocGF0aDogc3RyaW5nLCBkcnlSdW4gPSBmYWxzZSkge1xuICBjb25zdCBzdGF0ID0gYXdhaXQgc3RhdEFzeW5jKHBhdGgsIHt9KS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpXG5cbiAgLy8gZmlsZSBkZXNjcmlwdG9yIGV4aXN0c1xuICBpZiAoc3RhdCkge1xuICAgIGlmIChzdGF0LmlzRmlsZSgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBQYXRoICR7cGF0aH0gZm9yIGNyZWF0aW5nIG5ldyBuYXBpLXJzIHByb2plY3QgYWxyZWFkeSBleGlzdHMgYW5kIGl0J3Mgbm90IGEgZGlyZWN0b3J5LmAsXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChzdGF0LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgcmVhZGRpckFzeW5jKHBhdGgpXG4gICAgICBpZiAoZmlsZXMubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgUGF0aCAke3BhdGh9IGZvciBjcmVhdGluZyBuZXcgbmFwaS1ycyBwcm9qZWN0IGFscmVhZHkgZXhpc3RzIGFuZCBpdCdzIG5vdCBlbXB0eS5gLFxuICAgICAgICApXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKCFkcnlSdW4pIHtcbiAgICB0cnkge1xuICAgICAgZGVidWcoYFRyeSB0byBjcmVhdGUgdGFyZ2V0IGRpcmVjdG9yeTogJHtwYXRofWApXG4gICAgICBpZiAoIWRyeVJ1bikge1xuICAgICAgICBhd2FpdCBta2RpckFzeW5jKHBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gY3JlYXRlIHRhcmdldCBkaXJlY3Rvcnk6ICR7cGF0aH1gLCB7XG4gICAgICAgIGNhdXNlOiBlLFxuICAgICAgfSlcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0QmluYXJ5TmFtZShuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gbmFtZS5zcGxpdCgnLycpLnBvcCgpIVxufVxuXG5leHBvcnQgeyBOZXdPcHRpb25zIH1cbiIsIi8vIFRoaXMgZmlsZSBpcyBnZW5lcmF0ZWQgYnkgY29kZWdlbi9pbmRleC50c1xuLy8gRG8gbm90IGVkaXQgdGhpcyBmaWxlIG1hbnVhbGx5XG5pbXBvcnQgeyBDb21tYW5kLCBPcHRpb24gfSBmcm9tICdjbGlwYW5pb24nXG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCYXNlUHJlUHVibGlzaENvbW1hbmQgZXh0ZW5kcyBDb21tYW5kIHtcbiAgc3RhdGljIHBhdGhzID0gW1sncHJlLXB1Ymxpc2gnXSwgWydwcmVwdWJsaXNoJ11dXG5cbiAgc3RhdGljIHVzYWdlID0gQ29tbWFuZC5Vc2FnZSh7XG4gICAgZGVzY3JpcHRpb246XG4gICAgICAnVXBkYXRlIHBhY2thZ2UuanNvbiBhbmQgY29weSBhZGRvbnMgaW50byBwZXIgcGxhdGZvcm0gcGFja2FnZXMnLFxuICB9KVxuXG4gIGN3ZCA9IE9wdGlvbi5TdHJpbmcoJy0tY3dkJywgcHJvY2Vzcy5jd2QoKSwge1xuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgJ1RoZSB3b3JraW5nIGRpcmVjdG9yeSBvZiB3aGVyZSBuYXBpIGNvbW1hbmQgd2lsbCBiZSBleGVjdXRlZCBpbiwgYWxsIG90aGVyIHBhdGhzIG9wdGlvbnMgYXJlIHJlbGF0aXZlIHRvIHRoaXMgcGF0aCcsXG4gIH0pXG5cbiAgY29uZmlnUGF0aD86IHN0cmluZyA9IE9wdGlvbi5TdHJpbmcoJy0tY29uZmlnLXBhdGgsLWMnLCB7XG4gICAgZGVzY3JpcHRpb246ICdQYXRoIHRvIGBuYXBpYCBjb25maWcganNvbiBmaWxlJyxcbiAgfSlcblxuICBwYWNrYWdlSnNvblBhdGggPSBPcHRpb24uU3RyaW5nKCctLXBhY2thZ2UtanNvbi1wYXRoJywgJ3BhY2thZ2UuanNvbicsIHtcbiAgICBkZXNjcmlwdGlvbjogJ1BhdGggdG8gYHBhY2thZ2UuanNvbmAnLFxuICB9KVxuXG4gIG5wbURpciA9IE9wdGlvbi5TdHJpbmcoJy0tbnBtLWRpciwtcCcsICducG0nLCB7XG4gICAgZGVzY3JpcHRpb246ICdQYXRoIHRvIHRoZSBmb2xkZXIgd2hlcmUgdGhlIG5wbSBwYWNrYWdlcyBwdXQnLFxuICB9KVxuXG4gIHRhZ1N0eWxlID0gT3B0aW9uLlN0cmluZygnLS10YWctc3R5bGUsLS10YWdzdHlsZSwtdCcsICdsZXJuYScsIHtcbiAgICBkZXNjcmlwdGlvbjogJ2dpdCB0YWcgc3R5bGUsIGBucG1gIG9yIGBsZXJuYWAnLFxuICB9KVxuXG4gIGdoUmVsZWFzZSA9IE9wdGlvbi5Cb29sZWFuKCctLWdoLXJlbGVhc2UnLCB0cnVlLCB7XG4gICAgZGVzY3JpcHRpb246ICdXaGV0aGVyIGNyZWF0ZSBHaXRIdWIgcmVsZWFzZScsXG4gIH0pXG5cbiAgZ2hSZWxlYXNlTmFtZT86IHN0cmluZyA9IE9wdGlvbi5TdHJpbmcoJy0tZ2gtcmVsZWFzZS1uYW1lJywge1xuICAgIGRlc2NyaXB0aW9uOiAnR2l0SHViIHJlbGVhc2UgbmFtZScsXG4gIH0pXG5cbiAgZ2hSZWxlYXNlSWQ/OiBzdHJpbmcgPSBPcHRpb24uU3RyaW5nKCctLWdoLXJlbGVhc2UtaWQnLCB7XG4gICAgZGVzY3JpcHRpb246ICdFeGlzdGluZyBHaXRIdWIgcmVsZWFzZSBpZCcsXG4gIH0pXG5cbiAgZHJ5UnVuID0gT3B0aW9uLkJvb2xlYW4oJy0tZHJ5LXJ1bicsIGZhbHNlLCB7XG4gICAgZGVzY3JpcHRpb246ICdEcnkgcnVuIHdpdGhvdXQgdG91Y2hpbmcgZmlsZSBzeXN0ZW0nLFxuICB9KVxuXG4gIGdldE9wdGlvbnMoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGN3ZDogdGhpcy5jd2QsXG4gICAgICBjb25maWdQYXRoOiB0aGlzLmNvbmZpZ1BhdGgsXG4gICAgICBwYWNrYWdlSnNvblBhdGg6IHRoaXMucGFja2FnZUpzb25QYXRoLFxuICAgICAgbnBtRGlyOiB0aGlzLm5wbURpcixcbiAgICAgIHRhZ1N0eWxlOiB0aGlzLnRhZ1N0eWxlLFxuICAgICAgZ2hSZWxlYXNlOiB0aGlzLmdoUmVsZWFzZSxcbiAgICAgIGdoUmVsZWFzZU5hbWU6IHRoaXMuZ2hSZWxlYXNlTmFtZSxcbiAgICAgIGdoUmVsZWFzZUlkOiB0aGlzLmdoUmVsZWFzZUlkLFxuICAgICAgZHJ5UnVuOiB0aGlzLmRyeVJ1bixcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBVcGRhdGUgcGFja2FnZS5qc29uIGFuZCBjb3B5IGFkZG9ucyBpbnRvIHBlciBwbGF0Zm9ybSBwYWNrYWdlc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFByZVB1Ymxpc2hPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSB3b3JraW5nIGRpcmVjdG9yeSBvZiB3aGVyZSBuYXBpIGNvbW1hbmQgd2lsbCBiZSBleGVjdXRlZCBpbiwgYWxsIG90aGVyIHBhdGhzIG9wdGlvbnMgYXJlIHJlbGF0aXZlIHRvIHRoaXMgcGF0aFxuICAgKlxuICAgKiBAZGVmYXVsdCBwcm9jZXNzLmN3ZCgpXG4gICAqL1xuICBjd2Q/OiBzdHJpbmdcbiAgLyoqXG4gICAqIFBhdGggdG8gYG5hcGlgIGNvbmZpZyBqc29uIGZpbGVcbiAgICovXG4gIGNvbmZpZ1BhdGg/OiBzdHJpbmdcbiAgLyoqXG4gICAqIFBhdGggdG8gYHBhY2thZ2UuanNvbmBcbiAgICpcbiAgICogQGRlZmF1bHQgJ3BhY2thZ2UuanNvbidcbiAgICovXG4gIHBhY2thZ2VKc29uUGF0aD86IHN0cmluZ1xuICAvKipcbiAgICogUGF0aCB0byB0aGUgZm9sZGVyIHdoZXJlIHRoZSBucG0gcGFja2FnZXMgcHV0XG4gICAqXG4gICAqIEBkZWZhdWx0ICducG0nXG4gICAqL1xuICBucG1EaXI/OiBzdHJpbmdcbiAgLyoqXG4gICAqIGdpdCB0YWcgc3R5bGUsIGBucG1gIG9yIGBsZXJuYWBcbiAgICpcbiAgICogQGRlZmF1bHQgJ2xlcm5hJ1xuICAgKi9cbiAgdGFnU3R5bGU/OiAnbnBtJyB8ICdsZXJuYSdcbiAgLyoqXG4gICAqIFdoZXRoZXIgY3JlYXRlIEdpdEh1YiByZWxlYXNlXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIGdoUmVsZWFzZT86IGJvb2xlYW5cbiAgLyoqXG4gICAqIEdpdEh1YiByZWxlYXNlIG5hbWVcbiAgICovXG4gIGdoUmVsZWFzZU5hbWU/OiBzdHJpbmdcbiAgLyoqXG4gICAqIEV4aXN0aW5nIEdpdEh1YiByZWxlYXNlIGlkXG4gICAqL1xuICBnaFJlbGVhc2VJZD86IHN0cmluZ1xuICAvKipcbiAgICogRHJ5IHJ1biB3aXRob3V0IHRvdWNoaW5nIGZpbGUgc3lzdGVtXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICBkcnlSdW4/OiBib29sZWFuXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseURlZmF1bHRQcmVQdWJsaXNoT3B0aW9ucyhvcHRpb25zOiBQcmVQdWJsaXNoT3B0aW9ucykge1xuICByZXR1cm4ge1xuICAgIGN3ZDogcHJvY2Vzcy5jd2QoKSxcbiAgICBwYWNrYWdlSnNvblBhdGg6ICdwYWNrYWdlLmpzb24nLFxuICAgIG5wbURpcjogJ25wbScsXG4gICAgdGFnU3R5bGU6ICdsZXJuYScsXG4gICAgZ2hSZWxlYXNlOiB0cnVlLFxuICAgIGRyeVJ1bjogZmFsc2UsXG4gICAgLi4ub3B0aW9ucyxcbiAgfVxufVxuIiwiLy8gVGhpcyBmaWxlIGlzIGdlbmVyYXRlZCBieSBjb2RlZ2VuL2luZGV4LnRzXG4vLyBEbyBub3QgZWRpdCB0aGlzIGZpbGUgbWFudWFsbHlcbmltcG9ydCB7IENvbW1hbmQsIE9wdGlvbiB9IGZyb20gJ2NsaXBhbmlvbidcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VWZXJzaW9uQ29tbWFuZCBleHRlbmRzIENvbW1hbmQge1xuICBzdGF0aWMgcGF0aHMgPSBbWyd2ZXJzaW9uJ11dXG5cbiAgc3RhdGljIHVzYWdlID0gQ29tbWFuZC5Vc2FnZSh7XG4gICAgZGVzY3JpcHRpb246ICdVcGRhdGUgdmVyc2lvbiBpbiBjcmVhdGVkIG5wbSBwYWNrYWdlcycsXG4gIH0pXG5cbiAgY3dkID0gT3B0aW9uLlN0cmluZygnLS1jd2QnLCBwcm9jZXNzLmN3ZCgpLCB7XG4gICAgZGVzY3JpcHRpb246XG4gICAgICAnVGhlIHdvcmtpbmcgZGlyZWN0b3J5IG9mIHdoZXJlIG5hcGkgY29tbWFuZCB3aWxsIGJlIGV4ZWN1dGVkIGluLCBhbGwgb3RoZXIgcGF0aHMgb3B0aW9ucyBhcmUgcmVsYXRpdmUgdG8gdGhpcyBwYXRoJyxcbiAgfSlcblxuICBjb25maWdQYXRoPzogc3RyaW5nID0gT3B0aW9uLlN0cmluZygnLS1jb25maWctcGF0aCwtYycsIHtcbiAgICBkZXNjcmlwdGlvbjogJ1BhdGggdG8gYG5hcGlgIGNvbmZpZyBqc29uIGZpbGUnLFxuICB9KVxuXG4gIHBhY2thZ2VKc29uUGF0aCA9IE9wdGlvbi5TdHJpbmcoJy0tcGFja2FnZS1qc29uLXBhdGgnLCAncGFja2FnZS5qc29uJywge1xuICAgIGRlc2NyaXB0aW9uOiAnUGF0aCB0byBgcGFja2FnZS5qc29uYCcsXG4gIH0pXG5cbiAgbnBtRGlyID0gT3B0aW9uLlN0cmluZygnLS1ucG0tZGlyJywgJ25wbScsIHtcbiAgICBkZXNjcmlwdGlvbjogJ1BhdGggdG8gdGhlIGZvbGRlciB3aGVyZSB0aGUgbnBtIHBhY2thZ2VzIHB1dCcsXG4gIH0pXG5cbiAgZ2V0T3B0aW9ucygpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY3dkOiB0aGlzLmN3ZCxcbiAgICAgIGNvbmZpZ1BhdGg6IHRoaXMuY29uZmlnUGF0aCxcbiAgICAgIHBhY2thZ2VKc29uUGF0aDogdGhpcy5wYWNrYWdlSnNvblBhdGgsXG4gICAgICBucG1EaXI6IHRoaXMubnBtRGlyLFxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFVwZGF0ZSB2ZXJzaW9uIGluIGNyZWF0ZWQgbnBtIHBhY2thZ2VzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmVyc2lvbk9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIHdvcmtpbmcgZGlyZWN0b3J5IG9mIHdoZXJlIG5hcGkgY29tbWFuZCB3aWxsIGJlIGV4ZWN1dGVkIGluLCBhbGwgb3RoZXIgcGF0aHMgb3B0aW9ucyBhcmUgcmVsYXRpdmUgdG8gdGhpcyBwYXRoXG4gICAqXG4gICAqIEBkZWZhdWx0IHByb2Nlc3MuY3dkKClcbiAgICovXG4gIGN3ZD86IHN0cmluZ1xuICAvKipcbiAgICogUGF0aCB0byBgbmFwaWAgY29uZmlnIGpzb24gZmlsZVxuICAgKi9cbiAgY29uZmlnUGF0aD86IHN0cmluZ1xuICAvKipcbiAgICogUGF0aCB0byBgcGFja2FnZS5qc29uYFxuICAgKlxuICAgKiBAZGVmYXVsdCAncGFja2FnZS5qc29uJ1xuICAgKi9cbiAgcGFja2FnZUpzb25QYXRoPzogc3RyaW5nXG4gIC8qKlxuICAgKiBQYXRoIHRvIHRoZSBmb2xkZXIgd2hlcmUgdGhlIG5wbSBwYWNrYWdlcyBwdXRcbiAgICpcbiAgICogQGRlZmF1bHQgJ25wbSdcbiAgICovXG4gIG5wbURpcj86IHN0cmluZ1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlEZWZhdWx0VmVyc2lvbk9wdGlvbnMob3B0aW9uczogVmVyc2lvbk9wdGlvbnMpIHtcbiAgcmV0dXJuIHtcbiAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgcGFja2FnZUpzb25QYXRoOiAncGFja2FnZS5qc29uJyxcbiAgICBucG1EaXI6ICducG0nLFxuICAgIC4uLm9wdGlvbnMsXG4gIH1cbn1cbiIsImltcG9ydCB7IGpvaW4sIHJlc29sdmUgfSBmcm9tICdub2RlOnBhdGgnXG5cbmltcG9ydCB7IGFwcGx5RGVmYXVsdFZlcnNpb25PcHRpb25zLCBWZXJzaW9uT3B0aW9ucyB9IGZyb20gJy4uL2RlZi92ZXJzaW9uLmpzJ1xuaW1wb3J0IHtcbiAgcmVhZE5hcGlDb25maWcsXG4gIGRlYnVnRmFjdG9yeSxcbiAgdXBkYXRlUGFja2FnZUpzb24sXG59IGZyb20gJy4uL3V0aWxzL2luZGV4LmpzJ1xuXG5jb25zdCBkZWJ1ZyA9IGRlYnVnRmFjdG9yeSgndmVyc2lvbicpXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJzaW9uKHVzZXJPcHRpb25zOiBWZXJzaW9uT3B0aW9ucykge1xuICBjb25zdCBvcHRpb25zID0gYXBwbHlEZWZhdWx0VmVyc2lvbk9wdGlvbnModXNlck9wdGlvbnMpXG4gIGNvbnN0IHBhY2thZ2VKc29uUGF0aCA9IHJlc29sdmUob3B0aW9ucy5jd2QsIG9wdGlvbnMucGFja2FnZUpzb25QYXRoKVxuXG4gIGNvbnN0IGNvbmZpZyA9IGF3YWl0IHJlYWROYXBpQ29uZmlnKFxuICAgIHBhY2thZ2VKc29uUGF0aCxcbiAgICBvcHRpb25zLmNvbmZpZ1BhdGggPyByZXNvbHZlKG9wdGlvbnMuY3dkLCBvcHRpb25zLmNvbmZpZ1BhdGgpIDogdW5kZWZpbmVkLFxuICApXG5cbiAgZm9yIChjb25zdCB0YXJnZXQgb2YgY29uZmlnLnRhcmdldHMpIHtcbiAgICBjb25zdCBwa2dEaXIgPSByZXNvbHZlKG9wdGlvbnMuY3dkLCBvcHRpb25zLm5wbURpciwgdGFyZ2V0LnBsYXRmb3JtQXJjaEFCSSlcblxuICAgIGRlYnVnKGBVcGRhdGUgdmVyc2lvbiB0byAlaSBpbiBbJWldYCwgY29uZmlnLnBhY2thZ2VKc29uLnZlcnNpb24sIHBrZ0RpcilcbiAgICBhd2FpdCB1cGRhdGVQYWNrYWdlSnNvbihqb2luKHBrZ0RpciwgJ3BhY2thZ2UuanNvbicpLCB7XG4gICAgICB2ZXJzaW9uOiBjb25maWcucGFja2FnZUpzb24udmVyc2lvbixcbiAgICB9KVxuICB9XG59XG4iLCJpbXBvcnQgeyBleGVjU3luYyB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2VzcydcbmltcG9ydCB7IGV4aXN0c1N5bmMsIHN0YXRTeW5jIH0gZnJvbSAnbm9kZTpmcydcbmltcG9ydCB7IGpvaW4sIHJlc29sdmUgfSBmcm9tICdub2RlOnBhdGgnXG5cbmltcG9ydCB7IE9jdG9raXQgfSBmcm9tICdAb2N0b2tpdC9yZXN0J1xuXG5pbXBvcnQge1xuICBhcHBseURlZmF1bHRQcmVQdWJsaXNoT3B0aW9ucyxcbiAgUHJlUHVibGlzaE9wdGlvbnMsXG59IGZyb20gJy4uL2RlZi9wcmUtcHVibGlzaC5qcydcbmltcG9ydCB7XG4gIHJlYWRGaWxlQXN5bmMsXG4gIHJlYWROYXBpQ29uZmlnLFxuICBkZWJ1Z0ZhY3RvcnksXG4gIHVwZGF0ZVBhY2thZ2VKc29uLFxufSBmcm9tICcuLi91dGlscy9pbmRleC5qcydcblxuaW1wb3J0IHsgdmVyc2lvbiB9IGZyb20gJy4vdmVyc2lvbi5qcydcblxuY29uc3QgZGVidWcgPSBkZWJ1Z0ZhY3RvcnkoJ3ByZS1wdWJsaXNoJylcblxuaW50ZXJmYWNlIFBhY2thZ2VJbmZvIHtcbiAgbmFtZTogc3RyaW5nXG4gIHZlcnNpb246IHN0cmluZ1xuICB0YWc6IHN0cmluZ1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJlUHVibGlzaCh1c2VyT3B0aW9uczogUHJlUHVibGlzaE9wdGlvbnMpIHtcbiAgZGVidWcoJ1JlY2VpdmUgcHJlLXB1Ymxpc2ggb3B0aW9uczonKVxuICBkZWJ1ZygnICAlTycsIHVzZXJPcHRpb25zKVxuXG4gIGNvbnN0IG9wdGlvbnMgPSBhcHBseURlZmF1bHRQcmVQdWJsaXNoT3B0aW9ucyh1c2VyT3B0aW9ucylcblxuICBjb25zdCBwYWNrYWdlSnNvblBhdGggPSByZXNvbHZlKG9wdGlvbnMuY3dkLCBvcHRpb25zLnBhY2thZ2VKc29uUGF0aClcblxuICBjb25zdCB7IHBhY2thZ2VKc29uLCB0YXJnZXRzLCBwYWNrYWdlTmFtZSwgYmluYXJ5TmFtZSwgbnBtQ2xpZW50IH0gPVxuICAgIGF3YWl0IHJlYWROYXBpQ29uZmlnKFxuICAgICAgcGFja2FnZUpzb25QYXRoLFxuICAgICAgb3B0aW9ucy5jb25maWdQYXRoID8gcmVzb2x2ZShvcHRpb25zLmN3ZCwgb3B0aW9ucy5jb25maWdQYXRoKSA6IHVuZGVmaW5lZCxcbiAgICApXG5cbiAgYXN5bmMgZnVuY3Rpb24gY3JlYXRlR2hSZWxlYXNlKHBhY2thZ2VOYW1lOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZykge1xuICAgIGlmICghb3B0aW9ucy5naFJlbGVhc2UpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG93bmVyOiBudWxsLFxuICAgICAgICByZXBvOiBudWxsLFxuICAgICAgICBwa2dJbmZvOiB7IG5hbWU6IG51bGwsIHZlcnNpb246IG51bGwsIHRhZzogbnVsbCB9LFxuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCB7IHJlcG8sIG93bmVyLCBwa2dJbmZvLCBvY3Rva2l0IH0gPSBnZXRSZXBvSW5mbyhwYWNrYWdlTmFtZSwgdmVyc2lvbilcblxuICAgIGlmICghcmVwbyB8fCAhb3duZXIpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG93bmVyOiBudWxsLFxuICAgICAgICByZXBvOiBudWxsLFxuICAgICAgICBwa2dJbmZvOiB7IG5hbWU6IG51bGwsIHZlcnNpb246IG51bGwsIHRhZzogbnVsbCB9LFxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghb3B0aW9ucy5kcnlSdW4pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IG9jdG9raXQucmVwb3MuY3JlYXRlUmVsZWFzZSh7XG4gICAgICAgICAgb3duZXIsXG4gICAgICAgICAgcmVwbyxcbiAgICAgICAgICB0YWdfbmFtZTogcGtnSW5mby50YWcsXG4gICAgICAgICAgbmFtZTogb3B0aW9ucy5naFJlbGVhc2VOYW1lLFxuICAgICAgICAgIHByZXJlbGVhc2U6XG4gICAgICAgICAgICB2ZXJzaW9uLmluY2x1ZGVzKCdhbHBoYScpIHx8XG4gICAgICAgICAgICB2ZXJzaW9uLmluY2x1ZGVzKCdiZXRhJykgfHxcbiAgICAgICAgICAgIHZlcnNpb24uaW5jbHVkZXMoJ3JjJyksXG4gICAgICAgIH0pXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGRlYnVnKFxuICAgICAgICAgIGBQYXJhbXM6ICR7SlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgICB7IG93bmVyLCByZXBvLCB0YWdfbmFtZTogcGtnSW5mby50YWcgfSxcbiAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICAyLFxuICAgICAgICAgICl9YCxcbiAgICAgICAgKVxuICAgICAgICBjb25zb2xlLmVycm9yKGUpXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IG93bmVyLCByZXBvLCBwa2dJbmZvLCBvY3Rva2l0IH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGdldFJlcG9JbmZvKHBhY2thZ2VOYW1lOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZykge1xuICAgIGNvbnN0IGhlYWRDb21taXQgPSBleGVjU3luYygnZ2l0IGxvZyAtMSAtLXByZXR0eT0lQicsIHtcbiAgICAgIGVuY29kaW5nOiAndXRmLTgnLFxuICAgIH0pLnRyaW0oKVxuXG4gICAgY29uc3QgeyBHSVRIVUJfUkVQT1NJVE9SWSB9ID0gcHJvY2Vzcy5lbnZcbiAgICBpZiAoIUdJVEhVQl9SRVBPU0lUT1JZKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBvd25lcjogbnVsbCxcbiAgICAgICAgcmVwbzogbnVsbCxcbiAgICAgICAgcGtnSW5mbzogeyBuYW1lOiBudWxsLCB2ZXJzaW9uOiBudWxsLCB0YWc6IG51bGwgfSxcbiAgICAgIH1cbiAgICB9XG4gICAgZGVidWcoYEdpdGh1YiByZXBvc2l0b3J5OiAke0dJVEhVQl9SRVBPU0lUT1JZfWApXG4gICAgY29uc3QgW293bmVyLCByZXBvXSA9IEdJVEhVQl9SRVBPU0lUT1JZLnNwbGl0KCcvJylcbiAgICBjb25zdCBvY3Rva2l0ID0gbmV3IE9jdG9raXQoe1xuICAgICAgYXV0aDogcHJvY2Vzcy5lbnYuR0lUSFVCX1RPS0VOLFxuICAgIH0pXG4gICAgbGV0IHBrZ0luZm86IFBhY2thZ2VJbmZvIHwgdW5kZWZpbmVkXG4gICAgaWYgKG9wdGlvbnMudGFnU3R5bGUgPT09ICdsZXJuYScpIHtcbiAgICAgIGNvbnN0IHBhY2thZ2VzVG9QdWJsaXNoID0gaGVhZENvbW1pdFxuICAgICAgICAuc3BsaXQoJ1xcbicpXG4gICAgICAgIC5tYXAoKGxpbmUpID0+IGxpbmUudHJpbSgpKVxuICAgICAgICAuZmlsdGVyKChsaW5lLCBpbmRleCkgPT4gbGluZS5sZW5ndGggJiYgaW5kZXgpXG4gICAgICAgIC5tYXAoKGxpbmUpID0+IGxpbmUuc3Vic3RyaW5nKDIpKVxuICAgICAgICAubWFwKHBhcnNlVGFnKVxuXG4gICAgICBwa2dJbmZvID0gcGFja2FnZXNUb1B1Ymxpc2guZmluZChcbiAgICAgICAgKHBrZ0luZm8pID0+IHBrZ0luZm8ubmFtZSA9PT0gcGFja2FnZU5hbWUsXG4gICAgICApXG5cbiAgICAgIGlmICghcGtnSW5mbykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgIGBObyByZWxlYXNlIGNvbW1pdCBmb3VuZCB3aXRoICR7cGFja2FnZU5hbWV9LCBvcmlnaW5hbCBjb21taXQgaW5mbzogJHtoZWFkQ29tbWl0fWAsXG4gICAgICAgIClcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcGtnSW5mbyA9IHtcbiAgICAgICAgdGFnOiBgdiR7dmVyc2lvbn1gLFxuICAgICAgICB2ZXJzaW9uLFxuICAgICAgICBuYW1lOiBwYWNrYWdlTmFtZSxcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHsgb3duZXIsIHJlcG8sIHBrZ0luZm8sIG9jdG9raXQgfVxuICB9XG5cbiAgaWYgKCFvcHRpb25zLmRyeVJ1bikge1xuICAgIGF3YWl0IHZlcnNpb24odXNlck9wdGlvbnMpXG4gICAgYXdhaXQgdXBkYXRlUGFja2FnZUpzb24ocGFja2FnZUpzb25QYXRoLCB7XG4gICAgICBvcHRpb25hbERlcGVuZGVuY2llczogdGFyZ2V0cy5yZWR1Y2UoXG4gICAgICAgIChkZXBzLCB0YXJnZXQpID0+IHtcbiAgICAgICAgICBkZXBzW2Ake3BhY2thZ2VOYW1lfS0ke3RhcmdldC5wbGF0Zm9ybUFyY2hBQkl9YF0gPSBwYWNrYWdlSnNvbi52ZXJzaW9uXG5cbiAgICAgICAgICByZXR1cm4gZGVwc1xuICAgICAgICB9LFxuICAgICAgICB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICAgICAgKSxcbiAgICB9KVxuICB9XG5cbiAgY29uc3QgeyBvd25lciwgcmVwbywgcGtnSW5mbywgb2N0b2tpdCB9ID0gb3B0aW9ucy5naFJlbGVhc2VJZFxuICAgID8gZ2V0UmVwb0luZm8ocGFja2FnZU5hbWUsIHBhY2thZ2VKc29uLnZlcnNpb24pXG4gICAgOiBhd2FpdCBjcmVhdGVHaFJlbGVhc2UocGFja2FnZU5hbWUsIHBhY2thZ2VKc29uLnZlcnNpb24pXG5cbiAgZm9yIChjb25zdCB0YXJnZXQgb2YgdGFyZ2V0cykge1xuICAgIGNvbnN0IHBrZ0RpciA9IHJlc29sdmUoXG4gICAgICBvcHRpb25zLmN3ZCxcbiAgICAgIG9wdGlvbnMubnBtRGlyLFxuICAgICAgYCR7dGFyZ2V0LnBsYXRmb3JtQXJjaEFCSX1gLFxuICAgIClcbiAgICBjb25zdCBleHQgPVxuICAgICAgdGFyZ2V0LnBsYXRmb3JtID09PSAnd2FzaScgfHwgdGFyZ2V0LnBsYXRmb3JtID09PSAnd2FzbScgPyAnd2FzbScgOiAnbm9kZSdcbiAgICBjb25zdCBmaWxlbmFtZSA9IGAke2JpbmFyeU5hbWV9LiR7dGFyZ2V0LnBsYXRmb3JtQXJjaEFCSX0uJHtleHR9YFxuICAgIGNvbnN0IGRzdFBhdGggPSBqb2luKHBrZ0RpciwgZmlsZW5hbWUpXG5cbiAgICBpZiAoIW9wdGlvbnMuZHJ5UnVuKSB7XG4gICAgICBpZiAoIWV4aXN0c1N5bmMoZHN0UGF0aCkpIHtcbiAgICAgICAgZGVidWcud2FybihgJXMgZG9lc24ndCBleGlzdGAsIGRzdFBhdGgpXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGV4ZWNTeW5jKGAke25wbUNsaWVudH0gcHVibGlzaGAsIHtcbiAgICAgICAgY3dkOiBwa2dEaXIsXG4gICAgICAgIGVudjogcHJvY2Vzcy5lbnYsXG4gICAgICB9KVxuXG4gICAgICBpZiAob3B0aW9ucy5naFJlbGVhc2UgJiYgcmVwbyAmJiBvd25lcikge1xuICAgICAgICBkZWJ1Zy5pbmZvKGBDcmVhdGluZyBHaXRIdWIgcmVsZWFzZSAke3BrZ0luZm8udGFnfWApXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVsZWFzZUlkID0gb3B0aW9ucy5naFJlbGVhc2VJZFxuICAgICAgICAgICAgPyBOdW1iZXIob3B0aW9ucy5naFJlbGVhc2VJZClcbiAgICAgICAgICAgIDogKFxuICAgICAgICAgICAgICAgIGF3YWl0IG9jdG9raXQhLnJlcG9zLmdldFJlbGVhc2VCeVRhZyh7XG4gICAgICAgICAgICAgICAgICByZXBvOiByZXBvLFxuICAgICAgICAgICAgICAgICAgb3duZXI6IG93bmVyLFxuICAgICAgICAgICAgICAgICAgdGFnOiBwa2dJbmZvLnRhZyxcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICApLmRhdGEuaWRcbiAgICAgICAgICBjb25zdCBkc3RGaWxlU3RhdHMgPSBzdGF0U3luYyhkc3RQYXRoKVxuICAgICAgICAgIGNvbnN0IGFzc2V0SW5mbyA9IGF3YWl0IG9jdG9raXQhLnJlcG9zLnVwbG9hZFJlbGVhc2VBc3NldCh7XG4gICAgICAgICAgICBvd25lcjogb3duZXIsXG4gICAgICAgICAgICByZXBvOiByZXBvLFxuICAgICAgICAgICAgbmFtZTogZmlsZW5hbWUsXG4gICAgICAgICAgICByZWxlYXNlX2lkOiByZWxlYXNlSWQsXG4gICAgICAgICAgICBtZWRpYVR5cGU6IHsgZm9ybWF0OiAncmF3JyB9LFxuICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAnY29udGVudC1sZW5ndGgnOiBkc3RGaWxlU3RhdHMuc2l6ZSxcbiAgICAgICAgICAgICAgJ2NvbnRlbnQtdHlwZSc6ICdhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0nLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3Igb2N0b2tpdCB0eXBlcyBhcmUgd3JvbmdcbiAgICAgICAgICAgIGRhdGE6IGF3YWl0IHJlYWRGaWxlQXN5bmMoZHN0UGF0aCksXG4gICAgICAgICAgfSlcbiAgICAgICAgICBkZWJ1Zy5pbmZvKGBHaXRIdWIgcmVsZWFzZSBjcmVhdGVkYClcbiAgICAgICAgICBkZWJ1Zy5pbmZvKGBEb3dubG9hZCBVUkw6ICVzYCwgYXNzZXRJbmZvLmRhdGEuYnJvd3Nlcl9kb3dubG9hZF91cmwpXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBkZWJ1Zy5lcnJvcihcbiAgICAgICAgICAgIGBQYXJhbTogJHtKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICAgICAgeyBvd25lciwgcmVwbywgdGFnOiBwa2dJbmZvLnRhZywgZmlsZW5hbWU6IGRzdFBhdGggfSxcbiAgICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgICAgMixcbiAgICAgICAgICAgICl9YCxcbiAgICAgICAgICApXG4gICAgICAgICAgZGVidWcuZXJyb3IoZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVRhZyh0YWc6IHN0cmluZykge1xuICBjb25zdCBzZWdtZW50cyA9IHRhZy5zcGxpdCgnQCcpXG4gIGNvbnN0IHZlcnNpb24gPSBzZWdtZW50cy5wb3AoKSFcbiAgY29uc3QgbmFtZSA9IHNlZ21lbnRzLmpvaW4oJ0AnKVxuXG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICB2ZXJzaW9uLFxuICAgIHRhZyxcbiAgfVxufVxuIiwiLy8gVGhpcyBmaWxlIGlzIGdlbmVyYXRlZCBieSBjb2RlZ2VuL2luZGV4LnRzXG4vLyBEbyBub3QgZWRpdCB0aGlzIGZpbGUgbWFudWFsbHlcbmltcG9ydCB7IENvbW1hbmQsIE9wdGlvbiB9IGZyb20gJ2NsaXBhbmlvbidcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VVbml2ZXJzYWxpemVDb21tYW5kIGV4dGVuZHMgQ29tbWFuZCB7XG4gIHN0YXRpYyBwYXRocyA9IFtbJ3VuaXZlcnNhbGl6ZSddXVxuXG4gIHN0YXRpYyB1c2FnZSA9IENvbW1hbmQuVXNhZ2Uoe1xuICAgIGRlc2NyaXB0aW9uOiAnQ29tYmlsZSBidWlsdCBiaW5hcmllcyBpbnRvIG9uZSB1bml2ZXJzYWwgYmluYXJ5JyxcbiAgfSlcblxuICBjd2QgPSBPcHRpb24uU3RyaW5nKCctLWN3ZCcsIHByb2Nlc3MuY3dkKCksIHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgICdUaGUgd29ya2luZyBkaXJlY3Rvcnkgb2Ygd2hlcmUgbmFwaSBjb21tYW5kIHdpbGwgYmUgZXhlY3V0ZWQgaW4sIGFsbCBvdGhlciBwYXRocyBvcHRpb25zIGFyZSByZWxhdGl2ZSB0byB0aGlzIHBhdGgnLFxuICB9KVxuXG4gIGNvbmZpZ1BhdGg/OiBzdHJpbmcgPSBPcHRpb24uU3RyaW5nKCctLWNvbmZpZy1wYXRoLC1jJywge1xuICAgIGRlc2NyaXB0aW9uOiAnUGF0aCB0byBgbmFwaWAgY29uZmlnIGpzb24gZmlsZScsXG4gIH0pXG5cbiAgcGFja2FnZUpzb25QYXRoID0gT3B0aW9uLlN0cmluZygnLS1wYWNrYWdlLWpzb24tcGF0aCcsICdwYWNrYWdlLmpzb24nLCB7XG4gICAgZGVzY3JpcHRpb246ICdQYXRoIHRvIGBwYWNrYWdlLmpzb25gJyxcbiAgfSlcblxuICBvdXRwdXREaXIgPSBPcHRpb24uU3RyaW5nKCctLW91dHB1dC1kaXIsLW8nLCAnLi8nLCB7XG4gICAgZGVzY3JpcHRpb246XG4gICAgICAnUGF0aCB0byB0aGUgZm9sZGVyIHdoZXJlIGFsbCBidWlsdCBgLm5vZGVgIGZpbGVzIHB1dCwgc2FtZSBhcyBgLS1vdXRwdXQtZGlyYCBvZiBidWlsZCBjb21tYW5kJyxcbiAgfSlcblxuICBnZXRPcHRpb25zKCkge1xuICAgIHJldHVybiB7XG4gICAgICBjd2Q6IHRoaXMuY3dkLFxuICAgICAgY29uZmlnUGF0aDogdGhpcy5jb25maWdQYXRoLFxuICAgICAgcGFja2FnZUpzb25QYXRoOiB0aGlzLnBhY2thZ2VKc29uUGF0aCxcbiAgICAgIG91dHB1dERpcjogdGhpcy5vdXRwdXREaXIsXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ29tYmlsZSBidWlsdCBiaW5hcmllcyBpbnRvIG9uZSB1bml2ZXJzYWwgYmluYXJ5XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVW5pdmVyc2FsaXplT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgd29ya2luZyBkaXJlY3Rvcnkgb2Ygd2hlcmUgbmFwaSBjb21tYW5kIHdpbGwgYmUgZXhlY3V0ZWQgaW4sIGFsbCBvdGhlciBwYXRocyBvcHRpb25zIGFyZSByZWxhdGl2ZSB0byB0aGlzIHBhdGhcbiAgICpcbiAgICogQGRlZmF1bHQgcHJvY2Vzcy5jd2QoKVxuICAgKi9cbiAgY3dkPzogc3RyaW5nXG4gIC8qKlxuICAgKiBQYXRoIHRvIGBuYXBpYCBjb25maWcganNvbiBmaWxlXG4gICAqL1xuICBjb25maWdQYXRoPzogc3RyaW5nXG4gIC8qKlxuICAgKiBQYXRoIHRvIGBwYWNrYWdlLmpzb25gXG4gICAqXG4gICAqIEBkZWZhdWx0ICdwYWNrYWdlLmpzb24nXG4gICAqL1xuICBwYWNrYWdlSnNvblBhdGg/OiBzdHJpbmdcbiAgLyoqXG4gICAqIFBhdGggdG8gdGhlIGZvbGRlciB3aGVyZSBhbGwgYnVpbHQgYC5ub2RlYCBmaWxlcyBwdXQsIHNhbWUgYXMgYC0tb3V0cHV0LWRpcmAgb2YgYnVpbGQgY29tbWFuZFxuICAgKlxuICAgKiBAZGVmYXVsdCAnLi8nXG4gICAqL1xuICBvdXRwdXREaXI/OiBzdHJpbmdcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5RGVmYXVsdFVuaXZlcnNhbGl6ZU9wdGlvbnMob3B0aW9uczogVW5pdmVyc2FsaXplT3B0aW9ucykge1xuICByZXR1cm4ge1xuICAgIGN3ZDogcHJvY2Vzcy5jd2QoKSxcbiAgICBwYWNrYWdlSnNvblBhdGg6ICdwYWNrYWdlLmpzb24nLFxuICAgIG91dHB1dERpcjogJy4vJyxcbiAgICAuLi5vcHRpb25zLFxuICB9XG59XG4iLCJpbXBvcnQgeyBzcGF3blN5bmMgfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnXG5pbXBvcnQgeyBqb2luLCByZXNvbHZlIH0gZnJvbSAnbm9kZTpwYXRoJ1xuXG5pbXBvcnQge1xuICBhcHBseURlZmF1bHRVbml2ZXJzYWxpemVPcHRpb25zLFxuICBVbml2ZXJzYWxpemVPcHRpb25zLFxufSBmcm9tICcuLi9kZWYvdW5pdmVyc2FsaXplLmpzJ1xuaW1wb3J0IHsgcmVhZE5hcGlDb25maWcgfSBmcm9tICcuLi91dGlscy9jb25maWcuanMnXG5pbXBvcnQgeyBkZWJ1Z0ZhY3RvcnkgfSBmcm9tICcuLi91dGlscy9sb2cuanMnXG5pbXBvcnQgeyBmaWxlRXhpc3RzIH0gZnJvbSAnLi4vdXRpbHMvbWlzYy5qcydcbmltcG9ydCB7IFVuaUFyY2hzQnlQbGF0Zm9ybSB9IGZyb20gJy4uL3V0aWxzL3RhcmdldC5qcydcblxuY29uc3QgZGVidWcgPSBkZWJ1Z0ZhY3RvcnkoJ3VuaXZlcnNhbGl6ZScpXG5cbmNvbnN0IHVuaXZlcnNhbGl6ZXJzOiBQYXJ0aWFsPFxuICBSZWNvcmQ8Tm9kZUpTLlBsYXRmb3JtLCAoaW5wdXRzOiBzdHJpbmdbXSwgb3V0cHV0OiBzdHJpbmcpID0+IHZvaWQ+XG4+ID0ge1xuICBkYXJ3aW46IChpbnB1dHMsIG91dHB1dCkgPT4ge1xuICAgIHNwYXduU3luYygnbGlwbycsIFsnLWNyZWF0ZScsICctb3V0cHV0Jywgb3V0cHV0LCAuLi5pbnB1dHNdLCB7XG4gICAgICBzdGRpbzogJ2luaGVyaXQnLFxuICAgIH0pXG4gIH0sXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB1bml2ZXJzYWxpemVCaW5hcmllcyh1c2VyT3B0aW9uczogVW5pdmVyc2FsaXplT3B0aW9ucykge1xuICBjb25zdCBvcHRpb25zID0gYXBwbHlEZWZhdWx0VW5pdmVyc2FsaXplT3B0aW9ucyh1c2VyT3B0aW9ucylcblxuICBjb25zdCBwYWNrYWdlSnNvblBhdGggPSBqb2luKG9wdGlvbnMuY3dkLCBvcHRpb25zLnBhY2thZ2VKc29uUGF0aClcblxuICBjb25zdCBjb25maWcgPSBhd2FpdCByZWFkTmFwaUNvbmZpZyhcbiAgICBwYWNrYWdlSnNvblBhdGgsXG4gICAgb3B0aW9ucy5jb25maWdQYXRoID8gcmVzb2x2ZShvcHRpb25zLmN3ZCwgb3B0aW9ucy5jb25maWdQYXRoKSA6IHVuZGVmaW5lZCxcbiAgKVxuXG4gIGNvbnN0IHRhcmdldCA9IGNvbmZpZy50YXJnZXRzLmZpbmQoXG4gICAgKHQpID0+IHQucGxhdGZvcm0gPT09IHByb2Nlc3MucGxhdGZvcm0gJiYgdC5hcmNoID09PSAndW5pdmVyc2FsJyxcbiAgKVxuXG4gIGlmICghdGFyZ2V0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCd1bml2ZXJzYWwnIGFyY2ggZm9yIHBsYXRmb3JtICcke3Byb2Nlc3MucGxhdGZvcm19JyBub3QgZm91bmQgaW4gY29uZmlnIWAsXG4gICAgKVxuICB9XG5cbiAgY29uc3Qgc3JjRmlsZXMgPSBVbmlBcmNoc0J5UGxhdGZvcm1bcHJvY2Vzcy5wbGF0Zm9ybV0/Lm1hcCgoYXJjaCkgPT5cbiAgICByZXNvbHZlKFxuICAgICAgb3B0aW9ucy5jd2QsXG4gICAgICBvcHRpb25zLm91dHB1dERpcixcbiAgICAgIGAke2NvbmZpZy5iaW5hcnlOYW1lfS4ke3Byb2Nlc3MucGxhdGZvcm19LSR7YXJjaH0ubm9kZWAsXG4gICAgKSxcbiAgKVxuXG4gIGlmICghc3JjRmlsZXMgfHwgIXVuaXZlcnNhbGl6ZXJzW3Byb2Nlc3MucGxhdGZvcm1dKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCd1bml2ZXJzYWwnIGFyY2ggZm9yIHBsYXRmb3JtICcke3Byb2Nlc3MucGxhdGZvcm19JyBub3Qgc3VwcG9ydGVkLmAsXG4gICAgKVxuICB9XG5cbiAgZGVidWcoYExvb2tpbmcgdXAgc291cmNlIGJpbmFyaWVzIHRvIGNvbWJpbmU6IGApXG4gIGRlYnVnKCcgICVPJywgc3JjRmlsZXMpXG5cbiAgY29uc3Qgc3JjRmlsZUxvb2t1cCA9IGF3YWl0IFByb21pc2UuYWxsKHNyY0ZpbGVzLm1hcCgoZikgPT4gZmlsZUV4aXN0cyhmKSkpXG5cbiAgY29uc3Qgbm90Rm91bmRGaWxlcyA9IHNyY0ZpbGVzLmZpbHRlcigoXywgaSkgPT4gIXNyY0ZpbGVMb29rdXBbaV0pXG5cbiAgaWYgKG5vdEZvdW5kRmlsZXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYFNvbWUgYmluYXJ5IGZpbGVzIHdlcmUgbm90IGZvdW5kOiAke0pTT04uc3RyaW5naWZ5KG5vdEZvdW5kRmlsZXMpfWAsXG4gICAgKVxuICB9XG5cbiAgY29uc3Qgb3V0cHV0ID0gcmVzb2x2ZShcbiAgICBvcHRpb25zLmN3ZCxcbiAgICBvcHRpb25zLm91dHB1dERpcixcbiAgICBgJHtjb25maWcuYmluYXJ5TmFtZX0uJHtwcm9jZXNzLnBsYXRmb3JtfS11bml2ZXJzYWwubm9kZWAsXG4gIClcblxuICB1bml2ZXJzYWxpemVyc1twcm9jZXNzLnBsYXRmb3JtXT8uKHNyY0ZpbGVzLCBvdXRwdXQpXG5cbiAgZGVidWcoYFByb2R1Y2VkIHVuaXZlcnNhbCBiaW5hcnk6ICR7b3V0cHV0fWApXG59XG4iLCJpbXBvcnQgeyBjb2xsZWN0QXJ0aWZhY3RzIH0gZnJvbSAnLi9hcGkvYXJ0aWZhY3RzLmpzJ1xuaW1wb3J0IHsgYnVpbGRQcm9qZWN0IH0gZnJvbSAnLi9hcGkvYnVpbGQuanMnXG5pbXBvcnQgeyBjcmVhdGVOcG1EaXJzIH0gZnJvbSAnLi9hcGkvY3JlYXRlLW5wbS1kaXJzLmpzJ1xuaW1wb3J0IHsgbmV3UHJvamVjdCB9IGZyb20gJy4vYXBpL25ldy5qcydcbmltcG9ydCB7IHByZVB1Ymxpc2ggfSBmcm9tICcuL2FwaS9wcmUtcHVibGlzaC5qcydcbmltcG9ydCB7IHJlbmFtZVByb2plY3QgfSBmcm9tICcuL2FwaS9yZW5hbWUuanMnXG5pbXBvcnQgeyB1bml2ZXJzYWxpemVCaW5hcmllcyB9IGZyb20gJy4vYXBpL3VuaXZlcnNhbGl6ZS5qcydcbmltcG9ydCB7IHZlcnNpb24gfSBmcm9tICcuL2FwaS92ZXJzaW9uLmpzJ1xuXG4vKipcbiAqXG4gKiBAdXNhZ2VcbiAqXG4gKiBgYGB0c1xuICogY29uc3QgY2xpID0gbmV3IE5hcGlDbGkoKVxuICpcbiAqIGNsaS5idWlsZCh7XG4gKiAgIGN3ZDogJy9wYXRoL3RvL3lvdXIvcHJvamVjdCcsXG4gKiB9KVxuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBOYXBpQ2xpIHtcbiAgYXJ0aWZhY3RzID0gY29sbGVjdEFydGlmYWN0c1xuICBuZXcgPSBuZXdQcm9qZWN0XG4gIGJ1aWxkID0gYnVpbGRQcm9qZWN0XG4gIGNyZWF0ZU5wbURpcnMgPSBjcmVhdGVOcG1EaXJzXG4gIHByZVB1Ymxpc2ggPSBwcmVQdWJsaXNoXG4gIHJlbmFtZSA9IHJlbmFtZVByb2plY3RcbiAgdW5pdmVyc2FsaXplID0gdW5pdmVyc2FsaXplQmluYXJpZXNcbiAgdmVyc2lvbiA9IHZlcnNpb25cbn1cblxuZXhwb3J0IHsgcGFyc2VUcmlwbGUgfSBmcm9tICcuL3V0aWxzL3RhcmdldC5qcydcbiJdLCJ4X2dvb2dsZV9pZ25vcmVMaXN0IjpbMCwxLDIsMywyMywyNCwyNSwyNiwyNywyOCwyOSwzMCwzMSwzMiwzM10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQUFBLFNBQVNBLFVBQVEsR0FBRztBQUNsQjtBQUVBLFNBQU8sT0FBTyxVQUFVQSxZQUFVLHFCQUFxQixVQUFVLG1CQUFtQixPQUFPLFdBQVcsU0FBVUMsS0FBRztBQUNqSCxpQkFBY0E7RUFDZixJQUFHLFNBQVVBLEtBQUc7QUFDZixVQUFPQSxPQUFLLHFCQUFxQixVQUFVQSxJQUFFLGdCQUFnQixVQUFVQSxRQUFNLE9BQU8sWUFBWSxrQkFBa0JBO0VBQ25ILEdBQUUsT0FBTyxRQUFRLGFBQWEsTUFBTSxPQUFPLFFBQVEsYUFBYSxPQUFPLFNBQVMsVUFBUSxFQUFFO0NBQzVGO0FBQ0QsUUFBTyxVQUFVRCxXQUFTLE9BQU8sUUFBUSxhQUFhLE1BQU0sT0FBTyxRQUFRLGFBQWEsT0FBTzs7Ozs7O0NDVC9GLElBQUlFLDZCQUFpQztDQUNyQyxTQUFTQyxjQUFZLEdBQUcsR0FBRztBQUN6QixNQUFJLFlBQVksVUFBUSxFQUFFLEtBQUssRUFBRyxRQUFPO0VBQ3pDLElBQUksSUFBSSxFQUFFLE9BQU87QUFDakIsV0FBUyxNQUFNLEdBQUc7R0FDaEIsSUFBSSxJQUFJLEVBQUUsS0FBSyxHQUFHLEtBQUssVUFBVTtBQUNqQyxPQUFJLFlBQVksVUFBUSxFQUFFLENBQUUsUUFBTztBQUNuQyxTQUFNLElBQUksVUFBVTtFQUNyQjtBQUNELFNBQU8s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
|