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